// Bellia — Module Dépenses : workflow de validation des factures const FACTURES = [ { id: 'F-4218', supplier: 'Metro Cash & Carry', cat: 'Boucherie', amount: 1284.50, ht: 1070.42, tva: 214.08, date: '08/05/2026', due: '23/05/2026', status: 'a_valider', urgent: true, hasFile: true, by: 'Agent Dépenses', items: 12 }, { id: 'F-4217', supplier: 'Boulangerie Utopie', cat: 'Pain & viennoiseries', amount: 312.80, ht: 295.85, tva: 16.95, date: '07/05/2026', due: '22/05/2026', status: 'a_valider', urgent: false, hasFile: true, by: 'Agent Dépenses', items: 5 }, { id: 'F-4216', supplier: 'Brasseries de Paris', cat: 'Boissons', amount: 892.00, ht: 743.33, tva: 148.67, date: '07/05/2026', due: '06/06/2026', status: 'a_valider', urgent: false, hasFile: true, by: 'Agent Dépenses', items: 8 }, { id: 'F-4215', supplier: 'Rungis Primeurs', cat: 'Fruits & légumes', amount: 478.20, ht: 453.75, tva: 24.45, date: '06/05/2026', due: '21/05/2026', status: 'a_valider', urgent: true, hasFile: true, by: 'Yannis', items: 24 }, { id: 'F-4214', supplier: 'EDF Pro', cat: 'Énergie', amount: 1654.30, ht: 1378.58, tva: 275.72, date: '05/05/2026', due: '04/06/2026', status: 'planifie', urgent: false, hasFile: true, by: 'Agent Paiements', items: 1 }, { id: 'F-4213', supplier: 'Poissonnerie Loïc', cat: 'Poissons', amount: 642.80, ht: 535.67, tva: 107.13, date: '04/05/2026', due: '19/05/2026', status: 'paye', urgent: false, hasFile: true, by: 'Yannis', items: 9 }, { id: 'F-4212', supplier: 'Coca-Cola France', cat: 'Boissons', amount: 1124.00, ht: 936.67, tva: 187.33, date: '03/05/2026', due: '02/06/2026', status: 'planifie', urgent: false, hasFile: true, by: 'Agent Paiements', items: 3 }, { id: 'F-4211', supplier: 'Mariage Frères', cat: 'Café & thé', amount: 286.40, ht: 238.67, tva: 47.73, date: '02/05/2026', due: '17/05/2026', status: 'paye', urgent: false, hasFile: true, by: 'Yannis', items: 6 }, { id: 'F-4210', supplier: 'France Boissons', cat: 'Boissons', amount: 1452.60, ht: 1210.50, tva: 242.10, date: '01/05/2026', due: '31/05/2026', status: 'paye', urgent: false, hasFile: true, by: 'Yannis', items: 14 }, { id: 'F-4209', supplier: 'Davigel', cat: 'Surgelés', amount: 824.50, ht: 686.83, tva: 137.67, date: '30/04/2026', due: '15/05/2026', status: 'litige', urgent: true, hasFile: true, by: 'Yannis', items: 11, note: '2 colis manquants' }, ]; const STATUS_FACTURE = { a_valider: { l: 'À valider', c: C.warn, bg: C.warnSft }, planifie: { l: 'Planifié', c: C.orangeDp, bg: C.orangeWh }, paye: { l: 'Payé', c: C.ok, bg: C.okSft }, litige: { l: 'Litige', c: C.err, bg: C.errSft }, }; const DepensesScreen = ({ onNav }) => { const [tab, setTab] = React.useState('a_valider'); const [sel, setSel] = React.useState('F-4218'); const [selected, setSelected] = React.useState(new Set()); const filtered = FACTURES.filter(f => tab === 'tous' || f.status === tab); const current = FACTURES.find(f => f.id === sel) || FACTURES[0]; const totalAValider = FACTURES.filter(f => f.status === 'a_valider').reduce((a, b) => a + b.amount, 0); const totalPlanifie = FACTURES.filter(f => f.status === 'planifie').reduce((a, b) => a + b.amount, 0); const totalMois = FACTURES.reduce((a, b) => a + b.amount, 0); const toggleSel = (id) => { const n = new Set(selected); n.has(id) ? n.delete(id) : n.add(id); setSelected(n); }; return (
}>Exporter }>Nouvelle facture } /> {/* Stat banner */}
f.status === 'a_valider').length} factures`} accent="warn" /> f.status === 'planifie').length} factures`} accent="accent" /> f.status === 'paye').reduce((a, b) => a + b.amount, 0))} count={`${FACTURES.filter(f => f.status === 'paye').length} factures`} accent="ok" />
{/* Split: liste + détail */}
{/* ===== LISTE ===== */}
{/* Tabs */}
{[ { id: 'a_valider', l: 'À valider', n: FACTURES.filter(f => f.status === 'a_valider').length }, { id: 'planifie', l: 'Planifié', n: FACTURES.filter(f => f.status === 'planifie').length }, { id: 'paye', l: 'Payé', n: FACTURES.filter(f => f.status === 'paye').length }, { id: 'litige', l: 'Litige', n: FACTURES.filter(f => f.status === 'litige').length }, { id: 'tous', l: 'Tous', n: FACTURES.length }, ].map(t => { const active = tab === t.id; return ( ); })}
{/* Bulk bar */} {selected.size > 0 && (
{selected.size} sélectionnée{selected.size > 1 ? 's' : ''} · {eur([...selected].reduce((a, id) => a + (FACTURES.find(f => f.id === id)?.amount || 0), 0))}
setSelected(new Set())}>Annuler }>Valider la sélection
)} {/* Table */}
{filtered.map((f, idx) => { const s = STATUS_FACTURE[f.status]; const isSel = sel === f.id; const isChecked = selected.has(f.id); return (
setSel(f.id)} style={{ display: 'grid', gridTemplateColumns: '24px 1fr auto auto', gap: 14, alignItems: 'center', padding: '14px 16px', borderBottom: idx === filtered.length - 1 ? 'none' : `1px solid ${C.lineSoft}`, background: isSel ? C.card : 'transparent', cursor: 'pointer', borderLeft: isSel ? `3px solid ${C.orange}` : '3px solid transparent', }}> toggleSel(f.id)} />
{f.supplier} {f.urgent && Échéance proche}
{f.id} · {f.cat} · {f.date} · Échéance {f.due} {f.by === 'Agent Dépenses' && <>· Traité auto}
{s.l}
{eur(f.amount, 2)}
HT {eur(f.ht, 2)}
); })}
{/* Footer total */}
{filtered.length} factures affichées Total : {eur(filtered.reduce((a, b) => a + b.amount, 0), 2)}
{/* ===== DÉTAIL ===== */}
); }; const Checkbox = ({ checked, onChange }) => ( ); const BigStat = ({ label, value, count, accent, delta }) => { const cmap = { warn: { fg: C.warn, bg: C.warnSft }, accent: { fg: C.orangeDp, bg: C.orangeWh }, ok: { fg: C.ok, bg: C.okSft }, err: { fg: C.err, bg: C.errSft }, }; const m = cmap[accent]; return (
{label}
{value}
{delta && {delta}}
{count}
); }; // ===== Detail panel ===== const FactureDetail = ({ facture }) => { if (!facture) return null; const s = STATUS_FACTURE[facture.status]; return (
{/* mini preview */}
{[60, 80, 50, 70].map((w, i) =>
)}
{facture.id} · {facture.cat}

{facture.supplier}

{s.l} {facture.by === 'Agent Dépenses' && }>Auto}
{/* breakdown */}
Montant
Détails
{facture.note && (
Note de litige · {facture.note}
)} {facture.status === 'a_valider' && (
Agent Dépenses · extraction OCR vérifiée, TVA cohérente, fournisseur identifié. Pré-imputation en compte 6022.
)} {/* Actions */} {facture.status === 'a_valider' ? (
}>Refuser }>Valider
) : facture.status === 'planifie' ? ( }>Payer maintenant ) : facture.status === 'litige' ? ( }>Contacter le fournisseur ) : ( }>Télécharger le PDF )} {/* Activity */}
Activité
); }; const SectionLabel = ({ children }) => (
{children}
); const MiniBlock = ({ label, value, accent }) => (
{label}
{value}
); const KV = ({ label, v, accent, last }) => (
{label} {v}
); const Timeline = ({ items }) => (
{items.map((it, i) => (
{i < items.length - 1 && }
{it.t}
{it.when} · {it.by}
))}
); window.DepensesScreen = DepensesScreen;