{% extends "base_security.html.twig" %}
{% block fos_user_title %}
<h4 class="auth-header text-center" style="font-weight: 600; color: #2c3e50; margin-bottom: 0;">{{ 'title.new_user_account' | trans }}</h4>
{% endblock fos_user_title %}
{% block fos_user_content %}
<style>
.auth-box-w {
background: white;
border-radius: 16px;
padding: 25px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.auth-box-w:hover {
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.12);
}
.form-container {
max-width: 380px;
margin: 0 auto;
}
img {
width: 35px;
transition: transform 0.3s ease;
}
img:hover {
transform: scale(1.05);
}
/* Header avec Langue */
.header-separator {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 2px solid #e8ecf1;
}
.header-separator h4 {
background: linear-gradient(135deg, #1976d2, #0d47a1);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.language-selector {
display: flex;
align-items: center;
gap: 8px;
}
.language-selector label {
margin: 0;
color: #666;
font-size: 12px;
font-weight: 500;
}
.language-selector select {
padding: 4px 8px;
border: 1px solid #e0e4e8;
border-radius: 6px;
background: #fafbfc;
font-size: 12px;
cursor: pointer;
transition: all 0.2s ease;
}
.language-selector select:hover {
border-color: #1976d2;
background: white;
}
.form-group {
margin-bottom: 14px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: 600;
color: #2c3e50;
font-size: 12px;
letter-spacing: 0.3px;
}
.form-control, .custom-select {
width: 100%;
padding: 8px 12px;
border: 1.5px solid #e8ecf1;
border-radius: 8px;
font-size: 13px;
transition: all 0.3s ease;
background: #fafbfc;
font-family: inherit;
}
.form-control:hover, .custom-select:hover {
border-color: #bdc3c7;
background: white;
}
.form-control:focus, .custom-select:focus {
outline: none;
border-color: #1976d2;
background: white;
box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.1);
}
select.form-control, select.custom-select {
appearance: none;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="%23666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>');
background-repeat: no-repeat;
background-position: right 10px center;
background-size: 10px;
}
/* Groupe téléphone */
.phone-group {
display: flex;
gap: 8px;
align-items: center;
}
.phone-prefix {
width: 70px;
flex-shrink: 0;
}
.phone-prefix input {
text-align: center;
background: #f0f2f5;
border: 1.5px solid #e8ecf1;
font-weight: 600;
color: #1976d2;
}
.phone-number {
flex: 1;
}
.phone-hint {
font-size: 10px;
color: #95a5a6;
margin-top: 4px;
display: flex;
align-items: center;
gap: 4px;
}
.phone-hint::before {
content: "💡";
font-size: 10px;
}
/* Ligne de séparation */
.separator {
height: 1px;
background: linear-gradient(90deg, transparent, #e0e4e8, transparent);
margin: 18px 0;
}
/* Boutons */
.buttons-group {
display: flex;
gap: 12px;
margin-top: 18px;
}
.btn {
flex: 1;
padding: 9px;
border: none;
border-radius: 8px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
text-decoration: none;
display: inline-block;
letter-spacing: 0.5px;
}
.btn-primary {
background: linear-gradient(135deg, #1976d2, #0d47a1);
color: white;
box-shadow: 0 2px 4px rgba(25, 118, 210, 0.2);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(25, 118, 210, 0.3);
background: linear-gradient(135deg, #1e88e5, #1565c0);
}
.btn-primary:active {
transform: translateY(0);
}
.btn-secondary {
background: white;
color: #666;
border: 1.5px solid #e0e4e8;
}
.btn-secondary:hover {
background: #f8f9fa;
border-color: #1976d2;
color: #1976d2;
transform: translateY(-2px);
}
/* Alertes */
.alert {
border-radius: 8px;
padding: 10px 12px;
margin-bottom: 15px;
border: none;
font-size: 12px;
display: flex;
align-items: center;
gap: 8px;
}
.alert-danger {
background: linear-gradient(135deg, #fee, #fdd);
color: #c33;
border-left: 4px solid #c33;
}
.text-danger {
color: #e74c3c;
}
.help-block {
font-size: 10px;
margin-top: 3px;
display: flex;
align-items: center;
gap: 4px;
}
.help-block::before {
font-size: 9px;
}
/* Footer logos */
.footer-logos {
margin-top: 18px;
padding-top: 15px;
border-top: 1px solid #e8ecf1;
text-align: center;
}
.footer-logos span {
display: block;
color: #95a5a6;
font-size: 10px;
margin-bottom: 10px;
font-weight: 500;
}
.logos-container {
display: flex;
justify-content: center;
gap: 20px;
flex-wrap: wrap;
align-items: center;
}
.logos-container a {
display: inline-block;
line-height: 0;
transition: transform 0.3s ease;
}
.logos-container a:hover {
transform: translateY(-2px);
}
.logos-container img {
width: 32px !important;
height: auto !important;
max-width: 32px;
opacity: 0.6;
transition: all 0.3s ease;
border-radius: 6px;
filter: grayscale(0.2);
}
.logos-container img:hover {
opacity: 1;
filter: grayscale(0);
}
/* Diaspora container */
.diaspora-container {
background: linear-gradient(135deg, #f8f9fa, #f1f3f5);
border-radius: 8px;
padding: 10px 12px;
margin-top: 5px;
border: 1px solid #e8ecf1;
}
.diaspora-container label {
margin-bottom: 6px;
font-size: 11px;
color: #2c3e50;
}
/* Ligne pour mot de passe */
.password-row {
display: flex;
gap: 12px;
margin-bottom: 14px;
}
.password-col {
flex: 1;
}
.password-col .form-group {
margin-bottom: 0;
}
/* Champ avec icône */
.input-icon {
position: relative;
}
/* Checkbox personnalisée */
.custom-checkbox {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
}
/* Responsive */
@media (max-width: 576px) {
.form-container {
max-width: 100%;
padding: 0 10px;
}
.auth-box-w {
padding: 20px;
}
.buttons-group {
flex-direction: column;
gap: 10px;
}
.phone-group {
flex-direction: column;
gap: 8px;
}
.phone-prefix {
width: 100%;
}
.header-separator {
flex-direction: column;
gap: 10px;
align-items: flex-start;
}
.password-row {
flex-direction: column;
gap: 14px;
}
}
</style>
<div class="form-container">
{% if app.session.flashBag.has('danger') == true %}
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<span>⚠️</span>
{% for message in app.session.flashbag.get('danger') %}
<p class="text-center w-100 mb-0">{{ message }}</p>
{% endfor %}
<button type="button" class="close" data-dismiss="alert" aria-label="Close" style="margin-left: auto;">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
<div class="help-block form-text with-errors text-danger" style="margin-bottom: 10px;">{{ form_errors(form) | raw }}</div>
<form id="form-register" action="{{ path('register_create_account') }}" method="post" novalidate>
{{ form_widget(form._token) }}
<!-- Header avec Langue -->
<div class="header-separator">
<h4 style="margin: 0; font-size: 16px; font-weight: 700;">📝 {{ 'title.new_user_account' | trans }}</h4>
<div class="language-selector">
<label>🌐 {{ 'Langue' | trans }}</label>
<select id="language-select">
<option value="fr">Français</option>
<option value="en">English</option>
<option value="es">Español</option>
</select>
</div>
</div>
<!-- Type d'utilisateur -->
<div class="form-group">
<label>👤 {{ "menu.user_type" | trans }} <span class="text-danger">*</span></label>
{{ form_widget(form.typePerson, { 'attr': {'class': 'form-control', 'required': 'required'} }) }}
<div class="help-block text-danger">{{ form_errors(form.typePerson) }}</div>
</div>
<!-- Diaspora -->
<div id="diaspora" class="form-group" style="display: none;">
<div class="diaspora-container">
<label>🌍 {{ 'menu.diaspora' | trans }}</label>
<div class="d-flex align-items-center">
{{ form_widget(form.diaspora, { 'attr': {'class': 'form-check-input', 'style': 'margin-right: 8px; width: 16px; height: 16px; cursor: pointer;'} }) }}
<span style="font-size: 12px;">{{ 'menu.diaspora_help' | trans | default('Êtes-vous membre de la diaspora ?') }}</span>
</div>
<div class="help-block text-danger">{{ form_errors(form.diaspora) }}</div>
</div>
</div>
<!-- Région / Pays -->
<div class="form-group">
<label>📍
{% if struct_province_country_city == "true" %}
{{ 'menu.region' | trans }}
{% else %}
{{ 'menu.country' | trans }}
{% endif %}
<span class="text-danger">*</span>
</label>
{% if struct_province_country_city == "true" %}
{{ create_translated_select(form.region, { 'attr': {'class': 'form-control custom-select', 'id': 'userbundle_user_region'} }) }}
<div class="help-block text-danger">{{ form_errors(form.region) }}</div>
{% else %}
{{ create_translated_select(form.country, { 'attr': {'class': 'form-control custom-select', 'id': 'userbundle_user_country'} }) }}
<div class="help-block text-danger">{{ form_errors(form.country) }}</div>
{% endif %}
</div>
<!-- Pays de résidence -->
<div id="residenceCountry" class="form-group" style="display: none">
<label>🏠 {{ 'menu.residence_country' | trans }} <span class="text-danger">*</span></label>
{% if struct_province_country_city == "true" %}
{{ create_translated_select(form.residenceRegion, { 'attr': {'class': 'form-control custom-select', 'id': 'residence-select'} }) }}
<div class="help-block text-danger">{{ form_errors(form.residenceRegion) }}</div>
{% else %}
{{ create_translated_select(form.residenceCountry, { 'attr': {'class': 'form-control custom-select', 'id': 'residence-select'} }) }}
<div class="help-block text-danger">{{ form_errors(form.residenceCountry) }}</div>
{% endif %}
</div>
<!-- Téléphone -->
<div class="form-group">
<label>📞 {{ 'menu.phone' | trans }} : {{ 'menu.phone_indicator' | trans }} (<span id="phone_code">+XX</span>) + N° <span class="text-danger">*</span></label>
<div class="phone-group">
<div class="phone-prefix">
<input type="text" id="phone_prefix_display" class="form-control" value="+XX" readonly>
</div>
<div class="phone-number">
{{ form_widget(form.phone, { 'attr': {'class': 'form-control', 'type': 'tel', 'required': 'required', 'placeholder': 'Numéro de téléphone'} }) }}
</div>
</div>
<div class="phone-hint">{{ 'menu.phone_format_hint' | trans | default('Exemple: 612345678') }}</div>
<div class="help-block text-danger">{{ form_errors(form.phone) }}</div>
</div>
<!-- Champs optionnels cachés -->
<div class="form-group" style="display: none">
<label>👤 Pseudo (Optionnel)</label>
{{ form_widget(form.username, { 'attr': {'class': 'form-control'} }) }}
</div>
<div class="form-group" style="display: none">
<label>📧 Email (Optionnel)</label>
{{ form_widget(form.email, { 'attr': {'class': 'form-control', 'type': 'email'} }) }}
</div>
<!-- Mot de passe et Confirmation -->
<div class="password-row">
<div class="password-col">
<div class="form-group">
<label>🔒 {{ "menu.password" | trans }} <span class="text-danger">*</span></label>
{{ form_widget(form.plainPassword.first, { 'attr': {'class': 'form-control', 'type': 'password', 'required': 'required', 'minlength': '6', 'placeholder': '••••••'} }) }}
<small class="phone-hint">Minimum 6 caractères</small>
<div class="help-block text-danger">{{ form_errors(form.plainPassword.first) }}</div>
</div>
</div>
<div class="password-col">
<div class="form-group">
<label>✓ {{ "menu.confirm" | trans }} <span class="text-danger">*</span></label>
{{ form_widget(form.plainPassword.second, { 'attr': {'class': 'form-control', 'type': 'password', 'required': 'required', 'placeholder': '••••••'} }) }}
<div class="help-block text-danger">{{ form_errors(form.plainPassword.second) }}</div>
</div>
</div>
</div>
<!-- Ligne de séparation élégante -->
<div class="separator"></div>
<!-- Boutons -->
<div class="buttons-group">
<button type="submit" class="btn btn-primary" id="submitRegister">
✓ {{ 'menu.validate' | trans }}
</button>
<a href="{{ path('logout') }}" class="btn btn-secondary">
✗ {{ 'menu.cancel' | trans }}
</a>
</div>
<!-- Footer logos -->
<div class="footer-logos">
<span>{{ "footer.dev_by" | trans }}</span>
<div class="logos-container">
<a target="_blank" href="https://ifef.francophonie.org/" rel="noopener noreferrer">
<img src="{{ asset('build/images/pinsuprem/logo_ifef.jpg') }}" alt="IFEF" onerror="this.style.display='none'">
</a>
<a target="_blank" href="https://www.francophonie.org/" rel="noopener noreferrer">
<img src="{{ asset('build/images/pinsuprem/logo_oif.jpg') }}" alt="OIF" onerror="this.style.display='none'">
</a>
</div>
</div>
</form>
</div>
<select hidden id="indTel">
{% for country in allCountries %}
<option value="{{ country.id }}" data-code="{{ country.phoneCode }}">{{ country.phoneCode }}</option>
{% endfor %}
</select>
{% endblock %}
{% block fos_user_script %}
<script>
$(document).ready(function() {
$('#diaspora').hide();
$('#residenceCountry').hide();
if ($('#userbundle_user_typePerson option:selected').val() == 'ROLE_DIPLOME') {
$('#diaspora').show();
}
updatePhonePrefix();
$('#userbundle_user_typePerson').on('change', function() {
if ($(this).val() == 'ROLE_DIPLOME') {
$('#diaspora').slideDown(200);
} else {
$('#userbundle_user_diaspora').prop('checked', false);
$('#diaspora').slideUp(200);
$('#residenceCountry').slideUp(200);
updatePhonePrefix();
}
});
$('#userbundle_user_diaspora').on('change', function() {
if ($(this).is(':checked')) {
$('#residenceCountry').slideDown(200);
$('#residence-select').prop('required', true);
} else {
$('#residenceCountry').slideUp(200);
$('#residence-select').prop('required', false);
updatePhonePrefix();
}
});
if ($('#userbundle_user_region').length) {
$('#userbundle_user_region').on('change', function() {
if(!$('#userbundle_user_diaspora').is(':checked')) {
updatePhonePrefix();
}
});
}
if ($('#userbundle_user_country').length) {
$('#userbundle_user_country').on('change', function() {
if(!$('#userbundle_user_diaspora').is(':checked')) {
updatePhonePrefix();
}
});
}
$('#residence-select').on('change', function() {
if($('#userbundle_user_diaspora').is(':checked')) {
updatePhonePrefix();
}
});
function updatePhonePrefix() {
let selectedCountryId = null;
if ($('#residenceCountry').is(':visible') && $('#residence-select').val()) {
selectedCountryId = $('#residence-select').val();
} else if ($('#userbundle_user_region').length && $('#userbundle_user_region').val()) {
selectedCountryId = $('#userbundle_user_region').val();
} else if ($('#userbundle_user_country').length && $('#userbundle_user_country').val()) {
selectedCountryId = $('#userbundle_user_country').val();
}
if (selectedCountryId) {
let phoneCode = $('#indTel option[value="' + selectedCountryId + '"]').data('code');
if (phoneCode) {
phoneCode = '+' + phoneCode;
$('#phone_code').text(phoneCode);
$('#phone_prefix_display').val(phoneCode);
} else {
resetPhonePrefix();
}
} else {
resetPhonePrefix();
}
}
function resetPhonePrefix() {
$('#phone_code').text('+XX');
$('#phone_prefix_display').val('+XX');
}
$('#language-select').on('change', function() {
var lang = $(this).val();
console.log('Langue changée vers: ' + lang);
});
});
</script>
{% endblock %}