@flowselections/klanten-installatie-techniek-planner 1.0.29 → 1.0.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"KlantenDetailPage.d.ts","sourceRoot":"","sources":["../../src/components/KlantenDetailPage.tsx"],"names":[],"mappings":"AAwBA,wBAAgB,iBAAiB,gCAqLhC"}
1
+ {"version":3,"file":"KlantenDetailPage.d.ts","sourceRoot":"","sources":["../../src/components/KlantenDetailPage.tsx"],"names":[],"mappings":"AAwBA,wBAAgB,iBAAiB,gCAwLhC"}
@@ -29,5 +29,5 @@ export function KlantenDetailPage() {
29
29
  if (loading) {
30
30
  return (_jsx("main", { className: "p-6", children: _jsx("p", { className: "text-muted-foreground", children: "Laden\u2026" }) }));
31
31
  }
32
- return (_jsxs("main", { className: "p-6 space-y-6 max-w-5xl", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Link, { to: "/installatietechniek-klanten-planner", children: _jsxs(Button, { variant: "ghost", size: "sm", className: "gap-2", children: [_jsx(ArrowLeft, { className: "w-4 h-4" }), "Terug"] }) }), _jsx("h1", { className: "text-2xl font-bold text-foreground", children: isNew ? "Nieuwe klant" : form.name || "Klant" }), customerNumber && (_jsx("span", { className: "font-mono text-xs text-muted-foreground bg-muted px-2 py-1 rounded", children: customerNumber }))] }), _jsxs("div", { className: "flex gap-2", children: [!isNew && (_jsxs(Button, { variant: "outline", onClick: remove, className: "gap-2 text-destructive", children: [_jsx(Trash2, { className: "w-4 h-4" }), "Verwijderen"] })), _jsxs(Button, { onClick: save, disabled: saving, className: "gap-2", children: [_jsx(Save, { className: "w-4 h-4" }), saving ? "Opslaan…" : "Opslaan"] })] })] }), !isNew && (_jsxs("nav", { className: "flex flex-wrap gap-3 text-xs text-muted-foreground border-b pb-3", children: [_jsx("a", { href: "#gegevens", className: "hover:text-foreground transition-colors", children: "Gegevens" }), form.segment === "Business" && (_jsx("a", { href: "#contactpersonen", className: "hover:text-foreground transition-colors", children: "Contactpersonen" })), _jsx("a", { href: "#werklocaties", className: "hover:text-foreground transition-colors", children: "Werklocaties" }), fields.length > 0 && (_jsx("a", { href: "#aanvullend", className: "hover:text-foreground transition-colors", children: "Aanvullend" })), _jsx("a", { href: "#werkbonnen", className: "hover:text-foreground transition-colors", children: "Werkbonnen" }), _jsx("a", { href: "#notities", className: "hover:text-foreground transition-colors", children: "Notities" })] })), !isNew && _jsx(KlantRisicoBannerById, { customerId: id, refreshKey: riskKey }), !isNew && _jsx(KlantStatsCard, { customerId: id }), _jsxs(Card, { id: "gegevens", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: "Segment" }) }), _jsx(CardContent, { children: _jsx(SegmentToggle, { segment: form.segment, onChange: (s) => setForm((f) => ({ ...f, segment: s })) }) })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: "Algemene gegevens" }) }), _jsx(CardContent, { children: _jsx(AlgemeneGegevensFields, { form: form, setForm: setForm, isNew: isNew }) })] }), form.segment === "Business" && (_jsxs(Card, { id: "contactpersonen", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: "Contactpersonen" }) }), _jsx(CardContent, { children: _jsx(ContactenFields, { contacts: contacts, addContact: addContact, updateContact: updateContact, removeContact: removeContact }) })] })), _jsxs(Card, { id: "werklocaties", children: [_jsx(CardHeader, { children: _jsxs(CardTitle, { className: "text-base flex items-center gap-2", children: [_jsx(MapPin, { className: "w-4 h-4" }), "Werklocaties"] }) }), _jsx(CardContent, { children: _jsx(LocatiesFields, { locations: locations, addLocation: addLocation, updateLocation: updateLocation, removeLocation: removeLocation }) })] }), fields.length > 0 && (_jsxs(Card, { id: "aanvullend", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: "Aanvullende velden" }) }), _jsx(CardContent, { children: _jsx(DynamicFieldsGrid, { fields: fields, values: values, setValues: setValues }) })] })), !isNew && (_jsxs(_Fragment, { children: [_jsx(KlantGeschiedenisCard, { customerId: id }), _jsx(KlantNotitiesCard, { customerId: id, onStatusChanged: () => setRiskKey((k) => k + 1) })] })), _jsx(Separator, {}), _jsx("div", { className: "flex justify-end", children: _jsxs(Button, { onClick: save, disabled: saving, className: "gap-2", children: [_jsx(Save, { className: "w-4 h-4" }), saving ? "Opslaan…" : "Opslaan"] }) })] }));
32
+ return (_jsxs("main", { className: "p-6 space-y-6 max-w-5xl", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Link, { to: "/installatietechniek-klanten-planner", children: _jsxs(Button, { variant: "ghost", size: "sm", className: "gap-2", children: [_jsx(ArrowLeft, { className: "w-4 h-4" }), "Terug"] }) }), _jsx("h1", { className: "text-2xl font-bold text-foreground", children: isNew ? "Nieuwe klant" : form.name || "Klant" }), customerNumber && (_jsx("span", { className: "font-mono text-xs text-muted-foreground bg-muted px-2 py-1 rounded", children: customerNumber })), !isNew && form.vat_reverse_charge && (_jsx("span", { className: "text-xs rounded bg-muted px-2 py-1 text-muted-foreground", children: "Btw verlegd" }))] }), _jsxs("div", { className: "flex gap-2", children: [!isNew && (_jsxs(Button, { variant: "outline", onClick: remove, className: "gap-2 text-destructive", children: [_jsx(Trash2, { className: "w-4 h-4" }), "Verwijderen"] })), _jsxs(Button, { onClick: save, disabled: saving, className: "gap-2", children: [_jsx(Save, { className: "w-4 h-4" }), saving ? "Opslaan…" : "Opslaan"] })] })] }), !isNew && (_jsxs("nav", { className: "flex flex-wrap gap-3 text-xs text-muted-foreground border-b pb-3", children: [_jsx("a", { href: "#gegevens", className: "hover:text-foreground transition-colors", children: "Gegevens" }), form.segment === "Business" && (_jsx("a", { href: "#contactpersonen", className: "hover:text-foreground transition-colors", children: "Contactpersonen" })), _jsx("a", { href: "#werklocaties", className: "hover:text-foreground transition-colors", children: "Werklocaties" }), fields.length > 0 && (_jsx("a", { href: "#aanvullend", className: "hover:text-foreground transition-colors", children: "Aanvullend" })), _jsx("a", { href: "#werkbonnen", className: "hover:text-foreground transition-colors", children: "Werkbonnen" }), _jsx("a", { href: "#notities", className: "hover:text-foreground transition-colors", children: "Notities" })] })), !isNew && _jsx(KlantRisicoBannerById, { customerId: id, refreshKey: riskKey }), !isNew && _jsx(KlantStatsCard, { customerId: id }), _jsxs(Card, { id: "gegevens", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: "Segment" }) }), _jsx(CardContent, { children: _jsx(SegmentToggle, { segment: form.segment, onChange: (s) => setForm((f) => ({ ...f, segment: s })) }) })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: "Algemene gegevens" }) }), _jsx(CardContent, { children: _jsx(AlgemeneGegevensFields, { form: form, setForm: setForm, isNew: isNew }) })] }), form.segment === "Business" && (_jsxs(Card, { id: "contactpersonen", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: "Contactpersonen" }) }), _jsx(CardContent, { children: _jsx(ContactenFields, { contacts: contacts, addContact: addContact, updateContact: updateContact, removeContact: removeContact }) })] })), _jsxs(Card, { id: "werklocaties", children: [_jsx(CardHeader, { children: _jsxs(CardTitle, { className: "text-base flex items-center gap-2", children: [_jsx(MapPin, { className: "w-4 h-4" }), "Werklocaties"] }) }), _jsx(CardContent, { children: _jsx(LocatiesFields, { locations: locations, addLocation: addLocation, updateLocation: updateLocation, removeLocation: removeLocation }) })] }), fields.length > 0 && (_jsxs(Card, { id: "aanvullend", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: "Aanvullende velden" }) }), _jsx(CardContent, { children: _jsx(DynamicFieldsGrid, { fields: fields, values: values, setValues: setValues }) })] })), !isNew && (_jsxs(_Fragment, { children: [_jsx(KlantGeschiedenisCard, { customerId: id }), _jsx(KlantNotitiesCard, { customerId: id, onStatusChanged: () => setRiskKey((k) => k + 1) })] })), _jsx(Separator, {}), _jsx("div", { className: "flex justify-end", children: _jsxs(Button, { onClick: save, disabled: saving, className: "gap-2", children: [_jsx(Save, { className: "w-4 h-4" }), saving ? "Opslaan…" : "Opslaan"] }) })] }));
33
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"KlantenListPage.d.ts","sourceRoot":"","sources":["../../src/components/KlantenListPage.tsx"],"names":[],"mappings":"AAqBA,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAY3E,wBAAgB,eAAe,gCA2O9B;AAED,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,eAAe,CAAA;CAAE,+BAkBrE"}
1
+ {"version":3,"file":"KlantenListPage.d.ts","sourceRoot":"","sources":["../../src/components/KlantenListPage.tsx"],"names":[],"mappings":"AAqBA,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAY3E,wBAAgB,eAAe,gCA8O9B;AAED,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,eAAe,CAAA;CAAE,+BAkBrE"}
@@ -97,7 +97,7 @@ export function KlantenListPage() {
97
97
  const filtered = customers;
98
98
  const pageCount = Math.max(1, Math.ceil(total / PAGE_SIZE));
99
99
  const statCell = (id, pick) => stats[id] ? pick(stats[id]) : statsFailed ? "n.b." : "—";
100
- return (_jsxs("main", { className: "p-6 space-y-6", children: [_jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_auto] items-center gap-x-4 gap-y-3 sm:flex sm:flex-wrap sm:items-center sm:gap-6", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h1", { className: "truncate text-2xl font-bold text-foreground", children: "Klanten" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Beheer al je zakelijke en particuliere klanten" })] }), top.length > 0 && (_jsx("div", { className: "col-span-2 justify-self-start sm:col-span-1 sm:self-center sm:justify-self-auto", children: _jsx(KlantenPodium, { items: top, onSelect: openCustomer }) })), _jsxs(Button, { className: "col-start-2 row-start-1 shrink-0 justify-self-end gap-2 sm:col-start-auto sm:row-start-auto sm:ml-auto sm:justify-self-auto", onClick: () => openCustomer(null), children: [_jsx(Plus, { className: "w-4 h-4" }), "Nieuwe klant"] })] }), _jsx(Card, { children: _jsxs(CardContent, { className: "p-4 space-y-4", children: [_jsxs("div", { className: "flex gap-3 flex-wrap", children: [_jsxs("div", { className: "relative flex-1 min-w-[240px]", children: [_jsx(Search, { className: "w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { placeholder: "Zoek op klantnr, naam, e-mail of plaats\u2026", value: search, onChange: (e) => setSearch(e.target.value), className: "pl-9" })] }), _jsxs(Select, { value: segmentFilter, onValueChange: (v) => setSegmentFilter(v), children: [_jsx(SelectTrigger, { className: "w-[180px]", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "Alle segmenten" }), _jsx(SelectItem, { value: "Business", children: "Zakelijk" }), _jsx(SelectItem, { value: "Private", children: "Particulier" })] })] })] }), _jsx("div", { className: "rounded-md border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-[130px]", children: "Klantnr." }), _jsx(TableHead, { className: "w-[30%]", children: "Naam" }), _jsx(TableHead, { children: "Segment" }), _jsx(TableHead, { children: "E-mail" }), _jsx(TableHead, { children: "Telefoon" }), _jsx(TableHead, { children: "Plaats" }), _jsx(TableHead, { className: "text-right", children: "Omzet" }), _jsx(TableHead, { className: "text-right", children: "Klussen" })] }) }), _jsx(TableBody, { children: loading ? (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 8, className: "text-center text-muted-foreground py-8", children: "Laden\u2026" }) })) : filtered.length === 0 ? (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 8, className: "text-center text-muted-foreground py-8", children: loadError ? "Klanten konden niet geladen worden" : "Geen klanten gevonden" }) })) : (filtered.map((c) => (_jsxs(TableRow, { className: "hover:bg-muted/40 cursor-pointer", onClick: () => openCustomer(c.id), children: [_jsx(TableCell, { className: "font-mono text-xs text-muted-foreground", children: c.customer_number ?? "—" }), _jsxs(TableCell, { className: "font-medium text-foreground", children: [c.name, _jsx(KlantRisicoBadge, { status: c.risk_status })] }), _jsx(TableCell, { children: _jsx(SegmentBadge, { segment: c.segment }) }), _jsx(TableCell, { className: "text-sm", children: c.general_email ?? "—" }), _jsx(TableCell, { className: "text-sm", children: c.general_phone ?? "—" }), _jsx(TableCell, { className: "text-sm", children: c.billing_city ?? "—" }), _jsx(TableCell, { className: "text-sm text-right tabular-nums", children: statCell(c.id, (s) => formatEuro(s.omzetCents)) }), _jsx(TableCell, { className: "text-sm text-right tabular-nums", children: statCell(c.id, (s) => s.klussen) })] }, c.id)))) })] }) }), _jsxs("div", { className: "flex items-center justify-between gap-3 text-sm text-muted-foreground", children: [_jsxs("span", { children: [total, " ", total === 1 ? "klant" : "klanten", statsFailed && " · omzet/klussen niet beschikbaar"] }), pageCount > 1 && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { variant: "outline", size: "sm", disabled: page === 0 || loading, onClick: () => setPage((p) => p - 1), children: "Vorige" }), _jsxs("span", { className: "tabular-nums", children: [page + 1, " / ", pageCount] }), _jsx(Button, { variant: "outline", size: "sm", disabled: page + 1 >= pageCount || loading, onClick: () => setPage((p) => p + 1), children: "Volgende" })] }))] })] }) }), _jsx(KlantenTrendCard, {}), _jsx(KlantDialog, { open: dialogOpen, onOpenChange: setDialogOpen, customerId: selectedId, onChanged: () => { void load(); void loadTop(); } })] }));
100
+ return (_jsxs("main", { className: "p-6 space-y-6", children: [_jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_auto] items-center gap-x-4 gap-y-3 sm:flex sm:flex-wrap sm:items-center sm:gap-6", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h1", { className: "truncate text-2xl font-bold text-foreground", children: "Klanten" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Beheer al je zakelijke en particuliere klanten" })] }), top.length > 0 && (_jsx("div", { className: "col-span-2 justify-self-start sm:col-span-1 sm:self-center sm:justify-self-auto", children: _jsx(KlantenPodium, { items: top, onSelect: openCustomer }) })), _jsxs(Button, { className: "col-start-2 row-start-1 shrink-0 justify-self-end gap-2 sm:col-start-auto sm:row-start-auto sm:ml-auto sm:justify-self-auto", onClick: () => openCustomer(null), children: [_jsx(Plus, { className: "w-4 h-4" }), "Nieuwe klant"] })] }), _jsx(Card, { children: _jsxs(CardContent, { className: "p-4 space-y-4", children: [_jsxs("div", { className: "flex gap-3 flex-wrap", children: [_jsxs("div", { className: "relative flex-1 min-w-[240px]", children: [_jsx(Search, { className: "w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { placeholder: "Zoek op klantnr, naam, e-mail of plaats\u2026", value: search, onChange: (e) => setSearch(e.target.value), className: "pl-9" })] }), _jsxs(Select, { value: segmentFilter, onValueChange: (v) => setSegmentFilter(v), children: [_jsx(SelectTrigger, { className: "w-[180px]", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "Alle segmenten" }), _jsx(SelectItem, { value: "Business", children: "Zakelijk" }), _jsx(SelectItem, { value: "Private", children: "Particulier" })] })] })] }), _jsx("div", { className: "rounded-md border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-[130px]", children: "Klantnr." }), _jsx(TableHead, { className: "w-[30%]", children: "Naam" }), _jsx(TableHead, { children: "Segment" }), _jsx(TableHead, { children: "E-mail" }), _jsx(TableHead, { children: "Telefoon" }), _jsx(TableHead, { children: "Plaats" }), _jsx(TableHead, { className: "text-right", children: "Omzet" }), _jsx(TableHead, { className: "text-right", children: "Klussen" })] }) }), _jsx(TableBody, { children: loading ? (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 8, className: "text-center text-muted-foreground py-8", children: "Laden\u2026" }) })) : filtered.length === 0 ? (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 8, className: "text-center text-muted-foreground py-8", children: loadError ? "Klanten konden niet geladen worden" : "Geen klanten gevonden" }) })) : (filtered.map((c) => (_jsxs(TableRow, { className: "hover:bg-muted/40 cursor-pointer", onClick: () => openCustomer(c.id), children: [_jsx(TableCell, { className: "font-mono text-xs text-muted-foreground", children: c.customer_number ?? "—" }), _jsxs(TableCell, { className: "font-medium text-foreground", children: [c.name, _jsx(KlantRisicoBadge, { status: c.risk_status }), c.vat_reverse_charge && (_jsx("span", { className: "ml-2 text-[10px] uppercase tracking-wide rounded bg-muted px-1.5 py-0.5 text-muted-foreground", children: "Btw verlegd" }))] }), _jsx(TableCell, { children: _jsx(SegmentBadge, { segment: c.segment }) }), _jsx(TableCell, { className: "text-sm", children: c.general_email ?? "—" }), _jsx(TableCell, { className: "text-sm", children: c.general_phone ?? "—" }), _jsx(TableCell, { className: "text-sm", children: c.billing_city ?? "—" }), _jsx(TableCell, { className: "text-sm text-right tabular-nums", children: statCell(c.id, (s) => formatEuro(s.omzetCents)) }), _jsx(TableCell, { className: "text-sm text-right tabular-nums", children: statCell(c.id, (s) => s.klussen) })] }, c.id)))) })] }) }), _jsxs("div", { className: "flex items-center justify-between gap-3 text-sm text-muted-foreground", children: [_jsxs("span", { children: [total, " ", total === 1 ? "klant" : "klanten", statsFailed && " · omzet/klussen niet beschikbaar"] }), pageCount > 1 && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { variant: "outline", size: "sm", disabled: page === 0 || loading, onClick: () => setPage((p) => p - 1), children: "Vorige" }), _jsxs("span", { className: "tabular-nums", children: [page + 1, " / ", pageCount] }), _jsx(Button, { variant: "outline", size: "sm", disabled: page + 1 >= pageCount || loading, onClick: () => setPage((p) => p + 1), children: "Volgende" })] }))] })] }) }), _jsx(KlantenTrendCard, {}), _jsx(KlantDialog, { open: dialogOpen, onOpenChange: setDialogOpen, customerId: selectedId, onChanged: () => { void load(); void loadTop(); } })] }));
101
101
  }
102
102
  export function SegmentBadge({ segment }) {
103
103
  if (segment === "Business") {
@@ -1 +1 @@
1
- {"version":3,"file":"KlantFormSections.d.ts","sourceRoot":"","sources":["../../../src/components/klanten/KlantFormSections.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE9E,wBAAgB,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,+BAOtF;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,OAAO,EACP,IAAI,EACJ,KAAK,GACN,EAAE;IACD,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf,+BAgBA;AAED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IACnC,QAAQ,EAAE,CAAC,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;CAClD,+BAiBA;AAED,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,OAAO,EACP,KAAa,GACd,EAAE;IACD,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,CAAC;IAC9D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,+BAqDA;AAED,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,UAAU,EACV,aAAa,EACb,aAAa,GACd,EAAE;IACD,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IACjE,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC,+BAqDA;AAED,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAqB,GACtB,EAAE;IACD,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACnE,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,+BA8FA;AAED,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,YAAY,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B,+BA4CA;AAED,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,MAAM,EACN,SAAS,GACV,EAAE;IACD,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CACzE,+BAaA"}
1
+ {"version":3,"file":"KlantFormSections.d.ts","sourceRoot":"","sources":["../../../src/components/klanten/KlantFormSections.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE9E,wBAAgB,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,+BAOtF;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,OAAO,EACP,IAAI,EACJ,KAAK,GACN,EAAE;IACD,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf,+BAgBA;AAED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IACnC,QAAQ,EAAE,CAAC,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;CAClD,+BAiBA;AAED,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,OAAO,EACP,KAAa,GACd,EAAE;IACD,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,CAAC;IAC9D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,+BA6EA;AAED,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,UAAU,EACV,aAAa,EACb,aAAa,GACd,EAAE;IACD,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IACjE,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC,+BAqDA;AAED,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAqB,GACtB,EAAE;IACD,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACnE,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,+BA8FA;AAED,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,YAAY,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B,+BA4CA;AAED,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,MAAM,EACN,SAAS,GACV,EAAE;IACD,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CACzE,+BAaA"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Button, Input, Label, Textarea, Checkbox, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@flowselections/core";
3
3
  import { Building2, User, Plus, Trash2 } from "lucide-react";
4
4
  export function Field({ label, children }) {
@@ -14,7 +14,7 @@ export function SegmentToggle({ segment, onChange, }) {
14
14
  return (_jsxs("div", { className: "inline-flex rounded-lg border p-1 bg-muted/40", children: [_jsx(SegmentButton, { active: segment === "Business", onClick: () => onChange("Business"), icon: _jsx(Building2, { className: "w-4 h-4" }), label: "Zakelijk" }), _jsx(SegmentButton, { active: segment === "Private", onClick: () => onChange("Private"), icon: _jsx(User, { className: "w-4 h-4" }), label: "Particulier" })] }));
15
15
  }
16
16
  export function AlgemeneGegevensFields({ form, setForm, isNew = false, }) {
17
- return (_jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [isNew && (_jsx("p", { className: "text-xs text-muted-foreground md:col-span-2", children: "Het klantnummer wordt automatisch toegekend na het opslaan." })), _jsx(Field, { label: "Naam *", children: _jsx(Input, { value: form.name, onChange: (e) => setForm((f) => ({ ...f, name: e.target.value })), placeholder: "Bedrijf of persoonsnaam" }) }), _jsx(Field, { label: "Algemeen e-mailadres *", children: _jsx(Input, { type: "email", value: form.general_email ?? "", onChange: (e) => setForm((f) => ({ ...f, general_email: e.target.value })), placeholder: "info@voorbeeld.nl" }) }), _jsx(Field, { label: "Algemeen telefoonnummer *", children: _jsx(Input, { value: form.general_phone ?? "", onChange: (e) => setForm((f) => ({ ...f, general_phone: e.target.value })), placeholder: "+31 \u2026" }) }), _jsx("div", {}), _jsx(Field, { label: "Factuuradres \u2014 straat *", children: _jsx(Input, { value: form.billing_street ?? "", onChange: (e) => setForm((f) => ({ ...f, billing_street: e.target.value })) }) }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(Field, { label: "Postcode *", children: _jsx(Input, { value: form.billing_postcode ?? "", onChange: (e) => setForm((f) => ({ ...f, billing_postcode: e.target.value })) }) }), _jsx(Field, { label: "Plaats *", children: _jsx(Input, { value: form.billing_city ?? "", onChange: (e) => setForm((f) => ({ ...f, billing_city: e.target.value })) }) })] })] }));
17
+ return (_jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [isNew && (_jsx("p", { className: "text-xs text-muted-foreground md:col-span-2", children: "Het klantnummer wordt automatisch toegekend na het opslaan." })), _jsx(Field, { label: "Naam *", children: _jsx(Input, { value: form.name, onChange: (e) => setForm((f) => ({ ...f, name: e.target.value })), placeholder: "Bedrijf of persoonsnaam" }) }), _jsx(Field, { label: "Algemeen e-mailadres *", children: _jsx(Input, { type: "email", value: form.general_email ?? "", onChange: (e) => setForm((f) => ({ ...f, general_email: e.target.value })), placeholder: "info@voorbeeld.nl" }) }), _jsx(Field, { label: "Algemeen telefoonnummer *", children: _jsx(Input, { value: form.general_phone ?? "", onChange: (e) => setForm((f) => ({ ...f, general_phone: e.target.value })), placeholder: "+31 \u2026" }) }), _jsx("div", {}), _jsx(Field, { label: "Factuuradres \u2014 straat *", children: _jsx(Input, { value: form.billing_street ?? "", onChange: (e) => setForm((f) => ({ ...f, billing_street: e.target.value })) }) }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(Field, { label: "Postcode *", children: _jsx(Input, { value: form.billing_postcode ?? "", onChange: (e) => setForm((f) => ({ ...f, billing_postcode: e.target.value })) }) }), _jsx(Field, { label: "Plaats *", children: _jsx(Input, { value: form.billing_city ?? "", onChange: (e) => setForm((f) => ({ ...f, billing_city: e.target.value })) }) })] }), form.segment === "Business" && (_jsxs(_Fragment, { children: [_jsx(Field, { label: form.vat_reverse_charge ? "Btw-identificatienummer *" : "Btw-identificatienummer", children: _jsx(Input, { value: form.vat_number ?? "", onChange: (e) => setForm((f) => ({ ...f, vat_number: e.target.value })), placeholder: "NL123456789B01" }) }), _jsxs("div", { className: "flex items-start gap-2 pt-6", children: [_jsx(Checkbox, { id: "vat-reverse-charge", checked: !!form.vat_reverse_charge, onCheckedChange: (v) => setForm((f) => ({ ...f, vat_reverse_charge: !!v })) }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "vat-reverse-charge", className: "text-sm", children: "Btw automatisch verleggen" }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Nieuwe facturen krijgen standaard \"btw verlegd\". Per factuur blijft dit aan te passen." })] })] })] }))] }));
18
18
  }
19
19
  export function ContactenFields({ contacts, addContact, updateContact, removeContact, }) {
20
20
  return (_jsxs("div", { className: "space-y-4", children: [_jsx("div", { className: "flex justify-end", children: _jsxs(Button, { size: "sm", variant: "outline", onClick: addContact, className: "gap-2", children: [_jsx(Plus, { className: "w-4 h-4" }), "Toevoegen"] }) }), contacts.length === 0 && (_jsx("p", { className: "text-sm text-muted-foreground", children: "Nog geen contactpersonen." })), contacts.map((c, idx) => (_jsxs("div", { className: "border rounded-lg p-4 space-y-3 bg-muted/20", children: [_jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [_jsx(Field, { label: "Naam", children: _jsx(Input, { value: c.name, onChange: (e) => updateContact(idx, { name: e.target.value }) }) }), _jsx(Field, { label: "Functie", children: _jsx(Input, { value: c.role ?? "", onChange: (e) => updateContact(idx, { role: e.target.value }) }) }), _jsx(Field, { label: "Telefoon", children: _jsx(Input, { value: c.phone ?? "", onChange: (e) => updateContact(idx, { phone: e.target.value }) }) }), _jsx(Field, { label: "E-mail", children: _jsx(Input, { type: "email", value: c.email ?? "", onChange: (e) => updateContact(idx, { email: e.target.value }) }) })] }), _jsx("div", { className: "flex justify-end", children: _jsxs(Button, { size: "sm", variant: "ghost", onClick: () => removeContact(idx), className: "text-destructive gap-2", children: [_jsx(Trash2, { className: "w-4 h-4" }), "Verwijderen"] }) })] }, idx)))] }));
@@ -1 +1 @@
1
- {"version":3,"file":"useKlantForm.d.ts","sourceRoot":"","sources":["../../../src/components/klanten/useKlantForm.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,YAAY,EAElB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,cAAc,GAAG,IAAI,CAC/B,QAAQ,EACR,IAAI,GAAG,YAAY,GAAG,YAAY,GAAG,iBAAiB,CACvD,CAAC;AACF,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,aAAa,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACrF,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,aAAa,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErF,eAAO,MAAM,aAAa,EAAE,cAS3B,CAAC;AAEF,UAAU,OAAO;IACf,uCAAuC;IACvC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,wBAAgB,YAAY,CAAC,EAC3B,UAAU,EACV,OAAc,EACd,OAAO,EACP,SAAS,EACT,UAAU,GACX,EAAE,OAAO;;;;;;;;;yBA2EoB,MAAM,SAAS,OAAO,CAAC,UAAU,CAAC;yBAElC,MAAM;;;0BAgBL,MAAM,SAAS,OAAO,CAAC,WAAW,CAAC;0BAEnC,MAAM;;;;;;;EA0IpC"}
1
+ {"version":3,"file":"useKlantForm.d.ts","sourceRoot":"","sources":["../../../src/components/klanten/useKlantForm.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,YAAY,EAElB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,cAAc,GAAG,IAAI,CAC/B,QAAQ,EACR,IAAI,GAAG,YAAY,GAAG,YAAY,GAAG,iBAAiB,CACvD,CAAC;AACF,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,aAAa,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACrF,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,aAAa,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErF,eAAO,MAAM,aAAa,EAAE,cAW3B,CAAC;AAEF,UAAU,OAAO;IACf,uCAAuC;IACvC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,wBAAgB,YAAY,CAAC,EAC3B,UAAU,EACV,OAAc,EACd,OAAO,EACP,SAAS,EACT,UAAU,GACX,EAAE,OAAO;;;;;;;;;yBA6EoB,MAAM,SAAS,OAAO,CAAC,UAAU,CAAC;yBAElC,MAAM;;;0BAgBL,MAAM,SAAS,OAAO,CAAC,WAAW,CAAC;0BAEnC,MAAM;;;;;;;EAiJpC"}
@@ -1,4 +1,4 @@
1
- import { missingRequiredFields } from "../../lib/klantRules";
1
+ import { missingRequiredFields, vatReverseChargeError } from "../../lib/klantRules";
2
2
  import { useCallback, useEffect, useState } from "react";
3
3
  import { toast } from "@flowselections/core";
4
4
  import { db, } from "../../lib/itkClient";
@@ -11,6 +11,8 @@ export const emptyCustomer = {
11
11
  general_email: "",
12
12
  general_phone: "",
13
13
  legacy_customer_id: null,
14
+ vat_number: "",
15
+ vat_reverse_charge: false,
14
16
  };
15
17
  export function useKlantForm({ customerId, enabled = true, onSaved, onDeleted, onNotFound, }) {
16
18
  const isNew = !customerId || customerId === "nieuw";
@@ -56,6 +58,8 @@ export function useKlantForm({ customerId, enabled = true, onSaved, onDeleted, o
56
58
  general_email: c.general_email ?? "",
57
59
  general_phone: c.general_phone ?? "",
58
60
  legacy_customer_id: c.legacy_customer_id ?? null,
61
+ vat_number: c.vat_number ?? "",
62
+ vat_reverse_charge: !!c.vat_reverse_charge,
59
63
  });
60
64
  setCustomerNumber(c.customer_number ?? null);
61
65
  setContacts(Array.isArray(cons.data) ? cons.data : []);
@@ -107,6 +111,11 @@ export function useKlantForm({ customerId, enabled = true, onSaved, onDeleted, o
107
111
  toast.error(`Vul de verplichte velden in: ${missing.join(", ")}`);
108
112
  return;
109
113
  }
114
+ const vatErr = vatReverseChargeError(form);
115
+ if (vatErr) {
116
+ toast.error(vatErr);
117
+ return;
118
+ }
110
119
  setSaving(true);
111
120
  try {
112
121
  let newId = customerId;
@@ -118,6 +127,8 @@ export function useKlantForm({ customerId, enabled = true, onSaved, onDeleted, o
118
127
  billing_street: form.billing_street?.trim() || null,
119
128
  billing_city: form.billing_city?.trim() || null,
120
129
  billing_postcode: form.billing_postcode?.trim() || null,
130
+ vat_number: form.vat_number?.trim() || null,
131
+ vat_reverse_charge: form.segment === "Business" ? !!form.vat_reverse_charge : false,
121
132
  };
122
133
  if (isNew) {
123
134
  const { data, error } = await db