@flowselections/floriday-verkoop-module 1.0.2

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 (50) hide show
  1. package/dist-lib/_core-safelist.d.ts +2 -0
  2. package/dist-lib/_core-safelist.d.ts.map +1 -0
  3. package/dist-lib/_core-safelist.js +15 -0
  4. package/dist-lib/components/ui/dropdown-menu.d.ts +9 -0
  5. package/dist-lib/components/ui/dropdown-menu.d.ts.map +1 -0
  6. package/dist-lib/components/ui/dropdown-menu.js +14 -0
  7. package/dist-lib/components/verkoop/AnalyticsCards.d.ts +9 -0
  8. package/dist-lib/components/verkoop/AnalyticsCards.d.ts.map +1 -0
  9. package/dist-lib/components/verkoop/AnalyticsCards.js +18 -0
  10. package/dist-lib/components/verkoop/CreateOrderDialog.d.ts +5 -0
  11. package/dist-lib/components/verkoop/CreateOrderDialog.d.ts.map +1 -0
  12. package/dist-lib/components/verkoop/CreateOrderDialog.js +33 -0
  13. package/dist-lib/components/verkoop/SalesOrdersFilters.d.ts +16 -0
  14. package/dist-lib/components/verkoop/SalesOrdersFilters.d.ts.map +1 -0
  15. package/dist-lib/components/verkoop/SalesOrdersFilters.js +40 -0
  16. package/dist-lib/components/verkoop/SalesOrdersTable.d.ts +6 -0
  17. package/dist-lib/components/verkoop/SalesOrdersTable.d.ts.map +1 -0
  18. package/dist-lib/components/verkoop/SalesOrdersTable.js +83 -0
  19. package/dist-lib/index.d.ts +4 -0
  20. package/dist-lib/index.d.ts.map +1 -0
  21. package/dist-lib/index.js +20 -0
  22. package/dist-lib/integrations/supabase/auth-attacher.d.ts +2 -0
  23. package/dist-lib/integrations/supabase/auth-attacher.d.ts.map +1 -0
  24. package/dist-lib/integrations/supabase/auth-attacher.js +12 -0
  25. package/dist-lib/integrations/supabase/auth-middleware.d.ts +1029 -0
  26. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -0
  27. package/dist-lib/integrations/supabase/auth-middleware.js +44 -0
  28. package/dist-lib/integrations/supabase/client.d.ts +1025 -0
  29. package/dist-lib/integrations/supabase/client.d.ts.map +1 -0
  30. package/dist-lib/integrations/supabase/client.js +14 -0
  31. package/dist-lib/integrations/supabase/client.server.d.ts +1025 -0
  32. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -0
  33. package/dist-lib/integrations/supabase/client.server.js +30 -0
  34. package/dist-lib/integrations/supabase/types.d.ts +1112 -0
  35. package/dist-lib/integrations/supabase/types.d.ts.map +1 -0
  36. package/dist-lib/integrations/supabase/types.js +7 -0
  37. package/dist-lib/lib/floriday/floriday.server.d.ts +14 -0
  38. package/dist-lib/lib/floriday/floriday.server.d.ts.map +1 -0
  39. package/dist-lib/lib/floriday/floriday.server.js +92 -0
  40. package/dist-lib/lib/floriday/sales-orders.functions.d.ts +3143 -0
  41. package/dist-lib/lib/floriday/sales-orders.functions.d.ts.map +1 -0
  42. package/dist-lib/lib/floriday/sales-orders.functions.js +193 -0
  43. package/dist-lib/lib/utils.d.ts +3 -0
  44. package/dist-lib/lib/utils.d.ts.map +1 -0
  45. package/dist-lib/lib/utils.js +5 -0
  46. package/dist-lib/lib/validationSchemas.d.ts +15 -0
  47. package/dist-lib/lib/validationSchemas.d.ts.map +1 -0
  48. package/dist-lib/lib/validationSchemas.js +25 -0
  49. package/dist-lib/styles.css +1 -0
  50. package/package.json +76 -0
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=_core-safelist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_core-safelist.d.ts","sourceRoot":"","sources":["../src/_core-safelist.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,CAAC"}
@@ -0,0 +1,15 @@
1
+ // Forceert Tailwind classes die uit @flowselections/core komen maar niet
2
+ // voorkomen in de eigen broncode van deze module.
3
+ // Zonder dit bestand worden deze classes weggeoptimaliseerd op de
4
+ // Lovable productie build.
5
+ const _safelist = [
6
+ // Layout — Sidebar en shell structuur
7
+ 'h-full', 'flex-col', 'flex-1', 'min-h-screen', 'ml-64', 'pt-16',
8
+ 'items-start', 'items-center', 'justify-between', 'border-t',
9
+ 'w-64', 'h-screen', 'h-20', 'overflow-y-auto',
10
+ // Grid — InstellingenPage
11
+ 'grid', 'lg:grid-cols-2', 'gap-6', 'p-6', 'space-y-6',
12
+ // Toggle/Switch — aan/uit zichtbaarheid
13
+ 'data-[state=checked]:bg-primary', 'data-[state=unchecked]:bg-input',
14
+ ];
15
+ export {};
@@ -0,0 +1,9 @@
1
+ import * as React from "react";
2
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
3
+ declare const DropdownMenu: React.FC<DropdownMenuPrimitive.DropdownMenuProps>;
4
+ declare const DropdownMenuTrigger: React.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuTriggerProps & React.RefAttributes<HTMLButtonElement>>;
5
+ declare const DropdownMenuContent: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
6
+ declare const DropdownMenuItem: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
7
+ declare const DropdownMenuSeparator: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuSeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
8
+ export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, };
9
+ //# sourceMappingURL=dropdown-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../../src/components/ui/dropdown-menu.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,qBAAqB,MAAM,+BAA+B,CAAC;AAGvE,QAAA,MAAM,YAAY,mDAA6B,CAAC;AAChD,QAAA,MAAM,mBAAmB,0HAAgC,CAAC;AAE1D,QAAA,MAAM,mBAAmB,0KAgBvB,CAAC;AAGH,QAAA,MAAM,gBAAgB,uKAapB,CAAC;AAGH,QAAA,MAAM,qBAAqB,4KASzB,CAAC;AAGH,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,CAAC"}
@@ -0,0 +1,14 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
5
+ import { cn } from "@flowselections/core";
6
+ const DropdownMenu = DropdownMenuPrimitive.Root;
7
+ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
8
+ const DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => (_jsx(DropdownMenuPrimitive.Portal, { children: _jsx(DropdownMenuPrimitive.Content, { ref: ref, sideOffset: sideOffset, className: cn("z-50 min-w-[10rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md", "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", className), ...props }) })));
9
+ DropdownMenuContent.displayName = "DropdownMenuContent";
10
+ const DropdownMenuItem = React.forwardRef(({ className, ...props }, ref) => (_jsx(DropdownMenuPrimitive.Item, { ref: ref, className: cn("relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors", "focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className), ...props })));
11
+ DropdownMenuItem.displayName = "DropdownMenuItem";
12
+ const DropdownMenuSeparator = React.forwardRef(({ className, ...props }, ref) => (_jsx(DropdownMenuPrimitive.Separator, { ref: ref, className: cn("-mx-1 my-1 h-px bg-muted", className), ...props })));
13
+ DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
14
+ export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, };
@@ -0,0 +1,9 @@
1
+ export declare function AnalyticsCards({ totals, loading, }: {
2
+ totals?: {
3
+ revenue: number;
4
+ avgPrice: number;
5
+ fustCount: number;
6
+ };
7
+ loading?: boolean;
8
+ }): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=AnalyticsCards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalyticsCards.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/AnalyticsCards.tsx"],"names":[],"mappings":"AAWA,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,OAAO,GACR,EAAE;IACD,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,2CAwBA"}
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Card, CardContent, Skeleton } from "@flowselections/core";
3
+ const eur = new Intl.NumberFormat("nl-NL", { style: "currency", currency: "EUR" });
4
+ const eurPrecise = new Intl.NumberFormat("nl-NL", {
5
+ style: "currency",
6
+ currency: "EUR",
7
+ minimumFractionDigits: 3,
8
+ maximumFractionDigits: 3,
9
+ });
10
+ const num = new Intl.NumberFormat("nl-NL");
11
+ export function AnalyticsCards({ totals, loading, }) {
12
+ const items = [
13
+ { label: "Omzet", value: totals ? eur.format(totals.revenue) : null },
14
+ { label: "Gemiddelde prijs", value: totals ? eurPrecise.format(totals.avgPrice) : null },
15
+ { label: "Aantal fusten", value: totals ? num.format(totals.fustCount) : null },
16
+ ];
17
+ return (_jsx("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-3", children: items.map((it) => (_jsx(Card, { className: "border-border/60 shadow-none", children: _jsxs(CardContent, { className: "px-6 py-5", children: [_jsx("div", { className: "text-sm font-medium text-muted-foreground", children: it.label }), loading || !it.value ? (_jsx(Skeleton, { className: "mt-3 h-10 w-40" })) : (_jsx("div", { className: "mt-2 text-4xl font-bold tracking-tight text-primary", children: it.value }))] }) }, it.label))) }));
18
+ }
@@ -0,0 +1,5 @@
1
+ export declare function CreateOrderDialog({ open, onOpenChange, }: {
2
+ open: boolean;
3
+ onOpenChange: (v: boolean) => void;
4
+ }): import("react/jsx-runtime").JSX.Element;
5
+ //# sourceMappingURL=CreateOrderDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreateOrderDialog.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/CreateOrderDialog.tsx"],"names":[],"mappings":"AAiBA,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,YAAY,GACb,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC,2CAgFA"}
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Input, Label, toast, } from "@flowselections/core";
4
+ import { useServerFn } from "@tanstack/react-start";
5
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
6
+ import { createSalesOrder } from "@/lib/floriday/sales-orders.functions";
7
+ export function CreateOrderDialog({ open, onOpenChange, }) {
8
+ const queryClient = useQueryClient();
9
+ const createFn = useServerFn(createSalesOrder);
10
+ const [customerOrganizationId, setCustomerId] = useState("");
11
+ const [tradeItemId, setTradeItemId] = useState("");
12
+ const [deliveryDateTime, setDelivery] = useState("");
13
+ const [numberOfPieces, setPieces] = useState(1);
14
+ const [pricePerPiece, setPrice] = useState(0);
15
+ const [reference, setReference] = useState("");
16
+ const m = useMutation({
17
+ mutationFn: createFn,
18
+ onSuccess: () => {
19
+ toast.success("Verkooporder aangemaakt");
20
+ queryClient.invalidateQueries({ queryKey: ["floriday", "sales-orders"] });
21
+ onOpenChange(false);
22
+ },
23
+ onError: (e) => toast.error(e?.message ?? "Aanmaken mislukt"),
24
+ });
25
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "max-w-lg", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Bestelling aanmaken" }), _jsx(DialogDescription, { children: "Maak een nieuwe verkooporder aan in Floriday." })] }), _jsxs("div", { className: "grid gap-3 py-2", children: [_jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { htmlFor: "ref", children: "Referentie" }), _jsx(Input, { id: "ref", value: reference, onChange: (e) => setReference(e.target.value), placeholder: "ORD-2026-\u2026" })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { htmlFor: "cust", children: "Klant organisatie ID" }), _jsx(Input, { id: "cust", value: customerOrganizationId, onChange: (e) => setCustomerId(e.target.value), placeholder: "GLN of organization id" })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { htmlFor: "item", children: "Artikel (tradeItemId)" }), _jsx(Input, { id: "item", value: tradeItemId, onChange: (e) => setTradeItemId(e.target.value) })] }), _jsxs("div", { className: "grid grid-cols-3 gap-3", children: [_jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { htmlFor: "qty", children: "Aantal stuks" }), _jsx(Input, { id: "qty", type: "number", min: 1, value: numberOfPieces, onChange: (e) => setPieces(Number(e.target.value)) })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { htmlFor: "price", children: "Prijs/stuk (\u20AC)" }), _jsx(Input, { id: "price", type: "number", step: "0.01", min: 0, value: pricePerPiece, onChange: (e) => setPrice(Number(e.target.value)) })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { htmlFor: "del", children: "Levering" }), _jsx(Input, { id: "del", type: "datetime-local", value: deliveryDateTime, onChange: (e) => setDelivery(e.target.value) })] })] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: m.isPending, children: "Annuleren" }), _jsx(Button, { onClick: () => m.mutate({
26
+ data: {
27
+ customerOrganizationId,
28
+ deliveryDateTime: deliveryDateTime ? new Date(deliveryDateTime).toISOString() : "",
29
+ reference: reference || undefined,
30
+ lines: [{ tradeItemId, numberOfPieces, pricePerPiece }],
31
+ },
32
+ }), disabled: m.isPending || !customerOrganizationId || !tradeItemId || !deliveryDateTime, children: m.isPending ? "Aanmaken…" : "Aanmaken" })] })] }) }));
33
+ }
@@ -0,0 +1,16 @@
1
+ export interface Filters {
2
+ search?: string;
3
+ status?: string;
4
+ from?: string;
5
+ to?: string;
6
+ handelsvorm?: string;
7
+ klant?: string;
8
+ voorraadlocatie?: string;
9
+ week?: number;
10
+ year?: number;
11
+ }
12
+ export declare function SalesOrdersFilters({ value, onChange, }: {
13
+ value: Filters;
14
+ onChange: (next: Filters) => void;
15
+ }): import("react/jsx-runtime").JSX.Element;
16
+ //# sourceMappingURL=SalesOrdersFilters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SalesOrdersFilters.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/SalesOrdersFilters.tsx"],"names":[],"mappings":"AAoBA,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,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAcD,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,2CAkLA"}
@@ -0,0 +1,40 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Button, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@flowselections/core";
4
+ import { ChevronLeft, ChevronRight, MoreVertical, ShoppingCart, Truck, Filter, Search, } from "lucide-react";
5
+ function getCurrentWeek() {
6
+ const now = new Date();
7
+ const target = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()));
8
+ const dayNr = (target.getUTCDay() + 6) % 7;
9
+ target.setUTCDate(target.getUTCDate() - dayNr + 3);
10
+ const firstThursday = new Date(Date.UTC(target.getUTCFullYear(), 0, 4));
11
+ const week = 1 +
12
+ Math.round(((target.getTime() - firstThursday.getTime()) / 86400000 - 3 + ((firstThursday.getUTCDay() + 6) % 7)) / 7);
13
+ return { week, year: target.getUTCFullYear() };
14
+ }
15
+ export function SalesOrdersFilters({ value, onChange, }) {
16
+ const current = getCurrentWeek();
17
+ const week = value.week ?? current.week;
18
+ const year = value.year ?? current.year;
19
+ const [search, setSearch] = useState(value.search ?? "");
20
+ const shiftWeek = (delta) => {
21
+ let w = week + delta;
22
+ let y = year;
23
+ if (w < 1) {
24
+ w = 52;
25
+ y -= 1;
26
+ }
27
+ else if (w > 53) {
28
+ w = 1;
29
+ y += 1;
30
+ }
31
+ onChange({ ...value, week: w, year: y });
32
+ };
33
+ 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: [_jsx("button", { type: "button", onClick: () => shiftWeek(-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 week", children: _jsx(ChevronLeft, { className: "h-4 w-4" }) }), _jsx("button", { type: "button", onClick: () => shiftWeek(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 week", children: _jsx(ChevronRight, { className: "h-4 w-4" }) }), _jsxs("div", { className: "px-2 text-sm font-medium text-foreground whitespace-nowrap", children: ["Week ", week, " - ", year] }), _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": "Meer", children: _jsx(MoreVertical, { className: "h-4 w-4" }) })] }), _jsxs("div", { className: "flex h-9 items-center rounded-md border border-border bg-card", children: [_jsx("button", { type: "button", className: "inline-flex h-9 w-9 items-center justify-center rounded-l-md border-r border-border bg-accent text-foreground", "aria-label": "Bestellingen", children: _jsx(ShoppingCart, { className: "h-4 w-4" }) }), _jsx("button", { type: "button", className: "inline-flex h-9 w-9 items-center justify-center border-r border-border text-muted-foreground hover:bg-accent hover:text-foreground", "aria-label": "Leveringen", children: _jsx(Truck, { className: "h-4 w-4" }) }), _jsx("button", { type: "button", className: "inline-flex h-9 w-9 items-center justify-center rounded-r-md text-muted-foreground hover:bg-accent hover:text-foreground", "aria-label": "Filter", children: _jsx(Filter, { className: "h-4 w-4" }) })] }), _jsxs(Select, { value: value.handelsvorm ?? "all", onValueChange: (v) => onChange({ ...value, handelsvorm: v === "all" ? undefined : v }), children: [_jsx(SelectTrigger, { className: "h-9 w-40", children: _jsx(SelectValue, { placeholder: "- Handelsvorm -" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "- Handelsvorm -" }), _jsx(SelectItem, { value: "klok", children: "Klok" }), _jsx(SelectItem, { value: "direct", children: "Direct" })] })] }), _jsxs(Select, { value: value.klant ?? "all", onValueChange: (v) => onChange({ ...value, klant: v === "all" ? undefined : v }), children: [_jsx(SelectTrigger, { className: "h-9 w-44", children: _jsx(SelectValue, { placeholder: "- Alle klanten -" }) }), _jsx(SelectContent, { children: _jsx(SelectItem, { value: "all", children: "- Alle klanten -" }) })] }), _jsxs(Select, { value: value.voorraadlocatie ?? "all", onValueChange: (v) => onChange({ ...value, voorraadlocatie: v === "all" ? undefined : v }), children: [_jsx(SelectTrigger, { className: "h-9 w-52", children: _jsx(SelectValue, { placeholder: "- Alle voorraadlocaties -" }) }), _jsx(SelectContent, { children: _jsx(SelectItem, { value: "all", children: "- Alle voorraadlocaties -" }) })] }), _jsxs(Select, { value: value.status ?? "all", onValueChange: (v) => onChange({ ...value, status: v === "all" ? undefined : v }), children: [_jsx(SelectTrigger, { className: "h-9 w-36", children: _jsx(SelectValue, { placeholder: "Status" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "Alle statussen" }), _jsx(SelectItem, { value: "open", children: "Open" }), _jsx(SelectItem, { value: "shipped", children: "Verzonden" }), _jsx(SelectItem, { value: "invoiced", children: "Gefactureerd" }), _jsx(SelectItem, { value: "cancelled", children: "Geannuleerd" })] })] }), _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) => {
34
+ if (e.key === "Enter")
35
+ onChange({ ...value, search });
36
+ }, 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" }) })] }), (value.search || value.status || value.handelsvorm || value.klant || value.voorraadlocatie) && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => {
37
+ setSearch("");
38
+ onChange({ week, year });
39
+ }, children: "Wissen" }))] }));
40
+ }
@@ -0,0 +1,6 @@
1
+ import type { SalesOrderDTO } from "@/lib/floriday/sales-orders.functions";
2
+ export declare function SalesOrdersTable({ orders, loading, }: {
3
+ orders: SalesOrderDTO[];
4
+ loading?: boolean;
5
+ }): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=SalesOrdersTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SalesOrdersTable.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/SalesOrdersTable.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AA6E3E,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,OAAO,GACR,EAAE;IACD,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,2CAkJA"}
@@ -0,0 +1,83 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Badge, Checkbox, Skeleton, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@flowselections/core";
4
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@flowselections/core";
5
+ import { MoreVertical, Package, CheckCircle2, XCircle, Truck, FileText, ImageIcon, ArrowDown, } from "lucide-react";
6
+ const eur = new Intl.NumberFormat("nl-NL", { style: "currency", currency: "EUR" });
7
+ function formatDateShort(iso) {
8
+ if (!iso)
9
+ return { date: "—", time: "" };
10
+ const d = new Date(iso);
11
+ if (Number.isNaN(d.getTime()))
12
+ return { date: iso.slice(0, 10), time: "" };
13
+ const date = d
14
+ .toLocaleDateString("nl-NL", { day: "numeric", month: "short" })
15
+ .replace(".", "");
16
+ const time = d.toLocaleTimeString("nl-NL", { hour: "2-digit", minute: "2-digit" });
17
+ return { date, time };
18
+ }
19
+ function formatDateLong(iso) {
20
+ if (!iso)
21
+ return "—";
22
+ const d = new Date(iso);
23
+ if (Number.isNaN(d.getTime()))
24
+ return iso;
25
+ return d.toLocaleString("nl-NL", {
26
+ day: "numeric",
27
+ month: "short",
28
+ year: "numeric",
29
+ hour: "2-digit",
30
+ minute: "2-digit",
31
+ });
32
+ }
33
+ function StatusBadges({ status }) {
34
+ const items = [
35
+ {
36
+ key: "cancelled",
37
+ active: status.isCancelled,
38
+ icon: XCircle,
39
+ label: "Geannuleerd",
40
+ classes: "bg-destructive/10 text-destructive",
41
+ },
42
+ {
43
+ key: "shipped",
44
+ active: status.isShipped,
45
+ icon: Truck,
46
+ label: "Verzonden",
47
+ classes: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
48
+ },
49
+ {
50
+ key: "confirmed",
51
+ active: status.isConfirmed,
52
+ icon: CheckCircle2,
53
+ label: "Bevestigd",
54
+ classes: "bg-primary/10 text-primary",
55
+ },
56
+ {
57
+ key: "invoiced",
58
+ active: status.isInvoiced,
59
+ icon: FileText,
60
+ label: "Gefactureerd",
61
+ classes: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
62
+ },
63
+ ];
64
+ return (_jsx("div", { className: "flex items-center gap-1", children: items.map((it) => (_jsx("span", { title: it.label, className: "inline-flex h-7 w-7 items-center justify-center rounded-md " +
65
+ (it.active ? it.classes : "bg-muted text-muted-foreground/40"), children: _jsx(it.icon, { className: "h-4 w-4" }) }, it.key))) }));
66
+ }
67
+ export function SalesOrdersTable({ orders, loading, }) {
68
+ const [selected, setSelected] = useState(new Set());
69
+ const allChecked = orders.length > 0 && selected.size === orders.length;
70
+ const toggle = (id) => setSelected((s) => {
71
+ const n = new Set(s);
72
+ n.has(id) ? n.delete(id) : n.add(id);
73
+ return n;
74
+ });
75
+ 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: "Order" }), _jsx(TableHead, { children: _jsxs("span", { className: "inline-flex items-center gap-1", children: ["Bestelmoment ", _jsx(ArrowDown, { className: "h-3 w-3" })] }) }), _jsx(TableHead, { children: "Aantal" }), _jsx(TableHead, { children: "Klant" }), _jsx(TableHead, { children: "Levering" }), _jsx(TableHead, { children: "Status" }), _jsx(TableHead, { className: "w-10" })] }) }), _jsxs(TableBody, { children: [loading &&
76
+ Array.from({ length: 6 }).map((_, i) => (_jsx(TableRow, { children: Array.from({ length: 8 }).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: 8, className: "py-12 text-center text-muted-foreground", children: "Geen verkooporders gevonden." }) })), !loading &&
77
+ orders.map((o) => {
78
+ const ordered = formatDateShort(o.orderedAt);
79
+ return (_jsxs(TableRow, { className: "align-top", children: [_jsx(TableCell, { children: _jsx(Checkbox, { checked: selected.has(o.id), onCheckedChange: () => toggle(o.id) }) }), _jsx(TableCell, { children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center overflow-hidden rounded-md bg-muted", children: o.imageUrl ? (
80
+ // eslint-disable-next-line @next/next/no-img-element
81
+ _jsx("img", { src: o.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", children: [_jsx("div", { className: "truncate font-medium text-foreground", children: o.productName }), _jsx("div", { className: "truncate text-xs text-muted-foreground", children: o.sku || 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 })] })] }) }), _jsxs(TableCell, { children: [_jsxs("div", { className: "font-medium text-foreground", children: [o.quantity.multiplier, " \u00D7 ", o.quantity.count, " \u00D7 ", eur.format(o.quantity.unitPrice)] }), _jsx("div", { className: "text-xs text-muted-foreground", children: eur.format(o.revenue) })] }), _jsxs(TableCell, { children: [_jsx("div", { className: "font-medium text-foreground", children: o.customer.name }), _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: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(StatusBadges, { status: o.status }), o.orderNumber && (_jsx(Badge, { variant: "outline", className: "font-mono text-xs", children: o.orderNumber }))] }) }), _jsx(TableCell, { 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, { children: "Bewerken" }), _jsx(DropdownMenuItem, { children: "Details bekijken" }), _jsx(DropdownMenuItem, { children: "Bevestigen" }), _jsx(DropdownMenuItem, { className: "text-destructive focus:text-destructive", children: "Annuleren" })] })] }) })] }, o.id));
82
+ })] })] }) }));
83
+ }
@@ -0,0 +1,4 @@
1
+ import type { FlowModule } from "@flowselections/core";
2
+ export * from "./_core-safelist";
3
+ export declare const myModule: FlowModule;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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;AAEjC,eAAO,MAAM,QAAQ,EAAE,UAiBtB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { ShoppingCart, ListOrdered } from "lucide-react";
2
+ export * from "./_core-safelist";
3
+ export const myModule = {
4
+ id: "verkoop",
5
+ name: "Verkoop",
6
+ version: "1.0.0",
7
+ nav: {
8
+ label: "Verkoop",
9
+ href: "/verkoop/verkooporders",
10
+ icon: ShoppingCart,
11
+ children: [
12
+ {
13
+ label: "Verkooporders",
14
+ href: "/verkoop/verkooporders",
15
+ icon: ListOrdered,
16
+ },
17
+ ],
18
+ },
19
+ settingsCards: [],
20
+ };
@@ -0,0 +1,2 @@
1
+ export declare const attachSupabaseAuth: import("@tanstack/start-client-core").FunctionMiddlewareAfterClient<{}, unknown, undefined, undefined, undefined>;
2
+ //# sourceMappingURL=auth-attacher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-attacher.d.ts","sourceRoot":"","sources":["../../../src/integrations/supabase/auth-attacher.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,kBAAkB,mHAQ9B,CAAA"}
@@ -0,0 +1,12 @@
1
+ // This file is automatically generated. Do not edit it directly.
2
+ import { createMiddleware } from '@tanstack/react-start';
3
+ import { supabase } from './client';
4
+ // Must be registered as a global `functionMiddleware` in `src/start.ts`; otherwise
5
+ // the browser never attaches the bearer token to serverFn RPCs.
6
+ export const attachSupabaseAuth = createMiddleware({ type: 'function' }).client(async ({ next }) => {
7
+ const { data } = await supabase.auth.getSession();
8
+ const token = data.session?.access_token;
9
+ return next({
10
+ headers: token ? { Authorization: `Bearer ${token}` } : {},
11
+ });
12
+ });