@flowselections/floriday-klanten-module 1.0.50 → 1.0.53

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 (131) hide show
  1. package/dist-lib/components/CustomerAvatar.js +1 -1
  2. package/dist-lib/components/klanten/BewerkKlant.js +1 -1
  3. package/dist-lib/components/klanten/BewerkKlantRoute.js +1 -1
  4. package/dist-lib/components/klanten/BulkStickerUploadDialog.js +1 -1
  5. package/dist-lib/components/klanten/CustomerAnalyticsTab.js +2 -2
  6. package/dist-lib/components/klanten/CustomerAssortmentTab.js +4 -4
  7. package/dist-lib/components/klanten/DeliveryLocationsTab.d.ts.map +1 -1
  8. package/dist-lib/components/klanten/DeliveryLocationsTab.js +18 -7
  9. package/dist-lib/components/klanten/DiscountsTab.js +2 -2
  10. package/dist-lib/components/klanten/ExternalCacheBanner.d.ts +1 -1
  11. package/dist-lib/components/klanten/FloridayNetworkStatus.js +3 -3
  12. package/dist-lib/components/klanten/GroupedKlantDetailRoute.js +1 -1
  13. package/dist-lib/components/klanten/ImportKlanten.js +1 -1
  14. package/dist-lib/components/klanten/KlantBewerkenDialog.js +2 -2
  15. package/dist-lib/components/klanten/KlantDetailLayout.d.ts +1 -1
  16. package/dist-lib/components/klanten/KlantDetailLayout.js +5 -5
  17. package/dist-lib/components/klanten/KlantDetailRoute.js +1 -1
  18. package/dist-lib/components/klanten/KlantenOverzicht.js +16 -16
  19. package/dist-lib/components/klanten/LocalDiscountFormDialog.js +1 -1
  20. package/dist-lib/components/klanten/LocalDiscountsTab.js +2 -2
  21. package/dist-lib/components/klanten/NetwerkPagina.js +3 -3
  22. package/dist-lib/components/klanten/NieuweKlant.js +1 -1
  23. package/dist-lib/components/klanten/OvernemenTwinfieldKlant.js +1 -1
  24. package/dist-lib/components/klanten/OvernemenTwinfieldKlantRoute.js +1 -1
  25. package/dist-lib/components/klanten/RouteError.js +1 -1
  26. package/dist-lib/components/klanten/pricegroups/CustomerPickerDialog.js +6 -6
  27. package/dist-lib/components/klanten/pricegroups/CustomerPriceGroupSelect.js +3 -3
  28. package/dist-lib/components/klanten/pricegroups/PriceGroupEditRoute.js +1 -1
  29. package/dist-lib/components/klanten/pricegroups/PriceGroupFormPage.js +11 -11
  30. package/dist-lib/components/klanten/pricegroups/PriceGroupNewRoute.js +1 -1
  31. package/dist-lib/components/klanten/pricegroups/PriceGroupsPage.js +4 -4
  32. package/dist-lib/components/klanten/pricegroups/PriceGroupsRoute.js +1 -1
  33. package/dist-lib/components/klanten/pricegroups/ProductPickerDialog.d.ts +1 -1
  34. package/dist-lib/components/klanten/pricegroups/UnknownFloridayMembers.d.ts +1 -1
  35. package/dist-lib/components/klanten/pricegroups/UnknownFloridayMembers.js +2 -2
  36. package/dist-lib/components/klanten/useCustomerDefaults.d.ts +1 -1
  37. package/dist-lib/index.d.ts +34 -34
  38. package/dist-lib/index.js +35 -35
  39. package/dist-lib/integrations/supabase/auth-attacher.js +1 -1
  40. package/dist-lib/integrations/supabase/auth-middleware.d.ts +1 -1
  41. package/dist-lib/integrations/supabase/client.d.ts +1 -1
  42. package/dist-lib/integrations/supabase/client.server.d.ts +1 -1
  43. package/dist-lib/integrations/supabase/types.d.ts +903 -0
  44. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  45. package/dist-lib/lib/accounting/exact/client.server.d.ts +1 -1
  46. package/dist-lib/lib/accounting/exact/client.server.js +2 -2
  47. package/dist-lib/lib/accounting/exact/sync.server.d.ts +1 -1
  48. package/dist-lib/lib/accounting/exact/sync.server.js +3 -3
  49. package/dist-lib/lib/accounting/floriday/sync.server.d.ts +1 -1
  50. package/dist-lib/lib/accounting/floriday/sync.server.js +1 -1
  51. package/dist-lib/lib/accounting/registry.server.d.ts +1 -1
  52. package/dist-lib/lib/accounting/registry.server.js +2 -2
  53. package/dist-lib/lib/accounting/twinfield/client.server.js +2 -2
  54. package/dist-lib/lib/accounting/twinfield/field-coverage.test.js +6 -6
  55. package/dist-lib/lib/accounting/twinfield/mapping.js +3 -3
  56. package/dist-lib/lib/accounting/twinfield/rmw-push.server.d.ts +2 -2
  57. package/dist-lib/lib/accounting/twinfield/rmw-push.server.js +4 -4
  58. package/dist-lib/lib/accounting/twinfield/rmw.server.d.ts +1 -1
  59. package/dist-lib/lib/accounting/twinfield/rmw.server.js +2 -2
  60. package/dist-lib/lib/accounting/twinfield/sandbox-rmw.server.d.ts +6 -6
  61. package/dist-lib/lib/accounting/twinfield/sandbox-rmw.server.js +12 -12
  62. package/dist-lib/lib/accounting/twinfield/sandbox.server.js +3 -3
  63. package/dist-lib/lib/accounting/twinfield/sync.server.js +4 -4
  64. package/dist-lib/lib/accounting/twinfield/worker.functions.d.ts +7 -7
  65. package/dist-lib/lib/accounting/twinfield/worker.functions.js +6 -6
  66. package/dist-lib/lib/accounting/twinfield/worker.server.js +8 -8
  67. package/dist-lib/lib/accounting.functions.d.ts +4 -4
  68. package/dist-lib/lib/accounting.functions.js +2 -2
  69. package/dist-lib/lib/countries.test.js +3 -3
  70. package/dist-lib/lib/customer-analytics.functions.d.ts +1 -1
  71. package/dist-lib/lib/customer-analytics.functions.js +1 -1
  72. package/dist-lib/lib/customer-assortment.functions.d.ts +1 -1
  73. package/dist-lib/lib/customer-assortment.functions.js +3 -3
  74. package/dist-lib/lib/customer-defaults.test.js +3 -3
  75. package/dist-lib/lib/customer-insert.d.ts +1 -1
  76. package/dist-lib/lib/customer-insert.js +2 -2
  77. package/dist-lib/lib/customer-notes.functions.d.ts +2 -2
  78. package/dist-lib/lib/customer-notes.functions.js +1 -1
  79. package/dist-lib/lib/customer-orders.functions.d.ts +1 -1
  80. package/dist-lib/lib/customer-orders.functions.js +1 -1
  81. package/dist-lib/lib/customer-revenue.functions.d.ts +1 -1
  82. package/dist-lib/lib/customer-revenue.functions.js +2 -2
  83. package/dist-lib/lib/customer-schemas.js +1 -1
  84. package/dist-lib/lib/customer-schemas.test.js +1 -1
  85. package/dist-lib/lib/customer-stickers.functions.d.ts +9 -9
  86. package/dist-lib/lib/customer-stickers.functions.js +2 -2
  87. package/dist-lib/lib/customers.functions.d.ts +29 -29
  88. package/dist-lib/lib/customers.functions.js +11 -11
  89. package/dist-lib/lib/delivery-locations.functions.d.ts +18 -30
  90. package/dist-lib/lib/delivery-locations.functions.d.ts.map +1 -1
  91. package/dist-lib/lib/delivery-locations.functions.js +24 -5
  92. package/dist-lib/lib/external-customers.functions.d.ts +4 -4
  93. package/dist-lib/lib/external-customers.functions.js +2 -2
  94. package/dist-lib/lib/floriday-app-url.functions.d.ts +1 -1
  95. package/dist-lib/lib/floriday-app-url.functions.js +2 -2
  96. package/dist-lib/lib/floriday-assortment.functions.d.ts +1 -1
  97. package/dist-lib/lib/floriday-assortment.functions.js +2 -2
  98. package/dist-lib/lib/floriday-discounts.functions.d.ts +2 -2
  99. package/dist-lib/lib/floriday-discounts.functions.js +2 -2
  100. package/dist-lib/lib/floriday-network-status.functions.d.ts +1 -1
  101. package/dist-lib/lib/floriday-network-status.functions.js +1 -1
  102. package/dist-lib/lib/floriday-price-import.functions.d.ts +2 -2
  103. package/dist-lib/lib/floriday-price-import.functions.js +2 -2
  104. package/dist-lib/lib/floriday-sticker-import.functions.d.ts +1 -1
  105. package/dist-lib/lib/floriday-sticker-import.functions.js +1 -1
  106. package/dist-lib/lib/floriday-trade-items.functions.d.ts +1 -1
  107. package/dist-lib/lib/floriday-trade-items.functions.js +1 -1
  108. package/dist-lib/lib/floriday-trade-settings.functions.d.ts +1 -1
  109. package/dist-lib/lib/floriday-trade-settings.functions.js +1 -1
  110. package/dist-lib/lib/local-discounts.functions.d.ts +7 -7
  111. package/dist-lib/lib/local-discounts.functions.js +1 -1
  112. package/dist-lib/lib/logistics-events.functions.d.ts +1 -1
  113. package/dist-lib/lib/logistics-events.functions.js +1 -1
  114. package/dist-lib/lib/logistics-strategy.functions.d.ts +4 -4
  115. package/dist-lib/lib/logistics-strategy.functions.js +1 -1
  116. package/dist-lib/lib/overdue-invoices.functions.d.ts +1 -1
  117. package/dist-lib/lib/overdue-invoices.functions.js +2 -2
  118. package/dist-lib/lib/price-groups-local.functions.d.ts +15 -15
  119. package/dist-lib/lib/price-groups-local.functions.js +1 -1
  120. package/dist-lib/lib/price-groups.functions.d.ts +1 -1
  121. package/dist-lib/lib/price-groups.functions.js +1 -1
  122. package/dist-lib/lib/twinfield-adopt.functions.d.ts +5 -5
  123. package/dist-lib/lib/twinfield-adopt.functions.js +7 -7
  124. package/dist-lib/lib/twinfield-customer-defaults.functions.d.ts +2 -2
  125. package/dist-lib/lib/twinfield-customer-defaults.functions.js +2 -2
  126. package/dist-lib/lib/twinfield-customer-defaults.server.js +1 -1
  127. package/dist-lib/lib/twinfield-ledger.functions.d.ts +2 -2
  128. package/dist-lib/lib/twinfield-ledger.functions.js +2 -2
  129. package/dist-lib/lib/twinfield-ledger.server.js +2 -2
  130. package/dist-lib/lib/twinfield-required-fields.js +1 -1
  131. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { cn } from "../lib/utils";
2
+ import { cn } from "../lib/utils.js";
3
3
  function initials(name) {
4
4
  if (!name)
5
5
  return "?";
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useRef } from "react";
3
3
  import { REFRESH_MS } from "../../lib/refresh-intervals.js";
4
- import { friendlyError } from "../../lib/errors";
4
+ import { friendlyError } from "../../lib/errors.js";
5
5
  import { useNavigate } from "@tanstack/react-router";
6
6
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
7
7
  import { useServerFn } from "@tanstack/react-start";
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useParams } from "@tanstack/react-router";
3
- import { BewerkKlant } from "./BewerkKlant";
3
+ import { BewerkKlant } from "./BewerkKlant.js";
4
4
  /** Route-onafhankelijk: leest `$id` uit welke route de shell ook gebruikt. */
5
5
  export function BewerkKlantRoute({ id: propId } = {}) {
6
6
  const params = useParams({ strict: false });
@@ -7,7 +7,7 @@ import { toast } from "sonner";
7
7
  import { supabase } from "../../integrations/supabase/client.js";
8
8
  import { ALLOWED_STICKER_MIME, commitStickerBatch, discardStickerBatch, suggestStickerMatches, } from "../../lib/customer-stickers.functions.js";
9
9
  import { friendlyError } from "../../lib/errors.js";
10
- import { SearchableSelect } from "./SearchableSelect";
10
+ import { SearchableSelect } from "./SearchableSelect.js";
11
11
  const BUCKET = "customer-stickers";
12
12
  const MAX_SIZE = 10 * 1024 * 1024;
13
13
  const ACCEPT = ".pdf,.png,.jpg,.jpeg,.svg";
@@ -7,8 +7,8 @@ import { useServerFn } from "@tanstack/react-start";
7
7
  import { Card, CardContent, CardHeader, CardTitle, Badge, Button, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Input, } from "@flowselections/core";
8
8
  import { ResponsiveContainer, LineChart, Line, BarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid, PieChart, Pie, Cell, Legend, } from "recharts";
9
9
  import { TrendingUp, TrendingDown, Minus } from "lucide-react";
10
- import { getCustomerAnalytics } from "../../lib/customer-analytics.functions";
11
- import { decodeDeep } from "../../lib/decode-html";
10
+ import { getCustomerAnalytics } from "../../lib/customer-analytics.functions.js";
11
+ import { decodeDeep } from "../../lib/decode-html.js";
12
12
  function presetRange(key) {
13
13
  const now = new Date();
14
14
  const y = now.getFullYear(), m = now.getMonth(), d = now.getDate();
@@ -12,10 +12,10 @@ import { importFloridayStickers } from "../../lib/floriday-sticker-import.functi
12
12
  import { decodeDeep } from "../../lib/decode-html.js";
13
13
  import { friendlyError } from "../../lib/errors.js";
14
14
  import { formatMoney } from "../../lib/format-currency.js";
15
- import { FloridayPriceImportDialog } from "./FloridayPriceImportDialog";
16
- import { CustomerStickerCell } from "./CustomerStickerCell";
17
- import { CustomerStickerFormatDialog } from "./CustomerStickerFormatDialog";
18
- import { BulkStickerUploadDialog } from "./BulkStickerUploadDialog";
15
+ import { FloridayPriceImportDialog } from "./FloridayPriceImportDialog.js";
16
+ import { CustomerStickerCell } from "./CustomerStickerCell.js";
17
+ import { CustomerStickerFormatDialog } from "./CustomerStickerFormatDialog.js";
18
+ import { BulkStickerUploadDialog } from "./BulkStickerUploadDialog.js";
19
19
  function money(value, currency) {
20
20
  if (value == null)
21
21
  return "—";
@@ -1 +1 @@
1
- {"version":3,"file":"DeliveryLocationsTab.d.ts","sourceRoot":"","sources":["../../../src/components/klanten/DeliveryLocationsTab.tsx"],"names":[],"mappings":"AAwEA,wBAAgB,oBAAoB,CAAC,EACnC,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,WAAW,GACZ,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,+BAuhBA"}
1
+ {"version":3,"file":"DeliveryLocationsTab.d.ts","sourceRoot":"","sources":["../../../src/components/klanten/DeliveryLocationsTab.tsx"],"names":[],"mappings":"AAwEA,wBAAgB,oBAAoB,CAAC,EACnC,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,WAAW,GACZ,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,+BA6jBA"}
@@ -1,15 +1,15 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { friendlyError } from "../../lib/errors";
2
+ import { friendlyError } from "../../lib/errors.js";
3
3
  import { useCustomerDefaults } from "./useCustomerDefaults.js";
4
4
  import { useEffect, useMemo, useRef, useState } from "react";
5
5
  import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
6
6
  import { useServerFn } from "@tanstack/react-start";
7
7
  import { Button, Card, CardContent, Badge, toast, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "@flowselections/core";
8
8
  import { MapPin, Plus, Pencil, Trash2, Truck, Sparkles, PackageCheck, Download } from "lucide-react";
9
- import { listCarriers, listDeliveryLocations, upsertDeliveryLocation, deleteDeliveryLocation, pickCarrierForLocation, importFloridayDeliveryLocations, } from "../../lib/delivery-locations.functions";
10
- import { EU_COUNTRIES, findCountry } from "../../lib/eu-regions";
11
- import { decodeDeep } from "../../lib/decode-html";
12
- import { countryNameToFlag } from "../../lib/countries";
9
+ import { listCarriers, listDeliveryLocations, upsertDeliveryLocation, deleteDeliveryLocation, pickCarrierForLocation, importFloridayDeliveryLocations, setPrimaryDeliveryLocation, } from "../../lib/delivery-locations.functions.js";
10
+ import { EU_COUNTRIES, findCountry } from "../../lib/eu-regions.js";
11
+ import { decodeDeep } from "../../lib/decode-html.js";
12
+ import { countryNameToFlag } from "../../lib/countries.js";
13
13
  const EMPTY = {
14
14
  name: "", street: "", house_number: "", postal_code: "",
15
15
  city: "", province: "", country: "",
@@ -37,6 +37,7 @@ export function DeliveryLocationsTab({ customerId, groupKey, externalProvider, e
37
37
  const carriersFn = useServerFn(listCarriers);
38
38
  const upsertFn = useServerFn(upsertDeliveryLocation);
39
39
  const deleteFn = useServerFn(deleteDeliveryLocation);
40
+ const primaryFn = useServerFn(setPrimaryDeliveryLocation);
40
41
  const { data: list } = useQuery({
41
42
  queryKey: ["delivery-locations", ownerKey],
42
43
  queryFn: () => listFn({ data: owner }).then(decodeDeep),
@@ -158,6 +159,14 @@ export function DeliveryLocationsTab({ customerId, groupKey, externalProvider, e
158
159
  qc.invalidateQueries({ queryKey: ["customer", ownerKey] });
159
160
  },
160
161
  });
162
+ const primaryMut = useMutation({
163
+ mutationFn: (id) => primaryFn({ data: { id } }),
164
+ onSuccess: () => {
165
+ toast.success("Dit is nu de vaste afleverlocatie.");
166
+ qc.invalidateQueries({ queryKey: ["delivery-locations", ownerKey] });
167
+ },
168
+ onError: (e) => toast.error(friendlyError(e, "Vast maken mislukt")),
169
+ });
161
170
  const handleSubmit = () => {
162
171
  setSubmitted(true);
163
172
  const order = ["street", "house_number", "postal_code", "city", "country", "province"];
@@ -173,7 +182,9 @@ export function DeliveryLocationsTab({ customerId, groupKey, externalProvider, e
173
182
  };
174
183
  return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { className: "text-sm text-muted-foreground", children: "Afleverlocaties staan volledig los van de boekhoudlocatie uit Twinfield en worden alleen gebruikt voor orderverwerking, planning, picking en levering. De vervoerder wordt automatisch gekoppeld op basis van het bedieningsgebied." }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { size: "sm", variant: "outline", onClick: () => previewMut.mutate(), disabled: previewMut.isPending, children: [_jsx(Download, { className: "h-4 w-4 mr-2" }), previewMut.isPending ? "Laden…" : "Importeren uit Floriday"] }), _jsxs(Button, { size: "sm", onClick: startNew, children: [_jsx(Plus, { className: "h-4 w-4 mr-2" }), " Locatie toevoegen"] })] })] }), locations.length === 0 ? (_jsx(Card, { children: _jsx(CardContent, { className: "py-10 text-center text-sm text-muted-foreground", children: "Nog geen afleverlocaties." }) })) : (_jsx("div", { className: "grid gap-3 md:grid-cols-2", children: locations.map((loc) => {
175
184
  const street = [loc.street, loc.house_number].filter(Boolean).join(" ") || loc.raw?.address?.addressLine || loc.address_line || "";
176
- return (_jsx(Card, { children: _jsxs(CardContent, { className: "pt-5 space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("div", { className: "font-semibold flex items-center gap-2", children: [_jsx(MapPin, { className: "h-4 w-4 text-muted-foreground" }), loc.name || street || "Afleverlocatie"] }), _jsxs("div", { className: "text-sm text-muted-foreground mt-0.5", children: [loc.name ? street : "", loc.name && street && (loc.postal_code || loc.city) ? ", " : "", [loc.postal_code, loc.city].filter(Boolean).join(" "), loc.province ? ` · ${loc.province}` : "", loc.country ? (_jsxs("span", { className: "inline-flex items-center gap-1 ml-1", children: [_jsx("span", { className: "text-base", "aria-hidden": "true", children: countryNameToFlag(loc.country) ?? "🌐" }), _jsx("span", { children: loc.country })] })) : null] })] }), _jsxs("div", { className: "flex gap-1", children: [_jsx(Button, { variant: "ghost", size: "icon", onClick: () => startEdit(loc), children: _jsx(Pencil, { className: "h-4 w-4" }) }), _jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", children: _jsx(Trash2, { className: "h-4 w-4" }) }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Locatie verwijderen?" }), _jsx(AlertDialogDescription, { children: "Deze actie kan niet ongedaan worden gemaakt." })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Annuleren" }), _jsx(AlertDialogAction, { onClick: () => delMut.mutate(loc.id), children: "Verwijderen" })] })] })] })] })] }), _jsxs("div", { className: "flex items-center gap-2 flex-wrap text-sm", children: [loc.self_pickup ? (_jsxs(_Fragment, { children: [_jsx(PackageCheck, { className: "h-4 w-4 text-muted-foreground" }), _jsx("span", { className: "font-medium", children: "Eigen vervoer" }), _jsx(Badge, { variant: "secondary", children: "Klant haalt zelf op" })] })) : (_jsxs(_Fragment, { children: [_jsx(Truck, { className: "h-4 w-4 text-muted-foreground" }), _jsx("span", { className: "font-medium", children: carrierName(loc.carrier_id) }), loc.carrier_assignment_source === "auto" && loc.carrier_id && (_jsxs(Badge, { variant: "secondary", className: "gap-1", children: [_jsx(Sparkles, { className: "h-3 w-3" }), "Automatisch"] })), loc.carrier_assignment_source === "manual" && (_jsx(Badge, { variant: "outline", children: "Handmatig" })), !loc.carrier_id && (_jsx(Badge, { variant: "outline", className: "text-warning-soft-foreground border-warning bg-warning-soft", children: "Geen match" }))] })), loc.external_provider === "floriday" && (_jsx(Badge, { variant: "outline", className: "text-success-soft-foreground border-success", children: "Floriday" })), loc.gln && _jsxs(Badge, { variant: "secondary", children: ["GLN ", loc.gln] }), (loc.external_provider === "floriday" && loc.raw?.isDefault === true) ? _jsx(Badge, { children: "Vaste afleverlocatie" }) : loc.is_primary && _jsx(Badge, { children: "Vaste locatie" })] })] }) }, loc.id));
185
+ return (_jsx(Card, { children: _jsxs(CardContent, { className: "pt-5 space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("div", { className: "font-semibold flex items-center gap-2", children: [_jsx(MapPin, { className: "h-4 w-4 text-muted-foreground" }), loc.name || street || "Afleverlocatie"] }), _jsxs("div", { className: "text-sm text-muted-foreground mt-0.5", children: [loc.name ? street : "", loc.name && street && (loc.postal_code || loc.city) ? ", " : "", [loc.postal_code, loc.city].filter(Boolean).join(" "), loc.province ? ` · ${loc.province}` : "", loc.country ? (_jsxs("span", { className: "inline-flex items-center gap-1 ml-1", children: [_jsx("span", { className: "text-base", "aria-hidden": "true", children: countryNameToFlag(loc.country) ?? "🌐" }), _jsx("span", { children: loc.country })] })) : null] })] }), _jsxs("div", { className: "flex gap-1", children: [_jsx(Button, { variant: "ghost", size: "icon", onClick: () => startEdit(loc), children: _jsx(Pencil, { className: "h-4 w-4" }) }), _jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", children: _jsx(Trash2, { className: "h-4 w-4" }) }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Locatie verwijderen?" }), _jsx(AlertDialogDescription, { children: "Deze actie kan niet ongedaan worden gemaakt." })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Annuleren" }), _jsx(AlertDialogAction, { onClick: () => delMut.mutate(loc.id), children: "Verwijderen" })] })] })] })] })] }), _jsxs("div", { className: "flex items-center gap-2 flex-wrap text-sm", children: [loc.self_pickup ? (_jsxs(_Fragment, { children: [_jsx(PackageCheck, { className: "h-4 w-4 text-muted-foreground" }), _jsx("span", { className: "font-medium", children: "Eigen vervoer" }), _jsx(Badge, { variant: "secondary", children: "Klant haalt zelf op" })] })) : (_jsxs(_Fragment, { children: [_jsx(Truck, { className: "h-4 w-4 text-muted-foreground" }), _jsx("span", { className: "font-medium", children: carrierName(loc.carrier_id) }), loc.carrier_assignment_source === "auto" && loc.carrier_id && (_jsxs(Badge, { variant: "secondary", className: "gap-1", children: [_jsx(Sparkles, { className: "h-3 w-3" }), "Automatisch"] })), loc.carrier_assignment_source === "manual" && (_jsx(Badge, { variant: "outline", children: "Handmatig" })), !loc.carrier_id && (_jsx(Badge, { variant: "outline", className: "text-warning-soft-foreground border-warning bg-warning-soft", children: "Geen match" }))] })), loc.external_provider === "floriday" && (_jsx(Badge, { variant: "outline", className: "text-success-soft-foreground border-success", children: "Floriday" })), loc.gln && _jsxs(Badge, { variant: "secondary", children: ["GLN ", loc.gln] }), loc.is_primary && _jsx(Badge, { children: "Vaste afleverlocatie" }), loc.external_provider === "floriday" && loc.raw?.isDefault === true && (_jsx(Badge, { variant: "outline", children: "Standaard in Floriday" })), !loc.is_primary && (_jsx(Button, { size: "sm", variant: "outline", className: "h-7", disabled: primaryMut.isPending, onClick: () => primaryMut.mutate(loc.id), title: loc.external_provider === "floriday"
186
+ ? "Dit verandert niets in Floriday; de koper kiest daar zelf zijn standaard."
187
+ : undefined, children: "Maak vaste afleverlocatie" }))] })] }) }, loc.id));
177
188
  }) })), _jsx(Dialog, { open: open, onOpenChange: setOpen, children: _jsxs(DialogContent, { className: "max-w-2xl", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: form.id ? "Locatie bewerken" : "Nieuwe locatie" }), _jsx(DialogDescription, { children: "De vervoerder wordt automatisch gekozen op basis van plaats, provincie of land." })] }), _jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [_jsxs("div", { className: "md:col-span-2", children: [_jsx(Label, { children: "Locatienaam (optioneel)" }), _jsx(Input, { value: form.name, onChange: (e) => setForm({ ...form, name: e.target.value }) })] }), _jsxs("div", { className: "md:col-span-2 grid grid-cols-3 gap-3", children: [_jsxs("div", { className: "col-span-2", children: [_jsxs(Label, { children: ["Straat ", req && _jsx("span", { className: "text-destructive", children: "*" })] }), _jsx(Input, { ref: fieldRefs.street, value: form.street, onChange: (e) => setForm({ ...form, street: e.target.value }), onBlur: () => markTouched("street"), "aria-invalid": !!showError("street"), className: showError("street") ? "border-destructive" : undefined }), showError("street") && _jsx("p", { className: "mt-1 text-xs text-destructive", children: showError("street") })] }), _jsxs("div", { children: [_jsxs(Label, { children: ["Huisnummer ", req && _jsx("span", { className: "text-destructive", children: "*" })] }), _jsx(Input, { ref: fieldRefs.house_number, value: form.house_number, onChange: (e) => setForm({ ...form, house_number: e.target.value }), onBlur: () => markTouched("house_number"), "aria-invalid": !!showError("house_number"), className: showError("house_number") ? "border-destructive" : undefined }), showError("house_number") && _jsx("p", { className: "mt-1 text-xs text-destructive", children: showError("house_number") })] })] }), _jsxs("div", { children: [_jsxs(Label, { children: ["Postcode ", req && _jsx("span", { className: "text-destructive", children: "*" })] }), _jsx(Input, { ref: fieldRefs.postal_code, value: form.postal_code, onChange: (e) => setForm({ ...form, postal_code: e.target.value }), onBlur: () => {
178
189
  markTouched("postal_code");
179
190
  setForm((f) => ({ ...f, postal_code: normalizePostalCode(f.postal_code, f.country) }));
@@ -198,7 +209,7 @@ export function DeliveryLocationsTab({ customerId, groupKey, externalProvider, e
198
209
  setForm({ ...form, self_pickup: false, carrier_id: v, carrier_assignment_source: "manual" });
199
210
  }
200
211
  }, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Kies een vervoerder" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "__self__", children: "Eigen vervoer (klant haalt zelf op)" }), _jsx(SelectItem, { value: "__none__", children: "\u2014 Geen vervoerder \u2014" }), carriers.map((c) => (_jsx(SelectItem, { value: c.id, children: c.name }, c.id)))] })] }), form.self_pickup ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "De klant komt zelf de karren ophalen \u2014 er wordt geen vervoerder gekoppeld." })) : form.carrier_assignment_source === "manual" ? (_jsxs("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [_jsx("span", { children: "Handmatig overschreven." }), _jsx(Button, { variant: "link", size: "sm", className: "h-auto p-0", onClick: () => setForm({ ...form, carrier_assignment_source: "auto" }), children: "Terug naar automatisch" })] })) : autoSuggested?.carrier_id ? (_jsxs("div", { className: "text-xs text-muted-foreground flex items-center gap-1", children: [_jsx(Sparkles, { className: "h-3 w-3" }), "Automatisch geselecteerd op basis van ", autoSuggested.matched_on === "city"
201
- ? "plaats" : autoSuggested.matched_on === "province" ? "provincie" : "land", "."] })) : (_jsx("div", { className: "text-xs text-warning-soft-foreground", children: "Geen vervoerder gevonden voor dit bedieningsgebied \u2014 selecteer er handmatig \u00E9\u00E9n." }))] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: "outline", onClick: () => setOpen(false), children: "Annuleren" }), _jsx(Button, { onClick: handleSubmit, disabled: saveMut.isPending, children: form.id ? "Opslaan" : "Toevoegen" })] })] }) }), _jsx(Dialog, { open: importOpen, onOpenChange: setImportOpen, children: _jsxs(DialogContent, { className: "max-w-3xl", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Afleverlocaties importeren uit Floriday" }), _jsx(DialogDescription, { children: "Controleer de locaties voordat je importeert. Adres, plaats, land en GLN-code komen uit Floriday. De vervoerder wordt automatisch gekoppeld op basis van het bedieningsgebied." })] }), _jsx("div", { className: "max-h-[50vh] overflow-auto rounded-md border", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "bg-muted/50 text-left", children: _jsxs("tr", { children: [_jsx("th", { className: "px-3 py-2 font-medium", children: "Locatie" }), _jsx("th", { className: "px-3 py-2 font-medium", children: "Klant" }), _jsx("th", { className: "px-3 py-2 font-medium", children: "Adres" }), _jsx("th", { className: "px-3 py-2 font-medium", children: "GLN" }), _jsx("th", { className: "px-3 py-2 font-medium", children: "Actie" })] }) }), _jsxs("tbody", { children: [(importPreview?.items ?? []).map((it) => (_jsxs("tr", { className: "border-t", children: [_jsx("td", { className: "px-3 py-2", children: it.name }), _jsx("td", { className: "px-3 py-2", children: it.customer_name ?? "—" }), _jsx("td", { className: "px-3 py-2 text-muted-foreground", children: it.address || "—" }), _jsx("td", { className: "px-3 py-2 text-muted-foreground", children: it.gln ?? "—" }), _jsxs("td", { className: "px-3 py-2", children: [it.action === "create" && _jsx(Badge, { children: "Nieuw" }), it.action === "update" && _jsx(Badge, { variant: "secondary", children: "Bijwerken" }), it.action === "no_customer" && (_jsx(Badge, { variant: "outline", className: "text-warning-soft-foreground border-warning bg-warning-soft", children: "Geen klant gevonden" }))] })] }, it.floriday_id))), (importPreview?.items ?? []).length === 0 && (_jsx("tr", { children: _jsx("td", { colSpan: 5, className: "px-3 py-6 text-center text-muted-foreground", children: "Geen locaties gevonden in Floriday." }) }))] })] }) }), _jsxs("div", { className: "text-sm text-muted-foreground", children: [importPreview?.created ?? 0, " nieuw \u00B7 ", importPreview?.updated ?? 0, " bijwerken", (importPreview?.skipped ?? 0) > 0
212
+ ? "plaats" : autoSuggested.matched_on === "province" ? "provincie" : "land", "."] })) : (_jsx("div", { className: "text-xs text-warning-soft-foreground", children: "Geen vervoerder gevonden voor dit bedieningsgebied \u2014 selecteer er handmatig \u00E9\u00E9n." }))] }), _jsxs("label", { className: "md:col-span-2 flex items-start gap-2 text-sm", children: [_jsx("input", { type: "checkbox", className: "mt-1", checked: form.is_primary, onChange: (e) => setForm({ ...form, is_primary: e.target.checked }) }), _jsxs("span", { children: ["Vaste afleverlocatie", _jsx("span", { className: "block text-xs text-muted-foreground", children: "Wordt bij nieuwe orders vooraf gekozen. Een eventuele andere vaste locatie van deze klant vervalt." })] })] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: "outline", onClick: () => setOpen(false), children: "Annuleren" }), _jsx(Button, { onClick: handleSubmit, disabled: saveMut.isPending, children: form.id ? "Opslaan" : "Toevoegen" })] })] }) }), _jsx(Dialog, { open: importOpen, onOpenChange: setImportOpen, children: _jsxs(DialogContent, { className: "max-w-3xl", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Afleverlocaties importeren uit Floriday" }), _jsx(DialogDescription, { children: "Controleer de locaties voordat je importeert. Adres, plaats, land en GLN-code komen uit Floriday. De vervoerder wordt automatisch gekoppeld op basis van het bedieningsgebied." })] }), _jsx("div", { className: "max-h-[50vh] overflow-auto rounded-md border", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "bg-muted/50 text-left", children: _jsxs("tr", { children: [_jsx("th", { className: "px-3 py-2 font-medium", children: "Locatie" }), _jsx("th", { className: "px-3 py-2 font-medium", children: "Klant" }), _jsx("th", { className: "px-3 py-2 font-medium", children: "Adres" }), _jsx("th", { className: "px-3 py-2 font-medium", children: "GLN" }), _jsx("th", { className: "px-3 py-2 font-medium", children: "Actie" })] }) }), _jsxs("tbody", { children: [(importPreview?.items ?? []).map((it) => (_jsxs("tr", { className: "border-t", children: [_jsx("td", { className: "px-3 py-2", children: it.name }), _jsx("td", { className: "px-3 py-2", children: it.customer_name ?? "—" }), _jsx("td", { className: "px-3 py-2 text-muted-foreground", children: it.address || "—" }), _jsx("td", { className: "px-3 py-2 text-muted-foreground", children: it.gln ?? "—" }), _jsxs("td", { className: "px-3 py-2", children: [it.action === "create" && _jsx(Badge, { children: "Nieuw" }), it.action === "update" && _jsx(Badge, { variant: "secondary", children: "Bijwerken" }), it.action === "no_customer" && (_jsx(Badge, { variant: "outline", className: "text-warning-soft-foreground border-warning bg-warning-soft", children: "Geen klant gevonden" }))] })] }, it.floriday_id))), (importPreview?.items ?? []).length === 0 && (_jsx("tr", { children: _jsx("td", { colSpan: 5, className: "px-3 py-6 text-center text-muted-foreground", children: "Geen locaties gevonden in Floriday." }) }))] })] }) }), _jsxs("div", { className: "text-sm text-muted-foreground", children: [importPreview?.created ?? 0, " nieuw \u00B7 ", importPreview?.updated ?? 0, " bijwerken", (importPreview?.skipped ?? 0) > 0
202
213
  ? ` · ${importPreview?.skipped} overgeslagen omdat de Floriday-organisatie niet aan een klant gekoppeld is`
203
214
  : ""] }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: "outline", onClick: () => setImportOpen(false), children: "Afbreken" }), _jsx(Button, { onClick: () => importMut.mutate(), disabled: importMut.isPending || ((importPreview?.created ?? 0) + (importPreview?.updated ?? 0)) === 0, children: importMut.isPending ? "Importeren…" : "Importeren" })] })] }) })] }));
204
215
  }
@@ -6,8 +6,8 @@ import { useServerFn } from "@tanstack/react-start";
6
6
  import { Card, CardContent, Badge, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@flowselections/core";
7
7
  import { Info, Percent, FileText, Users } from "lucide-react";
8
8
  import { listCustomerDiscounts, } from "../../lib/floriday-discounts.functions.js";
9
- import { EmptyState } from "./KlantDetailLayout";
10
- import { ExternalCacheBanner } from "./ExternalCacheBanner";
9
+ import { EmptyState } from "./KlantDetailLayout.js";
10
+ import { ExternalCacheBanner } from "./ExternalCacheBanner.js";
11
11
  import { decodeDeep } from "../../lib/decode-html.js";
12
12
  import { formatMoney } from "../../lib/format-currency.js";
13
13
  const SOURCE_LABEL = {
@@ -1,4 +1,4 @@
1
- import type { ExternalProvider } from "../../lib/external-customers.functions";
1
+ import type { ExternalProvider } from "../../lib/external-customers.functions.js";
2
2
  export declare function ExternalCacheBanner({ lastFetchedAt, providers, title, description, }: {
3
3
  lastFetchedAt: string | null;
4
4
  providers: ExternalProvider[];
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useQuery } from "@tanstack/react-query";
3
3
  import { useServerFn } from "@tanstack/react-start";
4
- import { getFloridayNetworkStatus } from "../../lib/floriday-network-status.functions";
5
- import { formatDate } from "../../lib/format-date";
6
- import { useCustomerDefaults } from "./useCustomerDefaults";
4
+ import { getFloridayNetworkStatus } from "../../lib/floriday-network-status.functions.js";
5
+ import { formatDate } from "../../lib/format-date.js";
6
+ import { useCustomerDefaults } from "./useCustomerDefaults.js";
7
7
  /** Alleen weergave: staat deze Floriday-organisatie in je Floriday-netwerk? Geen klantstatus. */
8
8
  export function FloridayNetworkStatus({ organizationId }) {
9
9
  const fn = useServerFn(getFloridayNetworkStatus);
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useParams } from "@tanstack/react-router";
3
- import { GroupedKlantDetail } from "./GroupedKlantDetail";
3
+ import { GroupedKlantDetail } from "./GroupedKlantDetail.js";
4
4
  /** Route-onafhankelijk: leest `$groupKey` uit welke route de shell ook gebruikt. */
5
5
  export function GroupedKlantDetailRoute({ groupKey: propKey } = {}) {
6
6
  const params = useParams({ strict: false });
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { friendlyError } from "../../lib/errors";
2
+ import { friendlyError } from "../../lib/errors.js";
3
3
  import { useNavigate } from "@tanstack/react-router";
4
4
  import { useEffect, useMemo, useState } from "react";
5
5
  import { useMutation, useQueryClient } from "@tanstack/react-query";
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from "react";
3
3
  import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@flowselections/core";
4
- import { BewerkKlant } from "./BewerkKlant";
5
- import { OvernemenTwinfieldKlant } from "./OvernemenTwinfieldKlant";
4
+ import { BewerkKlant } from "./BewerkKlant.js";
5
+ import { OvernemenTwinfieldKlant } from "./OvernemenTwinfieldKlant.js";
6
6
  /**
7
7
  * Bewerken/overnemen in een dialoog, zodat de module geen eigen routes nodig
8
8
  * heeft. Werkt daardoor in elke shell, ongeacht welke routes die declareert.
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from "react";
2
- import type { ExternalCustomer, GroupedCustomer } from "../../lib/external-customers.functions";
2
+ import type { ExternalCustomer, GroupedCustomer } from "../../lib/external-customers.functions.js";
3
3
  export type CustomerProfile = {
4
4
  logo_url: string | null;
5
5
  company_name: string;
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useCustomerDefaults } from "./useCustomerDefaults";
2
+ import { useCustomerDefaults } from "./useCustomerDefaults.js";
3
3
  import { useState, useEffect } from "react";
4
4
  import { formatDateTime } from "../../lib/format-date.js";
5
5
  import { Card, CardContent, Badge, Separator, Textarea, Button, } from "@flowselections/core";
6
6
  import { Mail, Phone, Globe, MapPin, Hash, Building2, ChevronDown, ChevronRight, Users, Truck, Package, ShoppingCart, StickyNote, Pencil, Check, X, } from "lucide-react";
7
- import { CustomerAvatar } from "../CustomerAvatar";
8
- import { formatCountry, countryNameToFlag } from "../../lib/countries";
7
+ import { CustomerAvatar } from "../CustomerAvatar.js";
8
+ import { formatCountry, countryNameToFlag } from "../../lib/countries.js";
9
9
  function formatOrgType(t) {
10
10
  if (t === "CUSTOMER")
11
11
  return "Koper";
@@ -20,8 +20,8 @@ function firstNonEmpty(values) {
20
20
  }
21
21
  return null;
22
22
  }
23
- import { formatPaymentMethodLabel } from "../../lib/payment-method";
24
- import { FloridayNetworkStatus } from "./FloridayNetworkStatus";
23
+ import { formatPaymentMethodLabel } from "../../lib/payment-method.js";
24
+ import { FloridayNetworkStatus } from "./FloridayNetworkStatus.js";
25
25
  function fmtAddr(a) {
26
26
  if (!a)
27
27
  return null;
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useParams } from "@tanstack/react-router";
3
- import { KlantDetail } from "./KlantDetail";
3
+ import { KlantDetail } from "./KlantDetail.js";
4
4
  /** Route-onafhankelijk: leest `$id` uit welke route de shell ook gebruikt. */
5
5
  export function KlantDetailRoute({ id: propId } = {}) {
6
6
  const params = useParams({ strict: false });
@@ -5,25 +5,25 @@ import { formatDate } from "../../lib/format-date.js";
5
5
  import { useQuery, useQueryClient } from "@tanstack/react-query";
6
6
  import { useServerFn } from "@tanstack/react-start";
7
7
  import { useEffect, useMemo, useRef, useState } from "react";
8
- import { usePersistedState, markReturnToList, consumeReturnToList } from "../../lib/persisted-state";
9
- import { formatEur } from "../../lib/format-currency";
8
+ import { usePersistedState, markReturnToList, consumeReturnToList } from "../../lib/persisted-state.js";
9
+ import { formatEur } from "../../lib/format-currency.js";
10
10
  import { Button, Input, Card, CardContent, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Tabs, TabsList, TabsTrigger, Skeleton, } from "@flowselections/core";
11
11
  import { Plus, Search, Users, UserCheck, UserX, AlertCircle, X, ArrowUpDown, Mail, MapPin, Upload, ChevronLeft, ChevronRight, Pencil, } from "lucide-react";
12
12
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
13
- import { listCustomers } from "../../lib/customers.functions";
14
- import { listExternalCustomers } from "../../lib/external-customers.functions";
15
- import { listOverdueBalances } from "../../lib/overdue-invoices.functions";
16
- import { listRevenueActivity } from "../../lib/customer-revenue.functions";
17
- import { supabase } from "../../integrations/supabase/client";
18
- import { decodeDeep } from "../../lib/decode-html";
19
- import { friendlyError, isBackendUnavailable, retryOnTransient, retryBackoff } from "../../lib/errors";
20
- import { CustomerAvatar } from "../CustomerAvatar";
21
- import { PriceGroupBadges } from "./PriceGroupBadges";
22
- import { KlantBewerkenDialog } from "./KlantBewerkenDialog";
23
- import { ChannelBadges } from "./ChannelBadges";
24
- import { derivePaymentMethod, paymentToneClasses } from "../../lib/payment-method";
25
- import { formatCountry, getCountryFlagAndName, countryNameToFlag } from "../../lib/countries";
26
- import { MultiSearchableSelect } from "./MultiSearchableSelect";
13
+ import { listCustomers } from "../../lib/customers.functions.js";
14
+ import { listExternalCustomers } from "../../lib/external-customers.functions.js";
15
+ import { listOverdueBalances } from "../../lib/overdue-invoices.functions.js";
16
+ import { listRevenueActivity } from "../../lib/customer-revenue.functions.js";
17
+ import { supabase } from "../../integrations/supabase/client.js";
18
+ import { decodeDeep } from "../../lib/decode-html.js";
19
+ import { friendlyError, isBackendUnavailable, retryOnTransient, retryBackoff } from "../../lib/errors.js";
20
+ import { CustomerAvatar } from "../CustomerAvatar.js";
21
+ import { PriceGroupBadges } from "./PriceGroupBadges.js";
22
+ import { KlantBewerkenDialog } from "./KlantBewerkenDialog.js";
23
+ import { ChannelBadges } from "./ChannelBadges.js";
24
+ import { derivePaymentMethod, paymentToneClasses } from "../../lib/payment-method.js";
25
+ import { formatCountry, getCountryFlagAndName, countryNameToFlag } from "../../lib/countries.js";
26
+ import { MultiSearchableSelect } from "./MultiSearchableSelect.js";
27
27
  export function KlantenOverzicht() {
28
28
  const navigate = useNavigate();
29
29
  const queryClient = useQueryClient();
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { friendlyError } from "../../lib/errors";
2
+ import { friendlyError } from "../../lib/errors.js";
3
3
  import { useEffect, useState } from "react";
4
4
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
5
5
  import { useServerFn } from "@tanstack/react-start";
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { friendlyError } from "../../lib/errors";
2
+ import { friendlyError } from "../../lib/errors.js";
3
3
  import { formatDate } from "../../lib/format-date.js";
4
4
  import { useMemo, useState } from "react";
5
5
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
@@ -7,7 +7,7 @@ import { useServerFn } from "@tanstack/react-start";
7
7
  import { Card, CardContent, Badge, Input, Button, toast, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@flowselections/core";
8
8
  import { Percent, FileText, Users, Plus, Pencil, Trash2 } from "lucide-react";
9
9
  import { listLocalCustomerDiscounts, deleteLocalDiscount, } from "../../lib/local-discounts.functions.js";
10
- import { LocalDiscountFormDialog } from "./LocalDiscountFormDialog";
10
+ import { LocalDiscountFormDialog } from "./LocalDiscountFormDialog.js";
11
11
  import { decodeDeep } from "../../lib/decode-html.js";
12
12
  import { formatMoney } from "../../lib/format-currency.js";
13
13
  const SOURCE_LABEL = {
@@ -8,9 +8,9 @@ import { Search, MapPin, Globe } from "lucide-react";
8
8
  import { BackLink } from "./BackLink.js";
9
9
  import { countryNameToFlag } from "../../lib/countries.js";
10
10
  import { listFloridayNetwork } from "../../lib/customers.functions.js";
11
- import { CustomerAvatar } from "../CustomerAvatar";
12
- import { PriceGroupBadges } from "./PriceGroupBadges";
13
- import { FloridayDeeplinkButton } from "./FloridayDeeplinkButton";
11
+ import { CustomerAvatar } from "../CustomerAvatar.js";
12
+ import { PriceGroupBadges } from "./PriceGroupBadges.js";
13
+ import { FloridayDeeplinkButton } from "./FloridayDeeplinkButton.js";
14
14
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
15
15
  import { decodeDeep } from "../../lib/decode-html.js";
16
16
  const TYPE_OPTIONS = [
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { friendlyError } from "../../lib/errors";
2
+ import { friendlyError } from "../../lib/errors.js";
3
3
  import { useNavigate } from "@tanstack/react-router";
4
4
  import { useState } from "react";
5
5
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { friendlyError } from "../../lib/errors";
2
+ import { friendlyError } from "../../lib/errors.js";
3
3
  import { useNavigate } from "@tanstack/react-router";
4
4
  import { useEffect } from "react";
5
5
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useParams } from "@tanstack/react-router";
3
- import { OvernemenTwinfieldKlant } from "./OvernemenTwinfieldKlant";
3
+ import { OvernemenTwinfieldKlant } from "./OvernemenTwinfieldKlant.js";
4
4
  /** Route-onafhankelijk: leest `$code` uit welke route de shell ook gebruikt. */
5
5
  export function OvernemenTwinfieldKlantRoute({ code: propCode } = {}) {
6
6
  const params = useParams({ strict: false });
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useRouter } from "@tanstack/react-router";
3
3
  import { Button, Card, CardContent } from "@flowselections/core";
4
4
  import { AlertCircle, RefreshCw } from "lucide-react";
5
- import { friendlyError } from "../../lib/errors";
5
+ import { friendlyError } from "../../lib/errors.js";
6
6
  /** Nette foutweergave voor route-loaders en render-fouten binnen Klanten. */
7
7
  export function RouteError({ error }) {
8
8
  const router = useRouter();
@@ -4,12 +4,12 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
4
4
  import { useServerFn } from "@tanstack/react-start";
5
5
  import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, Button, Input, Checkbox, Badge, } from "@flowselections/core";
6
6
  import { Search } from "lucide-react";
7
- import { listExternalCustomers } from "../../../lib/external-customers.functions";
8
- import { setPriceGroupMembers, getCustomerPriceGroup, listUnknownFloridayMembers, } from "../../../lib/price-groups-local.functions";
9
- import { decodeDeep } from "../../../lib/decode-html";
10
- import { countryNameToFlag } from "../../../lib/countries";
11
- import { formatDateTime } from "../../../lib/format-date";
12
- import { UnknownFloridayMembers } from "./UnknownFloridayMembers";
7
+ import { listExternalCustomers } from "../../../lib/external-customers.functions.js";
8
+ import { setPriceGroupMembers, getCustomerPriceGroup, listUnknownFloridayMembers, } from "../../../lib/price-groups-local.functions.js";
9
+ import { decodeDeep } from "../../../lib/decode-html.js";
10
+ import { countryNameToFlag } from "../../../lib/countries.js";
11
+ import { formatDateTime } from "../../../lib/format-date.js";
12
+ import { UnknownFloridayMembers } from "./UnknownFloridayMembers.js";
13
13
  export function CustomerPickerDialog({ priceGroupId, open, onOpenChange, value, onChange, }) {
14
14
  const qc = useQueryClient();
15
15
  const listCustomers = useServerFn(listExternalCustomers);
@@ -3,9 +3,9 @@ import { useMemo, useState } from "react";
3
3
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
4
4
  import { useServerFn } from "@tanstack/react-start";
5
5
  import { toast } from "@flowselections/core";
6
- import { SearchableSelect } from "../SearchableSelect";
7
- import { listCustomerPriceGroups, getPriceGroupsForCustomer, setPriceGroupForCustomer, } from "../../../lib/price-groups-local.functions";
8
- import { friendlyError } from "../../../lib/errors";
6
+ import { SearchableSelect } from "../SearchableSelect.js";
7
+ import { listCustomerPriceGroups, getPriceGroupsForCustomer, setPriceGroupForCustomer, } from "../../../lib/price-groups-local.functions.js";
8
+ import { friendlyError } from "../../../lib/errors.js";
9
9
  const NONE = "__none__";
10
10
  export function CustomerPriceGroupSelect({ customerKey }) {
11
11
  const qc = useQueryClient();
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useParams } from "@tanstack/react-router";
3
- import { PriceGroupFormPage } from "./PriceGroupFormPage";
3
+ import { PriceGroupFormPage } from "./PriceGroupFormPage.js";
4
4
  export function PriceGroupEditRoute({ id: propId } = {}) {
5
5
  const params = useParams({ strict: false });
6
6
  const id = propId ?? ("id" in params ? params.id : undefined);
@@ -5,18 +5,18 @@ import { useServerFn } from "@tanstack/react-start";
5
5
  import { useNavigate } from "@tanstack/react-router";
6
6
  import { Button, Input, Label, Separator, Card, CardContent, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Checkbox, } from "@flowselections/core";
7
7
  import { ArrowRight, Check, ChevronDown, PencilLine, Calculator, Users, Globe2, Circle, CheckCircle2, Info, ChevronLeft, ChevronRight, ImageIcon } from "lucide-react";
8
- import { BackLink } from "../BackLink";
9
- import { createCustomerPriceGroup, updateCustomerPriceGroup, getCustomerPriceGroup, setPriceGroupMembers, } from "../../../lib/price-groups-local.functions";
10
- import { computePrice } from "../../../lib/pricing";
11
- import { formatEur } from "../../../lib/format-currency";
12
- import { listTradeItemsForPreview } from "../../../lib/floriday-trade-items.functions";
13
- import { ProductPickerDialog } from "./ProductPickerDialog";
14
- import { PriceGroupItemPrices } from "./PriceGroupItemPrices";
15
- import { CustomerPickerDialog } from "./CustomerPickerDialog";
8
+ import { BackLink } from "../BackLink.js";
9
+ import { createCustomerPriceGroup, updateCustomerPriceGroup, getCustomerPriceGroup, setPriceGroupMembers, } from "../../../lib/price-groups-local.functions.js";
10
+ import { computePrice } from "../../../lib/pricing.js";
11
+ import { formatEur } from "../../../lib/format-currency.js";
12
+ import { listTradeItemsForPreview } from "../../../lib/floriday-trade-items.functions.js";
13
+ import { ProductPickerDialog } from "./ProductPickerDialog.js";
14
+ import { PriceGroupItemPrices } from "./PriceGroupItemPrices.js";
15
+ import { CustomerPickerDialog } from "./CustomerPickerDialog.js";
16
16
  import { UserPlus, Users2 } from "lucide-react";
17
- import { listExternalCustomers } from "../../../lib/external-customers.functions";
18
- import { decodeDeep } from "../../../lib/decode-html";
19
- import { countryNameToFlag } from "../../../lib/countries";
17
+ import { listExternalCustomers } from "../../../lib/external-customers.functions.js";
18
+ import { decodeDeep } from "../../../lib/decode-html.js";
19
+ import { countryNameToFlag } from "../../../lib/countries.js";
20
20
  import { Badge } from "@flowselections/core";
21
21
  import { toast } from "sonner";
22
22
  const emptyInput = {
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { PriceGroupFormPage } from "./PriceGroupFormPage";
2
+ import { PriceGroupFormPage } from "./PriceGroupFormPage.js";
3
3
  export function PriceGroupNewRoute() {
4
4
  return _jsx(PriceGroupFormPage, {});
5
5
  }
@@ -10,10 +10,10 @@ import { Plus, Search, MoreVertical, GripVertical, EyeOff, Eye, Pencil, Users, C
10
10
  import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, } from "@dnd-kit/core";
11
11
  import { SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy, useSortable, arrayMove, } from "@dnd-kit/sortable";
12
12
  import { CSS } from "@dnd-kit/utilities";
13
- import { listCustomerPriceGroups, deleteCustomerPriceGroup, reorderCustomerPriceGroups, updateCustomerPriceGroup, createCustomerPriceGroup, importFloridayPriceGroups, } from "../../../lib/price-groups-local.functions";
14
- import { CustomerPickerDialog } from "./CustomerPickerDialog";
15
- import { UnknownFloridayMembers } from "./UnknownFloridayMembers";
16
- import { friendlyError } from "../../../lib/errors";
13
+ import { listCustomerPriceGroups, deleteCustomerPriceGroup, reorderCustomerPriceGroups, updateCustomerPriceGroup, createCustomerPriceGroup, importFloridayPriceGroups, } from "../../../lib/price-groups-local.functions.js";
14
+ import { CustomerPickerDialog } from "./CustomerPickerDialog.js";
15
+ import { UnknownFloridayMembers } from "./UnknownFloridayMembers.js";
16
+ import { friendlyError } from "../../../lib/errors.js";
17
17
  import { toast } from "sonner";
18
18
  function unitLabel(u) {
19
19
  switch (u) {
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Outlet, useRouterState } from "@tanstack/react-router";
3
- import { PriceGroupsPage } from "./PriceGroupsPage";
3
+ import { PriceGroupsPage } from "./PriceGroupsPage.js";
4
4
  export function PriceGroupsRoute() {
5
5
  const pathname = useRouterState({
6
6
  select: (state) => state.location.pathname.replace(/\/+$/, ""),
@@ -1,4 +1,4 @@
1
- import type { TradeItemPreview } from "../../../lib/floriday-trade-items.functions";
1
+ import type { TradeItemPreview } from "../../../lib/floriday-trade-items.functions.js";
2
2
  export declare function ProductPickerDialog({ open, onOpenChange, items, onSelect, }: {
3
3
  open: boolean;
4
4
  onOpenChange: (v: boolean) => void;
@@ -1,4 +1,4 @@
1
- import { type UnknownFloridayMember } from "../../../lib/price-groups-local.functions";
1
+ import { type UnknownFloridayMember } from "../../../lib/price-groups-local.functions.js";
2
2
  /**
3
3
  * Floriday-leden van een prijsgroep die nog geen ERP-klant zijn. Er wordt niets vastgelegd
4
4
  * tot iemand op "Toevoegen" klikt; dan ontstaat een klant zonder Twinfield-debiteur.
@@ -4,8 +4,8 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
4
4
  import { useServerFn } from "@tanstack/react-start";
5
5
  import { Button, Badge } from "@flowselections/core";
6
6
  import { toast } from "sonner";
7
- import { addFloridayMemberToPriceGroup, } from "../../../lib/price-groups-local.functions";
8
- import { friendlyError } from "../../../lib/errors";
7
+ import { addFloridayMemberToPriceGroup, } from "../../../lib/price-groups-local.functions.js";
8
+ import { friendlyError } from "../../../lib/errors.js";
9
9
  /**
10
10
  * Floriday-leden van een prijsgroep die nog geen ERP-klant zijn. Er wordt niets vastgelegd
11
11
  * tot iemand op "Toevoegen" klikt; dan ontstaat een klant zonder Twinfield-debiteur.
@@ -1,7 +1,7 @@
1
1
  /** Standaardwaarden van de actieve administratie (land, taal, grootboek, betaaltermijn). */
2
2
  export declare function useCustomerDefaults(): {
3
3
  isLoading: boolean;
4
- defaults?: import("../../lib/twinfield-customer-defaults.server").CustomerDefaults | undefined;
4
+ defaults?: import("../../lib/twinfield-customer-defaults.server.js").CustomerDefaults | undefined;
5
5
  isAdmin?: boolean | undefined;
6
6
  };
7
7
  export declare const MISSING_DEFAULT_MESSAGE = "Standaardwaarde ontbreekt in de Twinfield-instellingen";