import { useState } from 'react' // --------------------------------------------------------------------------- // StoreLogo — circular store avatar. // Renders logo_url when available; falls back to a deterministic // initial-letter avatar (never a broken-image icon). // --------------------------------------------------------------------------- export type StoreLogoSize = 'sm' | 'md' | 'lg' // Small palette in the Fabri-Ka register (pine / terracotta / earth tones). const AVATAR_COLORS = [ '#234438', // pine '#C4532E', // terracotta '#8A6D3B', // ochre '#5B5B8A', // slate violet '#A94525', // dark terracotta '#3E6253', // sage pine ] function hashString(s: string): number { let h = 0 for (let i = 0; i < s.length; i++) { h = (h * 31 + s.charCodeAt(i)) | 0 } return Math.abs(h) } interface StoreLogoProps { storeId: string name: string logoUrl?: string | null size?: StoreLogoSize /** white ring + soft shadow (hero usage) */ ring?: boolean className?: string } export default function StoreLogo({ storeId, name, logoUrl, size = 'md', ring = false, className, }: StoreLogoProps) { // track the failed URL (not a boolean) so navigation between stores // that reuses this component instance retries the new logo. const [failedUrl, setFailedUrl] = useState(null) const cls = [ 'store-logo', `store-logo-${size}`, ring ? 'store-logo-ring' : '', className ?? '', ] .filter(Boolean) .join(' ') if (logoUrl && failedUrl !== logoUrl) { return ( {`Logo setFailedUrl(logoUrl)} /> ) } const color = AVATAR_COLORS[hashString(storeId) % AVATAR_COLORS.length] const letter = (name.trim().charAt(0) || 'F').toUpperCase() return ( {letter} ) }