@flowselections/floriday-verkoop-module 1.0.16 → 1.0.18

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.
Files changed (60) hide show
  1. package/dist-lib/components/verkoop/CreateOrderPage.d.ts.map +1 -1
  2. package/dist-lib/components/verkoop/CreateOrderPage.js +12 -12
  3. package/dist-lib/components/verkoop/EditLocalOrderDialog.d.ts +6 -0
  4. package/dist-lib/components/verkoop/EditLocalOrderDialog.d.ts.map +1 -0
  5. package/dist-lib/components/verkoop/EditLocalOrderDialog.js +102 -0
  6. package/dist-lib/components/verkoop/OrderKarindelingCard.d.ts.map +1 -1
  7. package/dist-lib/components/verkoop/OrderKarindelingCard.js +26 -28
  8. package/dist-lib/components/verkoop/OrderShipmentsCard.d.ts +5 -0
  9. package/dist-lib/components/verkoop/OrderShipmentsCard.d.ts.map +1 -0
  10. package/dist-lib/components/verkoop/OrderShipmentsCard.js +137 -0
  11. package/dist-lib/components/verkoop/SalesOrderDetailPage.d.ts.map +1 -1
  12. package/dist-lib/components/verkoop/SalesOrderDetailPage.js +8 -2
  13. package/dist-lib/components/verkoop/SalesOrderDetailView.d.ts.map +1 -1
  14. package/dist-lib/components/verkoop/SalesOrderDetailView.js +2 -1
  15. package/dist-lib/components/verkoop/SalesOrdersFilters.d.ts.map +1 -1
  16. package/dist-lib/components/verkoop/SalesOrdersFilters.js +2 -8
  17. package/dist-lib/components/verkoop/SalesOrdersTable.d.ts +4 -1
  18. package/dist-lib/components/verkoop/SalesOrdersTable.d.ts.map +1 -1
  19. package/dist-lib/components/verkoop/SalesOrdersTable.js +2 -2
  20. package/dist-lib/components/verkoop/VerkoopOrdersPage.d.ts.map +1 -1
  21. package/dist-lib/components/verkoop/VerkoopOrdersPage.js +43 -1
  22. package/dist-lib/index.js +2 -2
  23. package/dist-lib/integrations/supabase/auth-middleware.d.ts +607 -169
  24. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  25. package/dist-lib/integrations/supabase/client.d.ts +607 -169
  26. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  27. package/dist-lib/integrations/supabase/client.server.d.ts +607 -169
  28. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  29. package/dist-lib/integrations/supabase/types.d.ts +623 -164
  30. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  31. package/dist-lib/lib/cart-lock.functions.d.ts +607 -169
  32. package/dist-lib/lib/cart-lock.functions.d.ts.map +1 -1
  33. package/dist-lib/lib/cart-replan.functions.d.ts +1221 -345
  34. package/dist-lib/lib/cart-replan.functions.d.ts.map +1 -1
  35. package/dist-lib/lib/create-order.functions.d.ts +40700 -1397
  36. package/dist-lib/lib/create-order.functions.d.ts.map +1 -1
  37. package/dist-lib/lib/create-order.functions.js +792 -52
  38. package/dist-lib/lib/expand-group-order-items.d.ts +13 -0
  39. package/dist-lib/lib/expand-group-order-items.d.ts.map +1 -0
  40. package/dist-lib/lib/expand-group-order-items.js +216 -0
  41. package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts +1767 -453
  42. package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts.map +1 -1
  43. package/dist-lib/lib/floriday-logistic-labels.functions.d.ts +607 -169
  44. package/dist-lib/lib/floriday-logistic-labels.functions.d.ts.map +1 -1
  45. package/dist-lib/lib/floriday-public.functions.d.ts +4123 -1057
  46. package/dist-lib/lib/floriday-public.functions.d.ts.map +1 -1
  47. package/dist-lib/lib/floriday-writes.functions.d.ts +2945 -755
  48. package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
  49. package/dist-lib/lib/order-shipments.functions.d.ts +47158 -0
  50. package/dist-lib/lib/order-shipments.functions.d.ts.map +1 -0
  51. package/dist-lib/lib/order-shipments.functions.js +178 -0
  52. package/dist-lib/lib/salesorders-mapping.d.ts +1 -0
  53. package/dist-lib/lib/salesorders-mapping.d.ts.map +1 -1
  54. package/dist-lib/lib/salesorders.functions.d.ts +1767 -453
  55. package/dist-lib/lib/salesorders.functions.d.ts.map +1 -1
  56. package/dist-lib/lib/tradeitems.functions.d.ts +607 -169
  57. package/dist-lib/lib/tradeitems.functions.d.ts.map +1 -1
  58. package/dist-lib/lib/useSalesOrdersQuery.d.ts.map +1 -1
  59. package/dist-lib/lib/useSalesOrdersQuery.js +39 -2
  60. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"CreateOrderPage.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/CreateOrderPage.tsx"],"names":[],"mappings":"AA6CA,wBAAgB,eAAe,4CAkd9B"}
1
+ {"version":3,"file":"CreateOrderPage.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/CreateOrderPage.tsx"],"names":[],"mappings":"AA6CA,wBAAgB,eAAe,4CA6d9B"}
@@ -11,7 +11,6 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
11
11
  import { ArrowLeft, Plus, Trash2 } from "lucide-react";
12
12
  import { useServerFn } from "@tanstack/react-start";
13
13
  import { SearchableSelect } from "./SearchableSelect";
14
- import { CartAssignmentWizard } from "./CartAssignmentWizard";
15
14
  import { listCustomersForCreateOrder, listProductsForCreateOrder, listDeliveryLocationsForCustomerCO, listPickupLocationsCO, listCarriersForCreateOrder, getOrderPickDaysCO, createManualOrder, } from "../../lib/create-order.functions";
16
15
  function ReadOnlyField({ label, value }) {
17
16
  return (_jsxs("div", { className: "space-y-0.5", children: [_jsx("div", { className: "text-[11px] uppercase tracking-wide text-muted-foreground", children: label }), _jsx("div", { className: "text-sm", children: value && String(value).trim() !== "" ? value : _jsx("span", { className: "text-muted-foreground", children: "\u2014" }) })] }));
@@ -57,11 +56,11 @@ export function CreateOrderPage() {
57
56
  const [pickupLocationId, setPickupLocationId] = useState(null);
58
57
  const [carrierId, setCarrierId] = useState(null);
59
58
  const [deliveryDate, setDeliveryDate] = useState("");
59
+ const [isReservation, setIsReservation] = useState(false);
60
60
  const [notes, setNotes] = useState("");
61
61
  const [lines, setLines] = useState([
62
62
  { product_id: null, product_name: "", quantity: null, unit: "stuks", unit_price: null },
63
63
  ]);
64
- const [cartOrderId, setCartOrderId] = useState(null);
65
64
  // Afleverlocaties van gekozen klant
66
65
  const deliveryLocQ = useQuery({
67
66
  queryKey: ["co-delivery-locations", customerId],
@@ -134,7 +133,7 @@ export function CreateOrderPage() {
134
133
  throw new Error("Selecteer een afhaallocatie (tuin)");
135
134
  if (!carrierId)
136
135
  throw new Error("Selecteer een vervoerder");
137
- if (!deliveryDate)
136
+ if (!isReservation && !deliveryDate)
138
137
  throw new Error("Selecteer een leverdatum");
139
138
  const validLines = lines.filter((l) => l.product_id && (l.quantity ?? 0) > 0);
140
139
  if (validLines.length === 0)
@@ -154,7 +153,8 @@ export function CreateOrderPage() {
154
153
  deliveryLocationId,
155
154
  pickupLocationId,
156
155
  carrierId,
157
- deliveryDate,
156
+ deliveryDate: isReservation ? null : deliveryDate,
157
+ isReservation,
158
158
  notes: notes.trim() ? notes.trim() : null,
159
159
  lines: validLines.map((l) => {
160
160
  const p = products.find((x) => x.id === l.product_id);
@@ -174,10 +174,13 @@ export function CreateOrderPage() {
174
174
  return await fetchCreate({ data: payload });
175
175
  },
176
176
  onSuccess: (res) => {
177
- toast.success("Bestelling aangemaakt — deel nu de karren in");
177
+ toast.success("Bestelling aangemaakt — karindeling is automatisch berekend");
178
178
  qc.invalidateQueries({ queryKey: ["floriday", "salesorders-cache"] });
179
179
  if (res?.orderId) {
180
- setCartOrderId(res.orderId);
180
+ navigate({
181
+ to: "/floriday-verkoop/verkooporders/$salesOrderId",
182
+ params: { salesOrderId: `local:${res.orderId}` },
183
+ });
181
184
  }
182
185
  else {
183
186
  navigate({ to: "/floriday-verkoop/verkooporders" });
@@ -202,7 +205,7 @@ export function CreateOrderPage() {
202
205
  : "Kies vervoerder...", disabled: !deliveryLocationId, allowClear: false, options: carriers.map((c) => ({
203
206
  value: c.id,
204
207
  label: c.name + (c.is_default ? " (standaard)" : ""),
205
- })), onChange: setCarrierId }), selectedLocation?.carrier_id && carrierId && carrierId !== selectedLocation.carrier_id && (_jsx("div", { className: "text-xs text-muted-foreground", children: "Wijkt af van standaard vervoerder van deze locatie \u2014 geldt alleen voor deze bestelling." }))] }), _jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { className: "flex items-center gap-2", children: ["Leverdatum ", _jsx("span", { className: "text-destructive", children: "*" })] }), _jsx(Input, { type: "date", value: canPickDate ? deliveryDate : "", min: canPickDate ? earliestISO : undefined, disabled: !canPickDate, onChange: (e) => {
208
+ })), onChange: setCarrierId }), selectedLocation?.carrier_id && carrierId && carrierId !== selectedLocation.carrier_id && (_jsx("div", { className: "text-xs text-muted-foreground", children: "Wijkt af van standaard vervoerder van deze locatie \u2014 geldt alleen voor deze bestelling." }))] }), _jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { className: "flex items-center gap-2", children: ["Leverdatum ", !isReservation && _jsx("span", { className: "text-destructive", children: "*" })] }), _jsx(Input, { type: "date", value: !isReservation && canPickDate ? deliveryDate : "", min: canPickDate ? earliestISO : undefined, disabled: isReservation || !canPickDate, onChange: (e) => {
206
209
  const v = e.target.value || "";
207
210
  if (v && v < earliestISO) {
208
211
  toast.error(`Eerst mogelijke leverdatum is ${earliestLabel}.`);
@@ -210,7 +213,7 @@ export function CreateOrderPage() {
210
213
  return;
211
214
  }
212
215
  setDeliveryDate(v);
213
- } }), !canPickDate ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "Selecteer eerst klant, afleverlocatie, afhaallocatie en vervoerder." })) : (_jsxs("div", { className: "text-xs text-muted-foreground", children: ["Eerst beschikbare leverdatum is ", earliestLabel, ", o.b.v. orderpicktijd (", pickDays, "d) en levertijd vervoerder (", carrierDeliveryDays, "d)."] }))] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Bestelregels" }), _jsxs("div", { className: "grid grid-cols-12 gap-2 text-xs text-muted-foreground px-1", children: [_jsx("div", { className: "col-span-5", children: "Product" }), _jsx("div", { className: "col-span-2", children: "Planten" }), _jsx("div", { className: "col-span-2", children: "Fusten" }), _jsx("div", { className: "col-span-2", children: "Prijs" }), _jsx("div", { className: "col-span-1" })] }), lines.map((line, idx) => {
216
+ } }), _jsxs("label", { className: "mt-1 flex items-center gap-2 text-sm text-foreground", children: [_jsx("input", { type: "checkbox", checked: isReservation, onChange: (e) => setIsReservation(e.target.checked), className: "h-4 w-4 rounded border-input" }), "Reservering (nog geen vaste leverdatum)"] }), isReservation ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "De bestelling wordt als reservering aangemaakt zonder leverdatumvalidatie." })) : !canPickDate ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "Selecteer eerst klant, afleverlocatie, afhaallocatie en vervoerder." })) : (_jsxs("div", { className: "text-xs text-muted-foreground", children: ["Eerst beschikbare leverdatum is ", earliestLabel, ", o.b.v. orderpicktijd (", pickDays, "d) en levertijd vervoerder (", carrierDeliveryDays, "d)."] }))] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Bestelregels" }), _jsxs("div", { className: "grid grid-cols-12 gap-2 text-xs text-muted-foreground px-1", children: [_jsx("div", { className: "col-span-5", children: "Product" }), _jsx("div", { className: "col-span-2", children: "Planten" }), _jsx("div", { className: "col-span-2", children: "Fusten" }), _jsx("div", { className: "col-span-2", children: "Prijs" }), _jsx("div", { className: "col-span-1" })] }), lines.map((line, idx) => {
214
217
  const product = line.product_id ? products.find((p) => p.id === line.product_id) : null;
215
218
  const ppc = Math.max(1, Number(product?.plants_per_crate ?? 1));
216
219
  const plants = line.quantity ?? null;
@@ -263,8 +266,5 @@ export function CreateOrderPage() {
263
266
  next[idx] = { ...next[idx], unit_price: v };
264
267
  setLines(next);
265
268
  }, placeholder: "\u20AC prijs" }), _jsx(Button, { variant: "ghost", size: "icon", className: "col-span-1", onClick: () => setLines(lines.filter((_, i) => i !== idx)), "aria-label": "Regel verwijderen", children: _jsx(Trash2, { className: "h-4 w-4" }) })] }, idx));
266
- }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setLines([...lines, { product_id: null, product_name: "", quantity: null, unit: "stuks", unit_price: null }]), children: [_jsx(Plus, { className: "h-3 w-3 mr-1" }), " Regel toevoegen"] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Opmerkingen" }), _jsx(Textarea, { value: notes, onChange: (e) => setNotes(e.target.value), placeholder: "Optionele notities bij deze bestelling", rows: 3 })] }), _jsxs("div", { className: "flex items-center justify-end gap-2 pt-2", children: [_jsx(Button, { variant: "outline", onClick: () => navigate({ to: "/floriday-verkoop/verkooporders" }), disabled: createMut.isPending, children: "Annuleren" }), _jsx(Button, { onClick: () => createMut.mutate(), disabled: createMut.isPending, children: createMut.isPending ? "Bezig..." : "Bestelling Aanmaken" })] })] })] }), _jsx(CartAssignmentWizard, { orderId: cartOrderId, open: !!cartOrderId, onClose: () => {
267
- setCartOrderId(null);
268
- navigate({ to: "/floriday-verkoop/verkooporders" });
269
- } })] }));
269
+ }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setLines([...lines, { product_id: null, product_name: "", quantity: null, unit: "stuks", unit_price: null }]), children: [_jsx(Plus, { className: "h-3 w-3 mr-1" }), " Regel toevoegen"] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Opmerkingen" }), _jsx(Textarea, { value: notes, onChange: (e) => setNotes(e.target.value), placeholder: "Optionele notities bij deze bestelling", rows: 3 })] }), _jsxs("div", { className: "flex items-center justify-end gap-2 pt-2", children: [_jsx(Button, { variant: "outline", onClick: () => navigate({ to: "/floriday-verkoop/verkooporders" }), disabled: createMut.isPending, children: "Annuleren" }), _jsx(Button, { onClick: () => createMut.mutate(), disabled: createMut.isPending, children: createMut.isPending ? "Bezig..." : "Bestelling Aanmaken" })] })] })] })] }));
270
270
  }
@@ -0,0 +1,6 @@
1
+ export declare function EditLocalOrderDialog({ orderId, open, onOpenChange, }: {
2
+ orderId: string;
3
+ open: boolean;
4
+ onOpenChange: (o: boolean) => void;
5
+ }): import("react/jsx-runtime").JSX.Element | null;
6
+ //# sourceMappingURL=EditLocalOrderDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EditLocalOrderDialog.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/EditLocalOrderDialog.tsx"],"names":[],"mappings":"AAoBA,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACP,IAAI,EACJ,YAAY,GACb,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC,kDAyMA"}
@@ -0,0 +1,102 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { Button, Input, toast } from "@flowselections/core";
4
+ import { useServerFn } from "@tanstack/react-start";
5
+ import { useQueryClient } from "@tanstack/react-query";
6
+ import { getLocalOrderForEdit, updateLocalOrder, } from "../../lib/create-order.functions";
7
+ export function EditLocalOrderDialog({ orderId, open, onOpenChange, }) {
8
+ const load = useServerFn(getLocalOrderForEdit);
9
+ const save = useServerFn(updateLocalOrder);
10
+ const queryClient = useQueryClient();
11
+ const [loading, setLoading] = useState(false);
12
+ const [saving, setSaving] = useState(false);
13
+ const [error, setError] = useState(null);
14
+ const [deliveryDate, setDeliveryDate] = useState("");
15
+ const [isReservation, setIsReservation] = useState(false);
16
+ const [items, setItems] = useState([]);
17
+ useEffect(() => {
18
+ if (!open)
19
+ return;
20
+ let cancelled = false;
21
+ setLoading(true);
22
+ setError(null);
23
+ load({ data: { orderId } })
24
+ .then((r) => {
25
+ if (cancelled)
26
+ return;
27
+ setDeliveryDate((r.deliveryDate ?? "").slice(0, 10));
28
+ setIsReservation(!!r.isReservation);
29
+ setItems(r.items.map((it) => ({
30
+ id: it.id,
31
+ productName: it.productName,
32
+ quantity: it.quantity,
33
+ unit: it.unit,
34
+ plantsPerCrate: it.plantsPerCrate ?? 1,
35
+ minQuantity: Number(it.minQuantity ?? 0),
36
+ shippedQuantity: Number(it.shippedQuantity ?? 0),
37
+ plannedQuantity: Number(it.plannedQuantity ?? 0),
38
+ })));
39
+ })
40
+ .catch((e) => !cancelled && setError(e?.message ?? "Laden mislukt"))
41
+ .finally(() => !cancelled && setLoading(false));
42
+ return () => {
43
+ cancelled = true;
44
+ };
45
+ }, [open, orderId, load]);
46
+ if (!open)
47
+ return null;
48
+ const setPlants = (idx, plants) => {
49
+ setItems((prev) => prev.map((p, i) => (i === idx ? { ...p, quantity: Number.isFinite(plants) ? Math.max(0, plants) : 0 } : p)));
50
+ };
51
+ const setFusten = (idx, fusten) => {
52
+ setItems((prev) => prev.map((p, i) => {
53
+ if (i !== idx)
54
+ return p;
55
+ const ppc = Math.max(1, p.plantsPerCrate);
56
+ const f = Number.isFinite(fusten) ? Math.max(0, fusten) : 0;
57
+ return { ...p, quantity: f * ppc };
58
+ }));
59
+ };
60
+ const handleSave = async () => {
61
+ for (const it of items) {
62
+ const ppc = Math.max(1, it.plantsPerCrate);
63
+ if (it.quantity < ppc || it.quantity % ppc !== 0) {
64
+ toast.error(`"${it.productName}" moet per hele fust besteld worden (min. 1 fust = ${ppc} planten).`);
65
+ return;
66
+ }
67
+ if (it.quantity < it.minQuantity) {
68
+ toast.error(`"${it.productName}" kan niet lager dan ${it.minQuantity} — er is al ${it.shippedQuantity} geleverd en ${it.plannedQuantity} gepland op bezorgmomenten.`);
69
+ return;
70
+ }
71
+ }
72
+ try {
73
+ setSaving(true);
74
+ await save({
75
+ data: {
76
+ orderId,
77
+ deliveryDate: !isReservation && deliveryDate ? deliveryDate : undefined,
78
+ items: items.map((i) => ({ itemId: i.id, quantity: Math.round(i.quantity) })),
79
+ },
80
+ });
81
+ toast.success("Bestelling bijgewerkt");
82
+ await Promise.all([
83
+ queryClient.invalidateQueries({ queryKey: ["floriday", "salesorders-cache"] }),
84
+ queryClient.invalidateQueries({ queryKey: ["order-shipments", orderId] }),
85
+ queryClient.invalidateQueries({ queryKey: ["order-carts", orderId] }),
86
+ queryClient.invalidateQueries({ queryKey: ["salesorder-detail", orderId] }),
87
+ ]);
88
+ onOpenChange(false);
89
+ }
90
+ catch (e) {
91
+ toast.error(e?.message ?? "Bijwerken mislukt");
92
+ }
93
+ finally {
94
+ setSaving(false);
95
+ }
96
+ };
97
+ return (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", onClick: () => !saving && onOpenChange(false), children: _jsxs("div", { className: "w-full max-w-xl rounded-lg border border-border bg-card p-6 shadow-lg", onClick: (e) => e.stopPropagation(), children: [_jsx("h2", { className: "text-lg font-semibold text-foreground", children: "Bestelling bewerken" }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Pas de leverdatum en het aantal planten of fusten per regel aan. Voorraad en karindeling worden automatisch bijgewerkt." }), loading ? (_jsx("div", { className: "mt-6 text-sm text-muted-foreground", children: "Laden\u2026" })) : error ? (_jsx("div", { className: "mt-6 rounded border border-destructive/30 bg-destructive/5 p-3 text-sm text-destructive", children: error })) : (_jsxs("div", { className: "mt-5 space-y-4", children: [!isReservation && (_jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-foreground", children: "Leverdatum" }), _jsx(Input, { type: "date", value: deliveryDate, onChange: (e) => setDeliveryDate(e.target.value) })] })), isReservation && (_jsx("div", { className: "rounded border border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground", children: "Dit is een reservering \u2014 er is nog geen leverdatum. Voeg een bezorgmoment toe om (deels) uit te leveren." })), _jsxs("div", { children: [_jsx("div", { className: "mb-2 text-sm font-medium text-foreground", children: "Regels" }), _jsxs("div", { className: "grid grid-cols-12 gap-2 px-1 text-xs text-muted-foreground", children: [_jsx("div", { className: "col-span-6", children: "Product" }), _jsx("div", { className: "col-span-3", children: "Planten" }), _jsx("div", { className: "col-span-3", children: "Fusten" })] }), _jsxs("div", { className: "mt-1 space-y-2", children: [items.map((it, idx) => {
98
+ const ppc = Math.max(1, it.plantsPerCrate);
99
+ const fusten = ppc > 0 ? Math.ceil(it.quantity / ppc) : 0;
100
+ return (_jsxs("div", { className: "grid grid-cols-12 items-start gap-2 rounded border border-border p-2", children: [_jsxs("div", { className: "col-span-6 min-w-0 text-sm", children: [_jsx("div", { className: "truncate font-medium text-foreground", children: it.productName }), _jsxs("div", { className: "text-xs text-muted-foreground", children: [ppc, " planten per fust"] }), it.minQuantity > 0 && (_jsxs("div", { className: "text-xs text-primary", children: ["min. ", it.minQuantity, " (reeds ", it.shippedQuantity, " geleverd, ", it.plannedQuantity, " gepland)"] }))] }), _jsx("div", { className: "col-span-3", children: _jsx(Input, { type: "number", min: 0, step: ppc, value: it.quantity, onChange: (e) => setPlants(idx, Number(e.target.value)) }) }), _jsx("div", { className: "col-span-3", children: _jsx(Input, { type: "number", min: 0, step: 1, value: fusten, onChange: (e) => setFusten(idx, Number(e.target.value)) }) })] }, it.id));
101
+ }), items.length === 0 && (_jsx("div", { className: "text-sm text-muted-foreground", children: "Geen regels op deze bestelling." }))] })] })] })), _jsxs("div", { className: "mt-6 flex justify-end gap-2", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => onOpenChange(false), disabled: saving, children: "Annuleren" }), _jsx(Button, { size: "sm", onClick: handleSave, disabled: saving || loading || !!error, children: saving ? "Bezig…" : "Opslaan" })] })] }) }));
102
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"OrderKarindelingCard.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/OrderKarindelingCard.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AA6F/D,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,aAAa,CAAA;CAAE,2CA+KvE"}
1
+ {"version":3,"file":"OrderKarindelingCard.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/OrderKarindelingCard.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AA8F/D,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,aAAa,CAAA;CAAE,2CAgLvE"}
@@ -9,6 +9,7 @@ import { Badge, Card, CardContent, CardHeader, CardTitle, Table, TableBody, Tabl
9
9
  import { CheckCircle2, Lock } from "lucide-react";
10
10
  import { supabase } from "../../integrations/supabase/client";
11
11
  import { planCarts } from "../../lib/cart-planner";
12
+ import { expandOrderItemsForPlanner } from "../../lib/expand-group-order-items";
12
13
  function deriveCartsFromFloriday(order) {
13
14
  const o = order.raw.order ?? {};
14
15
  const pack = o?.packingConfiguration ?? {};
@@ -74,6 +75,7 @@ export function OrderKarindelingCard({ order }) {
74
75
  const orderId = typeof rawId === "string" ? rawId.replace(/^(local:|mailbox-proposal:)/, "") : rawId;
75
76
  const [lockedAt, setLockedAt] = useState(null);
76
77
  const [dbItems, setDbItems] = useState(null);
78
+ const [plannerInputs, setPlannerInputs] = useState(null);
77
79
  // Laadt order_items + gekoppelde products (voorraad-belading) en
78
80
  // ververst live bij mutaties op order_items, orders of products.
79
81
  useEffect(() => {
@@ -90,8 +92,24 @@ export function OrderKarindelingCard({ order }) {
90
92
  ]);
91
93
  if (!active)
92
94
  return;
93
- setDbItems(itemRows ?? []);
95
+ const items = itemRows ?? [];
96
+ setDbItems(items);
94
97
  setLockedAt(orderRow?.plan_locked_at ?? null);
98
+ // Alle order_items doorgeven — expand-helper resolveert zelf groepen
99
+ // (via product_id óf via naamprefix "[Groep] ...") en losse artikelen.
100
+ const raws = items.map((it) => ({
101
+ id: it.id,
102
+ product_id: it.product_id,
103
+ product_name: it.product_name,
104
+ quantity: Number(it.quantity ?? 0),
105
+ plants_per_crate: Math.max(1, Number(it.products?.plants_per_crate ?? 1)),
106
+ crates_per_layer: Math.max(1, Number(it.products?.crates_per_layer ?? 1)),
107
+ layers_per_cart: Math.max(1, Number(it.products?.layers_per_cart ?? 1)),
108
+ }));
109
+ const expanded = await expandOrderItemsForPlanner(supabase, raws);
110
+ if (!active)
111
+ return;
112
+ setPlannerInputs(expanded);
95
113
  };
96
114
  void load();
97
115
  const channel = supabase
@@ -105,36 +123,16 @@ export function OrderKarindelingCard({ order }) {
105
123
  void supabase.removeChannel(channel);
106
124
  };
107
125
  }, [orderId]);
108
- // Bouw plannerinput uit voorraad-belading. Alleen items met een gekoppeld
109
- // product (product_id + belading in products-tabel) worden meegenomen.
126
+ // Bouw plannerinput. Bij een groep-order_item zijn de sub-items al
127
+ // opgesplitst met member-belading; anders is er één regel per item.
110
128
  const plannerCarts = useMemo(() => {
111
- if (!dbItems || dbItems.length === 0)
129
+ if (!plannerInputs || plannerInputs.length === 0) {
130
+ if (dbItems && dbItems.length > 0)
131
+ return null;
112
132
  return null;
113
- const inputs = [];
114
- for (const it of dbItems) {
115
- const p = it.products;
116
- if (!it.product_id || !p)
117
- continue;
118
- const ppc = Math.max(1, Number(p.plants_per_crate ?? 0));
119
- const cpl = Math.max(1, Number(p.crates_per_layer ?? 0));
120
- const lpc = Math.max(1, Number(p.layers_per_cart ?? 0));
121
- const plants = Math.max(0, Number(it.quantity ?? 0));
122
- if (plants <= 0)
123
- continue;
124
- inputs.push({
125
- order_item_id: it.id,
126
- product_id: it.product_id,
127
- product_name: it.product_name,
128
- plants,
129
- plants_per_crate: ppc,
130
- crates_per_layer: cpl,
131
- layers_per_cart: lpc,
132
- });
133
133
  }
134
- if (inputs.length === 0)
135
- return null;
136
- return planCarts(inputs).carts;
137
- }, [dbItems]);
134
+ return planCarts(plannerInputs).carts;
135
+ }, [plannerInputs, dbItems]);
138
136
  const floridayCarts = useMemo(() => deriveCartsFromFloriday(order), [order]);
139
137
  const usingVoorraad = plannerCarts !== null;
140
138
  const carts = usingVoorraad
@@ -0,0 +1,5 @@
1
+ import type { SalesOrderDTO } from "../../lib/salesorders-mapping";
2
+ export declare function OrderShipmentsCard({ order }: {
3
+ order: SalesOrderDTO;
4
+ }): import("react/jsx-runtime").JSX.Element | null;
5
+ //# sourceMappingURL=OrderShipmentsCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrderShipmentsCard.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/OrderShipmentsCard.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AA4C/D,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,aAAa,CAAA;CAAE,kDASrE"}
@@ -0,0 +1,137 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Bezorgmomenten (deelleveringen) voor een bestelling.
3
+ // Toont totalen (besteld / gepland / geleverd / openstaand), lijst met shipments
4
+ // en knoppen om nieuwe bezorgmomenten aan te maken en te markeren als geleverd.
5
+ import { useMemo, useState } from "react";
6
+ import { Badge, Button, Card, CardContent, CardHeader, CardTitle, Input, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, } from "@flowselections/core";
7
+ import { CalendarPlus, CheckCircle2, Trash2, Truck } from "lucide-react";
8
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
9
+ import { useServerFn } from "@tanstack/react-start";
10
+ import { cancelShipment, createShipment, listOrderShipments, markShipmentShipped, } from "../../lib/order-shipments.functions";
11
+ function formatDate(iso) {
12
+ if (!iso)
13
+ return "—";
14
+ const d = new Date(iso);
15
+ if (Number.isNaN(d.getTime()))
16
+ return iso;
17
+ return d.toLocaleDateString("nl-NL", { day: "numeric", month: "short", year: "numeric" });
18
+ }
19
+ export function OrderShipmentsCard({ order }) {
20
+ // Alleen lokale (en dus reserveer-bare) orders ondersteunen deelleveringen.
21
+ const rawId = order.isLocal && order.id.startsWith("local:")
22
+ ? order.id.slice("local:".length)
23
+ : null;
24
+ if (!rawId)
25
+ return null;
26
+ return _jsx(OrderShipmentsInner, { orderId: rawId });
27
+ }
28
+ function OrderShipmentsInner({ orderId }) {
29
+ const list = useServerFn(listOrderShipments);
30
+ const create = useServerFn(createShipment);
31
+ const markShipped = useServerFn(markShipmentShipped);
32
+ const cancel = useServerFn(cancelShipment);
33
+ const queryClient = useQueryClient();
34
+ const [openCreate, setOpenCreate] = useState(false);
35
+ const { data, isLoading } = useQuery({
36
+ queryKey: ["order-shipments", orderId],
37
+ queryFn: () => list({ data: { orderId } }),
38
+ });
39
+ const totals = data?.totals ?? [];
40
+ const shipments = data?.shipments ?? [];
41
+ const summed = useMemo(() => {
42
+ return totals.reduce((a, t) => ({
43
+ ordered: a.ordered + t.ordered,
44
+ shipped: a.shipped + t.shipped,
45
+ planned: a.planned + t.planned,
46
+ outstanding: a.outstanding + t.outstanding,
47
+ }), { ordered: 0, shipped: 0, planned: 0, outstanding: 0 });
48
+ }, [totals]);
49
+ const refresh = () => {
50
+ queryClient.invalidateQueries({ queryKey: ["order-shipments", orderId] });
51
+ queryClient.invalidateQueries({ queryKey: ["floriday", "salesorders-cache"] });
52
+ };
53
+ const hasOpen = totals.some((t) => t.remaining > 0);
54
+ const allShipped = totals.length > 0 && summed.outstanding === 0;
55
+ return (_jsxs(_Fragment, { children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "flex flex-row items-center justify-between", children: [_jsx(CardTitle, { className: "text-base", children: "Bezorgmomenten & deelleveringen" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Badge, { variant: allShipped ? "default" : "secondary", children: [summed.shipped, " / ", summed.ordered, " geleverd"] }), _jsxs(Button, { size: "sm", onClick: () => setOpenCreate(true), disabled: !hasOpen, title: hasOpen ? "" : "Er zijn geen openstaande aantallen meer.", children: [_jsx(CalendarPlus, { className: "mr-2 h-4 w-4" }), "Nieuw bezorgmoment"] })] })] }), _jsx(CardContent, { className: "space-y-6", children: isLoading ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Laden\u2026" })) : (_jsxs(_Fragment, { children: [_jsxs("div", { children: [_jsx("div", { className: "mb-2 text-sm font-medium", children: "Voortgang per artikel" }), _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Artikel" }), _jsx(TableHead, { className: "text-right", children: "Besteld" }), _jsx(TableHead, { className: "text-right", children: "Gepland" }), _jsx(TableHead, { className: "text-right", children: "Geleverd" }), _jsx(TableHead, { className: "text-right", children: "Nog te leveren" })] }) }), _jsx(TableBody, { children: totals.map((t) => (_jsxs(TableRow, { children: [_jsx(TableCell, { className: "font-medium", children: t.product_name }), _jsx(TableCell, { className: "text-right", children: t.ordered }), _jsx(TableCell, { className: "text-right", children: t.planned }), _jsx(TableCell, { className: "text-right", children: t.shipped }), _jsx(TableCell, { className: "text-right", children: _jsx("span", { className: t.outstanding > 0 ? "font-semibold text-primary" : "text-muted-foreground", children: t.outstanding }) })] }, t.order_item_id))) })] })] }), _jsxs("div", { children: [_jsx("div", { className: "mb-2 text-sm font-medium", children: "Bezorgmomenten" }), shipments.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Nog geen bezorgmomenten aangemaakt. Maak er \u00E9\u00E9n aan om (deels) uit te leveren." })) : (_jsx("div", { className: "space-y-3", children: shipments.map((s) => (_jsxs("div", { className: "rounded-md border border-border", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 border-b border-border bg-muted/30 px-3 py-2 text-sm", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("span", { className: "font-mono font-medium", children: ["Levering #", s.shipment_number] }), _jsx("span", { className: "text-muted-foreground", children: formatDate(s.delivery_date) }), _jsxs(Badge, { variant: s.status === "shipped" ? "default" : "secondary", className: "gap-1", children: [s.status === "shipped" && _jsx(CheckCircle2, { className: "h-3 w-3" }), s.status === "shipped"
56
+ ? "Geleverd"
57
+ : s.status === "cancelled"
58
+ ? "Geannuleerd"
59
+ : "Gepland"] })] }), _jsx("div", { className: "flex gap-2", children: s.status === "planned" && (_jsxs(_Fragment, { children: [_jsxs(Button, { size: "sm", variant: "default", onClick: async () => {
60
+ try {
61
+ await markShipped({ data: { shipmentId: s.id } });
62
+ toast.success("Bezorgmoment geleverd");
63
+ refresh();
64
+ }
65
+ catch (e) {
66
+ toast.error(e?.message ?? "Markeren mislukt");
67
+ }
68
+ }, children: [_jsx(Truck, { className: "mr-2 h-4 w-4" }), "Markeer geleverd"] }), _jsx(Button, { size: "sm", variant: "outline", onClick: async () => {
69
+ if (!confirm("Bezorgmoment verwijderen?"))
70
+ return;
71
+ try {
72
+ await cancel({ data: { shipmentId: s.id } });
73
+ toast.success("Bezorgmoment verwijderd");
74
+ refresh();
75
+ }
76
+ catch (e) {
77
+ toast.error(e?.message ?? "Verwijderen mislukt");
78
+ }
79
+ }, children: _jsx(Trash2, { className: "h-4 w-4" }) })] })) })] }), _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Artikel" }), _jsx(TableHead, { className: "text-right", children: "Aantal" })] }) }), _jsx(TableBody, { children: s.order_shipment_items.map((i) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: i.product_name }), _jsx(TableCell, { className: "text-right", children: i.quantity })] }, i.id))) })] })] }, s.id))) }))] })] })) })] }), openCreate && (_jsx(CreateShipmentDialog, { orderId: orderId, totals: totals.filter((t) => t.remaining > 0), onClose: () => setOpenCreate(false), onCreated: () => {
80
+ setOpenCreate(false);
81
+ refresh();
82
+ }, create: create }))] }));
83
+ }
84
+ function CreateShipmentDialog({ orderId, totals, onClose, onCreated, create, }) {
85
+ const [deliveryDate, setDeliveryDate] = useState(() => {
86
+ const d = new Date();
87
+ d.setDate(d.getDate() + 1);
88
+ return d.toISOString().slice(0, 10);
89
+ });
90
+ const [qtyByItem, setQtyByItem] = useState(() => {
91
+ const init = {};
92
+ for (const t of totals)
93
+ init[t.order_item_id] = 0;
94
+ return init;
95
+ });
96
+ const [saving, setSaving] = useState(false);
97
+ const items = totals.map((t) => ({
98
+ total: t,
99
+ qty: qtyByItem[t.order_item_id] ?? 0,
100
+ }));
101
+ const canSave = items.some((i) => i.qty > 0) && !!deliveryDate;
102
+ const handleSave = async () => {
103
+ setSaving(true);
104
+ try {
105
+ const selected = items.filter((i) => i.qty > 0);
106
+ await create({
107
+ data: {
108
+ orderId,
109
+ deliveryDate,
110
+ items: selected.map((i) => ({
111
+ orderItemId: i.total.order_item_id,
112
+ productId: i.total.product_id,
113
+ productName: i.total.product_name,
114
+ quantity: i.qty,
115
+ })),
116
+ },
117
+ });
118
+ toast.success("Bezorgmoment aangemaakt");
119
+ onCreated();
120
+ }
121
+ catch (e) {
122
+ toast.error(e?.message ?? "Aanmaken mislukt");
123
+ }
124
+ finally {
125
+ setSaving(false);
126
+ }
127
+ };
128
+ return (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", onClick: () => !saving && onClose(), children: _jsxs("div", { className: "w-full max-w-xl rounded-lg border border-border bg-card p-6 shadow-lg", onClick: (e) => e.stopPropagation(), children: [_jsx("h2", { className: "text-lg font-semibold text-foreground", children: "Nieuw bezorgmoment" }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Geef aan wat er op deze datum wordt geleverd. Aantallen mogen niet hoger zijn dan het openstaande aantal." }), _jsxs("div", { className: "mt-5 space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium", children: "Bezorgdatum" }), _jsx(Input, { type: "date", value: deliveryDate, onChange: (e) => setDeliveryDate(e.target.value) })] }), _jsxs("div", { children: [_jsx("div", { className: "mb-2 text-sm font-medium", children: "Regels" }), _jsxs("div", { className: "space-y-2", children: [items.map((i) => {
129
+ const ppc = Math.max(1, i.total.plants_per_crate ?? 1);
130
+ const remainingFusten = Math.floor(i.total.remaining / ppc);
131
+ const qtyFusten = Math.floor(i.qty / ppc);
132
+ return (_jsxs("div", { className: "grid grid-cols-12 items-center gap-2 rounded border border-border p-2", children: [_jsxs("div", { className: "col-span-6 min-w-0", children: [_jsx("div", { className: "truncate text-sm font-medium", children: i.total.product_name }), _jsxs("div", { className: "text-xs text-muted-foreground", children: ["openstaand: ", remainingFusten, " fusten (", i.total.remaining, " planten) \u00B7 ", ppc, "/fust"] })] }), _jsx("div", { className: "col-span-3", children: _jsx(Input, { type: "number", min: 0, max: remainingFusten, step: 1, value: qtyFusten, onChange: (e) => {
133
+ const f = Math.max(0, Math.min(remainingFusten, Number(e.target.value) || 0));
134
+ setQtyByItem((prev) => ({ ...prev, [i.total.order_item_id]: f * ppc }));
135
+ } }) }), _jsx("div", { className: "col-span-1 text-xs text-muted-foreground", children: "fusten" }), _jsx("div", { className: "col-span-2 flex gap-1", children: _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setQtyByItem((prev) => ({ ...prev, [i.total.order_item_id]: remainingFusten * ppc })), children: "Alles" }) })] }, i.total.order_item_id));
136
+ }), items.length === 0 && (_jsx("div", { className: "text-sm text-muted-foreground", children: "Geen openstaande aantallen." }))] })] })] }), _jsxs("div", { className: "mt-6 flex justify-end gap-2", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: onClose, disabled: saving, children: "Annuleren" }), _jsx(Button, { size: "sm", onClick: handleSave, disabled: !canSave || saving, children: saving ? "Bezig…" : "Aanmaken" })] })] }) }));
137
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"SalesOrderDetailPage.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/SalesOrderDetailPage.tsx"],"names":[],"mappings":"AAMA,wBAAgB,oBAAoB,4CAsCnC"}
1
+ {"version":3,"file":"SalesOrderDetailPage.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/SalesOrderDetailPage.tsx"],"names":[],"mappings":"AAQA,wBAAgB,oBAAoB,4CA0DnC"}
@@ -1,8 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
2
3
  import { Link, useParams } from "@tanstack/react-router";
3
4
  import { Button } from "@flowselections/core";
4
- import { ArrowLeft } from "lucide-react";
5
+ import { ArrowLeft, Pencil } from "lucide-react";
5
6
  import { SalesOrderDetailView } from "../../components/verkoop/SalesOrderDetailView";
7
+ import { EditLocalOrderDialog } from "../../components/verkoop/EditLocalOrderDialog";
6
8
  import { useSalesOrdersQuery } from "../../lib/useSalesOrdersQuery";
7
9
  export function SalesOrderDetailPage() {
8
10
  const { salesOrderId } = useParams({
@@ -10,5 +12,9 @@ export function SalesOrderDetailPage() {
10
12
  });
11
13
  const { data, isLoading, error } = useSalesOrdersQuery();
12
14
  const order = data?.orders.find((o) => o.id === salesOrderId) ?? null;
13
- return (_jsxs("main", { className: "space-y-5 p-6", children: [_jsx("div", { className: "flex items-center justify-between gap-3", children: _jsx(Button, { asChild: true, variant: "ghost", size: "sm", children: _jsxs(Link, { to: "/floriday-verkoop/verkooporders", children: [_jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), "Terug naar verkooporders"] }) }) }), isLoading && (_jsx("div", { className: "rounded-lg border border-border bg-card p-8 text-sm text-muted-foreground", children: "Laden\u2026" })), error && (_jsx("div", { className: "rounded-lg border border-destructive/30 bg-destructive/5 p-4 text-sm text-destructive", children: error.message })), !isLoading && !error && !order && (_jsx("div", { className: "rounded-lg border border-border bg-card p-8 text-sm text-muted-foreground", children: "Order niet gevonden." })), order && (_jsx(SalesOrderDetailView, { order: order, sellerFallback: data?.sellerFallback ?? null }))] }));
15
+ const [editOpen, setEditOpen] = useState(false);
16
+ const rawLocalId = order?.isLocal && order.id.startsWith("local:")
17
+ ? order.id.slice("local:".length)
18
+ : null;
19
+ return (_jsxs("main", { className: "space-y-5 p-6", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx(Button, { asChild: true, variant: "ghost", size: "sm", children: _jsxs(Link, { to: "/floriday-verkoop/verkooporders", children: [_jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), "Terug naar verkooporders"] }) }), rawLocalId && (_jsxs(Button, { variant: "outline", size: "sm", onClick: () => setEditOpen(true), children: [_jsx(Pencil, { className: "mr-2 h-4 w-4" }), "Bestelling bewerken"] }))] }), isLoading && (_jsx("div", { className: "rounded-lg border border-border bg-card p-8 text-sm text-muted-foreground", children: "Laden\u2026" })), error && (_jsx("div", { className: "rounded-lg border border-destructive/30 bg-destructive/5 p-4 text-sm text-destructive", children: error.message })), !isLoading && !error && !order && (_jsx("div", { className: "rounded-lg border border-border bg-card p-8 text-sm text-muted-foreground", children: "Order niet gevonden." })), order && (_jsx(SalesOrderDetailView, { order: order, sellerFallback: data?.sellerFallback ?? null })), rawLocalId && (_jsx(EditLocalOrderDialog, { orderId: rawLocalId, open: editOpen, onOpenChange: setEditOpen }))] }));
14
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SalesOrderDetailView.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/SalesOrderDetailView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AA+HnE,wBAAgB,oBAAoB,CAAC,EACnC,KAAK,EACL,cAAc,GACf,EAAE;IACD,KAAK,EAAE,aAAa,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,2CA8RA"}
1
+ {"version":3,"file":"SalesOrderDetailView.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/SalesOrderDetailView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAiInE,wBAAgB,oBAAoB,CAAC,EACnC,KAAK,EACL,cAAc,GACf,EAAE;IACD,KAAK,EAAE,aAAa,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,2CAgSA"}
@@ -3,6 +3,7 @@ import { CheckCircle2, ImageIcon } from "lucide-react";
3
3
  import { OrderKarindelingCard } from "./OrderKarindelingCard";
4
4
  import { OrderAfleverbrievenCard } from "./OrderAfleverbrievenCard";
5
5
  import { AutoFulfillmentStatusCard } from "./AutoFulfillmentStatusCard";
6
+ import { OrderShipmentsCard } from "./OrderShipmentsCard";
6
7
  const eurFlex = new Intl.NumberFormat("nl-NL", {
7
8
  style: "currency",
8
9
  currency: "EUR",
@@ -212,5 +213,5 @@ export function SalesOrderDetailView({ order, sellerFallback, }) {
212
213
  const bestellingLabel = order.status.isCancelled
213
214
  ? "Geannuleerd"
214
215
  : STATUS_LABELS[statusKey] ?? (order.status.isShipped ? "Verzonden" : order.status.isConfirmed ? "Order bevestigd" : "Open");
215
- return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "flex items-center gap-3 rounded-md border border-border bg-muted/30 p-3", children: [_jsx("div", { className: "flex h-12 w-12 shrink-0 items-center justify-center overflow-hidden rounded-md bg-muted", children: order.imageUrl ? (_jsx("img", { src: order.imageUrl, alt: "", className: "h-full w-full object-cover" })) : (_jsx(ImageIcon, { className: "h-6 w-6 text-muted-foreground" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "truncate text-base font-semibold text-foreground", children: [order.productName, o.tradeItemVersion ? (_jsxs("span", { className: "ml-2 text-xs font-normal text-muted-foreground", children: ["\u00B7 v", o.tradeItemVersion] })) : null] }), _jsx("div", { className: "truncate text-xs text-muted-foreground", children: order.orderNumber || order.sku || "—" })] })] }), _jsxs("div", { className: "grid grid-cols-1 gap-6 lg:grid-cols-[1fr_360px]", children: [_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { children: [_jsx(SectionTitle, { children: "Verkooporder" }), _jsx(Row, { label: "Ordernummer", children: order.orderNumber || "—" }), _jsx(Row, { label: "Handelsvorm", children: tradingType }), _jsx(Row, { label: "Bestelmoment", children: fmtDateTime(order.orderedAt) }), _jsx(Row, { label: "Aantal", children: _jsxs("div", { className: "flex flex-wrap gap-4", children: [_jsxs("div", { children: [order.fustCount, " fusten"] }), _jsxs("div", { children: [order.karCount, " karren"] })] }) }), _jsx(Row, { label: "Belading", children: belading }), _jsx(Row, { label: "Klant referentie", children: klantReferentie }), _jsx(Row, { label: "Floriday-referentie", children: floridayRef }), _jsx(Row, { label: "Verkoopkanaal", children: verkoopkanaal }), _jsx(Row, { label: "Financi\u00EBle afhandeling", children: financial }), _jsx(Row, { label: "Verkoper", children: sellerName ? (_jsxs("span", { className: "inline-flex items-center gap-2", children: [_jsx("span", { className: "inline-flex h-6 w-6 items-center justify-center rounded-full bg-muted text-[10px] font-semibold text-muted-foreground", children: initials(sellerName) }), sellerName] })) : ("—") })] }), _jsxs("div", { children: [_jsx(SectionTitle, { children: "Levering" }), _jsx(Row, { label: "Afleverdatum", children: fmtDateTime(order.deliveryAt) }), _jsx(Row, { label: "Incoterm", children: incoterm }), _jsx(Row, { label: "Levering", children: _jsxs("div", { className: "inline-flex max-w-xs items-start gap-3 rounded-md border border-border bg-card p-3", children: [_jsx("div", { className: "flex h-9 w-9 items-center justify-center rounded-md bg-primary/10 text-primary", children: _jsxs("svg", { viewBox: "0 0 24 24", className: "h-5 w-5", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M3 11l9-8 9 8" }), _jsx("path", { d: "M5 10v10h14V10" }), _jsx("path", { d: "M10 20v-6h4v6" })] }) }), _jsxs("div", { className: "text-sm", children: [_jsx("div", { children: addr.line || "—" }), _jsx("div", { children: [addr.postal, addr.city].filter(Boolean).join(" ") || "—" }), _jsx("div", { children: countryLabel ?? "" }), addr.gln && (_jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: addr.gln }))] })] }) })] }), _jsxs("div", { children: [_jsx(SectionTitle, { children: "Klant" }), _jsx(Row, { label: "Naam", children: _jsx("span", { className: "font-medium", children: customerName }) }), _jsx(Row, { label: "GLN", children: customerGln }), _jsx(Row, { label: "Administratienummer", children: customerAdmin }), _jsx(Row, { label: "Telefoonnummer", children: customerPhone })] })] }), _jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "rounded-md border border-border p-4", children: [_jsx("div", { className: "mb-3 text-sm font-semibold", children: "Prijs per stuk" }), _jsxs("div", { className: "space-y-2 text-sm", children: [_jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-muted-foreground", children: "Product" }), _jsxs("span", { children: [oldProductPrice !== null && (_jsx("span", { className: "mr-2 text-destructive line-through", children: eurFlex.format(oldProductPrice) })), eurFlex.format(productUnit)] })] }), _jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-muted-foreground", children: "Transportkosten" }), _jsx("span", { children: eurFlex.format(transportPerPiece) })] }), _jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-muted-foreground", children: "Inkoopprijs" }), _jsx("span", { children: eurFlex.format(purchaseUnit) })] }), _jsxs("div", { className: "mt-2 flex justify-between border-t border-border pt-2 font-semibold", children: [_jsx("span", { children: "Totaal" }), _jsxs("span", { children: [_jsxs("span", { className: "mr-2 text-xs font-normal text-muted-foreground", children: ["(", packages, " \u00D7 ", piecesPerPackage, " \u00D7 ", eurFlex.format(productUnit), ")"] }), eurFlex.format(totalAmount)] })] })] })] }), _jsxs("div", { className: "rounded-md border border-border p-4", children: [_jsx("div", { className: "mb-3 text-sm font-semibold", children: "Status" }), _jsxs("div", { className: "space-y-3 text-sm", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { className: "text-muted-foreground", children: "Bestelling" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-emerald-600" }), bestellingLabel] })] }), hasCorrection && (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { className: "text-muted-foreground", children: "Correctie" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-emerald-600" }), "Correctie is verwerkt"] })] }))] })] })] })] }), _jsx(OrderKarindelingCard, { order: order }), o?.salesOrderId ? (_jsxs(_Fragment, { children: [_jsx(AutoFulfillmentStatusCard, { salesOrderId: String(o.salesOrderId) }), _jsx(OrderAfleverbrievenCard, { salesOrderId: String(o.salesOrderId) })] })) : null] }));
216
+ return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "flex items-center gap-3 rounded-md border border-border bg-muted/30 p-3", children: [_jsx("div", { className: "flex h-12 w-12 shrink-0 items-center justify-center overflow-hidden rounded-md bg-muted", children: order.imageUrl ? (_jsx("img", { src: order.imageUrl, alt: "", className: "h-full w-full object-cover" })) : (_jsx(ImageIcon, { className: "h-6 w-6 text-muted-foreground" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "truncate text-base font-semibold text-foreground", children: [order.productName, o.tradeItemVersion ? (_jsxs("span", { className: "ml-2 text-xs font-normal text-muted-foreground", children: ["\u00B7 v", o.tradeItemVersion] })) : null] }), _jsx("div", { className: "truncate text-xs text-muted-foreground", children: order.orderNumber || order.sku || "—" })] })] }), _jsxs("div", { className: "grid grid-cols-1 gap-6 lg:grid-cols-[1fr_360px]", children: [_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { children: [_jsx(SectionTitle, { children: "Verkooporder" }), _jsx(Row, { label: "Ordernummer", children: order.orderNumber || "—" }), _jsx(Row, { label: "Handelsvorm", children: tradingType }), _jsx(Row, { label: "Bestelmoment", children: fmtDateTime(order.orderedAt) }), _jsx(Row, { label: "Aantal", children: _jsxs("div", { className: "flex flex-wrap gap-4", children: [_jsxs("div", { children: [order.fustCount, " fusten"] }), _jsxs("div", { children: [order.karCount, " karren"] })] }) }), _jsx(Row, { label: "Belading", children: belading }), _jsx(Row, { label: "Klant referentie", children: klantReferentie }), _jsx(Row, { label: "Floriday-referentie", children: floridayRef }), _jsx(Row, { label: "Verkoopkanaal", children: verkoopkanaal }), _jsx(Row, { label: "Financi\u00EBle afhandeling", children: financial }), _jsx(Row, { label: "Verkoper", children: sellerName ? (_jsxs("span", { className: "inline-flex items-center gap-2", children: [_jsx("span", { className: "inline-flex h-6 w-6 items-center justify-center rounded-full bg-muted text-[10px] font-semibold text-muted-foreground", children: initials(sellerName) }), sellerName] })) : ("—") })] }), _jsxs("div", { children: [_jsx(SectionTitle, { children: "Levering" }), _jsx(Row, { label: "Afleverdatum", children: fmtDateTime(order.deliveryAt) }), _jsx(Row, { label: "Incoterm", children: incoterm }), _jsx(Row, { label: "Levering", children: _jsxs("div", { className: "inline-flex max-w-xs items-start gap-3 rounded-md border border-border bg-card p-3", children: [_jsx("div", { className: "flex h-9 w-9 items-center justify-center rounded-md bg-primary/10 text-primary", children: _jsxs("svg", { viewBox: "0 0 24 24", className: "h-5 w-5", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M3 11l9-8 9 8" }), _jsx("path", { d: "M5 10v10h14V10" }), _jsx("path", { d: "M10 20v-6h4v6" })] }) }), _jsxs("div", { className: "text-sm", children: [_jsx("div", { children: addr.line || "—" }), _jsx("div", { children: [addr.postal, addr.city].filter(Boolean).join(" ") || "—" }), _jsx("div", { children: countryLabel ?? "" }), addr.gln && (_jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: addr.gln }))] })] }) })] }), _jsxs("div", { children: [_jsx(SectionTitle, { children: "Klant" }), _jsx(Row, { label: "Naam", children: _jsx("span", { className: "font-medium", children: customerName }) }), _jsx(Row, { label: "GLN", children: customerGln }), _jsx(Row, { label: "Administratienummer", children: customerAdmin }), _jsx(Row, { label: "Telefoonnummer", children: customerPhone })] })] }), _jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "rounded-md border border-border p-4", children: [_jsx("div", { className: "mb-3 text-sm font-semibold", children: "Prijs per stuk" }), _jsxs("div", { className: "space-y-2 text-sm", children: [_jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-muted-foreground", children: "Product" }), _jsxs("span", { children: [oldProductPrice !== null && (_jsx("span", { className: "mr-2 text-destructive line-through", children: eurFlex.format(oldProductPrice) })), eurFlex.format(productUnit)] })] }), _jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-muted-foreground", children: "Transportkosten" }), _jsx("span", { children: eurFlex.format(transportPerPiece) })] }), _jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-muted-foreground", children: "Inkoopprijs" }), _jsx("span", { children: eurFlex.format(purchaseUnit) })] }), _jsxs("div", { className: "mt-2 flex justify-between border-t border-border pt-2 font-semibold", children: [_jsx("span", { children: "Totaal" }), _jsxs("span", { children: [_jsxs("span", { className: "mr-2 text-xs font-normal text-muted-foreground", children: ["(", packages, " \u00D7 ", piecesPerPackage, " \u00D7 ", eurFlex.format(productUnit), ")"] }), eurFlex.format(totalAmount)] })] })] })] }), _jsxs("div", { className: "rounded-md border border-border p-4", children: [_jsx("div", { className: "mb-3 text-sm font-semibold", children: "Status" }), _jsxs("div", { className: "space-y-3 text-sm", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { className: "text-muted-foreground", children: "Bestelling" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-emerald-600" }), bestellingLabel] })] }), hasCorrection && (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { className: "text-muted-foreground", children: "Correctie" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-emerald-600" }), "Correctie is verwerkt"] })] }))] })] })] })] }), _jsx(OrderShipmentsCard, { order: order }), _jsx(OrderKarindelingCard, { order: order }), o?.salesOrderId ? (_jsxs(_Fragment, { children: [_jsx(AutoFulfillmentStatusCard, { salesOrderId: String(o.salesOrderId) }), _jsx(OrderAfleverbrievenCard, { salesOrderId: String(o.salesOrderId) })] })) : null] }));
216
217
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SalesOrdersFilters.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/SalesOrdersFilters.tsx"],"names":[],"mappings":"AA8BA,MAAM,WAAW,OAAO;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;CACnE;AAoCD,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACnC,2CA4PA"}
1
+ {"version":3,"file":"SalesOrdersFilters.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/SalesOrdersFilters.tsx"],"names":[],"mappings":"AA4BA,MAAM,WAAW,OAAO;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;CACnE;AAoCD,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACnC,2CA0NA"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
3
  import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger, Input, Popover, PopoverContent, PopoverTrigger, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@flowselections/core";
4
- import { ChevronDown, ChevronLeft, ChevronRight, MoreVertical, ShoppingCart, Truck, Search, } from "lucide-react";
4
+ import { ChevronDown, ChevronLeft, ChevronRight, MoreVertical, Search, } from "lucide-react";
5
5
  import { WeekCalendar } from "./WeekCalendar";
6
6
  function getCurrentWeek() {
7
7
  const now = new Date();
@@ -127,13 +127,7 @@ export function SalesOrdersFilters({ value, onChange, }) {
127
127
  return (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs("div", { className: "flex h-9 items-center gap-1 rounded-md border border-border bg-card px-1", children: [showArrows && (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", onClick: () => shiftPeriod(-1), className: "inline-flex h-7 w-7 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground", "aria-label": "Vorige", children: _jsx(ChevronLeft, { className: "h-4 w-4" }) }), _jsx("button", { type: "button", onClick: () => shiftPeriod(1), className: "inline-flex h-7 w-7 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground", "aria-label": "Volgende", children: _jsx(ChevronRight, { className: "h-4 w-4" }) })] })), period === "month" ? (_jsxs(Select, { value: `${monthYear}-${month}`, onValueChange: (v) => {
128
128
  const [y, m] = v.split("-").map(Number);
129
129
  onChange({ ...value, month: m, monthYear: y });
130
- }, children: [_jsx(SelectTrigger, { className: "h-7 w-36 border-0 bg-transparent px-2 text-sm font-medium text-foreground shadow-none focus:ring-0", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: monthOptions.map((opt) => (_jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value))) })] })) : period === "day" ? (_jsx(Input, { type: "date", value: day, onChange: (e) => onChange({ ...value, day: e.target.value }), className: "h-7 w-40 border-0 bg-transparent px-2 text-sm font-medium text-foreground shadow-none focus-visible:ring-0" })) : period === "custom" ? (_jsxs("div", { className: "flex items-center gap-1 px-2", children: [_jsx(Input, { type: "date", value: value.customFrom ?? todayYmd, onChange: (e) => onChange({ ...value, customFrom: e.target.value }), className: "h-7 w-36 border-0 bg-transparent px-1 text-sm font-medium text-foreground shadow-none focus-visible:ring-0" }), _jsx("span", { className: "text-muted-foreground", children: "\u2013" }), _jsx(Input, { type: "date", value: value.customTo ?? todayYmd, onChange: (e) => onChange({ ...value, customTo: e.target.value }), className: "h-7 w-36 border-0 bg-transparent px-1 text-sm font-medium text-foreground shadow-none focus-visible:ring-0" })] })) : period === "last7" || period === "last30" ? (_jsx("span", { className: "px-2 text-sm font-medium text-foreground whitespace-nowrap", children: period === "last7" ? "Afgelopen 7 dagen" : "Afgelopen 30 dagen" })) : (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "px-2 text-sm font-medium text-foreground whitespace-nowrap rounded hover:bg-accent h-7", "aria-label": "Kies week", children: ["Week ", week, " - ", year] }) }), _jsx(PopoverContent, { className: "w-auto p-0 pointer-events-auto", align: "start", children: _jsx(WeekCalendar, { week: week, year: year, onSelect: (w, y) => onChange({ ...value, week: w, year: y }) }) })] })), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "inline-flex h-7 w-7 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground", "aria-label": "Periode-opties", children: _jsx(MoreVertical, { className: "h-4 w-4" }) }) }), _jsxs(DropdownMenuContent, { align: "end", className: "w-56", children: [_jsxs(DropdownMenuRadioGroup, { value: period, onValueChange: (v) => handlePeriodChange(v), children: [_jsx(DropdownMenuRadioItem, { value: "day", children: "Dag" }), _jsx(DropdownMenuRadioItem, { value: "week", children: "Week" }), _jsx(DropdownMenuRadioItem, { value: "month", children: "Maand" }), _jsx(DropdownMenuRadioItem, { value: "last7", children: "Afgelopen 7 dagen" }), _jsx(DropdownMenuRadioItem, { value: "last30", children: "Afgelopen 30 dagen" }), _jsx(DropdownMenuRadioItem, { value: "custom", children: "Aangepast tijdsbestek" })] }), _jsx(DropdownMenuSeparator, {}), _jsxs("div", { className: "px-2 py-1.5 text-sm text-muted-foreground inline-flex items-center gap-1", children: [periodLabel(), _jsx(ChevronDown, { className: "h-3.5 w-3.5" })] })] })] })] }), _jsxs("div", { className: "flex h-9 items-center rounded-md border border-border bg-card", children: [_jsx("button", { type: "button", onClick: () => onChange({ ...value, dateField: "ordered" }), className: "inline-flex h-9 w-9 items-center justify-center rounded-l-md border-r border-border " +
131
- ((value.dateField ?? "ordered") === "ordered"
132
- ? "bg-accent text-foreground"
133
- : "text-muted-foreground hover:bg-accent hover:text-foreground"), "aria-label": "Filter op besteldatum", title: "Filter op besteldatum", "aria-pressed": (value.dateField ?? "ordered") === "ordered", children: _jsx(ShoppingCart, { className: "h-4 w-4" }) }), _jsx("button", { type: "button", onClick: () => onChange({ ...value, dateField: "delivery" }), className: "inline-flex h-9 w-9 items-center justify-center rounded-r-md " +
134
- (value.dateField === "delivery"
135
- ? "bg-accent text-foreground"
136
- : "text-muted-foreground hover:bg-accent hover:text-foreground"), "aria-label": "Filter op transportdatum", title: "Filter op transportdatum", "aria-pressed": value.dateField === "delivery", children: _jsx(Truck, { className: "h-4 w-4" }) })] }), _jsxs("div", { className: "flex h-9 items-center overflow-hidden rounded-md border border-border bg-card", children: [_jsx(Input, { placeholder: "Op briefnummer zoeken", value: search, onChange: (e) => setSearch(e.target.value), onKeyDown: (e) => {
130
+ }, children: [_jsx(SelectTrigger, { className: "h-7 w-36 border-0 bg-transparent px-2 text-sm font-medium text-foreground shadow-none focus:ring-0", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: monthOptions.map((opt) => (_jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value))) })] })) : period === "day" ? (_jsx(Input, { type: "date", value: day, onChange: (e) => onChange({ ...value, day: e.target.value }), className: "h-7 w-40 border-0 bg-transparent px-2 text-sm font-medium text-foreground shadow-none focus-visible:ring-0" })) : period === "custom" ? (_jsxs("div", { className: "flex items-center gap-1 px-2", children: [_jsx(Input, { type: "date", value: value.customFrom ?? todayYmd, onChange: (e) => onChange({ ...value, customFrom: e.target.value }), className: "h-7 w-36 border-0 bg-transparent px-1 text-sm font-medium text-foreground shadow-none focus-visible:ring-0" }), _jsx("span", { className: "text-muted-foreground", children: "\u2013" }), _jsx(Input, { type: "date", value: value.customTo ?? todayYmd, onChange: (e) => onChange({ ...value, customTo: e.target.value }), className: "h-7 w-36 border-0 bg-transparent px-1 text-sm font-medium text-foreground shadow-none focus-visible:ring-0" })] })) : period === "last7" || period === "last30" ? (_jsx("span", { className: "px-2 text-sm font-medium text-foreground whitespace-nowrap", children: period === "last7" ? "Afgelopen 7 dagen" : "Afgelopen 30 dagen" })) : (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "px-2 text-sm font-medium text-foreground whitespace-nowrap rounded hover:bg-accent h-7", "aria-label": "Kies week", children: ["Week ", week, " - ", year] }) }), _jsx(PopoverContent, { className: "w-auto p-0 pointer-events-auto", align: "start", children: _jsx(WeekCalendar, { week: week, year: year, onSelect: (w, y) => onChange({ ...value, week: w, year: y }) }) })] })), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "inline-flex h-7 w-7 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground", "aria-label": "Periode-opties", children: _jsx(MoreVertical, { className: "h-4 w-4" }) }) }), _jsxs(DropdownMenuContent, { align: "end", className: "w-56", children: [_jsxs(DropdownMenuRadioGroup, { value: period, onValueChange: (v) => handlePeriodChange(v), children: [_jsx(DropdownMenuRadioItem, { value: "day", children: "Dag" }), _jsx(DropdownMenuRadioItem, { value: "week", children: "Week" }), _jsx(DropdownMenuRadioItem, { value: "month", children: "Maand" }), _jsx(DropdownMenuRadioItem, { value: "last7", children: "Afgelopen 7 dagen" }), _jsx(DropdownMenuRadioItem, { value: "last30", children: "Afgelopen 30 dagen" }), _jsx(DropdownMenuRadioItem, { value: "custom", children: "Aangepast tijdsbestek" })] }), _jsx(DropdownMenuSeparator, {}), _jsxs("div", { className: "px-2 py-1.5 text-sm text-muted-foreground inline-flex items-center gap-1", children: [periodLabel(), _jsx(ChevronDown, { className: "h-3.5 w-3.5" })] })] })] })] }), _jsxs("div", { className: "flex h-9 items-center overflow-hidden rounded-md border border-border bg-card", children: [_jsx(Input, { placeholder: "Op briefnummer zoeken", value: search, onChange: (e) => setSearch(e.target.value), onKeyDown: (e) => {
137
131
  if (e.key === "Enter")
138
132
  onChange({ ...value, search });
139
133
  }, onBlur: () => onChange({ ...value, search }), className: "h-9 w-56 border-0 shadow-none focus-visible:ring-0" }), _jsx("button", { type: "button", onClick: () => onChange({ ...value, search }), className: "inline-flex h-9 w-10 items-center justify-center bg-primary text-primary-foreground hover:opacity-90", "aria-label": "Zoeken", children: _jsx(Search, { className: "h-4 w-4" }) })] })] }));