// Project detail slide-over panel const { useState: useStateDetail } = React; const ProjectDetail = ({ p, onClose }) => { const [tab, setTab] = useStateDetail('plan'); if (!p) return null; const klant = window.klantById(p.klant); const bucket = window.bucketById(p.huidigeBucket); const teamC = window.TEAM_COLORS[bucket.team]; const steps = window.BUCKETS .filter(b => p.plan[b.id]) .map(b => ({ ...b, ...p.plan[b.id] })); const done = steps.filter(s => s.done).length; const total = steps.length || 1; return ( <>
); }; const PlanPerStap = ({ p, steps }) => { return (
Elke stap heeft een eigen deadline. Zo blijft het project niet liggen tot de laatste week.
{steps.map((s, i) => { const tc = window.TEAM_COLORS[s.team]; const isCurrent = s.id === p.huidigeBucket; const overdue = !s.done && window.daysUntil(s.deadline) < 0; const owner = s.owner ? window.medewerkerById(s.owner) : null; return (
{s.done && }
{s.naam} {!s.done && } {s.done && ✓ klaar}
{owner && (
{owner.naam} uiterlijk {window.fmtDateLong(s.deadline)}
)}
); })}
{p.notities && (
NOTITIE
{p.notities}
)}
); }; const SauzenTab = ({ p }) => { return (
Dit project bestaat uit {p.sauzen.length} saus{p.sauzen.length > 1 ? 'en' : ''}. Elke saus kan zelfstandig door de buckets bewegen.
{p.sauzen.map((s, i) => { const b = window.bucketById(s.bucketId); const prog = window.sausProgress(p, s.bucketId); return (
{s.naam} {b.naam}
{Math.round(prog * 100)}%
); })}
); }; const ChatTab = ({ p }) => { const msgs = [ { who: 'sanne', time: 'gisteren 16:42', text: 'Monster nr 3 is vandaag verstuurd naar klant. Wacht op feedback.' }, { who: 'marco', time: 'gisteren 17:10', text: 'Heb de receptuur iets bijgesteld — 0.4% meer zuurgraad. Nieuwe charge morgenvroeg.' }, { who: 'wilco', time: 'vandaag 09:02', text: 'Calculatie staat klaar voor controle. Heb wel een vraag over de verpakkingskosten, zie bijlage.' }, { who: 'patrick', time: 'vandaag 10:33', text: 'Wilco, zijn die verpakkingskosten excl. labels? Anders klopt de prijs per eenheid niet.' }, ]; return (
{msgs.map((m, i) => { const pers = window.medewerkerById(m.who); return (
{pers.naam} {m.time}
{m.text}
); })}
); }; const FilesTab = ({ p }) => { const files = [ { naam: 'Specificatie v3.pdf', grootte: '412 kB', type: 'pdf', wie: 'linda', wanneer: 'gisteren' }, { naam: 'Calculatie lente 2026.xlsx', grootte: '89 kB', type: 'xls', wie: 'patrick', wanneer: 'vandaag' }, { naam: 'Klant briefing.eml', grootte: '12 kB', type: 'mail', wie: 'sanne', wanneer: '12 apr' }, { naam: 'Monster foto.jpg', grootte: '2.1 MB', type: 'img', wie: 'marco', wanneer: '14 apr' }, ]; return (
{files.slice(0, p.bijlagen).map((f, i) => { const pers = window.medewerkerById(f.wie); return (
{f.type.toUpperCase()}
{f.naam}
{f.grootte} · {pers?.naam.split(' ')[0]} · {f.wanneer}
); })}
); }; window.ProjectDetail = ProjectDetail;