{% extends "base.html.twig" %}
{% block title %}
Full Service - Contact
{% endblock %}
{% block body %}
<!-- Page Header -->
<header class="bg-white shadow-sm px-4 py-3 z-index-20">
<div class="container-fluid px-0">
<h1 class="mb-0 p-1">Contact</h1>
</div>
</header>
<!-- Breadcrumb -->
<div class="bg-white">
<div class="container-fluid">
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0 py-3">
<li class="breadcrumb-item"><a class="fw-light" href="{{path('home.index')}}">Accueil</a></li>
<li class="breadcrumb-item active fw-light" aria-current="page">Contact</li>
</ol>
</nav>
</div>
</div>
<!-- Form Section -->
<section class="forms">
<div class="container-fluid">
<div class="row">
<!-- Form Elements -->
<div class="col-lg-8">
<div class="card">
<div class="card-header">
<h3 class="h4 mb-0">Nous contacter</h3>
</div>
<div class="card-body">
{{ form_start(form) }}
<!-- Type d'utilisateur -->
<div class="form-group mb-3">
{{ form_row(form.userType) }}
</div>
<div id="garage-fields" class="d-none">
<!-- Masquer tout par défaut -->
<!-- Bandeau d'information pour Garage -->
<div id="garage-banner" class="alert alert-warning alert-dismissible fade show" role="alert">
Pour toute demande d'accès, merci de vous rapprocher d'abord de votre distributeur.
</div>
<div class="form-group mb-3 garage-field">
{{ form_row(form.autreDistributeurToggle) }}
</div>
<!-- Champs conditionnels pour Garage -->
<div class="form-group mb-3 garage-field position-relative">
<label class="form-label" for="contact_distributeurRattachement">
{{ form_label(form.distributeurRattachement) }}
<span class="tooltip-container ms-2">
<span class="tooltip-text"><i class="fas fa-question-circle"></i></span>
<div class="tooltip-content">
Saisissez une ville, un code postal ou un département<br />
pour rechercher un distributeur.
</div>
</span>
</label>
{{ form_widget(form.distributeurRattachement) }}
{{ form_errors(form.distributeurRattachement) }}
{{ form_row(form.distributeurId) }}
<ul id="autocomplete-list" class="list-group position-absolute w-100" style="z-index: 10;"></ul>
</div>
</div>
<div id="autre-distributeur-block" class="form-group mb-3 d-none garage-field">
<div class="row">
<!-- autreDistributeur -->
<div class="form-group col-md-6 mb-1">
{{ form_row(form.autreDistributeur) }}
</div>
<!-- codePostal -->
<div class="form-group col-md-6 mb-1">
{{ form_row(form.codePostal) }}
</div>
</div>
</div>
<div class="d-flex align-items-center my-2 mb-0">
<hr class="flex-grow-1" style="border-top: 1px solid #ccc;">
<i class="fas fa-building mx-3 text-secondary"></i>
<hr class="flex-grow-1" style="border-top: 1px solid #ccc;">
</div>
<!-- Société -->
<div class="form-group mb-3">
{{ form_row(form.raisonSociale) }}
</div>
<div class="d-flex align-items-center my-2 mb-0">
<hr class="flex-grow-1" style="border-top: 1px solid #ccc;">
<i class="fas fa-user mx-3 text-secondary"></i>
<hr class="flex-grow-1" style="border-top: 1px solid #ccc;">
</div>
<div class="row">
<!-- Nom -->
<div class="form-group col-md-6 mb-1">
{{ form_row(form.name) }}
</div>
<!-- Prénom -->
<div class="form-group col-md-6 mb-1">
{{ form_row(form.firstName) }}
</div>
</div>
<div class="row">
<!-- Téléphone -->
<div class="form-group col-md-6 mb-1">
{{ form_row(form.phoneNumber) }}
</div>
<!-- Adresse email -->
<div class="form-group col-md-6 mb-1">
{{ form_row(form.email) }}
</div>
</div>
<div class="d-flex align-items-center my-2 mb-0">
<hr class="flex-grow-1" style="border-top: 1px solid #ccc;">
<i class="fas fa-envelope mx-3 text-secondary"></i>
<hr class="flex-grow-1" style="border-top: 1px solid #ccc;">
</div>
<!-- Objet -->
<div class="form-group mb-1">
{{ form_row(form.subject) }}
</div>
<!-- Message -->
<div class="form-group mb-1">
{{ form_row(form.message) }}
</div>
<!-- Captcha -->
<div class="form-group mb-1">
{{ form_row(form.captcha) }}
</div>
<!-- Bouton Envoyer -->
<div class="form-group">
{{ form_row(form.submit) }}
</div>
{{ form_end(form) }}
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Notifications -->
{% for message in app.flashes('success') %}
<div class="toast-container position-fixed top-0 end-0 p-4">
<div class="toast bg-success text-white fade show" id="successLiveToast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header bg-success text-white">
<strong class="me-auto">Envoi du message</strong><small>à l'instant</small>
<button class="btn-close btn-close-white" type="button" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">{{ message }}</div>
</div>
</div>
{% endfor %}
{% for message in app.flashes('alert') %}
<div class="toast-container position-fixed top-0 end-0 p-4">
<div class="toast hide bg-danger text-white" id="errorLiveToast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header bg-danger text-white">
<strong class="me-auto">Erreur de saisie</strong><small></small>
<button class="btn-close btn-close-white" type="button" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">{{ message }}</div>
</div>
</div>
{% endfor %}
<script>
document.addEventListener('DOMContentLoaded', function () {
const garageFields = document.getElementById('garage-fields');
const userTypeRadios = document.querySelectorAll('input[name="contact[userType]"]');
const distributeurField = document.querySelector('input[name="contact[distributeurRattachement]"]');
const codePostalField = document.querySelector('input[name="contact[codePostal]"]');
const autreDistributeurToggle = document.querySelector('input[name="contact[autreDistributeurToggle]"]');
const autreDistributeurBlock = document.getElementById('autre-distributeur-block');
const autocompleteList = document.getElementById('autocomplete-list');
const autocompleteUrl = distributeurField?.dataset.autocompleteUrl;
const autreDistributeurToggleContainer = autreDistributeurToggle?.closest('.form-group');
const hiddenDistributeurIdInput = document.getElementById('contact_distributeurId');
// Affiche/Masque les champs pour les garages
function toggleGarageFields() {
const selectedRadio = document.querySelector('input[name="contact[userType]"]:checked');
const isGarage = selectedRadio && selectedRadio.value === 'Garage';
garageFields.classList.toggle('d-none', !isGarage);
if (distributeurField) distributeurField.toggleAttribute('required', isGarage && !autreDistributeurToggle.checked);
if (codePostalField) codePostalField.toggleAttribute('required', isGarage);
// Cache "J'ai un autre distributeur" si non garage
if (!isGarage && autreDistributeurToggleContainer) {
autreDistributeurToggle.checked = false;
autreDistributeurToggleContainer.classList.add('d-none');
autreDistributeurBlock.classList.add('d-none');
}
}
// Affiche/Masque le champ "Nom autre distributeur"
function toggleAutreDistributeurField() {
const isGarage = document.querySelector('input[name="contact[userType]"]:checked')?.value === 'Garage';
const autreDistributeurInput = document.querySelector('input[name="contact[autreDistributeur]"]');
if (!autreDistributeurToggle || !autreDistributeurBlock) return;
if (autreDistributeurToggle.checked) {
// Affiche les champs libres
autreDistributeurBlock.classList.remove('d-none');
hiddenDistributeurIdInput.value = '';
codePostalField.value = '';
//Ajout du required pour validation HTML native
if (autreDistributeurInput) autreDistributeurInput.setAttribute('required', 'required');
// Vide et désactive distributeurRattachement
if (distributeurField) {
distributeurField.value = '';
distributeurField.setAttribute('readonly', 'readonly');
distributeurField.classList.add('text-muted');
distributeurField.setAttribute('placeholder', 'Aucun distributeur trouvé');
}
} else {
autreDistributeurBlock.classList.add('d-none');
// Supprime le required s'il ne doit pas être actif
if (autreDistributeurInput) autreDistributeurInput.removeAttribute('required');
// Réactive distributeurRattachement
if (distributeurField) {
distributeurField.removeAttribute('readonly');
distributeurField.classList.remove('text-muted');
distributeurField.setAttribute('placeholder', 'Saisissez une ville ou un code postal');
}
}
}
// Gère les événements radio
userTypeRadios.forEach(radio => radio.addEventListener('change', () => {
toggleGarageFields();
toggleAutreDistributeurField();
}));
if (autreDistributeurToggle) {
autreDistributeurToggle.addEventListener('change', toggleAutreDistributeurField);
}
toggleGarageFields();
toggleAutreDistributeurField();
// AUTOCOMPLÉTION DISTRIBUTEUR
if (distributeurField && autocompleteList && autocompleteUrl) {
let debounceTimer;
distributeurField.addEventListener('input', function () {
clearTimeout(debounceTimer);
const query = this.value.trim();
if (query.length < 2) {
autocompleteList.innerHTML = '';
return;
}
debounceTimer = setTimeout(() => {
fetch(`${autocompleteUrl}?q=${encodeURIComponent(query)}`)
.then(response => response.json())
.then(data => {
autocompleteList.innerHTML = '';
const selectedRadio = document.querySelector('input[name="contact[userType]"]:checked');
const isGarage = selectedRadio && selectedRadio.value === 'Garage';
if (data.length === 0) {
const li = document.createElement('li');
li.classList.add('autocomplete-no-result');
li.textContent = 'Aucun distributeur trouvé - vous pouvez le renseigner manuellement';
autocompleteList.appendChild(li);
if (isGarage && autreDistributeurToggleContainer) {
autreDistributeurToggleContainer.classList.remove('d-none');
autreDistributeurToggle.checked = true;
toggleAutreDistributeurField();
}
return;
}
if (autreDistributeurToggleContainer) {
autreDistributeurToggle.checked = false;
autreDistributeurToggleContainer.classList.add('d-none');
autreDistributeurBlock.classList.add('d-none');
}
data.forEach(item => {
const li = document.createElement('li');
li.classList.add('list-group-item', 'list-group-item-action');
li.textContent = item.label;
li.dataset.id = item.id;
li.addEventListener('click', () => {
distributeurField.value = item.label;
autocompleteList.innerHTML = '';
// Champ caché pour stocker l'ID sélectionné
if (hiddenDistributeurIdInput) {
hiddenDistributeurIdInput.value = item.id;
}
// Renseigne automatiquement le code postal si détecté dans le label
const codePostalMatch = item.label.match(/\b\d{5}\b/);
if (codePostalMatch && codePostalField) {
codePostalField.value = codePostalMatch[0];
}
// Cache la partie "autre distributeur"
if (autreDistributeurToggle) {
autreDistributeurToggle.checked = false;
toggleAutreDistributeurField();
}
});
autocompleteList.appendChild(li);
});
})
.catch(err => {
autocompleteList.innerHTML = '';
console.error('Erreur autocomplétion :', err);
});
}, 300);
});
document.addEventListener('click', (e) => {
if (!distributeurField.contains(e.target) && !autocompleteList.contains(e.target)) {
autocompleteList.innerHTML = '';
}
});
}
});
</script>
<style>
#autocomplete-list {
background-color: #f8f9fa;
border: 1px solid #ced4da;
border-radius: 4px;
overflow: hidden;
margin-top: 2px;
box-shadow: 0px 4px 8px rgba(0,0,0,0.05);
max-height: 300px;
overflow-y: auto;
}
#autocomplete-list li {
padding: 8px 12px;
border-bottom: 1px solid #dee2e6;
background-color: #f8f9fa;
font-size: 14px;
line-height: 1.4;
color: #212529;
}
#autocomplete-list li:last-child {
border-bottom: none;
}
#autocomplete-list li:hover {
background-color: rgb(216, 233, 255);
cursor: pointer;
}
#autocomplete-list:empty {
display: none;
}
.autocomplete-no-result {
background-color: #f1f1f1;
color:rgb(125, 108, 108);
font-style: italic;
padding: 8px 12px;
border-bottom: none;
cursor: default;
}
.tooltip-container {
position: relative;
display: inline-block;
cursor: help;
}
.tooltip-container:hover .tooltip-content {
visibility: visible;
opacity: 1;
}
.tooltip-text {
display: inline-block;
}
.tooltip-content {
visibility: hidden;
background-color: #333;
color: #fff;
text-align: left;
border-radius: 6px;
padding: 6px 10px;
position: absolute;
z-index: 1000;
white-space: nowrap;
bottom: 125%;
left: 0;
opacity: 0;
transition: opacity 0.3s ease-in-out;
font-size: 12px;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2);
}
</style>
{% endblock %}