Promotions : logo de l'adhérent dans l'angle des cartes

Le logo du commerce identifie l'offre avant même qu'on lise le nom. Il est
posé en pastille ronde dans l'angle haut-gauche de la carte, la catégorie se
décalant juste à côté sur la même ligne.

- `src/components/MemberAvatar.tsx` : logo en `contain` sur fond blanc (les
  logos d'adhérents sont des marques sur fond clair, un `cover` les rognerait),
  repli sur les initiales colorées quand la fiche n'a pas de logo.
- Appliqué à la carte d'accueil, à la carte de la fiche adhérent, à l'aperçu
  en direct de l'espace adhérent et à la carte de modération : même composition
  partout, l'aperçu montre donc bien ce que verra le visiteur.
- `getLivePromotions` remonte `members.logo_url` ; la page espace le passe au
  formulaire.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QXNXRC4j5VLfKvpyyisrnb
This commit is contained in:
Claude committed 2026-09-06 14:02:53 +00:00
1 parent e980ab6e04
commit d99ee7ec07
7 files changed
+126 -25

No files matched your search

+73
View File
@@ -0,0 +1,73 @@
/**
* Pastille ronde d'un adhérent : son logo, sinon ses initiales.
*
* Sert à identifier le commerce d'un coup d'œil devant son nom, notamment sur
* les cartes de promotion. Le logo est rendu en `contain` sur fond blanc : la
* plupart des logos d'adhérents sont des marques sur fond clair, un `cover` les
* rognerait.
*/
export function memberInitials(name: string): string {
return name
.split(/\s+/)
.filter(Boolean)
.map((w) => w[0])
.join("")
.slice(0, 2)
.toUpperCase();
}
export function MemberAvatar({
name,
logoUrl,
size = 26,
accent = "#E0A63C",
}: {
name: string;
logoUrl?: string | null;
size?: number;
accent?: string;
}) {
const common: React.CSSProperties = {
width: size,
height: size,
borderRadius: "50%",
flexShrink: 0,
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
overflow: "hidden",
};
if (logoUrl) {
return (
<span
aria-hidden="true"
style={{ ...common, background: "#fff", border: "1px solid #eee3cf" }}
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={logoUrl}
alt=""
style={{ width: "100%", height: "100%", objectFit: "contain", padding: 2, boxSizing: "border-box" }}
/>
</span>
);
}
return (
<span
aria-hidden="true"
style={{
...common,
background: accent,
color: "#fff",
fontWeight: 800,
fontSize: Math.round(size * 0.4),
letterSpacing: "0.02em",
}}
>
{memberInitials(name)}
</span>
);
}