@flowselections/mailbox-orders 1.0.13 → 1.0.15
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/MailboxFilterBar.d.ts +31 -0
- package/dist-lib/components/MailboxFilterBar.d.ts.map +1 -0
- package/dist-lib/components/MailboxFilterBar.js +67 -0
- package/dist-lib/components/MailboxProcessedPage.d.ts.map +1 -1
- package/dist-lib/components/MailboxProcessedPage.js +41 -5
- package/dist-lib/components/MailboxProposalsPage.d.ts.map +1 -1
- package/dist-lib/components/MailboxProposalsPage.js +38 -28
- package/dist-lib/index.d.ts +1 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +1 -0
- package/dist-lib/integrations/supabase/client.d.ts +114 -0
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +114 -0
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +114 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/mailbox.functions.d.ts.map +1 -1
- package/dist-lib/lib/mailbox.functions.js +35 -5
- package/dist-lib/lib/product-name.d.ts +3 -0
- package/dist-lib/lib/product-name.d.ts.map +1 -0
- package/dist-lib/lib/product-name.js +10 -0
- package/package.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** State die bewaard blijft in localStorage (per pagina-sleutel). */
|
|
2
|
+
export declare function usePersistedState<T>(key: string, initial: T): readonly [T, import("react").Dispatch<import("react").SetStateAction<T>>];
|
|
3
|
+
export type PeriodValue = "all" | "today" | "7d" | "30d";
|
|
4
|
+
export type SortOrderValue = "date-desc" | "date-asc";
|
|
5
|
+
/** Hoofdletter- en accent-ongevoelig normaliseren voor zoeken. */
|
|
6
|
+
export declare function normalizeText(value: unknown): string;
|
|
7
|
+
/** Valt een datum binnen de gekozen periode? */
|
|
8
|
+
export declare function matchesPeriod(date: unknown, period: PeriodValue): boolean;
|
|
9
|
+
interface Props {
|
|
10
|
+
search: string;
|
|
11
|
+
onSearchChange: (value: string) => void;
|
|
12
|
+
period: PeriodValue;
|
|
13
|
+
onPeriodChange: (value: PeriodValue) => void;
|
|
14
|
+
sortOrder: SortOrderValue;
|
|
15
|
+
onSortOrderChange: (value: SortOrderValue) => void;
|
|
16
|
+
status?: string;
|
|
17
|
+
onStatusChange?: (value: string) => void;
|
|
18
|
+
statusOptions?: {
|
|
19
|
+
value: string;
|
|
20
|
+
label: string;
|
|
21
|
+
}[];
|
|
22
|
+
filteredCount: number;
|
|
23
|
+
totalCount: number;
|
|
24
|
+
countLabel?: string;
|
|
25
|
+
onClear: () => void;
|
|
26
|
+
hasActiveFilters: boolean;
|
|
27
|
+
searchPlaceholder?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function MailboxFilterBar({ search, onSearchChange, period, onPeriodChange, sortOrder, onSortOrderChange, status, onStatusChange, statusOptions, filteredCount, totalCount, countLabel, onClear, hasActiveFilters, searchPlaceholder, }: Props): import("react").JSX.Element;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=MailboxFilterBar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MailboxFilterBar.d.ts","sourceRoot":"","sources":["../../src/components/MailboxFilterBar.tsx"],"names":[],"mappings":"AAOA,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,6EAkB3D;AAED,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,OAAO,GAAG,IAAI,GAAG,KAAK,CAAC;AACzD,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,UAAU,CAAC;AAEtD,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKpD;AAED,gDAAgD;AAChD,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAYzE;AAED,UAAU,KAAK;IACb,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,EAAE,WAAW,CAAC;IACpB,cAAc,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,SAAS,EAAE,cAAc,CAAC;IAC1B,iBAAiB,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAoBD,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,cAAc,EAAE,aAAa,EACrC,aAAa,EAAE,UAAU,EAAE,UAA0B,EACrD,OAAO,EAAE,gBAAgB,EACzB,iBAAkE,GACnE,EAAE,KAAK,+BA6FP"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@flowselections/core";
|
|
3
|
+
import { Search, X, ArrowDown, ArrowUp } from "lucide-react";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
/** State die bewaard blijft in localStorage (per pagina-sleutel). */
|
|
6
|
+
export function usePersistedState(key, initial) {
|
|
7
|
+
const [value, setValue] = useState(initial);
|
|
8
|
+
const [hydrated, setHydrated] = useState(false);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
try {
|
|
11
|
+
const raw = window.localStorage.getItem(key);
|
|
12
|
+
if (raw !== null)
|
|
13
|
+
setValue(JSON.parse(raw));
|
|
14
|
+
}
|
|
15
|
+
catch { /* negeer */ }
|
|
16
|
+
setHydrated(true);
|
|
17
|
+
}, [key]);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (!hydrated)
|
|
20
|
+
return;
|
|
21
|
+
try {
|
|
22
|
+
window.localStorage.setItem(key, JSON.stringify(value));
|
|
23
|
+
}
|
|
24
|
+
catch { /* negeer */ }
|
|
25
|
+
}, [key, value, hydrated]);
|
|
26
|
+
return [value, setValue];
|
|
27
|
+
}
|
|
28
|
+
/** Hoofdletter- en accent-ongevoelig normaliseren voor zoeken. */
|
|
29
|
+
export function normalizeText(value) {
|
|
30
|
+
return String(value ?? "")
|
|
31
|
+
.normalize("NFD")
|
|
32
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
33
|
+
.toLowerCase();
|
|
34
|
+
}
|
|
35
|
+
/** Valt een datum binnen de gekozen periode? */
|
|
36
|
+
export function matchesPeriod(date, period) {
|
|
37
|
+
if (period === "all")
|
|
38
|
+
return true;
|
|
39
|
+
if (!date)
|
|
40
|
+
return false;
|
|
41
|
+
const d = new Date(date);
|
|
42
|
+
if (Number.isNaN(d.getTime()))
|
|
43
|
+
return false;
|
|
44
|
+
const now = new Date();
|
|
45
|
+
if (period === "today") {
|
|
46
|
+
return d.toDateString() === now.toDateString();
|
|
47
|
+
}
|
|
48
|
+
const days = period === "7d" ? 7 : 30;
|
|
49
|
+
const from = new Date(now.getTime() - days * 24 * 60 * 60 * 1000);
|
|
50
|
+
return d.getTime() >= from.getTime();
|
|
51
|
+
}
|
|
52
|
+
function Chip({ label, onRemove }) {
|
|
53
|
+
return (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-full border bg-muted/40 px-2.5 py-1 text-xs", children: [label, _jsx("button", { type: "button", "aria-label": `${label} verwijderen`, onClick: onRemove, className: "text-muted-foreground hover:text-foreground", children: _jsx(X, { className: "h-3 w-3" }) })] }));
|
|
54
|
+
}
|
|
55
|
+
const PERIOD_LABELS = {
|
|
56
|
+
all: "Alle periodes",
|
|
57
|
+
today: "Vandaag",
|
|
58
|
+
"7d": "Laatste 7 dagen",
|
|
59
|
+
"30d": "Laatste 30 dagen",
|
|
60
|
+
};
|
|
61
|
+
export function MailboxFilterBar({ search, onSearchChange, period, onPeriodChange, sortOrder, onSortOrderChange, status, onStatusChange, statusOptions, filteredCount, totalCount, countLabel = "voorstellen", onClear, hasActiveFilters, searchPlaceholder = "Zoek op klant, afzender, onderwerp of tekst…", }) {
|
|
62
|
+
const sortIcon = sortOrder === "date-desc"
|
|
63
|
+
? _jsx(ArrowDown, { className: "h-4 w-4 text-muted-foreground" })
|
|
64
|
+
: _jsx(ArrowUp, { className: "h-4 w-4 text-muted-foreground" });
|
|
65
|
+
const statusLabel = statusOptions?.find((o) => o.value === status)?.label;
|
|
66
|
+
return (_jsxs("div", { className: "flex flex-col gap-2 shrink-0", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs("div", { className: "relative min-w-[240px] flex-1 max-w-md", children: [_jsx(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { value: search, onChange: (e) => onSearchChange(e.target.value), placeholder: searchPlaceholder, className: "h-9 pl-8 pr-8" }), search && (_jsx("button", { type: "button", "aria-label": "Zoekopdracht wissen", className: "absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground", onClick: () => onSearchChange(""), children: _jsx(X, { className: "h-4 w-4" }) }))] }), _jsxs(Select, { value: period, onValueChange: (v) => onPeriodChange(v), children: [_jsx(SelectTrigger, { className: "h-9 w-[170px]", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "Alle periodes" }), _jsx(SelectItem, { value: "today", children: "Vandaag" }), _jsx(SelectItem, { value: "7d", children: "Laatste 7 dagen" }), _jsx(SelectItem, { value: "30d", children: "Laatste 30 dagen" })] })] }), _jsxs(Select, { value: sortOrder, onValueChange: (v) => onSortOrderChange(v), children: [_jsxs(SelectTrigger, { className: "h-9 w-[210px] flex items-center gap-2", children: [sortIcon, _jsx(SelectValue, {})] }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "date-desc", children: "Datum: nieuwste eerst" }), _jsx(SelectItem, { value: "date-asc", children: "Datum: oudste eerst" })] })] }), statusOptions && onStatusChange && (_jsxs(Select, { value: status ?? "all", onValueChange: onStatusChange, children: [_jsx(SelectTrigger, { className: "h-9 w-[160px]", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: statusOptions.map((o) => (_jsx(SelectItem, { value: o.value, children: o.label }, o.value))) })] })), _jsxs("div", { className: "ml-auto flex items-center gap-2", children: [_jsxs("span", { className: "text-sm text-muted-foreground", children: [filteredCount, " van ", totalCount, " ", countLabel] }), hasActiveFilters && (_jsx(Button, { size: "sm", variant: "ghost", onClick: onClear, children: "Filters wissen" }))] })] }), hasActiveFilters && (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [search && _jsx(Chip, { label: `Zoeken: ${search}`, onRemove: () => onSearchChange("") }), period !== "all" && _jsx(Chip, { label: `Periode: ${PERIOD_LABELS[period]}`, onRemove: () => onPeriodChange("all") }), status && status !== "all" && onStatusChange && (_jsx(Chip, { label: `Status: ${statusLabel ?? status}`, onRemove: () => onStatusChange("all") })), sortOrder !== "date-desc" && (_jsx(Chip, { label: "Sortering: oudste eerst", onRemove: () => onSortOrderChange("date-desc") })), _jsx("button", { type: "button", onClick: onClear, className: "text-xs text-primary underline underline-offset-2", children: "Alles wissen" })] }))] }));
|
|
67
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MailboxProcessedPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProcessedPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MailboxProcessedPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProcessedPage.tsx"],"names":[],"mappings":"AAaA,wBAAgB,oBAAoB,gCA4KnC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from "react";
|
|
2
|
+
import { useEffect, useMemo, useState } from "react";
|
|
3
3
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
4
4
|
import { useServerFn } from "@tanstack/react-start";
|
|
5
5
|
import { toast } from "sonner";
|
|
@@ -7,6 +7,7 @@ import { Badge, Button, Card, CardContent, Table, TableBody, TableCell, TableHea
|
|
|
7
7
|
import { listProposals, reopenProposal, getActiveOrdersMailbox } from "../lib/mailbox.functions";
|
|
8
8
|
import { MailboxAuthBanner } from "./MailboxAuthBanner";
|
|
9
9
|
import { TablePagination } from "./TablePagination";
|
|
10
|
+
import { MailboxFilterBar, usePersistedState, normalizeText, matchesPeriod } from "./MailboxFilterBar";
|
|
10
11
|
export function MailboxProcessedPage() {
|
|
11
12
|
const fetchList = useServerFn(listProposals);
|
|
12
13
|
const reopen = useServerFn(reopenProposal);
|
|
@@ -29,13 +30,44 @@ export function MailboxProcessedPage() {
|
|
|
29
30
|
const items = [
|
|
30
31
|
...(Array.isArray(approved.data?.items) ? approved.data.items : []),
|
|
31
32
|
...(Array.isArray(rejected.data?.items) ? rejected.data.items : []),
|
|
32
|
-
]
|
|
33
|
+
];
|
|
33
34
|
const [busyId, setBusyId] = useState(null);
|
|
34
35
|
const [page, setPage] = useState(1);
|
|
35
36
|
const [pageSize, setPageSize] = useState(25);
|
|
36
|
-
const
|
|
37
|
+
const [search, setSearch] = usePersistedState("mailbox-processed:search", "");
|
|
38
|
+
const [period, setPeriod] = usePersistedState("mailbox-processed:period", "all");
|
|
39
|
+
const [sortOrder, setSortOrder] = usePersistedState("mailbox-processed:sort", "date-desc");
|
|
40
|
+
const [statusFilter, setStatusFilter] = usePersistedState("mailbox-processed:status", "all");
|
|
41
|
+
const customerNameFor = (p) => p.mailbox_messages?.from_name || p.mailbox_messages?.from_email || "Onbekend";
|
|
42
|
+
const filteredItems = useMemo(() => {
|
|
43
|
+
const q = normalizeText(search).trim();
|
|
44
|
+
const filtered = items.filter((p) => {
|
|
45
|
+
if (statusFilter !== "all" && p.status !== statusFilter)
|
|
46
|
+
return false;
|
|
47
|
+
if (!matchesPeriod(p.reviewed_at, period))
|
|
48
|
+
return false;
|
|
49
|
+
if (!q)
|
|
50
|
+
return true;
|
|
51
|
+
const haystack = normalizeText([
|
|
52
|
+
customerNameFor(p),
|
|
53
|
+
p.mailbox_messages?.from_email,
|
|
54
|
+
p.mailbox_messages?.subject,
|
|
55
|
+
p.mailbox_messages?.preview,
|
|
56
|
+
].join(" "));
|
|
57
|
+
return q.split(/\s+/).every((token) => haystack.includes(token));
|
|
58
|
+
});
|
|
59
|
+
return filtered.sort((a, b) => {
|
|
60
|
+
const aDate = a.reviewed_at ?? "";
|
|
61
|
+
const bDate = b.reviewed_at ?? "";
|
|
62
|
+
return sortOrder === "date-desc" ? bDate.localeCompare(aDate) : aDate.localeCompare(bDate);
|
|
63
|
+
});
|
|
64
|
+
}, [items, search, period, sortOrder, statusFilter]);
|
|
65
|
+
const hasActiveFilters = !!search || period !== "all" || sortOrder !== "date-desc" || statusFilter !== "all";
|
|
66
|
+
const clearFilters = () => { setSearch(""); setPeriod("all"); setSortOrder("date-desc"); setStatusFilter("all"); };
|
|
67
|
+
useEffect(() => { setPage(1); }, [search, period, sortOrder, statusFilter]);
|
|
68
|
+
const pageCount = Math.max(1, Math.ceil(filteredItems.length / pageSize));
|
|
37
69
|
const currentPage = Math.min(page, pageCount);
|
|
38
|
-
const pagedItems =
|
|
70
|
+
const pagedItems = filteredItems.slice((currentPage - 1) * pageSize, currentPage * pageSize);
|
|
39
71
|
const handleReopen = async (proposalId) => {
|
|
40
72
|
setBusyId(proposalId);
|
|
41
73
|
try {
|
|
@@ -50,5 +82,9 @@ export function MailboxProcessedPage() {
|
|
|
50
82
|
setBusyId(null);
|
|
51
83
|
}
|
|
52
84
|
};
|
|
53
|
-
return (_jsxs("div", { className: "p-6 flex flex-col gap-4 flex-1 min-h-0 overflow-hidden", children: [_jsx(MailboxAuthBanner, { active: activeMailbox }), _jsx("h1", { className: "text-2xl font-semibold shrink-0", children: "Verwerkt" }),
|
|
85
|
+
return (_jsxs("div", { className: "p-6 flex flex-col gap-4 flex-1 min-h-0 overflow-hidden", children: [_jsx(MailboxAuthBanner, { active: activeMailbox }), _jsx("h1", { className: "text-2xl font-semibold shrink-0", children: "Verwerkt" }), items.length > 0 && (_jsx(MailboxFilterBar, { search: search, onSearchChange: setSearch, period: period, onPeriodChange: setPeriod, sortOrder: sortOrder, onSortOrderChange: setSortOrder, status: statusFilter, onStatusChange: setStatusFilter, statusOptions: [
|
|
86
|
+
{ value: "all", label: "Alle statussen" },
|
|
87
|
+
{ value: "approved", label: "Goedgekeurd" },
|
|
88
|
+
{ value: "rejected", label: "Afgewezen" },
|
|
89
|
+
], filteredCount: filteredItems.length, totalCount: items.length, countLabel: "mails", onClear: clearFilters, hasActiveFilters: hasActiveFilters })), _jsx("div", { className: "flex-1 min-h-0 overflow-y-auto overscroll-contain [scrollbar-gutter:stable]", children: _jsx(Card, { children: _jsxs(CardContent, { className: "p-0", children: [items.length === 0 ? (_jsx("div", { className: "p-8 text-center text-muted-foreground", children: "Nog geen verwerkte voorstellen." })) : filteredItems.length === 0 ? (_jsx("div", { className: "p-8 text-center text-muted-foreground", children: "Geen mails gevonden voor deze zoekopdracht." })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Status" }), _jsx(TableHead, { children: "Afzender" }), _jsx(TableHead, { children: "Onderwerp" }), _jsx(TableHead, { children: "Verwerkt op" }), _jsx(TableHead, { className: "text-right", children: "Acties" })] }) }), _jsx(TableBody, { children: pagedItems.map((p) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Badge, { variant: p.status === "approved" ? "default" : "destructive", children: p.status === "approved" ? "Goedgekeurd" : "Afgewezen" }) }), _jsx(TableCell, { children: p.mailbox_messages?.from_email ?? "-" }), _jsxs(TableCell, { className: "max-w-md", children: [_jsx("div", { className: "truncate", children: p.mailbox_messages?.subject ?? "-" }), _jsx("div", { className: "truncate text-xs text-muted-foreground", children: p.mailbox_messages?.preview || "" })] }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: p.reviewed_at ? new Date(p.reviewed_at).toLocaleString("nl-NL") : "-" }), _jsx(TableCell, { className: "text-right space-x-2", children: p.status === "rejected" && (_jsx(Button, { size: "sm", variant: "outline", disabled: busyId === p.id, onClick: () => handleReopen(p.id), children: busyId === p.id ? "Bezig..." : "Terugzetten" })) })] }, p.id))) })] })), items.length > 0 && (_jsx(TablePagination, { total: filteredItems.length, page: currentPage, pageSize: pageSize, onPageChange: setPage, onPageSizeChange: setPageSize }))] }) }) })] }));
|
|
54
90
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MailboxProposalsPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProposalsPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MailboxProposalsPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProposalsPage.tsx"],"names":[],"mappings":"AA6FA,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AA2CD,wBAAgB,oBAAoB,gCA8bnC"}
|
|
@@ -5,13 +5,14 @@ import { useServerFn } from "@tanstack/react-start";
|
|
|
5
5
|
import { Button, Badge, Card, CardContent, CardHeader, CardTitle, Input, Label, Textarea, Switch, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Dialog, DialogContent, DialogHeader, DialogTitle, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, } from "@flowselections/core";
|
|
6
6
|
import { Check, X, Trash2, Plus, AlertTriangle, RefreshCw } from "lucide-react";
|
|
7
7
|
import { computeEarliestDelivery, isValidDeliveryDate } from "../lib/delivery-date";
|
|
8
|
-
import { listProposals, getProposalDetail, approveProposal, rejectProposal, listCustomersForPicker, createCustomerFromGroup, listProductsForPicker, listDeliveryLocationsForCustomer, listPickupLocations, listCarriersForPicker, getOrderPickDays, getActiveOrdersMailbox, syncMailboxNow,
|
|
8
|
+
import { listProposals, getProposalDetail, approveProposal, rejectProposal, listCustomersForPicker, createCustomerFromGroup, listProductsForPicker, listDeliveryLocationsForCustomer, listPickupLocations, listCarriersForPicker, getOrderPickDays, getActiveOrdersMailbox, syncMailboxNow, refreshProposalsForAgentChange, reparseProposalNow, listBeladingOptionsForProducts, listAllowedLoadCarriers, } from "../lib/mailbox.functions";
|
|
9
9
|
import { enabledLoadCarriers, normalizeAllowedLoadCarriers, EMPTY_LOAD_CARRIERS } from "../lib/load-carriers";
|
|
10
10
|
import { listTemplateFields, listPlantTypesForPicker, listSuppliersForPicker, } from "../lib/mailbox-template.functions";
|
|
11
11
|
import { SearchableSelect } from "./SearchableSelect";
|
|
12
12
|
import { MailboxAuthBanner } from "./MailboxAuthBanner";
|
|
13
13
|
import { EmailPreview } from "./EmailPreview";
|
|
14
14
|
import { TablePagination } from "./TablePagination";
|
|
15
|
+
import { MailboxFilterBar, usePersistedState, normalizeText, matchesPeriod } from "./MailboxFilterBar";
|
|
15
16
|
import { supabase } from "../integrations/supabase/client";
|
|
16
17
|
const beladingKey = (b) => `${b.plants_per_crate}x${b.crates_per_layer}x${b.layers_per_cart}|${b.crate_code ?? ""}|${b.carrier_code ?? ""}`;
|
|
17
18
|
const beladingLabel = (b) => `${b.plants_per_crate} planten/fust · ${b.crates_per_layer} fusten/laag · ${b.layers_per_cart} lagen`;
|
|
@@ -88,7 +89,6 @@ export function MailboxProposalsPage() {
|
|
|
88
89
|
const fetchPickupLocations = useServerFn(listPickupLocations);
|
|
89
90
|
const fetchActive = useServerFn(getActiveOrdersMailbox);
|
|
90
91
|
const fetchSync = useServerFn(syncMailboxNow);
|
|
91
|
-
const fetchLastRun = useServerFn(getLastIngestRun);
|
|
92
92
|
// Server fns met requireSupabaseAuth gooien een raw Response bij een stale
|
|
93
93
|
// bearer-token. Die bubbelt op als "[object Response]" en blankt het scherm.
|
|
94
94
|
// Vang elke fout en geef een lege fallback terug — UI blijft bruikbaar.
|
|
@@ -105,6 +105,9 @@ export function MailboxProposalsPage() {
|
|
|
105
105
|
const [activeId, setActiveId] = useState(null);
|
|
106
106
|
const [page, setPage] = useState(1);
|
|
107
107
|
const [pageSize, setPageSize] = useState(25);
|
|
108
|
+
const [search, setSearch] = usePersistedState("mailbox-proposals:search", "");
|
|
109
|
+
const [period, setPeriod] = usePersistedState("mailbox-proposals:period", "all");
|
|
110
|
+
const [sortOrder, setSortOrder] = usePersistedState("mailbox-proposals:sort", "date-desc");
|
|
108
111
|
const [refsEnabled, setRefsEnabled] = useState(false);
|
|
109
112
|
useEffect(() => { if (activeId)
|
|
110
113
|
setRefsEnabled(true); }, [activeId]);
|
|
@@ -168,22 +171,9 @@ export function MailboxProposalsPage() {
|
|
|
168
171
|
onSuccess: (res) => {
|
|
169
172
|
if (res?.ok && ((res.inserted ?? 0) > 0 || (res.processed ?? 0) > 0)) {
|
|
170
173
|
qc.invalidateQueries({ queryKey: ["mailbox-proposals"] });
|
|
171
|
-
qc.invalidateQueries({ queryKey: ["mailbox-last-ingest-run"] });
|
|
172
174
|
}
|
|
173
175
|
},
|
|
174
176
|
});
|
|
175
|
-
const handleManualSync = () => {
|
|
176
|
-
const p = syncMut.mutateAsync("manual");
|
|
177
|
-
toast.promise(p, {
|
|
178
|
-
loading: "Mailbox synchroniseren...",
|
|
179
|
-
success: (res) => res?.ok
|
|
180
|
-
? (res.inserted ?? 0) > 0
|
|
181
|
-
? `${res.inserted} nieuwe bestelling(en) opgehaald`
|
|
182
|
-
: "Geen nieuwe bestellingen"
|
|
183
|
-
: `Sync mislukt: ${res?.error ?? "onbekende fout"}`,
|
|
184
|
-
error: "Sync mislukt",
|
|
185
|
-
});
|
|
186
|
-
};
|
|
187
177
|
// Realtime hint: zodra er een nieuw event binnenkomt vragen we de server om
|
|
188
178
|
// het meteen te verwerken (zelfde pipeline). Cron is de garantiestrook.
|
|
189
179
|
useEffect(() => {
|
|
@@ -212,13 +202,6 @@ export function MailboxProposalsPage() {
|
|
|
212
202
|
return () => clearInterval(t);
|
|
213
203
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
214
204
|
}, [activeMailboxId]);
|
|
215
|
-
// Laatste ingest-run tonen voor observability.
|
|
216
|
-
const { data: lastRunData } = useQuery({
|
|
217
|
-
queryKey: ["mailbox-last-ingest-run"],
|
|
218
|
-
queryFn: () => safe(() => fetchLastRun()),
|
|
219
|
-
refetchInterval: 60000,
|
|
220
|
-
});
|
|
221
|
-
const lastRun = lastRunData?.run ?? null;
|
|
222
205
|
// AI-agent gewijzigd? Dan worden openstaande voorstellen automatisch opnieuw
|
|
223
206
|
// geanalyseerd met de nieuwste agent. Server-side draait dit ook elke
|
|
224
207
|
// cron-run; hier reageren we direct op wijzigingen in de AI-module.
|
|
@@ -283,9 +266,6 @@ export function MailboxProposalsPage() {
|
|
|
283
266
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
284
267
|
}, []);
|
|
285
268
|
const items = Array.isArray(data?.items) ? data.items : [];
|
|
286
|
-
const pageCount = Math.max(1, Math.ceil(items.length / pageSize));
|
|
287
|
-
const currentPage = Math.min(page, pageCount);
|
|
288
|
-
const pagedItems = items.slice((currentPage - 1) * pageSize, currentPage * pageSize);
|
|
289
269
|
const template = Array.isArray(templateData?.items) ? templateData.items : [];
|
|
290
270
|
const customers = Array.isArray(customersData?.items) ? customersData.items : [];
|
|
291
271
|
const products = Array.isArray(productsData?.items) ? productsData.items : [];
|
|
@@ -310,12 +290,42 @@ export function MailboxProposalsPage() {
|
|
|
310
290
|
}
|
|
311
291
|
return p.mailbox_messages?.from_name || p.mailbox_messages?.from_email || "Onbekend";
|
|
312
292
|
};
|
|
313
|
-
|
|
293
|
+
// --- Zoeken, filteren en sorteren --------------------------------------
|
|
294
|
+
const filteredItems = useMemo(() => {
|
|
295
|
+
const q = normalizeText(search).trim();
|
|
296
|
+
const filtered = items.filter((p) => {
|
|
297
|
+
const name = customerNameFor(p);
|
|
298
|
+
if (!matchesPeriod(p.mailbox_messages?.received_at ?? p.created_at, period))
|
|
299
|
+
return false;
|
|
300
|
+
if (!q)
|
|
301
|
+
return true;
|
|
302
|
+
const haystack = normalizeText([
|
|
303
|
+
name,
|
|
304
|
+
p.mailbox_messages?.from_email,
|
|
305
|
+
p.mailbox_messages?.from_name,
|
|
306
|
+
p.mailbox_messages?.subject,
|
|
307
|
+
p.mailbox_messages?.preview,
|
|
308
|
+
].join(" "));
|
|
309
|
+
return q.split(/\s+/).every((token) => haystack.includes(token));
|
|
310
|
+
});
|
|
311
|
+
return filtered.sort((a, b) => {
|
|
312
|
+
const aDate = a.mailbox_messages?.received_at ?? a.created_at ?? "";
|
|
313
|
+
const bDate = b.mailbox_messages?.received_at ?? b.created_at ?? "";
|
|
314
|
+
return sortOrder === "date-desc" ? bDate.localeCompare(aDate) : aDate.localeCompare(bDate);
|
|
315
|
+
});
|
|
316
|
+
}, [items, customers, search, sortOrder, period]);
|
|
317
|
+
const hasActiveFilters = !!search || period !== "all" || sortOrder !== "date-desc";
|
|
318
|
+
const clearFilters = () => { setSearch(""); setPeriod("all"); setSortOrder("date-desc"); };
|
|
319
|
+
useEffect(() => { setPage(1); }, [search, period, sortOrder]);
|
|
320
|
+
const pageCount = Math.max(1, Math.ceil(filteredItems.length / pageSize));
|
|
321
|
+
const currentPage = Math.min(page, pageCount);
|
|
322
|
+
const pagedItems = filteredItems.slice((currentPage - 1) * pageSize, currentPage * pageSize);
|
|
323
|
+
return (_jsxs("div", { className: "p-6 flex flex-col gap-4 flex-1 min-h-0 overflow-hidden", children: [_jsx(MailboxAuthBanner, { active: activeMailbox }), _jsx("div", { className: "flex items-center justify-between shrink-0", children: _jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold", children: "Bestelvoorstellen" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Nieuw binnengekomen bestellingen die nog handmatig gecontroleerd moeten worden." })] }) }), items.length > 0 && (_jsx(MailboxFilterBar, { search: search, onSearchChange: setSearch, period: period, onPeriodChange: setPeriod, sortOrder: sortOrder, onSortOrderChange: setSortOrder, filteredCount: filteredItems.length, totalCount: items.length, countLabel: "voorstellen", onClear: clearFilters, hasActiveFilters: hasActiveFilters })), _jsx("div", { className: "flex-1 min-h-0 overflow-y-auto overscroll-contain [scrollbar-gutter:stable]", children: isLoading ? (_jsx("div", { className: "text-muted-foreground", children: "Laden..." })) : listError ? (_jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/5 p-4 text-sm", children: [_jsx("p", { className: "font-medium text-destructive", children: "Bestellingen konden niet worden opgehaald." }), _jsxs("p", { className: "text-muted-foreground mt-1", children: [listError?.message ?? "Onbekende fout", " \u2014 de lijst is niet leeg, alleen niet geladen."] }), _jsx(Button, { size: "sm", variant: "outline", className: "mt-3", onClick: () => void refetchList(), children: "Opnieuw proberen" })] })) : items.length === 0 ? (_jsx("p", { className: "text-muted-foreground", children: "Geen bestellingen te controleren." })) : filteredItems.length === 0 ? (_jsx("p", { className: "text-muted-foreground", children: "Geen voorstellen gevonden voor deze zoekopdracht." })) : (_jsx(Card, { children: _jsxs(CardContent, { className: "p-0", children: [_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Klantnaam" }), _jsx(TableHead, { children: "Bericht" }), _jsx(TableHead, { children: "Orderdatum" }), _jsx(TableHead, { children: "Status" })] }) }), _jsx(TableBody, { children: pagedItems.map((p) => {
|
|
314
324
|
const fvs = Array.isArray(p.mailbox_proposal_field_values) ? p.mailbox_proposal_field_values : [];
|
|
315
325
|
const needsReview = fvs.some((v) => v.needs_review);
|
|
316
326
|
const date = p.mailbox_messages?.received_at ?? p.created_at;
|
|
317
|
-
return (_jsxs(TableRow, { className: "cursor-pointer hover:bg-muted/50", onClick: () => setActiveId(p.id), children: [_jsx(TableCell, { className: "font-medium", children: customerNameFor(p) }),
|
|
318
|
-
}) })] }), _jsx(TablePagination, { total:
|
|
327
|
+
return (_jsxs(TableRow, { className: "cursor-pointer hover:bg-muted/50", onClick: () => setActiveId(p.id), children: [_jsx(TableCell, { className: "font-medium", children: customerNameFor(p) }), _jsxs(TableCell, { className: "max-w-sm", children: [_jsx("div", { className: "truncate text-sm font-medium", children: p.mailbox_messages?.subject || "(geen onderwerp)" }), _jsx("div", { className: "truncate text-xs text-muted-foreground", children: p.mailbox_messages?.preview || "Geen voorbeeldtekst" })] }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: date ? new Date(date).toLocaleDateString("nl-NL") : "-" }), _jsx(TableCell, { children: _jsx(Badge, { variant: "secondary", children: "Te controleren" }) })] }, p.id));
|
|
328
|
+
}) })] }), _jsx(TablePagination, { total: filteredItems.length, page: currentPage, pageSize: pageSize, onPageChange: setPage, onPageSizeChange: setPageSize })] }) })) }), _jsx(Dialog, { open: !!activeId, onOpenChange: (o) => { if (!o) {
|
|
319
329
|
setActiveId(null);
|
|
320
330
|
setReparseError(null);
|
|
321
331
|
} }, children: _jsx(DialogContent, { className: "max-w-[95vw] w-[95vw] h-[92vh] max-h-[92vh] p-0 flex flex-col overflow-hidden", children: !active ? (_jsxs("div", { className: "flex-1 flex flex-col items-center justify-center gap-2 text-sm text-muted-foreground", children: [_jsx(DialogTitle, { className: "text-base", children: "Bestelling" }), detailLoading ? "Bestelling laden…" : "Bestelling niet gevonden."] })) : (_jsxs(_Fragment, { children: [_jsxs(DialogHeader, { className: "px-6 pt-6 pb-3 shrink-0 border-b", children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsx(DialogTitle, { children: customerNameFor(activeSummary ?? active) }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", className: "mr-8", disabled: reparseMutation.isPending, onClick: () => reparseMutation.mutate(active.id), children: [_jsx(RefreshCw, { className: `h-4 w-4 mr-2 ${reparseMutation.isPending ? "animate-spin" : ""}` }), reparseMutation.isPending ? "Analyseren…" : "Mail opnieuw analyseren"] })] }), reparseError && (_jsxs("div", { className: "mt-2 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [_jsx(AlertTriangle, { className: "h-4 w-4 mt-0.5 shrink-0" }), _jsx("span", { children: reparseError })] }))] }), _jsx("div", { className: "flex-1 min-h-0 overflow-hidden p-6", children: _jsx(ProposalEditor, { proposal: active, template: template, customers: customers, products: products, allowBackorder: allowBackorder, plantTypes: plantTypes, suppliers: suppliers, carriers: carriers, pickupLocations: pickupLocations, onApprove: async (payload) => {
|
package/dist-lib/index.d.ts
CHANGED
|
@@ -5,5 +5,6 @@ export { SearchableSelect } from "./components/SearchableSelect";
|
|
|
5
5
|
export { MailboxProcessedPage } from "./components/MailboxProcessedPage";
|
|
6
6
|
export { EmailPreview } from "./components/EmailPreview";
|
|
7
7
|
export { TablePagination } from "./components/TablePagination";
|
|
8
|
+
export { MailboxFilterBar } from "./components/MailboxFilterBar";
|
|
8
9
|
export declare const mailboxOrdersModule: FlowModule;
|
|
9
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist-lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE,eAAO,MAAM,mBAAmB,EAAE,UAmBjC,CAAC"}
|
package/dist-lib/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export { SearchableSelect } from "./components/SearchableSelect";
|
|
|
10
10
|
export { MailboxProcessedPage } from "./components/MailboxProcessedPage";
|
|
11
11
|
export { EmailPreview } from "./components/EmailPreview";
|
|
12
12
|
export { TablePagination } from "./components/TablePagination";
|
|
13
|
+
export { MailboxFilterBar } from "./components/MailboxFilterBar";
|
|
13
14
|
export const mailboxOrdersModule = {
|
|
14
15
|
id: "mailbox_orders",
|
|
15
16
|
name: "Mailbox bestellingen",
|
|
@@ -6479,6 +6479,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
6479
6479
|
Row: {
|
|
6480
6480
|
buyer_organization_id: string | null;
|
|
6481
6481
|
connection_id: string;
|
|
6482
|
+
controlled_at: string | null;
|
|
6482
6483
|
created_at: string;
|
|
6483
6484
|
data: import("./types").Json;
|
|
6484
6485
|
floriday_id: string;
|
|
@@ -6490,6 +6491,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
6490
6491
|
Insert: {
|
|
6491
6492
|
buyer_organization_id?: string | null;
|
|
6492
6493
|
connection_id: string;
|
|
6494
|
+
controlled_at?: string | null;
|
|
6493
6495
|
created_at?: string;
|
|
6494
6496
|
data: import("./types").Json;
|
|
6495
6497
|
floriday_id: string;
|
|
@@ -6501,6 +6503,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
6501
6503
|
Update: {
|
|
6502
6504
|
buyer_organization_id?: string | null;
|
|
6503
6505
|
connection_id?: string;
|
|
6506
|
+
controlled_at?: string | null;
|
|
6504
6507
|
created_at?: string;
|
|
6505
6508
|
data?: import("./types").Json;
|
|
6506
6509
|
floriday_id?: string;
|
|
@@ -7402,6 +7405,54 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
7402
7405
|
};
|
|
7403
7406
|
Relationships: [];
|
|
7404
7407
|
};
|
|
7408
|
+
invoice_timing_settings: {
|
|
7409
|
+
Row: {
|
|
7410
|
+
anchor: string;
|
|
7411
|
+
business_days_only: boolean;
|
|
7412
|
+
created_at: string;
|
|
7413
|
+
enabled: boolean;
|
|
7414
|
+
id: string;
|
|
7415
|
+
offset_days: number;
|
|
7416
|
+
pickup_anchor: string;
|
|
7417
|
+
pickup_business_days_only: boolean;
|
|
7418
|
+
pickup_offset_days: number;
|
|
7419
|
+
pickup_time_of_day: string;
|
|
7420
|
+
singleton: boolean;
|
|
7421
|
+
time_of_day: string;
|
|
7422
|
+
updated_at: string;
|
|
7423
|
+
};
|
|
7424
|
+
Insert: {
|
|
7425
|
+
anchor?: string;
|
|
7426
|
+
business_days_only?: boolean;
|
|
7427
|
+
created_at?: string;
|
|
7428
|
+
enabled?: boolean;
|
|
7429
|
+
id?: string;
|
|
7430
|
+
offset_days?: number;
|
|
7431
|
+
pickup_anchor?: string;
|
|
7432
|
+
pickup_business_days_only?: boolean;
|
|
7433
|
+
pickup_offset_days?: number;
|
|
7434
|
+
pickup_time_of_day?: string;
|
|
7435
|
+
singleton?: boolean;
|
|
7436
|
+
time_of_day?: string;
|
|
7437
|
+
updated_at?: string;
|
|
7438
|
+
};
|
|
7439
|
+
Update: {
|
|
7440
|
+
anchor?: string;
|
|
7441
|
+
business_days_only?: boolean;
|
|
7442
|
+
created_at?: string;
|
|
7443
|
+
enabled?: boolean;
|
|
7444
|
+
id?: string;
|
|
7445
|
+
offset_days?: number;
|
|
7446
|
+
pickup_anchor?: string;
|
|
7447
|
+
pickup_business_days_only?: boolean;
|
|
7448
|
+
pickup_offset_days?: number;
|
|
7449
|
+
pickup_time_of_day?: string;
|
|
7450
|
+
singleton?: boolean;
|
|
7451
|
+
time_of_day?: string;
|
|
7452
|
+
updated_at?: string;
|
|
7453
|
+
};
|
|
7454
|
+
Relationships: [];
|
|
7455
|
+
};
|
|
7405
7456
|
itk_contact_persons: {
|
|
7406
7457
|
Row: {
|
|
7407
7458
|
created_at: string;
|
|
@@ -10978,6 +11029,42 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
10978
11029
|
};
|
|
10979
11030
|
Relationships: [];
|
|
10980
11031
|
};
|
|
11032
|
+
order_invoice_links: {
|
|
11033
|
+
Row: {
|
|
11034
|
+
attempts: number;
|
|
11035
|
+
created_at: string;
|
|
11036
|
+
error_message: string | null;
|
|
11037
|
+
id: string;
|
|
11038
|
+
invoice_number: string | null;
|
|
11039
|
+
order_id: string;
|
|
11040
|
+
processed_at: string | null;
|
|
11041
|
+
status: string;
|
|
11042
|
+
updated_at: string;
|
|
11043
|
+
};
|
|
11044
|
+
Insert: {
|
|
11045
|
+
attempts?: number;
|
|
11046
|
+
created_at?: string;
|
|
11047
|
+
error_message?: string | null;
|
|
11048
|
+
id?: string;
|
|
11049
|
+
invoice_number?: string | null;
|
|
11050
|
+
order_id: string;
|
|
11051
|
+
processed_at?: string | null;
|
|
11052
|
+
status?: string;
|
|
11053
|
+
updated_at?: string;
|
|
11054
|
+
};
|
|
11055
|
+
Update: {
|
|
11056
|
+
attempts?: number;
|
|
11057
|
+
created_at?: string;
|
|
11058
|
+
error_message?: string | null;
|
|
11059
|
+
id?: string;
|
|
11060
|
+
invoice_number?: string | null;
|
|
11061
|
+
order_id?: string;
|
|
11062
|
+
processed_at?: string | null;
|
|
11063
|
+
status?: string;
|
|
11064
|
+
updated_at?: string;
|
|
11065
|
+
};
|
|
11066
|
+
Relationships: [];
|
|
11067
|
+
};
|
|
10981
11068
|
order_items: {
|
|
10982
11069
|
Row: {
|
|
10983
11070
|
crates_per_layer: number | null;
|
|
@@ -11160,6 +11247,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
11160
11247
|
delivery_date: string | null;
|
|
11161
11248
|
floriday_sales_order_id: string | null;
|
|
11162
11249
|
id: string;
|
|
11250
|
+
invoice_due_at: string | null;
|
|
11163
11251
|
is_reservation: boolean;
|
|
11164
11252
|
notes: string | null;
|
|
11165
11253
|
order_date: string;
|
|
@@ -11181,6 +11269,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
11181
11269
|
delivery_date?: string | null;
|
|
11182
11270
|
floriday_sales_order_id?: string | null;
|
|
11183
11271
|
id?: string;
|
|
11272
|
+
invoice_due_at?: string | null;
|
|
11184
11273
|
is_reservation?: boolean;
|
|
11185
11274
|
notes?: string | null;
|
|
11186
11275
|
order_date?: string;
|
|
@@ -11202,6 +11291,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
11202
11291
|
delivery_date?: string | null;
|
|
11203
11292
|
floriday_sales_order_id?: string | null;
|
|
11204
11293
|
id?: string;
|
|
11294
|
+
invoice_due_at?: string | null;
|
|
11205
11295
|
is_reservation?: boolean;
|
|
11206
11296
|
notes?: string | null;
|
|
11207
11297
|
order_date?: string;
|
|
@@ -15396,6 +15486,8 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
15396
15486
|
};
|
|
15397
15487
|
twinfield_invoice_settings: {
|
|
15398
15488
|
Row: {
|
|
15489
|
+
auto_invoice_enabled: boolean;
|
|
15490
|
+
auto_invoice_trigger_statuses: string[];
|
|
15399
15491
|
created_at: string;
|
|
15400
15492
|
debtor_gl_account: string;
|
|
15401
15493
|
default_credit_invoice_type: string | null;
|
|
@@ -15416,6 +15508,8 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
15416
15508
|
vat_code_export: string | null;
|
|
15417
15509
|
};
|
|
15418
15510
|
Insert: {
|
|
15511
|
+
auto_invoice_enabled?: boolean;
|
|
15512
|
+
auto_invoice_trigger_statuses?: string[];
|
|
15419
15513
|
created_at?: string;
|
|
15420
15514
|
debtor_gl_account?: string;
|
|
15421
15515
|
default_credit_invoice_type?: string | null;
|
|
@@ -15436,6 +15530,8 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
15436
15530
|
vat_code_export?: string | null;
|
|
15437
15531
|
};
|
|
15438
15532
|
Update: {
|
|
15533
|
+
auto_invoice_enabled?: boolean;
|
|
15534
|
+
auto_invoice_trigger_statuses?: string[];
|
|
15439
15535
|
created_at?: string;
|
|
15440
15536
|
debtor_gl_account?: string;
|
|
15441
15537
|
default_credit_invoice_type?: string | null;
|
|
@@ -18358,6 +18454,10 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
18358
18454
|
processed_items: number;
|
|
18359
18455
|
}[];
|
|
18360
18456
|
};
|
|
18457
|
+
backfill_order_auto_invoice_queue: {
|
|
18458
|
+
Args: never;
|
|
18459
|
+
Returns: number;
|
|
18460
|
+
};
|
|
18361
18461
|
calculate_layer_stock: {
|
|
18362
18462
|
Args: {
|
|
18363
18463
|
p_product_id: string;
|
|
@@ -18588,6 +18688,10 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
18588
18688
|
Args: never;
|
|
18589
18689
|
Returns: undefined;
|
|
18590
18690
|
};
|
|
18691
|
+
cleanup_voorraad_module_history: {
|
|
18692
|
+
Args: never;
|
|
18693
|
+
Returns: undefined;
|
|
18694
|
+
};
|
|
18591
18695
|
complete_floriday_stock_queue: {
|
|
18592
18696
|
Args: {
|
|
18593
18697
|
p_attempt_id?: string;
|
|
@@ -20312,6 +20416,12 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
20312
20416
|
};
|
|
20313
20417
|
Returns: undefined;
|
|
20314
20418
|
};
|
|
20419
|
+
reset_stalled_floriday_stock_queue: {
|
|
20420
|
+
Args: {
|
|
20421
|
+
p_include_failed?: boolean;
|
|
20422
|
+
};
|
|
20423
|
+
Returns: number;
|
|
20424
|
+
};
|
|
20315
20425
|
resolve_group_allocation: {
|
|
20316
20426
|
Args: {
|
|
20317
20427
|
_needed: number;
|
|
@@ -20366,6 +20476,10 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
|
|
|
20366
20476
|
Args: never;
|
|
20367
20477
|
Returns: undefined;
|
|
20368
20478
|
};
|
|
20479
|
+
run_floriday_stock_queue_process: {
|
|
20480
|
+
Args: never;
|
|
20481
|
+
Returns: undefined;
|
|
20482
|
+
};
|
|
20369
20483
|
run_logistics_tasks_dispatch: {
|
|
20370
20484
|
Args: never;
|
|
20371
20485
|
Returns: undefined;
|