Espace adhérent en deux pages, e-mail de contact, logo sans débordement, types de produits pour les promos

- Espace adhérent : /backend/espace (profil, inscriptions, droit à l'image)
  et /backend/espace/promotions (dépôt et suivi). Bandeau et onglets communs
  (EspaceHeader) avec le nombre d'offres en ligne ; la page promotions ouvre
  sur « Mes promotions en cours », puis le formulaire, puis les offres en
  attente et l'historique. Deux entrées dans le menu, titres de page dédiés,
  revalidation des deux chemins.
- Fiche adhérent : colonne members.contact_email (migration 0013), saisie
  dans l'espace adhérent et la fiche staff ; la fiche publique et le JSON-LD
  affichent contact_email, sinon l'e-mail du compte.
- VitrineImage : sans photo de couverture, le logo est contenu à ~60 % d'un
  cadre à hauteur fixe sur un fond du logo flouté ; le conteneur sans hauteur
  qui laissait le logo déborder est supprimé.
- Promotions : la catégorie devient un type de produit ou de service
  (src/lib/promo-categories.ts, 10 groupes, ~85 entrées) pré-sélectionné
  depuis le métier de l'adhérent, à la place de la liste des métiers.
- Tests : catégories de promo (largeur, unicité, pré-sélection pour chaque
  métier du référentiel).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDbKbJrPWweXXYSxA8MXW7
This commit is contained in:
Claude committed 2026-09-06 09:02:27 +00:00
1 parent 8b46cd6316
commit 23d1d14a49
18 files changed
+2289 -278

No files matched your search

+36 -21
View File
@@ -6,7 +6,9 @@ const STRIPE_WARM =
/**
* Zone d'image "vitrine" d'un adhérent.
* - Photo de couverture présente -> affichée en plein cadre (cover).
* - Sinon, le logo est affiché centré et réduit (contain ~80%), pas étiré.
* - Sinon, le logo est affiché centré et réduit (contain, ~60 % du cadre) sur
* un fond fait du logo lui-même flouté : le cadre prend les couleurs de la
* marque sans que le logo soit étiré ni ne déborde.
* - Sinon, fond rayé + texte placeholder.
*/
export function VitrineImage({
@@ -43,30 +45,43 @@ export function VitrineImage({
}
if (logoOnly) {
// `height` est fixe sur le cadre : les max-height en % du logo sont donc
// résolus, là où un conteneur intermédiaire sans hauteur les laissait sans
// effet et le logo débordait.
return (
<div style={{ ...base, background: "linear-gradient(160deg,#fffdf8 0%,#f3ecdc 100%)", padding: "min(8%, 22px)" }}>
{/* Cadre thème autour du logo (évite le bloc blanc nu) */}
<div style={{ ...base, background: "linear-gradient(160deg,#fffdf8 0%,#f3ecdc 100%)" }}>
<div
aria-hidden
style={{
background: "#fff",
border: "1px solid #e6dcc6",
borderRadius: 14,
boxShadow: "0 14px 30px -20px rgba(40,30,15,0.35)",
padding: "min(6%, 18px) min(9%, 28px)",
maxWidth: "84%",
maxHeight: "84%",
display: "flex",
alignItems: "center",
justifyContent: "center",
position: "absolute",
inset: 0,
backgroundImage: `url(${logoOnly})`,
backgroundSize: "cover",
backgroundPosition: "center",
filter: "blur(28px) saturate(1.25)",
transform: "scale(1.25)",
opacity: 0.32,
}}
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={logoOnly}
alt=""
style={{ maxWidth: "100%", maxHeight: "100%", objectFit: "contain", display: "block" }}
/>
</div>
/>
<div
aria-hidden
style={{ position: "absolute", inset: 0, background: "linear-gradient(180deg, rgba(255,253,248,0.35) 0%, rgba(246,242,232,0.6) 100%)" }}
/>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={logoOnly}
alt=""
style={{
position: "relative",
maxWidth: "62%",
maxHeight: "62%",
width: "auto",
height: "auto",
objectFit: "contain",
display: "block",
filter: "drop-shadow(0 12px 24px rgba(40,30,15,0.18))",
}}
/>
{children}
</div>
);