@flowselections/floriday-verkoop-module 1.0.20 → 1.0.24

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 (89) hide show
  1. package/dist-lib/components/karindeling/AfmetingenTab.d.ts +6 -0
  2. package/dist-lib/components/karindeling/AfmetingenTab.d.ts.map +1 -0
  3. package/dist-lib/components/karindeling/AfmetingenTab.js +128 -0
  4. package/dist-lib/components/karindeling/KarindelingPage.d.ts +2 -0
  5. package/dist-lib/components/karindeling/KarindelingPage.d.ts.map +1 -0
  6. package/dist-lib/components/karindeling/KarindelingPage.js +102 -0
  7. package/dist-lib/components/verkoop/OrderControlStatusCard.d.ts +6 -0
  8. package/dist-lib/components/verkoop/OrderControlStatusCard.d.ts.map +1 -0
  9. package/dist-lib/components/verkoop/OrderControlStatusCard.js +41 -0
  10. package/dist-lib/components/verkoop/OrderKarindelingCard.d.ts.map +1 -1
  11. package/dist-lib/components/verkoop/OrderKarindelingCard.js +83 -37
  12. package/dist-lib/components/verkoop/SalesOrderDetailPage.d.ts.map +1 -1
  13. package/dist-lib/components/verkoop/SalesOrderDetailPage.js +74 -8
  14. package/dist-lib/components/verkoop/SalesOrderDetailView.d.ts +2 -1
  15. package/dist-lib/components/verkoop/SalesOrderDetailView.d.ts.map +1 -1
  16. package/dist-lib/components/verkoop/SalesOrderDetailView.js +3 -2
  17. package/dist-lib/components/verkoop/SalesOrdersTable.d.ts.map +1 -1
  18. package/dist-lib/components/verkoop/SalesOrdersTable.js +40 -5
  19. package/dist-lib/components/verkoop/VerkoopOrdersPage.d.ts.map +1 -1
  20. package/dist-lib/components/verkoop/VerkoopOrdersPage.js +19 -3
  21. package/dist-lib/index.d.ts +1 -0
  22. package/dist-lib/index.d.ts.map +1 -1
  23. package/dist-lib/index.js +12 -1
  24. package/dist-lib/integrations/supabase/auth-middleware.d.ts +1536 -581
  25. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  26. package/dist-lib/integrations/supabase/client.d.ts +1536 -581
  27. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  28. package/dist-lib/integrations/supabase/client.js +24 -9
  29. package/dist-lib/integrations/supabase/client.server.d.ts +1536 -581
  30. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  31. package/dist-lib/integrations/supabase/types.d.ts +1543 -562
  32. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  33. package/dist-lib/integrations/supabase/types.js +3 -9
  34. package/dist-lib/lib/cart-lock.functions.d.ts +1536 -581
  35. package/dist-lib/lib/cart-lock.functions.d.ts.map +1 -1
  36. package/dist-lib/lib/cart-planner.d.ts +9 -1
  37. package/dist-lib/lib/cart-planner.d.ts.map +1 -1
  38. package/dist-lib/lib/cart-planner.js +21 -4
  39. package/dist-lib/lib/cart-planning-settings.functions.d.ts +140842 -0
  40. package/dist-lib/lib/cart-planning-settings.functions.d.ts.map +1 -0
  41. package/dist-lib/lib/cart-planning-settings.functions.js +375 -0
  42. package/dist-lib/lib/cart-replan.functions.d.ts +15811 -1082
  43. package/dist-lib/lib/cart-replan.functions.d.ts.map +1 -1
  44. package/dist-lib/lib/cart-replan.functions.js +85 -27
  45. package/dist-lib/lib/create-order.functions.d.ts +19021 -7561
  46. package/dist-lib/lib/create-order.functions.d.ts.map +1 -1
  47. package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts +4558 -1693
  48. package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts.map +1 -1
  49. package/dist-lib/lib/floriday-auto-fulfillment.server.js +1 -1
  50. package/dist-lib/lib/floriday-central-token.server.d.ts +12 -0
  51. package/dist-lib/lib/floriday-central-token.server.d.ts.map +1 -0
  52. package/dist-lib/lib/floriday-central-token.server.js +58 -0
  53. package/dist-lib/lib/floriday-gateway.server.d.ts +2 -2
  54. package/dist-lib/lib/floriday-gateway.server.d.ts.map +1 -1
  55. package/dist-lib/lib/floriday-gateway.server.js +10 -37
  56. package/dist-lib/lib/floriday-logistic-labels.functions.d.ts +1536 -581
  57. package/dist-lib/lib/floriday-logistic-labels.functions.d.ts.map +1 -1
  58. package/dist-lib/lib/floriday-logistic-labels.functions.js +14 -4
  59. package/dist-lib/lib/floriday-mirror.functions.d.ts +12806 -0
  60. package/dist-lib/lib/floriday-mirror.functions.d.ts.map +1 -0
  61. package/dist-lib/lib/floriday-mirror.functions.js +278 -0
  62. package/dist-lib/lib/floriday-public.functions.d.ts +10989 -4301
  63. package/dist-lib/lib/floriday-public.functions.d.ts.map +1 -1
  64. package/dist-lib/lib/floriday-public.functions.js +114 -38
  65. package/dist-lib/lib/floriday-sync.d.ts +0 -1
  66. package/dist-lib/lib/floriday-sync.d.ts.map +1 -1
  67. package/dist-lib/lib/floriday-sync.js +1 -1
  68. package/dist-lib/lib/floriday-writes.functions.d.ts +7772 -2997
  69. package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
  70. package/dist-lib/lib/order-buffers.functions.d.ts +38420 -0
  71. package/dist-lib/lib/order-buffers.functions.d.ts.map +1 -0
  72. package/dist-lib/lib/order-buffers.functions.js +244 -0
  73. package/dist-lib/lib/order-shipments.functions.d.ts +6165 -2345
  74. package/dist-lib/lib/order-shipments.functions.d.ts.map +1 -1
  75. package/dist-lib/lib/salesorders-mapping.d.ts +5 -0
  76. package/dist-lib/lib/salesorders-mapping.d.ts.map +1 -1
  77. package/dist-lib/lib/salesorders-mapping.js +8 -1
  78. package/dist-lib/lib/salesorders.functions.d.ts +30443 -1979
  79. package/dist-lib/lib/salesorders.functions.d.ts.map +1 -1
  80. package/dist-lib/lib/salesorders.functions.js +307 -0
  81. package/dist-lib/lib/tradeitems.functions.d.ts +1536 -581
  82. package/dist-lib/lib/tradeitems.functions.d.ts.map +1 -1
  83. package/dist-lib/lib/useSalesOrderDetailQuery.d.ts +2 -0
  84. package/dist-lib/lib/useSalesOrderDetailQuery.d.ts.map +1 -0
  85. package/dist-lib/lib/useSalesOrderDetailQuery.js +50 -0
  86. package/dist-lib/lib/useSalesOrdersQuery.d.ts +2 -2
  87. package/dist-lib/lib/useSalesOrdersQuery.d.ts.map +1 -1
  88. package/dist-lib/lib/useSalesOrdersQuery.js +139 -10
  89. package/package.json +5 -5
@@ -1,20 +1,86 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from "react";
2
+ import { useMemo, useState } from "react";
3
3
  import { Link, useParams } from "@tanstack/react-router";
4
- import { Button } from "@flowselections/core";
5
- import { ArrowLeft, Pencil } from "lucide-react";
4
+ import { Badge, Button } from "@flowselections/core";
5
+ import { ArrowLeft, Pencil, Layers, ChevronDown, ChevronRight, ImageIcon } from "lucide-react";
6
6
  import { SalesOrderDetailView } from "../../components/verkoop/SalesOrderDetailView";
7
+ import { OrderKarindelingCard } from "../../components/verkoop/OrderKarindelingCard";
7
8
  import { EditLocalOrderDialog } from "../../components/verkoop/EditLocalOrderDialog";
8
9
  import { useSalesOrdersQuery } from "../../lib/useSalesOrdersQuery";
10
+ import { useSalesOrderDetailQuery } from "../../lib/useSalesOrderDetailQuery";
11
+ const eur = new Intl.NumberFormat("nl-NL", {
12
+ style: "currency",
13
+ currency: "EUR",
14
+ minimumFractionDigits: 2,
15
+ maximumFractionDigits: 2,
16
+ });
9
17
  export function SalesOrderDetailPage() {
10
18
  const { salesOrderId } = useParams({
11
19
  from: "/_authenticated/floriday-verkoop/verkooporders/$salesOrderId",
12
20
  });
13
- const { data, isLoading, error } = useSalesOrdersQuery();
14
- const order = data?.orders.find((o) => o.id === salesOrderId) ?? null;
21
+ const isLocal = salesOrderId.startsWith("local:");
22
+ const isMailboxProposal = salesOrderId.startsWith("mailbox-proposal:");
23
+ const isFloriday = !isLocal && !isMailboxProposal;
24
+ // Floriday-orders: gerichte, snelle per-order fetch.
25
+ const detailQuery = useSalesOrderDetailQuery(isFloriday ? salesOrderId : null);
26
+ // Lijst-query gebruiken we altijd: voor lokale/mailbox-orders als bron,
27
+ // en voor Floriday-orders om buffer-siblings te vinden.
28
+ const listQuery = useSalesOrdersQuery();
29
+ const isLoading = isFloriday ? detailQuery.isLoading : listQuery.isLoading;
30
+ const error = isFloriday ? detailQuery.error : listQuery.error;
31
+ const primary = isFloriday
32
+ ? (detailQuery.data?.order ?? null)
33
+ : (listQuery.data?.orders.find((o) => o.id === salesOrderId) ?? null);
34
+ const sellerFallback = isFloriday
35
+ ? (detailQuery.data?.sellerFallback ?? null)
36
+ : (listQuery.data?.sellerFallback ?? null);
37
+ // Buffer-siblings: voor Floriday-orders levert de detailQuery zelf al de
38
+ // volledige buffer op (server-side gejoined via de orders-tabel), zodat we
39
+ // niet meer afhankelijk zijn van de tragere/gefilterde lijst-query.
40
+ const bufferId = useMemo(() => {
41
+ if (isFloriday) {
42
+ return detailQuery.data?.bufferId ?? primary?.bufferId ?? null;
43
+ }
44
+ if (primary?.bufferId)
45
+ return primary.bufferId;
46
+ const all = listQuery.data?.orders ?? [];
47
+ return all.find((o) => o.id === salesOrderId)?.bufferId ?? null;
48
+ }, [isFloriday, detailQuery.data?.bufferId, primary, listQuery.data?.orders, salesOrderId]);
49
+ const bufferOrders = useMemo(() => {
50
+ if (!bufferId)
51
+ return primary ? [primary] : [];
52
+ const head = primary;
53
+ if (isFloriday) {
54
+ const siblings = detailQuery.data?.bufferSiblings ?? [];
55
+ const rest = siblings
56
+ .filter((o) => o.id !== (primary?.id ?? salesOrderId))
57
+ .sort((a, b) => (b.orderedAt || "").localeCompare(a.orderedAt || ""));
58
+ return head ? [head, ...rest] : rest;
59
+ }
60
+ const all = listQuery.data?.orders ?? [];
61
+ const siblings = all.filter((o) => o.bufferId === bufferId);
62
+ if (siblings.length === 0)
63
+ return primary ? [primary] : [];
64
+ const rest = siblings
65
+ .filter((o) => o.id !== (primary?.id ?? salesOrderId))
66
+ .sort((a, b) => (b.orderedAt || "").localeCompare(a.orderedAt || ""));
67
+ const localHead = primary ?? siblings.find((o) => o.id === salesOrderId) ?? siblings[0];
68
+ return [localHead, ...rest];
69
+ }, [primary, bufferId, isFloriday, detailQuery.data?.bufferSiblings, listQuery.data?.orders, salesOrderId]);
70
+ const isBuffer = bufferOrders.length > 1;
71
+ const totals = useMemo(() => {
72
+ const revenue = bufferOrders.reduce((s, o) => s + (o.revenue ?? 0), 0);
73
+ const karren = bufferOrders.reduce((s, o) => s + (o.karCount ?? 0), 0);
74
+ const fusten = bufferOrders.reduce((s, o) => s + (o.fustCount ?? 0), 0);
75
+ return { revenue, karren, fusten };
76
+ }, [bufferOrders]);
15
77
  const [editOpen, setEditOpen] = useState(false);
16
- const rawLocalId = order?.isLocal && order.id.startsWith("local:")
17
- ? order.id.slice("local:".length)
78
+ const rawLocalId = isLocal && salesOrderId.startsWith("local:")
79
+ ? salesOrderId.slice("local:".length)
18
80
  : 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 }))] }));
81
+ 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 && !primary && (_jsx("div", { className: "rounded-lg border border-border bg-card p-8 text-sm text-muted-foreground", children: "Order niet gevonden." })), primary && isBuffer && (_jsxs("div", { className: "rounded-lg border border-primary/30 bg-primary/5 p-4", children: [_jsxs("div", { className: "mb-3 flex items-center gap-2", children: [_jsx(Layers, { className: "h-4 w-4 text-primary" }), _jsx("span", { className: "text-sm font-semibold text-foreground", children: "Orderbuffer" }), _jsxs(Badge, { variant: "outline", className: "border-primary/40 text-primary", children: [bufferOrders.length, " orders samengevoegd"] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-3 text-sm md:grid-cols-4", children: [_jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground", children: "Totale omzet" }), _jsx("div", { className: "font-semibold text-foreground", children: eur.format(totals.revenue) })] }), _jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground", children: "Karren" }), _jsx("div", { className: "font-semibold text-foreground", children: totals.karren })] }), _jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground", children: "Fusten" }), _jsx("div", { className: "font-semibold text-foreground", children: totals.fusten })] }), _jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground", children: "Klant" }), _jsx("div", { className: "font-semibold text-foreground", children: primary.customer.name })] })] }), _jsx("div", { className: "mt-3 flex flex-wrap gap-2", children: bufferOrders.map((o) => (_jsx(Badge, { variant: "outline", className: "text-xs", children: o.orderNumber || o.id.slice(0, 8) }, o.id))) })] })), primary && !isBuffer && (_jsx(SalesOrderDetailView, { order: primary, sellerFallback: sellerFallback })), primary && isBuffer && (_jsxs("div", { className: "grid grid-cols-1 gap-6 xl:grid-cols-[minmax(0,1fr)_minmax(0,1fr)]", children: [_jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "text-sm font-semibold text-foreground", children: ["Orders in deze buffer (", bufferOrders.length, ")"] }), bufferOrders.map((o) => (_jsx(BufferOrderRow, { order: o, sellerFallback: sellerFallback }, o.id)))] }), _jsxs("div", { className: "space-y-3 xl:sticky xl:top-4 xl:self-start", children: [_jsx("div", { className: "text-sm font-semibold text-foreground", children: "Gecombineerde karindeling" }), _jsx(OrderKarindelingCard, { order: primary })] })] })), rawLocalId && (_jsx(EditLocalOrderDialog, { orderId: rawLocalId, open: editOpen, onOpenChange: setEditOpen }))] }));
82
+ }
83
+ function BufferOrderRow({ order, sellerFallback, }) {
84
+ const [open, setOpen] = useState(false);
85
+ return (_jsxs("div", { className: "overflow-hidden rounded-lg border border-border bg-card", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "flex w-full items-center gap-3 p-3 text-left hover:bg-muted/40", children: [open ? (_jsx(ChevronDown, { className: "h-4 w-4 shrink-0 text-muted-foreground" })) : (_jsx(ChevronRight, { className: "h-4 w-4 shrink-0 text-muted-foreground" })), _jsx("div", { className: "flex h-10 w-10 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-5 w-5 text-muted-foreground" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-sm font-semibold text-foreground", children: order.productName }), _jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-muted-foreground", children: [order.orderNumber && _jsx("span", { children: order.orderNumber }), _jsxs("span", { children: [order.karCount, " karren"] }), _jsxs("span", { children: [order.fustCount, " fusten"] }), _jsx("span", { children: eur.format(order.revenue ?? 0) })] })] }), order.isLocal ? (_jsx(Badge, { variant: "outline", className: "text-[10px]", children: "BVO" })) : (_jsx(Badge, { variant: "outline", className: "text-[10px]", children: "FO" }))] }), open && (_jsx("div", { className: "border-t border-border bg-background p-4", children: _jsx(SalesOrderDetailView, { order: order, sellerFallback: sellerFallback ?? null, hideKarindeling: true }) }))] }));
20
86
  }
@@ -1,6 +1,7 @@
1
1
  import type { SalesOrderDTO } from "../../lib/salesorders-mapping";
2
- export declare function SalesOrderDetailView({ order, sellerFallback, }: {
2
+ export declare function SalesOrderDetailView({ order, sellerFallback, hideKarindeling, }: {
3
3
  order: SalesOrderDTO;
4
4
  sellerFallback?: string | null;
5
+ hideKarindeling?: boolean;
5
6
  }): import("react/jsx-runtime").JSX.Element;
6
7
  //# sourceMappingURL=SalesOrderDetailView.d.ts.map
@@ -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;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"}
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;AAmInE,wBAAgB,oBAAoB,CAAC,EACnC,KAAK,EACL,cAAc,EACd,eAAuB,GACxB,EAAE;IACD,KAAK,EAAE,aAAa,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,2CAuSA"}
@@ -4,6 +4,7 @@ import { OrderKarindelingCard } from "./OrderKarindelingCard";
4
4
  import { OrderAfleverbrievenCard } from "./OrderAfleverbrievenCard";
5
5
  import { AutoFulfillmentStatusCard } from "./AutoFulfillmentStatusCard";
6
6
  import { OrderShipmentsCard } from "./OrderShipmentsCard";
7
+ import { OrderControlStatusCard } from "./OrderControlStatusCard";
7
8
  const eurFlex = new Intl.NumberFormat("nl-NL", {
8
9
  style: "currency",
9
10
  currency: "EUR",
@@ -109,7 +110,7 @@ function Row({ label, children }) {
109
110
  function SectionTitle({ children }) {
110
111
  return (_jsx("div", { className: "border-b border-border pb-2 text-sm font-semibold text-foreground", children: children }));
111
112
  }
112
- export function SalesOrderDetailView({ order, sellerFallback, }) {
113
+ export function SalesOrderDetailView({ order, sellerFallback, hideKarindeling = false, }) {
113
114
  const o = order.raw.order ?? {};
114
115
  const c = order.raw.customer ?? {};
115
116
  const cRaw = c?.raw ?? {};
@@ -213,5 +214,5 @@ export function SalesOrderDetailView({ order, sellerFallback, }) {
213
214
  const bestellingLabel = order.status.isCancelled
214
215
  ? "Geannuleerd"
215
216
  : STATUS_LABELS[statusKey] ?? (order.status.isShipped ? "Verzonden" : order.status.isConfirmed ? "Order bevestigd" : "Open");
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] }));
217
+ 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 }), !hideKarindeling && _jsx(OrderKarindelingCard, { order: order }), o?.salesOrderId ? (_jsxs(_Fragment, { children: [_jsx(OrderControlStatusCard, { floridayId: String(o.salesOrderId), isControlled: order.status.isControlled, controlledAt: order.status.controlledAt }), _jsx(AutoFulfillmentStatusCard, { salesOrderId: String(o.salesOrderId) }), _jsx(OrderAfleverbrievenCard, { salesOrderId: String(o.salesOrderId) })] })) : null] }));
217
218
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SalesOrdersTable.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/SalesOrdersTable.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAsEnE,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,OAAO,EACP,aAAa,EACb,aAAa,EACb,WAAW,EACX,cAAc,GACf,EAAE;IACD,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CACjD,2CAsKA"}
1
+ {"version":3,"file":"SalesOrdersTable.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/SalesOrdersTable.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AA8EnE,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,OAAO,EACP,aAAa,EACb,aAAa,EACb,WAAW,EACX,cAAc,GACf,EAAE;IACD,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CACjD,2CAmNA"}
@@ -40,9 +40,12 @@ function StatusTag({ status, rawOrder, }) {
40
40
  if (rawStatus === "SHIPPED" || status.isShipped) {
41
41
  return (_jsx(Badge, { variant: "outline", className: "border-blue-500/30 bg-blue-500/10 text-blue-600 dark:text-blue-400", children: "Onderweg" }));
42
42
  }
43
- if (rawStatus === "COMMITTED" || status.isConfirmed) {
43
+ if (status.isControlled) {
44
44
  return (_jsx(Badge, { variant: "outline", className: "border-amber-500/30 bg-amber-500/10 text-amber-600 dark:text-amber-400", children: "Verzend klaar" }));
45
45
  }
46
+ if (rawStatus === "COMMITTED" || status.isConfirmed) {
47
+ return (_jsx(Badge, { variant: "outline", className: "border-sky-500/30 bg-sky-500/10 text-sky-600 dark:text-sky-400", children: "Nog niet gepakt" }));
48
+ }
46
49
  return (_jsx(Badge, { variant: "outline", className: "border-muted-foreground/30 bg-muted text-muted-foreground", children: "Nog picken" }));
47
50
  }
48
51
  export function SalesOrdersTable({ orders, loading, onSelectOrder, onDeleteOrder, onEditOrder, onConfirmOrder, }) {
@@ -55,8 +58,40 @@ export function SalesOrdersTable({ orders, loading, onSelectOrder, onDeleteOrder
55
58
  });
56
59
  return (_jsx("div", { className: "rounded-lg border border-border bg-card", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { className: "hover:bg-transparent", children: [_jsx(TableHead, { className: "w-10", children: _jsx(Checkbox, { checked: allChecked, onCheckedChange: (v) => setSelected(v === true ? new Set(orders.map((o) => o.id)) : new Set()) }) }), _jsx(TableHead, { children: "Omzet" }), _jsx(TableHead, { children: _jsxs("span", { className: "inline-flex items-center gap-1", children: ["Bestelmoment ", _jsx(ArrowDown, { className: "h-3 w-3" })] }) }), _jsx(TableHead, { children: "Karren" }), _jsx(TableHead, { children: "Fusten" }), _jsx(TableHead, { children: "Klant" }), _jsx(TableHead, { children: "Levering" }), _jsx(TableHead, { children: "Status" }), _jsx(TableHead, { className: "w-10" })] }) }), _jsxs(TableBody, { children: [loading &&
57
60
  Array.from({ length: 6 }).map((_, i) => (_jsx(TableRow, { children: Array.from({ length: 9 }).map((__, j) => (_jsx(TableCell, { children: _jsx(Skeleton, { className: "h-6 w-full" }) }, j))) }, `s-${i}`))), !loading && orders.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 9, className: "py-12 text-center text-muted-foreground", children: "Geen verkooporders gevonden." }) })), !loading &&
58
- orders.map((o) => {
59
- const ordered = formatDateShort(o.orderedAt);
60
- return (_jsxs(TableRow, { className: "align-top cursor-pointer", onClick: () => onSelectOrder?.(o), children: [_jsx(TableCell, { onClick: (e) => e.stopPropagation(), children: _jsx(Checkbox, { checked: selected.has(o.id), onCheckedChange: () => toggle(o.id) }) }), _jsxs(TableCell, { children: [_jsxs("div", { className: "font-medium text-foreground", children: ["\u20AC ", o.revenue.toFixed(2)] }), o.orderNumber && (_jsx("div", { className: "text-xs text-muted-foreground", children: o.orderNumber }))] }), _jsx(TableCell, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Package, { className: "h-4 w-4 text-primary" }), _jsxs("div", { children: [_jsx("div", { className: "font-medium text-foreground", children: ordered.date }), _jsx("div", { className: "text-xs text-muted-foreground", children: ordered.time })] })] }) }), _jsx(TableCell, { children: _jsx("div", { className: "font-medium text-foreground", children: o.karCount }) }), _jsx(TableCell, { children: _jsx("div", { className: "font-medium text-foreground", children: o.fustCount }) }), _jsxs(TableCell, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-medium text-foreground", children: o.customer.name }), o.isLocal && (_jsx(Badge, { variant: "outline", className: "border-primary/30 text-primary", children: "Lokaal" })), o.isReservation && (_jsx(Badge, { variant: "outline", className: "border-amber-400/40 text-amber-600", children: "Reservering" }))] }), _jsx("div", { className: "text-xs text-muted-foreground", children: [o.customer.postalCode, o.customer.city].filter(Boolean).join(" ") })] }), _jsx(TableCell, { className: "text-sm text-foreground", children: formatDateLong(o.deliveryAt) }), _jsx(TableCell, { children: _jsx(StatusTag, { status: o.status, rawOrder: o.raw?.order }) }), _jsx(TableCell, { onClick: (e) => e.stopPropagation(), children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: _jsx(MoreVertical, { className: "h-4 w-4" }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsx(DropdownMenuItem, { disabled: !o.isLocal, onClick: () => o.isLocal && onEditOrder?.(o), title: o.isLocal ? undefined : "FO-orders kunnen niet bewerkt worden.", children: "Bewerken" }), _jsx(DropdownMenuItem, { onClick: () => onSelectOrder?.(o), children: "Details bekijken" }), _jsx(DropdownMenuItem, { onClick: () => onConfirmOrder?.(o), children: "Bevestigen" }), o.isLocal ? (_jsx(DropdownMenuItem, { className: "text-destructive focus:text-destructive", onClick: () => onDeleteOrder?.(o), children: "Verwijderen" })) : (_jsx(DropdownMenuItem, { disabled: true, title: "FO-orders kunnen niet verwijderd worden.", children: "Verwijderen (FO)" }))] })] }) })] }, o.id));
61
- })] })] }) }));
61
+ (() => {
62
+ // Groepeer orders met dezelfde bufferId volledig tot één rij.
63
+ // Orders zonder buffer (of buffer met 1 order) blijven staan.
64
+ const groupsMap = new Map();
65
+ const order = [];
66
+ for (const o of orders) {
67
+ const key = o.bufferId && (o.bufferSize ?? 1) > 1 ? `buf:${o.bufferId}` : `one:${o.id}`;
68
+ if (!groupsMap.has(key)) {
69
+ groupsMap.set(key, []);
70
+ order.push(key);
71
+ }
72
+ groupsMap.get(key).push(o);
73
+ }
74
+ const groups = order.map((k) => groupsMap.get(k));
75
+ // Sorteer groepen op meest recente bestelmoment binnen de groep (desc).
76
+ groups.sort((a, b) => {
77
+ const ta = a.reduce((m, o) => (o.orderedAt > m ? o.orderedAt : m), "");
78
+ const tb = b.reduce((m, o) => (o.orderedAt > m ? o.orderedAt : m), "");
79
+ return tb.localeCompare(ta);
80
+ });
81
+ const nodes = [];
82
+ for (const group of groups) {
83
+ const isBuffer = group.length > 1;
84
+ const first = group[0];
85
+ const revenue = group.reduce((s, o) => s + o.revenue, 0);
86
+ const karren = group.reduce((s, o) => s + o.karCount, 0);
87
+ const fusten = group.reduce((s, o) => s + o.fustCount, 0);
88
+ const orderedAt = group.reduce((m, o) => (o.orderedAt > m ? o.orderedAt : m), "");
89
+ const deliveryAt = group.reduce((m, o) => (o.deliveryAt > m ? o.deliveryAt : m), "");
90
+ const ordered = formatDateShort(orderedAt || first.orderedAt);
91
+ const rowId = isBuffer ? `buf-${first.bufferId}` : first.id;
92
+ const orderNumbers = Array.from(new Set(group.map((o) => o.orderNumber).filter(Boolean)));
93
+ nodes.push(_jsxs(TableRow, { className: `align-top cursor-pointer ${isBuffer ? "bg-muted/20 border-l-2 border-primary/40" : ""}`, onClick: () => onSelectOrder?.(first), children: [_jsx(TableCell, { onClick: (e) => e.stopPropagation(), children: _jsx(Checkbox, { checked: selected.has(rowId), onCheckedChange: () => toggle(rowId) }) }), _jsxs(TableCell, { children: [_jsxs("div", { className: "font-medium text-foreground", children: ["\u20AC ", revenue.toFixed(2)] }), isBuffer ? (_jsx("div", { className: "text-xs text-muted-foreground", children: first.isLocal ? "BVO-order" : "FO-order" })) : (first.orderNumber && (_jsx("div", { className: "text-xs text-muted-foreground", children: first.orderNumber })))] }), _jsx(TableCell, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Package, { className: "h-4 w-4 text-primary" }), _jsxs("div", { children: [_jsx("div", { className: "font-medium text-foreground", children: ordered.date }), _jsx("div", { className: "text-xs text-muted-foreground", children: ordered.time })] })] }) }), _jsx(TableCell, { children: _jsx("div", { className: "font-medium text-foreground", children: karren }) }), _jsx(TableCell, { children: _jsx("div", { className: "font-medium text-foreground", children: fusten }) }), _jsxs(TableCell, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-medium text-foreground", children: first.customer.name }), isBuffer && (_jsxs(Badge, { variant: "outline", className: "border-primary/30 text-primary", children: ["Buffer \u00B7 ", group.length] })), !isBuffer && first.isLocal && (_jsx(Badge, { variant: "outline", className: "border-primary/30 text-primary", children: "Lokaal" })), !isBuffer && first.isReservation && (_jsx(Badge, { variant: "outline", className: "border-amber-400/40 text-amber-600", children: "Reservering" }))] }), _jsx("div", { className: "text-xs text-muted-foreground", children: [first.customer.postalCode, first.customer.city].filter(Boolean).join(" ") })] }), _jsx(TableCell, { className: "text-sm text-foreground", children: formatDateLong(deliveryAt || first.deliveryAt) }), _jsx(TableCell, { children: _jsx(StatusTag, { status: first.status, rawOrder: first.raw?.order }) }), _jsx(TableCell, { onClick: (e) => e.stopPropagation(), children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: _jsx(MoreVertical, { className: "h-4 w-4" }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsx(DropdownMenuItem, { disabled: isBuffer || !first.isLocal, onClick: () => !isBuffer && first.isLocal && onEditOrder?.(first), title: isBuffer ? "Buffer-orders kunnen niet gebundeld bewerkt worden." : first.isLocal ? undefined : "FO-orders kunnen niet bewerkt worden.", children: "Bewerken" }), _jsx(DropdownMenuItem, { onClick: () => onSelectOrder?.(first), children: "Details bekijken" }), _jsx(DropdownMenuItem, { onClick: () => onConfirmOrder?.(first), children: "Bevestigen" }), !isBuffer && first.isLocal ? (_jsx(DropdownMenuItem, { className: "text-destructive focus:text-destructive", onClick: () => onDeleteOrder?.(first), children: "Verwijderen" })) : (_jsxs(DropdownMenuItem, { disabled: true, title: isBuffer ? "Buffer-orders kunnen niet gebundeld verwijderd worden." : "FO-orders kunnen niet verwijderd worden.", children: ["Verwijderen", isBuffer ? "" : " (FO)"] }))] })] }) })] }, rowId));
94
+ }
95
+ return nodes;
96
+ })()] })] }) }));
62
97
  }
@@ -1 +1 @@
1
- {"version":3,"file":"VerkoopOrdersPage.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/VerkoopOrdersPage.tsx"],"names":[],"mappings":"AAkEA,wBAAgB,iBAAiB,4CAyahC"}
1
+ {"version":3,"file":"VerkoopOrdersPage.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/VerkoopOrdersPage.tsx"],"names":[],"mappings":"AAkFA,wBAAgB,iBAAiB,4CAyahC"}
@@ -36,6 +36,22 @@ function matchesStatus(o, tab) {
36
36
  return !o.status.isCancelled && !o.status.isShipped;
37
37
  return true;
38
38
  }
39
+ /**
40
+ * Groepeer orders die tot dezelfde buffer horen tot één "logische" order.
41
+ * Wordt gebruikt voor tellingen en totalen zodat een buffer als 1 order geldt.
42
+ */
43
+ function collapseBuffers(orders) {
44
+ const seen = new Set();
45
+ const out = [];
46
+ for (const o of orders) {
47
+ const key = o.bufferId && (o.bufferSize ?? 1) > 1 ? `buf:${o.bufferId}` : `one:${o.id}`;
48
+ if (seen.has(key))
49
+ continue;
50
+ seen.add(key);
51
+ out.push(o);
52
+ }
53
+ return out;
54
+ }
39
55
  export function VerkoopOrdersPage() {
40
56
  const [tab, setTab] = useState("all");
41
57
  const [filterPanelOpen, setFilterPanelOpen] = useState(false);
@@ -83,7 +99,7 @@ export function VerkoopOrdersPage() {
83
99
  setDeleting(false);
84
100
  }
85
101
  };
86
- const { data, isLoading, error, refetch, isFetching } = useSalesOrdersQuery();
102
+ const { data, isLoading, error, refetch, isFetching } = useSalesOrdersQuery(filters);
87
103
  const orders = data?.orders ?? [];
88
104
  const activeEnvironment = data?.environment ?? "staging";
89
105
  // Automatisch omschakelen wanneer de Authenticatie-module de omgeving wijzigt.
@@ -121,9 +137,9 @@ export function VerkoopOrdersPage() {
121
137
  }, [queryClient]);
122
138
  const statusFiltered = useMemo(() => orders.filter((o) => matchesStatus(o, tab)), [orders, tab]);
123
139
  const filtered = useMemo(() => applyFilters(statusFiltered, filters), [statusFiltered, filters]);
124
- const totals = useMemo(() => computeTotals(filtered), [filtered]);
140
+ const totals = useMemo(() => computeTotals(collapseBuffers(filtered)), [filtered]);
125
141
  const statusCounts = useMemo(() => {
126
- const base = applyFilters(orders, filters);
142
+ const base = collapseBuffers(applyFilters(orders, filters));
127
143
  const counts = {
128
144
  all: base.length,
129
145
  open: 0,
@@ -4,4 +4,5 @@ export { VerkoopOrdersPage } from "./components/verkoop/VerkoopOrdersPage";
4
4
  export { SalesOrderDetailPage } from "./components/verkoop/SalesOrderDetailPage";
5
5
  export { CreateOrderPage } from "./components/verkoop/CreateOrderPage";
6
6
  export declare const floridayVerkoopModule: FlowModule;
7
+ export declare const karindelingModule: FlowModule;
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAEvE,eAAO,MAAM,qBAAqB,EAAE,UAiBnC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAEvE,eAAO,MAAM,qBAAqB,EAAE,UAiBnC,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,UAU/B,CAAC"}
package/dist-lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ShoppingCart, ListOrdered } from "lucide-react";
1
+ import { ShoppingCart, ListOrdered, LayoutGrid } from "lucide-react";
2
2
  export * from "./_core-safelist";
3
3
  export { VerkoopOrdersPage } from "./components/verkoop/VerkoopOrdersPage";
4
4
  export { SalesOrderDetailPage } from "./components/verkoop/SalesOrderDetailPage";
@@ -21,3 +21,14 @@ export const floridayVerkoopModule = {
21
21
  },
22
22
  settingsCards: [],
23
23
  };
24
+ export const karindelingModule = {
25
+ id: "karindeling",
26
+ name: "Karindeling",
27
+ version: "1.0.0",
28
+ nav: {
29
+ label: "Karindeling",
30
+ href: "/karindeling",
31
+ icon: LayoutGrid,
32
+ },
33
+ settingsCards: [],
34
+ };