Le fondu en CSS mask-image ne s'affichait pas correctement : les cartes
en bord de carrousel étaient tronquées net au lieu de s'estomper.
Remplacé par un vrai dégradé en overlay (deux calques blanc→transparent
superposés aux bords), plus fiable visuellement, avec une largeur de
fondu réduite sur mobile.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
- Le carrousel « Nos entreprises membres » est maintenant contenu dans le
même conteneur que le reste des sections (au lieu de déborder pleine
largeur jusqu'aux bords de l'écran).
- Header : la barre de navigation passe en hauteur flexible pour ne plus
être tronquée quand les liens (dont « Rencontres passées ») passent à
la ligne sur petit écran.
- Back-office admin : la barre latérale fixe de 250px passait en dehors
de l'écran sur mobile ; elle se replie désormais en liste verticale
au-dessus du contenu sous 860px.
- Cartes de rencontres passées et carrousel photo plein écran : paddings,
tailles de police et de flèches réduits sur petit écran ; le fond du
carrousel plein écran passe d'un rgba semi-transparent à une couleur
opaque (le fond semi-transparent laissait apparaître le header du site
par transparence sur mobile).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
Le nombre d'entreprises membres et de rencontres organisées provient
maintenant des données réelles (nombre de membres validés, nombre de
rencontres passées) au lieu de chiffres codés en dur. Le nombre de
membres est aussi affiché dans le pied de page.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
Seules les vignettes photo individuelles ouvraient le carrousel ; un clic
ailleurs sur la carte (titre, texte) ne faisait rien. Toute la carte est
maintenant cliquable dès qu'une rencontre a au moins une photo.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
Photos :
- Nouvelle table rencontre_passee_photos (photos illimitées par rencontre
passée, avec position). Migration idempotente au démarrage des anciennes
colonnes image_path/_2/_3 vers cette table (puis colonnes nullées)
- Le nombre de photos affiché est désormais celui réellement uploadé
(calculé), le champ manuel nb_photos n'est plus utilisé
- Gestion admin : ajout illimité, choix de la photo « principale » (mise
en avant), suppression réservée aux admins (les modérateurs ajoutent et
réordonnent mais ne suppriment pas)
Participants auto :
- rencontres_passees.rencontre_id (FK, ON DELETE SET NULL) ; quand une
rencontre passée est liée à une rencontre, le nombre de participants est
calculé depuis ses inscriptions ; sinon valeur manuelle de repli. Le
formulaire admin propose la liaison et affiche le compte auto
Public :
- Nouvelle page /rencontres-passees (menu « Rencontres passées ») listant
toutes les rencontres passées
- Carrousel plein écran (composant Carousel) montrant TOUTES les photos
(flèches, clavier ←/→/Échap, compteur, miniatures) ; ouvert au clic sur
une carte. La grille d'accueil montre 3 aperçus avec badge « +N » et un
lien « Voir toutes les rencontres → »
- Composant PastEventCard partagé entre l'accueil et la page dédiée
Vérifié : 34 + 21 + 26 tests existants au vert, 19 nouveaux tests
(participants auto liés/déliés, upload illimité, nb_photos calculé,
principale, restrictions modérateur sur suppression de photo, migration
legacy des colonnes inline), parcours navigateur complet (galerie admin,
page publique, carrousel).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
Rencontres passées (section « Ils y étaient » de l'accueil) :
- Nouvel onglet « Rencontres passées » (admin + modérateur) : création,
édition, jusqu'à 3 photos par rencontre (1 grande + 2 petites, upload
après enregistrement — même schéma que la photo des rencontres à venir)
- Nouvelles colonnes rencontres_passees.image_path/_2/_3 (migration
ALTER TABLE IF NOT EXISTS)
- Home.jsx affiche désormais les vraies photos uploadées (repli sur le
motif placeholder si absentes) ; ordre passé de ORDER BY id à
ORDER BY id DESC (les plus récentes en premier, seed réordonné en
conséquence pour préserver l'affichage actuel)
- Suppression réservée aux administrateurs
Modérateurs : plus aucune action destructrice possible, imposé côté
serveur (adminOnly) et masqué côté interface :
- Validation/suspension d'un membre (toggle-valide)
- Suppression d'une rencontre, d'une rencontre passée, d'une inscription
Vérifié : 34 + 21 + 26 tests existants toujours au vert, 21 nouveaux
tests (CRUD rencontres passées, upload des 3 emplacements photo, ordre
d'affichage, restrictions modérateur sur chaque action désormais admin-
only), parcours navigateur complet (upload des 3 photos, rendu réel sur
la page d'accueil).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
- Nouveau rôle users.role='moderator' (contrainte CHECK migrée via
DROP+ADD CONSTRAINT, idempotent) : accès à Membres, Rencontres,
Inscriptions uniquement. Dashboard, Catégories (écriture), Contenu du
site, Demandes d'adhésion et gestion des comptes restent admin-only,
imposé côté serveur (requireAuth accepte désormais un tableau de rôles)
- Nouvel onglet « Administrateurs » (admin-only) : créer un compte admin
ou modérateur (mot de passe temporaire généré, même mécanique que pour
les membres — visible tant que non changé, changement forcé à la
première connexion), réinitialiser l'accès, promouvoir/rétrograder,
supprimer. Garde-fous : impossible de se supprimer ou de se rétrograder
soi-même, impossible de supprimer le dernier administrateur
- users.full_name (colonne migrée) pour l'affichage des comptes staff
- AccessCell/CredentialsModal extraits dans AccessControls.jsx, partagés
entre la gestion des membres et celle des comptes admin/modérateur
- AdminShell filtre ses onglets par rôle ; Espace.jsx route admin et
modérateur vers le back-office
Corrigé en cours de route : GET /api/admin/categories doit rester lisible
par les modérateurs (nécessaire au formulaire membre) même si sa gestion
en écriture reste admin-only — sans quoi le Promise.all du frontend
échouait silencieusement et vidait la liste des membres.
Vérifié : 34 + 21 tests existants toujours au vert, 26 nouveaux tests de
permissions par rôle, parcours navigateur complet (création modérateur,
connexion, changement forcé, menu restreint, accès aux membres).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
- Nouveau membre créé avec email : un mot de passe temporaire aléatoire
(~69 bits, sans caractères ambigus) est généré et haché ; il est retourné
à l'admin et reste lisible en clair (users.temp_password) tant que le
membre ne l'a pas changé
- Colonnes users.temp_password / must_change_password (migration
ALTER TABLE IF NOT EXISTS, appliquée au démarrage par le bootstrap)
- POST /api/admin/members/:id/reset-access : régénère l'accès (création
s'il n'existait pas, ou réinitialisation si le membre a perdu son mot
de passe) ; login/me exposent mustChangePassword ; change-password
efface systématiquement le mot de passe temporaire et lève le blocage
- Frontend : colonne « Accès » dans la liste des membres (mot de passe
visible + copier + réinitialiser, ou « Défini », ou « Créer l'accès »),
modal de confirmation après création/réinitialisation, écran de
changement de mot de passe obligatoire avant tout accès au portail ou
au back-office
Vérifié : cycle complet (création → mot de passe visible côté admin →
connexion → changement forcé → effacement automatique → réinitialisation
admin en cas de perte) via 21 tests e2e dédiés + parcours navigateur ;
34 tests existants toujours au vert.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
- Le menu public n'affiche plus « Espace admin » — un seul lien
« Espace membre » pour tous les comptes
- /espace-membre devient le point de connexion unique : après connexion,
le contenu affiché dépend du rôle du compte (portail membre avec header
du site, ou back-office admin plein écran avec sa propre barre latérale)
- Admin.jsx exporte désormais AdminShell (coquille admin authentifiée,
sans logique de connexion) réutilisée par Espace.jsx ; l'export par
défaut devient une redirection de /admin vers /espace-membre pour ne
pas casser d'anciens liens
- App.jsx masque le header/footer public uniquement quand un admin est
affiché sur /espace-membre (ou sur l'ancienne route /admin)
Vérifié : navigation sans lien admin, /admin redirige, connexion membre
→ portail avec header, connexion admin → back-office sans header ; 34
tests e2e toujours au vert.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
Plus aucune référence au port 3000 : l'application écoute sur 8321 dans
le conteneur (PORT, EXPOSE, healthcheck, mapping 8321:8321, upstream
nginx sbc-app:8321, proxy de dev Vite, README).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
- Un seul conteneur applicatif : Express sert l'API, le frontend React
compilé (fallback SPA, cache immutable sur /assets) et les images
/uploads (nosniff + CSP default-src 'none')
- En-têtes de sécurité (CSP stricte, X-Frame-Options DENY, etc.) portés
de nginx vers helmet, compression gzip ajoutée
- Application exposée sur le port 8321 (APP_PORT), PostgreSQL sur
127.0.0.1:56432 (DB_PORT, loopback uniquement pour l'admin locale)
- TRUST_PROXY pilote la confiance aux en-têtes X-Forwarded-* (désactivé
par défaut hors reverse-proxy)
- Dockerfile multi-étages unique à la racine (build React → deps → image
finale non-root, fs en lecture seule)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o