@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.
- package/dist-lib/components/CustomerAvatar.js +1 -1
- package/dist-lib/components/klanten/BewerkKlant.js +1 -1
- package/dist-lib/components/klanten/BewerkKlantRoute.js +1 -1
- package/dist-lib/components/klanten/BulkStickerUploadDialog.js +1 -1
- package/dist-lib/components/klanten/CustomerAnalyticsTab.js +2 -2
- package/dist-lib/components/klanten/CustomerAssortmentTab.js +4 -4
- package/dist-lib/components/klanten/DeliveryLocationsTab.d.ts.map +1 -1
- package/dist-lib/components/klanten/DeliveryLocationsTab.js +18 -7
- package/dist-lib/components/klanten/DiscountsTab.js +2 -2
- package/dist-lib/components/klanten/ExternalCacheBanner.d.ts +1 -1
- package/dist-lib/components/klanten/FloridayNetworkStatus.js +3 -3
- package/dist-lib/components/klanten/GroupedKlantDetailRoute.js +1 -1
- package/dist-lib/components/klanten/ImportKlanten.js +1 -1
- package/dist-lib/components/klanten/KlantBewerkenDialog.js +2 -2
- package/dist-lib/components/klanten/KlantDetailLayout.d.ts +1 -1
- package/dist-lib/components/klanten/KlantDetailLayout.js +5 -5
- package/dist-lib/components/klanten/KlantDetailRoute.js +1 -1
- package/dist-lib/components/klanten/KlantenOverzicht.js +16 -16
- package/dist-lib/components/klanten/LocalDiscountFormDialog.js +1 -1
- package/dist-lib/components/klanten/LocalDiscountsTab.js +2 -2
- package/dist-lib/components/klanten/NetwerkPagina.js +3 -3
- package/dist-lib/components/klanten/NieuweKlant.js +1 -1
- package/dist-lib/components/klanten/OvernemenTwinfieldKlant.js +1 -1
- package/dist-lib/components/klanten/OvernemenTwinfieldKlantRoute.js +1 -1
- package/dist-lib/components/klanten/RouteError.js +1 -1
- package/dist-lib/components/klanten/pricegroups/CustomerPickerDialog.js +6 -6
- package/dist-lib/components/klanten/pricegroups/CustomerPriceGroupSelect.js +3 -3
- package/dist-lib/components/klanten/pricegroups/PriceGroupEditRoute.js +1 -1
- package/dist-lib/components/klanten/pricegroups/PriceGroupFormPage.js +11 -11
- package/dist-lib/components/klanten/pricegroups/PriceGroupNewRoute.js +1 -1
- package/dist-lib/components/klanten/pricegroups/PriceGroupsPage.js +4 -4
- package/dist-lib/components/klanten/pricegroups/PriceGroupsRoute.js +1 -1
- package/dist-lib/components/klanten/pricegroups/ProductPickerDialog.d.ts +1 -1
- package/dist-lib/components/klanten/pricegroups/UnknownFloridayMembers.d.ts +1 -1
- package/dist-lib/components/klanten/pricegroups/UnknownFloridayMembers.js +2 -2
- package/dist-lib/components/klanten/useCustomerDefaults.d.ts +1 -1
- package/dist-lib/index.d.ts +34 -34
- package/dist-lib/index.js +35 -35
- package/dist-lib/integrations/supabase/auth-attacher.js +1 -1
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +903 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/accounting/exact/client.server.d.ts +1 -1
- package/dist-lib/lib/accounting/exact/client.server.js +2 -2
- package/dist-lib/lib/accounting/exact/sync.server.d.ts +1 -1
- package/dist-lib/lib/accounting/exact/sync.server.js +3 -3
- package/dist-lib/lib/accounting/floriday/sync.server.d.ts +1 -1
- package/dist-lib/lib/accounting/floriday/sync.server.js +1 -1
- package/dist-lib/lib/accounting/registry.server.d.ts +1 -1
- package/dist-lib/lib/accounting/registry.server.js +2 -2
- package/dist-lib/lib/accounting/twinfield/client.server.js +2 -2
- package/dist-lib/lib/accounting/twinfield/field-coverage.test.js +6 -6
- package/dist-lib/lib/accounting/twinfield/mapping.js +3 -3
- package/dist-lib/lib/accounting/twinfield/rmw-push.server.d.ts +2 -2
- package/dist-lib/lib/accounting/twinfield/rmw-push.server.js +4 -4
- package/dist-lib/lib/accounting/twinfield/rmw.server.d.ts +1 -1
- package/dist-lib/lib/accounting/twinfield/rmw.server.js +2 -2
- package/dist-lib/lib/accounting/twinfield/sandbox-rmw.server.d.ts +6 -6
- package/dist-lib/lib/accounting/twinfield/sandbox-rmw.server.js +12 -12
- package/dist-lib/lib/accounting/twinfield/sandbox.server.js +3 -3
- package/dist-lib/lib/accounting/twinfield/sync.server.js +4 -4
- package/dist-lib/lib/accounting/twinfield/worker.functions.d.ts +7 -7
- package/dist-lib/lib/accounting/twinfield/worker.functions.js +6 -6
- package/dist-lib/lib/accounting/twinfield/worker.server.js +8 -8
- package/dist-lib/lib/accounting.functions.d.ts +4 -4
- package/dist-lib/lib/accounting.functions.js +2 -2
- package/dist-lib/lib/countries.test.js +3 -3
- package/dist-lib/lib/customer-analytics.functions.d.ts +1 -1
- package/dist-lib/lib/customer-analytics.functions.js +1 -1
- package/dist-lib/lib/customer-assortment.functions.d.ts +1 -1
- package/dist-lib/lib/customer-assortment.functions.js +3 -3
- package/dist-lib/lib/customer-defaults.test.js +3 -3
- package/dist-lib/lib/customer-insert.d.ts +1 -1
- package/dist-lib/lib/customer-insert.js +2 -2
- package/dist-lib/lib/customer-notes.functions.d.ts +2 -2
- package/dist-lib/lib/customer-notes.functions.js +1 -1
- package/dist-lib/lib/customer-orders.functions.d.ts +1 -1
- package/dist-lib/lib/customer-orders.functions.js +1 -1
- package/dist-lib/lib/customer-revenue.functions.d.ts +1 -1
- package/dist-lib/lib/customer-revenue.functions.js +2 -2
- package/dist-lib/lib/customer-schemas.js +1 -1
- package/dist-lib/lib/customer-schemas.test.js +1 -1
- package/dist-lib/lib/customer-stickers.functions.d.ts +9 -9
- package/dist-lib/lib/customer-stickers.functions.js +2 -2
- package/dist-lib/lib/customers.functions.d.ts +29 -29
- package/dist-lib/lib/customers.functions.js +11 -11
- package/dist-lib/lib/delivery-locations.functions.d.ts +18 -30
- package/dist-lib/lib/delivery-locations.functions.d.ts.map +1 -1
- package/dist-lib/lib/delivery-locations.functions.js +24 -5
- package/dist-lib/lib/external-customers.functions.d.ts +4 -4
- package/dist-lib/lib/external-customers.functions.js +2 -2
- package/dist-lib/lib/floriday-app-url.functions.d.ts +1 -1
- package/dist-lib/lib/floriday-app-url.functions.js +2 -2
- package/dist-lib/lib/floriday-assortment.functions.d.ts +1 -1
- package/dist-lib/lib/floriday-assortment.functions.js +2 -2
- package/dist-lib/lib/floriday-discounts.functions.d.ts +2 -2
- package/dist-lib/lib/floriday-discounts.functions.js +2 -2
- package/dist-lib/lib/floriday-network-status.functions.d.ts +1 -1
- package/dist-lib/lib/floriday-network-status.functions.js +1 -1
- package/dist-lib/lib/floriday-price-import.functions.d.ts +2 -2
- package/dist-lib/lib/floriday-price-import.functions.js +2 -2
- package/dist-lib/lib/floriday-sticker-import.functions.d.ts +1 -1
- package/dist-lib/lib/floriday-sticker-import.functions.js +1 -1
- package/dist-lib/lib/floriday-trade-items.functions.d.ts +1 -1
- package/dist-lib/lib/floriday-trade-items.functions.js +1 -1
- package/dist-lib/lib/floriday-trade-settings.functions.d.ts +1 -1
- package/dist-lib/lib/floriday-trade-settings.functions.js +1 -1
- package/dist-lib/lib/local-discounts.functions.d.ts +7 -7
- package/dist-lib/lib/local-discounts.functions.js +1 -1
- package/dist-lib/lib/logistics-events.functions.d.ts +1 -1
- package/dist-lib/lib/logistics-events.functions.js +1 -1
- package/dist-lib/lib/logistics-strategy.functions.d.ts +4 -4
- package/dist-lib/lib/logistics-strategy.functions.js +1 -1
- package/dist-lib/lib/overdue-invoices.functions.d.ts +1 -1
- package/dist-lib/lib/overdue-invoices.functions.js +2 -2
- package/dist-lib/lib/price-groups-local.functions.d.ts +15 -15
- package/dist-lib/lib/price-groups-local.functions.js +1 -1
- package/dist-lib/lib/price-groups.functions.d.ts +1 -1
- package/dist-lib/lib/price-groups.functions.js +1 -1
- package/dist-lib/lib/twinfield-adopt.functions.d.ts +5 -5
- package/dist-lib/lib/twinfield-adopt.functions.js +7 -7
- package/dist-lib/lib/twinfield-customer-defaults.functions.d.ts +2 -2
- package/dist-lib/lib/twinfield-customer-defaults.functions.js +2 -2
- package/dist-lib/lib/twinfield-customer-defaults.server.js +1 -1
- package/dist-lib/lib/twinfield-ledger.functions.d.ts +2 -2
- package/dist-lib/lib/twinfield-ledger.functions.js +2 -2
- package/dist-lib/lib/twinfield-ledger.server.js +2 -2
- package/dist-lib/lib/twinfield-required-fields.js +1 -1
- package/package.json +2 -2
|
@@ -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,+
|
|
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
|
|
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 = {
|
|
@@ -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";
|