// --------------------------------------------------------------------------- // Fabri-Ka — Agrégateur de produits fabriqués au Québec // Auteur : Simon-Pierre Boucher — contact@spboucher.ai // fiche/ProductFacts.tsx : « Le produit » — grille icône/valeur (marque, // catégorie, type, origine, poids, dimensions, SKU), fiche technique // (attributs) en rangées, description tronquée, informations additionnelles // (matériaux, entretien…) en accordéons, étiquettes. // --------------------------------------------------------------------------- import { ReactNode, useState } from 'react' import { CATEGORY_LABELS, ProductDetail, STORE_KIND_LABELS } from '../api' import { Ico } from '../components/KaIcons' import { Accordion, MoreButton, SectionCard } from './ui' import { origineLabel } from './synthese' export default function ProductFacts({ p }: { p: ProductDetail }) { const [open, setOpen] = useState(false) const det = p.details ?? {} const facts: { ico: ReactNode; v: string; l: string }[] = [] if (p.vendor) facts.push({ ico: , v: p.vendor, l: 'Marque' }) if (p.category) facts.push({ ico: , v: CATEGORY_LABELS[p.category] ?? p.category, l: 'Catégorie' }) if (p.product_type) facts.push({ ico: , v: p.product_type, l: 'Type' }) if (origineLabel(p)) facts.push({ ico: , v: origineLabel(p), l: `Origine (classe ${p.origin_class})` }) const poids = det.formatted_weight || (det.weight ? String(det.weight) : det.weight_grams ? `${det.weight_grams} g` : null) if (poids) facts.push({ ico: , v: poids, l: 'Poids' }) const dims = det.formatted_dimensions || (det.dimensions ? [det.dimensions.length, det.dimensions.width, det.dimensions.height].filter(Boolean).join(' × ') : '') if (dims) facts.push({ ico: , v: dims, l: 'Dimensions' }) if (det.sku) facts.push({ ico: , v: det.sku, l: 'SKU' }) if (det.model) facts.push({ ico: , v: det.model, l: 'Modèle' }) const rows: [string, string][] = [] for (const a of det.attributes ?? []) if (a.name && a.terms?.length) rows.push([a.name, a.terms.join(', ')]) if (det.gtin) rows.push(['Code (GTIN/MPN)', det.gtin]) if (p.store_kind && STORE_KIND_LABELS[p.store_kind]) rows.push(['Type de boutique', STORE_KIND_LABELS[p.store_kind]]) if (det.categories?.length) rows.push(['Rayons chez la boutique', det.categories.slice(0, 6).join(' · ')]) if (det.published_at) rows.push(['Publié par la boutique', new Date(det.published_at).toLocaleDateString('fr-CA', { day: 'numeric', month: 'long', year: 'numeric' })]) const texte = (p.description || '').trim() const long = texte.length > 420 const infos = det.additional_info ?? [] return ( {facts.length > 0 && (
{facts.map((x) => (
{x.v}
{x.l}
))}
)} {rows.length > 0 && (
{rows.map(([k, v]) =>
{k}{v}
)}
)}

Description

{texte ? ( <>

{texte}

{long && setOpen(!open)} expanded={open}>{open ? 'Réduire' : 'Lire la suite'}} ) :

La boutique ne fournit pas de description pour ce produit.

} {infos.length > 0 && (
{infos.map((a) =>

{a.description}

)}
)} {p.tags.length > 0 && (
{p.tags.slice(0, 16).map((t) => {t})}
)}
) }