feat(assets/app.js): Ajoute la gestion des menus utilisateur et améliore l'UI.

Ajoute la gestion des menus utilisateur (desktop et mobile) avec des fonctions pour basculer la visibilité et ferme les menus au clic extérieur.
Ajoute aussi la gestion de la touche "Echap" pour fermer les menus.

 feat(translations/messages.en.yaml): Add security translations for login & password.

Ajoute les traductions anglaises pour la sécurité (connexion, mot de passe oublié).

 feat(translations/messages.fr.yaml): Ajoute les traductions pour la sécurité.

Ajoute les traductions françaises pour les formulaires de connexion et mot de passe oublié.

 feat(templates/security): Crée les templates pour login et mot de passe oublié.

Crée les templates login.twig, forgot_password.twig et forgot_password_success.twig.

 feat(src/Service/ResetPassword): Adapte ResetPasswordSubscriber pour E-Cosplay.

Adapte le service ResetPasswordSubscriber pour le projet E-Cosplay.

 feat(src/Controller/SecurityController): Crée le contrôleur de sécurité.

Crée le SecurityController avec les routes pour la connexion et la gestion du mot de passe oublié.

 feat(templates/base.twig): Ajoute le menu utilisateur desktop et mobile.

Ajoute le menu utilisateur (desktop et mobile) avec gestion de la connexion/déconnexion.
This commit is contained in:
Serreau Jovann
2025-11-17 13:12:56 +01:00
parent 24406d0184
commit 5930f0435f
9 changed files with 507 additions and 32 deletions

View File

@@ -1,22 +1,43 @@
import './app.scss'
import * as Turbo from "@hotwired/turbo"
/**
* Fonction générique pour basculer la visibilité d'un menu déroulant.
* @param {HTMLElement} button - Le bouton qui déclenche l'action.
* @param {HTMLElement} menu - Le menu à afficher/masquer.
*/
function toggleMenu(button, menu) {
if (!button || !menu) return;
const isExpanded = button.getAttribute('aria-expanded') === 'true' || false;
button.setAttribute('aria-expanded', !isExpanded);
menu.classList.toggle('hidden');
}
/**
* Fonction d'initialisation pour les composants qui DOIVENT être réinitialisés
* après un chargement Turbo (comme les compteurs d'articles, les états initiaux).
* Le menu mobile et le panier sont gérés par délégation d'événements.
*/
function initializeUI() {
// Réinitialisation des états des menus cachés après un chargement Turbo,
// au cas où ils étaient ouverts lors de la navigation précédente.
document.querySelectorAll('#mobile-menu, #userMenuDesktop, #userMenuMobile').forEach(menu => {
if (!menu.classList.contains('hidden')) {
menu.classList.add('hidden');
}
});
document.querySelectorAll('#mobileMenuButton, #userMenuButtonDesktop, #userMenuButtonMobile').forEach(button => {
button.setAttribute('aria-expanded', 'false');
});
// --- 2. Gestion du Panier Latéral (Off-Canvas) ---
// Les fonctions open/close ont besoin de l'accès direct aux éléments,
// mais les listeners d'ouverture/fermeture seront gérés par délégation en bas.
const cartSidebar = document.getElementById('cartSidebar');
const cartBackdrop = document.getElementById('cartBackdrop');
const closeCartButton = document.getElementById('closeCartButton');
// Mettez les fonctions ici pour qu'elles soient toujours définies si les éléments existent
if (cartSidebar && cartBackdrop && closeCartButton) {
// ... (Fonctions openCart et closeCart inchangées)
function openCart() {
document.body.style.overflow = 'hidden';
cartBackdrop.classList.remove('hidden');
@@ -36,12 +57,15 @@ function initializeUI() {
// Stocker les fonctions dans une variable globale accessible par l'écouteur du document
window.openCart = openCart;
window.closeCart = closeCart;
} else {
// Sécurité si les éléments du panier n'existent pas
window.openCart = null;
window.closeCart = null;
}
// --- 3. Logique Panier Mock (Affichage du compteur) ---
function updateCartDisplay(count) {
// ... (Logique inchangée)
const desktopCounter = document.getElementById('cartCountDesktop');
const mobileCounter = document.getElementById('cartCountMobile');
@@ -73,20 +97,55 @@ document.addEventListener('turbo:load', initializeUI);
document.addEventListener('click', (event) => {
const target = event.target;
// 1. GESTION DU MENU MOBILE (Burger)
// --- 1. GESTION DU MENU MOBILE (Burger) ---
const mobileMenuButton = document.getElementById('mobileMenuButton');
const mobileMenu = document.getElementById('mobile-menu');
// On vérifie si la cible cliquée est le bouton ou un de ses enfants
if (mobileMenuButton && mobileMenu && (target === mobileMenuButton || mobileMenuButton.contains(target))) {
event.preventDefault(); // Empêche l'action par défaut du bouton
const isExpanded = mobileMenuButton.getAttribute('aria-expanded') === 'true';
mobileMenuButton.setAttribute('aria-expanded', !isExpanded);
mobileMenu.classList.toggle('hidden');
event.preventDefault();
toggleMenu(mobileMenuButton, mobileMenu);
return;
}
// 2. GESTION DE L'OUVERTURE ET FERMETURE DU PANIER
// --- 2. GESTION DU MENU UTILISATEUR (Dropdown) ---
const userMenuButtonDesktop = document.getElementById('userMenuButtonDesktop');
const userMenuDesktop = document.getElementById('userMenuDesktop');
const userMenuButtonMobile = document.getElementById('userMenuButtonMobile');
const userMenuMobile = document.getElementById('userMenuMobile');
// Ouverture/Fermeture du menu utilisateur Desktop
if (userMenuButtonDesktop && userMenuDesktop && (target === userMenuButtonDesktop || userMenuButtonDesktop.contains(target))) {
event.preventDefault();
// S'assurer que les autres menus sont fermés
userMenuMobile.classList.add('hidden');
toggleMenu(userMenuButtonDesktop, userMenuDesktop);
return;
}
// Ouverture/Fermeture du menu utilisateur Mobile
if (userMenuButtonMobile && userMenuMobile && (target === userMenuButtonMobile || userMenuButtonMobile.contains(target))) {
event.preventDefault();
// S'assurer que les autres menus sont fermés
userMenuDesktop.classList.add('hidden');
toggleMenu(userMenuButtonMobile, userMenuMobile);
return;
}
// Fermeture des menus s'il y a un clic en dehors
const isClickInsideDesktopMenu = userMenuDesktop && (userMenuDesktop.contains(target) || userMenuButtonDesktop.contains(target));
const isClickInsideMobileMenu = userMenuMobile && (userMenuMobile.contains(target) || userMenuButtonMobile.contains(target));
if (userMenuDesktop && userMenuButtonDesktop && !isClickInsideDesktopMenu) {
userMenuDesktop.classList.add('hidden');
userMenuButtonDesktop.setAttribute('aria-expanded', 'false');
}
if (userMenuMobile && userMenuButtonMobile && !isClickInsideMobileMenu) {
userMenuMobile.classList.add('hidden');
userMenuButtonMobile.setAttribute('aria-expanded', 'false');
}
// --- 3. GESTION DE L'OUVERTURE ET FERMETURE DU PANIER ---
const openCartDesktop = document.getElementById('openCartDesktop');
const openCartMobile = document.getElementById('openCartMobile');
const closeCartButton = document.getElementById('closeCartButton');
@@ -114,12 +173,32 @@ document.addEventListener('click', (event) => {
window.closeCart();
return;
}
});
// --- GESTION GLOBALE DE LA TOUCHE ESC (Une seule fois) ---
document.addEventListener('keydown', (event) => {
const cartSidebar = document.getElementById('cartSidebar');
// Fermer le panier
if (cartSidebar && window.closeCart && event.key === 'Escape' && !cartSidebar.classList.contains('translate-x-full')) {
window.closeCart();
return;
}
// Fermer les menus utilisateur
const userMenuDesktop = document.getElementById('userMenuDesktop');
const userMenuButtonDesktop = document.getElementById('userMenuButtonDesktop');
const userMenuMobile = document.getElementById('userMenuMobile');
const userMenuButtonMobile = document.getElementById('userMenuButtonMobile');
if (event.key === 'Escape') {
if (userMenuDesktop && !userMenuDesktop.classList.contains('hidden')) {
toggleMenu(userMenuButtonDesktop, userMenuDesktop);
return;
}
if (userMenuMobile && !userMenuMobile.classList.contains('hidden')) {
toggleMenu(userMenuButtonMobile, userMenuMobile);
return;
}
}
});