@flowselections/mailbox-orders 1.0.53 → 1.0.55
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/MailboxAuthBanner.d.ts.map +1 -1
- package/dist-lib/components/MailboxAuthBanner.js +6 -5
- package/dist-lib/components/MailboxPageFrame.d.ts +19 -0
- package/dist-lib/components/MailboxPageFrame.d.ts.map +1 -0
- package/dist-lib/components/MailboxPageFrame.js +95 -0
- package/dist-lib/components/MailboxProcessedPage.d.ts.map +1 -1
- package/dist-lib/components/MailboxProcessedPage.js +94 -62
- package/dist-lib/components/MailboxProposalsPage.d.ts.map +1 -1
- package/dist-lib/components/MailboxProposalsPage.js +178 -71
- package/dist-lib/components/MailboxSkippedPage.d.ts.map +1 -1
- package/dist-lib/components/MailboxSkippedPage.js +80 -14
- package/dist-lib/components/MailboxStatusLine.d.ts +3 -1
- package/dist-lib/components/MailboxStatusLine.d.ts.map +1 -1
- package/dist-lib/components/MailboxStatusLine.js +31 -8
- package/dist-lib/components/fs-ui/DataTable.d.ts +36 -0
- package/dist-lib/components/fs-ui/DataTable.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/DataTable.js +33 -0
- package/dist-lib/components/fs-ui/EmptyState.d.ts +9 -0
- package/dist-lib/components/fs-ui/EmptyState.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/EmptyState.js +5 -0
- package/dist-lib/components/fs-ui/FilterChips.d.ts +13 -0
- package/dist-lib/components/fs-ui/FilterChips.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/FilterChips.js +8 -0
- package/dist-lib/components/fs-ui/HoverTip.d.ts +15 -0
- package/dist-lib/components/fs-ui/HoverTip.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/HoverTip.js +24 -0
- package/dist-lib/components/fs-ui/InlineAlert.d.ts +9 -0
- package/dist-lib/components/fs-ui/InlineAlert.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/InlineAlert.js +14 -0
- package/dist-lib/components/fs-ui/KpiRow.d.ts +6 -0
- package/dist-lib/components/fs-ui/KpiRow.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/KpiRow.js +7 -0
- package/dist-lib/components/fs-ui/KpiTile.d.ts +21 -0
- package/dist-lib/components/fs-ui/KpiTile.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/KpiTile.js +40 -0
- package/dist-lib/components/fs-ui/MobilePrimaryAction.d.ts +10 -0
- package/dist-lib/components/fs-ui/MobilePrimaryAction.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/MobilePrimaryAction.js +7 -0
- package/dist-lib/components/fs-ui/PageHeader.d.ts +8 -0
- package/dist-lib/components/fs-ui/PageHeader.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/PageHeader.js +5 -0
- package/dist-lib/components/fs-ui/PillTabs.d.ts +15 -0
- package/dist-lib/components/fs-ui/PillTabs.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/PillTabs.js +14 -0
- package/dist-lib/components/fs-ui/SearchInput.d.ts +12 -0
- package/dist-lib/components/fs-ui/SearchInput.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/SearchInput.js +33 -0
- package/dist-lib/components/fs-ui/ShortcutHelp.d.ts +7 -0
- package/dist-lib/components/fs-ui/ShortcutHelp.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/ShortcutHelp.js +6 -0
- package/dist-lib/components/fs-ui/StatusIcon.d.ts +8 -0
- package/dist-lib/components/fs-ui/StatusIcon.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/StatusIcon.js +16 -0
- package/dist-lib/components/fs-ui/TableSkeleton.d.ts +6 -0
- package/dist-lib/components/fs-ui/TableSkeleton.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/TableSkeleton.js +6 -0
- package/dist-lib/components/fs-ui/Toolbar.d.ts +8 -0
- package/dist-lib/components/fs-ui/Toolbar.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/Toolbar.js +5 -0
- package/dist-lib/components/fs-ui/UpdatedAt.d.ts +7 -0
- package/dist-lib/components/fs-ui/UpdatedAt.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/UpdatedAt.js +9 -0
- package/dist-lib/components/fs-ui/useListHotkeys.d.ts +18 -0
- package/dist-lib/components/fs-ui/useListHotkeys.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/useListHotkeys.js +48 -0
- package/dist-lib/components/settings/MailboxAiPromptCard.d.ts +2 -1
- package/dist-lib/components/settings/MailboxAiPromptCard.d.ts.map +1 -1
- package/dist-lib/components/settings/MailboxAiPromptCard.js +9 -1
- package/dist-lib/components/settings/MailboxFilterSettingsCard.js +1 -1
- package/dist-lib/components/settings/MailboxTestSetCard.d.ts +2 -1
- package/dist-lib/components/settings/MailboxTestSetCard.d.ts.map +1 -1
- package/dist-lib/components/settings/MailboxTestSetCard.js +10 -2
- package/dist-lib/integrations/supabase/types.d.ts +372 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/mailbox-list.functions.d.ts +67 -0
- package/dist-lib/lib/mailbox-list.functions.d.ts.map +1 -0
- package/dist-lib/lib/mailbox-list.functions.js +63 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PillTabs.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/PillTabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,SAAS,GACV,EAAE;IACD,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BA6CA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** Tabbladen als pillen met icoon, label en teller. Veegbaar op mobiel. */
|
|
3
|
+
export function PillTabs({ tabs, active, onSelect, ariaLabel, }) {
|
|
4
|
+
return (_jsxs("div", { className: "relative shrink-0", children: [_jsx("div", { role: "tablist", "aria-label": ariaLabel, className: "-mx-4 flex gap-2 overflow-x-auto px-4 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden sm:mx-0 sm:px-0", children: tabs.map((t) => {
|
|
5
|
+
const isActive = t.key === active;
|
|
6
|
+
const empty = (t.count ?? null) === 0;
|
|
7
|
+
return (_jsxs("button", { type: "button", role: "tab", "aria-selected": isActive, onClick: () => onSelect(t.key), className: "inline-flex h-9 shrink-0 items-center gap-2 rounded-lg border px-3 text-sm font-medium transition-colors duration-150 ease-out motion-reduce:transition-none " +
|
|
8
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring [&_svg]:h-4 [&_svg]:w-4 " +
|
|
9
|
+
(isActive
|
|
10
|
+
? "border-primary/40 bg-primary/10 text-primary"
|
|
11
|
+
: "border-transparent text-foreground hover:bg-muted " + (empty ? "text-muted-foreground" : "")), children: [t.icon, _jsx("span", { children: t.label }), t.count != null && (_jsx("span", { className: "inline-flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-xs font-semibold tabular-nums " +
|
|
12
|
+
(isActive ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"), children: t.count }))] }, t.key));
|
|
13
|
+
}) }), _jsx("div", { className: "pointer-events-none absolute inset-y-0 right-0 w-8 bg-gradient-to-l from-background sm:hidden", "aria-hidden": true })] }));
|
|
14
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zoekveld: filtert tijdens typen (250 ms), wis-kruisje, Esc wist.
|
|
3
|
+
* De sneltoets "/" wordt door de pagina geregeld (useListHotkeys).
|
|
4
|
+
*/
|
|
5
|
+
export declare const SearchInput: import("react").ForwardRefExoticComponent<{
|
|
6
|
+
value: string;
|
|
7
|
+
onChange: (v: string) => void;
|
|
8
|
+
placeholder?: string;
|
|
9
|
+
delay?: number;
|
|
10
|
+
ariaLabel?: string;
|
|
11
|
+
} & import("react").RefAttributes<HTMLInputElement>>;
|
|
12
|
+
//# sourceMappingURL=SearchInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchInput.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/SearchInput.tsx"],"names":[],"mappings":"AAGA;;;GAGG;AACH,eAAO,MAAM,WAAW;WACf,MAAM;cACH,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI;kBACf,MAAM;YACZ,MAAM;gBACF,MAAM;oDAgDlB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { Search, X } from "lucide-react";
|
|
4
|
+
/**
|
|
5
|
+
* Zoekveld: filtert tijdens typen (250 ms), wis-kruisje, Esc wist.
|
|
6
|
+
* De sneltoets "/" wordt door de pagina geregeld (useListHotkeys).
|
|
7
|
+
*/
|
|
8
|
+
export const SearchInput = forwardRef(function SearchInput({ value, onChange, placeholder = "Zoeken…", delay = 250, ariaLabel }, ref) {
|
|
9
|
+
const [local, setLocal] = useState(value);
|
|
10
|
+
const timer = useRef(null);
|
|
11
|
+
useEffect(() => { setLocal(value); }, [value]);
|
|
12
|
+
const push = (v, now = false) => {
|
|
13
|
+
setLocal(v);
|
|
14
|
+
if (timer.current)
|
|
15
|
+
clearTimeout(timer.current);
|
|
16
|
+
if (now)
|
|
17
|
+
onChange(v);
|
|
18
|
+
else
|
|
19
|
+
timer.current = setTimeout(() => onChange(v), delay);
|
|
20
|
+
};
|
|
21
|
+
useEffect(() => () => { if (timer.current)
|
|
22
|
+
clearTimeout(timer.current); }, []);
|
|
23
|
+
return (_jsxs("div", { className: "relative w-full max-w-md", children: [_jsx(Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground", "aria-hidden": true }), _jsx("input", { ref: ref, type: "search", value: local, "aria-label": ariaLabel ?? placeholder, placeholder: placeholder, onChange: (e) => push(e.target.value), onKeyDown: (e) => {
|
|
24
|
+
if (e.key === "Escape") {
|
|
25
|
+
e.preventDefault();
|
|
26
|
+
if (local)
|
|
27
|
+
push("", true);
|
|
28
|
+
else
|
|
29
|
+
e.target.blur();
|
|
30
|
+
}
|
|
31
|
+
}, className: "h-10 w-full rounded-lg border border-input bg-background pl-9 pr-16 text-base text-foreground placeholder:text-muted-foreground sm:h-9 sm:text-sm " +
|
|
32
|
+
"transition-shadow duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring [&::-webkit-search-cancel-button]:hidden" }), local ? (_jsx("button", { type: "button", "aria-label": "Zoekopdracht wissen", onClick: () => push("", true), className: "absolute right-2 top-1/2 inline-flex h-7 w-7 -translate-y-1/2 items-center justify-center rounded text-muted-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: _jsx(X, { className: "h-4 w-4" }) })) : (_jsx("kbd", { className: "pointer-events-none absolute right-2 top-1/2 hidden -translate-y-1/2 rounded-sm border border-border px-1.5 text-[11px] text-muted-foreground sm:inline-block", children: "/" }))] }));
|
|
33
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Overzicht van de sneltoetsen (opent met "?"). */
|
|
2
|
+
export declare function ShortcutHelp({ open, onOpenChange, items }: {
|
|
3
|
+
open: boolean;
|
|
4
|
+
onOpenChange: (v: boolean) => void;
|
|
5
|
+
items: Array<[string, string]>;
|
|
6
|
+
}): import("react").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=ShortcutHelp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShortcutHelp.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/ShortcutHelp.tsx"],"names":[],"mappings":"AAEA,oDAAoD;AACpD,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAAC,KAAK,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,+BAgBhJ"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@flowselections/core";
|
|
3
|
+
/** Overzicht van de sneltoetsen (opent met "?"). */
|
|
4
|
+
export function ShortcutHelp({ open, onOpenChange, items }) {
|
|
5
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "max-w-sm rounded-lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: "Sneltoetsen" }) }), _jsx("ul", { className: "space-y-2 text-sm", children: items.map(([k, label]) => (_jsxs("li", { className: "flex items-center justify-between gap-4", children: [_jsx("span", { className: "text-muted-foreground", children: label }), _jsx("kbd", { className: "rounded-sm border border-border px-1.5 py-0.5 text-xs", children: k })] }, k))) })] }) }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type StatusTone = "done" | "open" | "busy" | "error" | "rejected";
|
|
2
|
+
/** Klein rond statusicoon met tooltip. Geen gekleurd vlak eromheen. */
|
|
3
|
+
export declare function StatusIcon({ tone, label, detail }: {
|
|
4
|
+
tone: StatusTone;
|
|
5
|
+
label: string;
|
|
6
|
+
detail?: string;
|
|
7
|
+
}): import("react").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=StatusIcon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusIcon.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/StatusIcon.tsx"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;AAWzE,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,+BAevG"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { AlertCircle, CheckCircle2, Circle, Clock, XCircle } from "lucide-react";
|
|
3
|
+
import { HoverTip } from "./HoverTip.js";
|
|
4
|
+
const ICON = { done: CheckCircle2, open: Circle, busy: Clock, error: AlertCircle, rejected: XCircle };
|
|
5
|
+
const TONE = {
|
|
6
|
+
done: "text-primary",
|
|
7
|
+
open: "text-muted-foreground",
|
|
8
|
+
busy: "text-warning",
|
|
9
|
+
error: "text-destructive",
|
|
10
|
+
rejected: "text-muted-foreground",
|
|
11
|
+
};
|
|
12
|
+
/** Klein rond statusicoon met tooltip. Geen gekleurd vlak eromheen. */
|
|
13
|
+
export function StatusIcon({ tone, label, detail }) {
|
|
14
|
+
const Icon = ICON[tone];
|
|
15
|
+
return (_jsx(HoverTip, { label: label, content: _jsxs("div", { children: [_jsx("div", { className: "text-[13px] font-semibold text-foreground", children: label }), detail && _jsx("div", { className: "mt-1 text-muted-foreground", children: detail })] }), children: _jsx(Icon, { className: "h-4 w-4 " + TONE[tone], "aria-hidden": true }) }));
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TableSkeleton.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/TableSkeleton.tsx"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,IAAQ,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,+BAwBxF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Skeleton } from "@flowselections/core";
|
|
3
|
+
/** Skelet in de vorm van de echte tabel (desktop) of kaarten (mobiel). */
|
|
4
|
+
export function TableSkeleton({ columns, rows = 8 }) {
|
|
5
|
+
return (_jsxs("div", { className: "overflow-hidden rounded-xl border border-border bg-card shadow-sm", "aria-busy": "true", "aria-label": "Laden", children: [_jsxs("div", { className: "hidden md:block", children: [_jsx("div", { className: "grid h-10 items-center gap-4 border-b border-border px-4", style: { gridTemplateColumns: columns.join(" ") }, children: columns.map((_, i) => _jsx(Skeleton, { className: "h-3 w-16" }, i)) }), Array.from({ length: rows }).map((_, r) => (_jsx("div", { className: "grid h-[60px] items-center gap-4 border-b border-border px-4 last:border-0", style: { gridTemplateColumns: columns.join(" ") }, children: columns.map((_, i) => _jsx(Skeleton, { className: i === 1 ? "h-4 w-4/5" : "h-4 w-3/5" }, i)) }, r)))] }), _jsx("div", { className: "divide-y divide-border md:hidden", children: Array.from({ length: Math.min(rows, 5) }).map((_, r) => (_jsxs("div", { className: "space-y-2 p-4", children: [_jsx(Skeleton, { className: "h-4 w-1/2" }), _jsx(Skeleton, { className: "h-3 w-4/5" }), _jsx(Skeleton, { className: "h-3 w-1/3" })] }, r))) })] }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/** Werkbalk: zoeken + filters links, extra acties rechts; chips eronder. */
|
|
3
|
+
export declare function Toolbar({ children, right, chips }: {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
right?: ReactNode;
|
|
6
|
+
chips?: ReactNode;
|
|
7
|
+
}): import("react").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=Toolbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/Toolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,4EAA4E;AAC5E,wBAAgB,OAAO,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,+BAUhH"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** Werkbalk: zoeken + filters links, extra acties rechts; chips eronder. */
|
|
3
|
+
export function Toolbar({ children, right, chips }) {
|
|
4
|
+
return (_jsxs("div", { className: "flex shrink-0 flex-col gap-2", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: children }), right && _jsx("div", { className: "flex items-center gap-2", children: right })] }), chips] }));
|
|
5
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/** "Bijgewerkt hh:mm" met optionele extra tekst. */
|
|
3
|
+
export declare function UpdatedAt({ at, extra }: {
|
|
4
|
+
at: number | string | Date | null | undefined;
|
|
5
|
+
extra?: ReactNode;
|
|
6
|
+
}): import("react").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=UpdatedAt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UpdatedAt.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/UpdatedAt.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,oDAAoD;AACpD,wBAAgB,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE;IAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,+BAW5G"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** "Bijgewerkt hh:mm" met optionele extra tekst. */
|
|
3
|
+
export function UpdatedAt({ at, extra }) {
|
|
4
|
+
const d = at ? new Date(at) : null;
|
|
5
|
+
const time = d && !Number.isNaN(d.getTime())
|
|
6
|
+
? d.toLocaleTimeString("nl-NL", { hour: "2-digit", minute: "2-digit" })
|
|
7
|
+
: null;
|
|
8
|
+
return (_jsxs("span", { className: "tabular-nums", children: [time ? `Bijgewerkt ${time}` : "Nog niet bijgewerkt", extra ? _jsxs(_Fragment, { children: [" \u00B7 ", extra] }) : null] }));
|
|
9
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** True als de gebruiker in een invoerveld typt; dan werken sneltoetsen niet. */
|
|
2
|
+
export declare function isTypingTarget(t: EventTarget | null): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Sneltoetsen zoals Verkooporders: / zoeken, J/K rij, Enter openen, Esc wissen,
|
|
5
|
+
* ? overzicht, N nieuw (alleen als onNew is meegegeven). Nooit tijdens typen of
|
|
6
|
+
* als een dialoog open staat (`disabled`).
|
|
7
|
+
*/
|
|
8
|
+
export declare function useListHotkeys(opts: {
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
onSearch?: () => void;
|
|
11
|
+
onNext?: () => void;
|
|
12
|
+
onPrev?: () => void;
|
|
13
|
+
onOpen?: () => void;
|
|
14
|
+
onEscape?: () => void;
|
|
15
|
+
onHelp?: () => void;
|
|
16
|
+
onNew?: () => void;
|
|
17
|
+
}): void;
|
|
18
|
+
//# sourceMappingURL=useListHotkeys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useListHotkeys.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/useListHotkeys.ts"],"names":[],"mappings":"AAEA,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAK7D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CACpB,QAqBA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
/** True als de gebruiker in een invoerveld typt; dan werken sneltoetsen niet. */
|
|
3
|
+
export function isTypingTarget(t) {
|
|
4
|
+
const el = t;
|
|
5
|
+
if (!el || !el.tagName)
|
|
6
|
+
return false;
|
|
7
|
+
const tag = el.tagName.toLowerCase();
|
|
8
|
+
return tag === "input" || tag === "textarea" || tag === "select" || el.isContentEditable === true;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Sneltoetsen zoals Verkooporders: / zoeken, J/K rij, Enter openen, Esc wissen,
|
|
12
|
+
* ? overzicht, N nieuw (alleen als onNew is meegegeven). Nooit tijdens typen of
|
|
13
|
+
* als een dialoog open staat (`disabled`).
|
|
14
|
+
*/
|
|
15
|
+
export function useListHotkeys(opts) {
|
|
16
|
+
const ref = useRef(opts);
|
|
17
|
+
ref.current = opts;
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const h = (e) => {
|
|
20
|
+
const o = ref.current;
|
|
21
|
+
if (o.disabled || e.metaKey || e.ctrlKey || e.altKey)
|
|
22
|
+
return;
|
|
23
|
+
if (isTypingTarget(e.target))
|
|
24
|
+
return;
|
|
25
|
+
const k = e.key;
|
|
26
|
+
const run = (fn) => { if (fn) {
|
|
27
|
+
e.preventDefault();
|
|
28
|
+
fn();
|
|
29
|
+
} };
|
|
30
|
+
if (k === "/")
|
|
31
|
+
run(o.onSearch);
|
|
32
|
+
else if (k === "j" || k === "J")
|
|
33
|
+
run(o.onNext);
|
|
34
|
+
else if (k === "k" || k === "K")
|
|
35
|
+
run(o.onPrev);
|
|
36
|
+
else if (k === "Enter")
|
|
37
|
+
run(o.onOpen);
|
|
38
|
+
else if (k === "Escape")
|
|
39
|
+
run(o.onEscape);
|
|
40
|
+
else if (k === "?")
|
|
41
|
+
run(o.onHelp);
|
|
42
|
+
else if (k === "n" || k === "N")
|
|
43
|
+
run(o.onNew);
|
|
44
|
+
};
|
|
45
|
+
window.addEventListener("keydown", h);
|
|
46
|
+
return () => window.removeEventListener("keydown", h);
|
|
47
|
+
}, []);
|
|
48
|
+
}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
/** Beheeronderdeel: alleen zichtbaar voor admin en superadmin. */
|
|
2
|
+
export declare function MailboxAiPromptCard(): import("react").JSX.Element | null;
|
|
2
3
|
//# sourceMappingURL=MailboxAiPromptCard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MailboxAiPromptCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/MailboxAiPromptCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MailboxAiPromptCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/MailboxAiPromptCard.tsx"],"names":[],"mappings":"AAwGA,kEAAkE;AAClE,wBAAgB,mBAAmB,uCAIlC"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useIsSuperadmin } from "@flowselections/core";
|
|
2
3
|
import { useEffect, useState } from "react";
|
|
3
4
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
4
5
|
import { useServerFn } from "@tanstack/react-start";
|
|
5
6
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Label, Textarea, Badge, toast, } from "@flowselections/core";
|
|
6
7
|
import { getMailboxAiSettings, saveMailboxAiSettings } from "../../lib/mailbox-ai-settings.functions.js";
|
|
7
8
|
import { REQUIRED_FIELD_CHOICES, DEFAULT_REQUIRED_FIELDS } from "../../lib/mailbox-ai-prompt.js";
|
|
8
|
-
|
|
9
|
+
function MailboxAiPromptCardInner() {
|
|
9
10
|
const qc = useQueryClient();
|
|
10
11
|
const fetchSettings = useServerFn(getMailboxAiSettings);
|
|
11
12
|
const save = useServerFn(saveMailboxAiSettings);
|
|
@@ -37,3 +38,10 @@ export function MailboxAiPromptCard() {
|
|
|
37
38
|
setRequired(DEFAULT_REQUIRED_FIELDS);
|
|
38
39
|
}, children: "Standaard herstellen" })] })] })] }));
|
|
39
40
|
}
|
|
41
|
+
/** Beheeronderdeel: alleen zichtbaar voor admin en superadmin. */
|
|
42
|
+
export function MailboxAiPromptCard() {
|
|
43
|
+
const { isAdmin, isLoading } = useIsSuperadmin();
|
|
44
|
+
if (isLoading || !isAdmin)
|
|
45
|
+
return null;
|
|
46
|
+
return _jsx(MailboxAiPromptCardInner, {});
|
|
47
|
+
}
|
|
@@ -74,7 +74,7 @@ export function MailboxFilterSettingsCard() {
|
|
|
74
74
|
const savedKeywords = Array.isArray(data?.settings?.order_keywords) ? data.settings.order_keywords : [];
|
|
75
75
|
const set = (k, v) => setForm((p) => ({ ...(p ?? {}), [k]: v }));
|
|
76
76
|
const u = data?.usage;
|
|
77
|
-
return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { children: "Voorfilter en kosten bestelmails" }), _jsx(CardDescription, { children: "Bepaalt welke mails de AI leest en hoeveel analyses er maximaal mogen. Mails die geen bestelling zijn, kosten geen AI-analyse." })] }), _jsxs(CardContent, { className: "space-y-5", children: [error && _jsx("p", { className: "text-sm text-destructive", children: "De instellingen konden niet worden geladen." }), u && (_jsxs("div", { className: "rounded-md border bg-muted/30 p-3 text-sm grid gap-1 sm:grid-cols-2", children: [_jsxs("div", { children: ["AI-analyses deze maand: ", _jsx("strong", { children: u.month_analyses }), form ? ` van ${form.max_ai_per_month}` : ""] }), _jsxs("div", { children: ["Vandaag: ", _jsx("strong", { children: u.today_analyses }), form ? ` van ${form.max_ai_per_day}` : ""] }), _jsxs("div", { children: ["Tokens deze maand: ", Number(u.input_tokens).toLocaleString("nl-NL"), " in \u00B7 ", Number(u.output_tokens).toLocaleString("nl-NL"), " uit"] }), _jsxs("div", { children: ["AI-aanroepen volgens het AI-logboek: ", u.ai_calls_month] }), u.test_analyses > 0 && _jsxs("div", { children: ["Waarvan testset: ", u.test_analyses] }), u.waiting > 0 && _jsxs("div", { className: "text-
|
|
77
|
+
return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { children: "Voorfilter en kosten bestelmails" }), _jsx(CardDescription, { children: "Bepaalt welke mails de AI leest en hoeveel analyses er maximaal mogen. Mails die geen bestelling zijn, kosten geen AI-analyse." })] }), _jsxs(CardContent, { className: "space-y-5", children: [error && _jsx("p", { className: "text-sm text-destructive", children: "De instellingen konden niet worden geladen." }), u && (_jsxs("div", { className: "rounded-md border bg-muted/30 p-3 text-sm grid gap-1 sm:grid-cols-2", children: [_jsxs("div", { children: ["AI-analyses deze maand: ", _jsx("strong", { children: u.month_analyses }), form ? ` van ${form.max_ai_per_month}` : ""] }), _jsxs("div", { children: ["Vandaag: ", _jsx("strong", { children: u.today_analyses }), form ? ` van ${form.max_ai_per_day}` : ""] }), _jsxs("div", { children: ["Tokens deze maand: ", Number(u.input_tokens).toLocaleString("nl-NL"), " in \u00B7 ", Number(u.output_tokens).toLocaleString("nl-NL"), " uit"] }), _jsxs("div", { children: ["AI-aanroepen volgens het AI-logboek: ", u.ai_calls_month] }), u.test_analyses > 0 && _jsxs("div", { children: ["Waarvan testset: ", u.test_analyses] }), u.waiting > 0 && _jsxs("div", { className: "text-warning-soft-foreground", children: ["Wachten op analyse: ", u.waiting] })] })), data?.settings && savedKeywords.length === 0 && (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 rounded-md border border-destructive/40 bg-destructive/5 p-3 text-sm", children: [_jsx("span", { children: "Er zijn geen bestelwoorden; de mailbox herkent dan weinig bestellingen" }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => addMut.mutate(), disabled: addMut.isPending, children: addMut.isPending ? "Toevoegen…" : "Standaardwoorden toevoegen" })] })), form && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "space-y-3", children: [_jsxs("label", { className: "flex items-center justify-between gap-3", children: [_jsx("span", { className: "text-sm", children: "Automatisch analyseren" }), _jsx(Switch, { checked: !!form.auto_analyze, onCheckedChange: (v) => set("auto_analyze", v) })] }), _jsxs("label", { className: "flex items-center justify-between gap-3", children: [_jsx("span", { className: "text-sm", children: "Onbekende afzender met bestel-signalen ook analyseren" }), _jsx(Switch, { checked: !!form.analyze_unknown_with_signals, onCheckedChange: (v) => set("analyze_unknown_with_signals", v) })] }), _jsxs("label", { className: "flex items-center justify-between gap-3", children: [_jsx("span", { className: "text-sm", children: "Klant herkennen op domein van het e-mailadres" }), _jsx(Switch, { checked: !!form.domain_match, onCheckedChange: (v) => set("domain_match", v) })] })] }), _jsx("div", { className: "grid gap-3 sm:grid-cols-2", children: NUMBERS.map((n) => (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs", children: n.label }), _jsx(Input, { type: "number", step: n.step ?? "1", value: form[n.key] ?? "", onChange: (e) => set(n.key, e.target.value) })] }, n.key))) }), LISTS.map((l) => (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: l.label }), _jsx(Textarea, { rows: 4, className: "font-mono text-xs", value: form[l.key] ?? "", onChange: (e) => set(l.key, e.target.value) }), _jsx("p", { className: "text-xs text-muted-foreground", children: l.help })] }, l.key))), _jsx(Button, { onClick: () => mut.mutate(), disabled: mut.isPending, children: mut.isPending ? "Opslaan..." : "Opslaan" })] })), _jsxs("div", { className: "border-t pt-4 space-y-2", children: [_jsx(Label, { children: "Bestaande voorstellen tellen" }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Telt hoeveel openstaande voorstellen het filter nu als \"geen bestelling\" zou zien. Er wordt niets verborgen of verwijderd." }), _jsx(Button, { variant: "outline", disabled: counting, onClick: async () => {
|
|
78
78
|
setCounting(true);
|
|
79
79
|
try {
|
|
80
80
|
setCount(await fetchCount());
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
/** Beheeronderdeel: alleen zichtbaar voor admin en superadmin. */
|
|
2
|
+
export declare function MailboxTestSetCard(): import("react").JSX.Element | null;
|
|
2
3
|
//# sourceMappingURL=MailboxTestSetCard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MailboxTestSetCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/MailboxTestSetCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MailboxTestSetCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/MailboxTestSetCard.tsx"],"names":[],"mappings":"AA8JA,kEAAkE;AAClE,wBAAgB,kBAAkB,uCAIjC"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useIsSuperadmin } from "@flowselections/core";
|
|
2
3
|
import { useState } from "react";
|
|
3
4
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
4
5
|
import { useServerFn } from "@tanstack/react-start";
|
|
5
6
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Badge, Input, Label, Textarea, Switch, toast, } from "@flowselections/core";
|
|
6
7
|
import { listTestCases, runTestCase, saveTestCase, deleteTestCase } from "../../lib/mailbox-filter-settings.functions.js";
|
|
7
|
-
|
|
8
|
+
function MailboxTestSetCardInner() {
|
|
8
9
|
const qc = useQueryClient();
|
|
9
10
|
const fetchCases = useServerFn(listTestCases);
|
|
10
11
|
const runOne = useServerFn(runTestCase);
|
|
@@ -60,10 +61,17 @@ export function MailboxTestSetCard() {
|
|
|
60
61
|
};
|
|
61
62
|
return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { children: "Testset bestelmails" }), _jsx(CardDescription, { children: "Voorbeeldmails met de verwachte uitkomst. \"Testset draaien\" doorloopt filter en uitlezen, maar maakt geen voorstellen of orders aan." })] }), _jsxs(CardContent, { className: "space-y-3", children: [_jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { onClick: runAll, disabled: !!running || cases.length === 0, children: running ? "Bezig…" : "Testset draaien" }), _jsx(Button, { variant: "outline", onClick: () => setEdit({ name: "", subject: "", from_email: "", body_text: "", has_attachment: false, expectedText: '{"is_order": true}' }), children: "Voorbeeld toevoegen" })] }), summary && (_jsxs("div", { className: "rounded-md border bg-muted/30 p-3 text-sm", children: [summary.passed, " van ", summary.total, " goed \u00B7 ", summary.analyses, " AI-analyses \u00B7 ", summary.tokens.toLocaleString("nl-NL"), " tokens"] })), _jsx("div", { className: "divide-y rounded-md border", children: cases.map((c) => {
|
|
62
63
|
const r = c.last_result;
|
|
63
|
-
return (_jsxs("div", { className: "p-3 text-sm space-y-1", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("button", { type: "button", className: "text-left font-medium", onClick: () => setOpenId(openId === c.id ? null : c.id), children: c.name }), _jsxs("div", { className: "flex items-center gap-2", children: [running === c.id ? (_jsx(Badge, { variant: "outline", children: "Bezig\u2026" })) : r ? (_jsx(Badge, { variant: "outline", className: r.passed ? "border-
|
|
64
|
+
return (_jsxs("div", { className: "p-3 text-sm space-y-1", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("button", { type: "button", className: "text-left font-medium", onClick: () => setOpenId(openId === c.id ? null : c.id), children: c.name }), _jsxs("div", { className: "flex items-center gap-2", children: [running === c.id ? (_jsx(Badge, { variant: "outline", children: "Bezig\u2026" })) : r ? (_jsx(Badge, { variant: "outline", className: r.passed ? "border-primary/30 bg-primary/10 text-primary" : "border-destructive/40 text-destructive", children: r.passed ? "Goed" : "Fout" })) : null, _jsx(Button, { size: "sm", variant: "ghost", onClick: () => setEdit({ ...c, expectedText: JSON.stringify(c.expected ?? {}, null, 2) }), children: "Wijzigen" })] })] }), r && _jsxs("div", { className: "text-xs text-muted-foreground", children: [r.filter?.reason, r.analyzed ? ` · ${Number(r.tokens?.input ?? 0) + Number(r.tokens?.output ?? 0)} tokens` : " · geen AI-analyse"] }), openId === c.id && r && Array.isArray(r.checks) && (_jsx("ul", { className: "text-xs space-y-0.5 pt-1", children: r.checks.map((k, i) => (_jsxs("li", { className: k.ok ? "text-primary" : "text-destructive", children: [k.ok ? "Goed" : "Fout", " \u2014 ", k.field, ": verwacht ", JSON.stringify(k.expected), ", gevonden ", JSON.stringify(k.actual)] }, i))) }))] }, c.id));
|
|
64
65
|
}) }), edit && (_jsxs("div", { className: "rounded-md border p-3 space-y-2", children: [_jsxs("div", { className: "grid gap-2 sm:grid-cols-2", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Naam" }), _jsx(Input, { value: edit.name, onChange: (e) => setEdit({ ...edit, name: e.target.value }) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Afzender" }), _jsx(Input, { value: edit.from_email, onChange: (e) => setEdit({ ...edit, from_email: e.target.value }) })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Onderwerp" }), _jsx(Input, { value: edit.subject, onChange: (e) => setEdit({ ...edit, subject: e.target.value }) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Tekst" }), _jsx(Textarea, { rows: 6, value: edit.body_text, onChange: (e) => setEdit({ ...edit, body_text: e.target.value }) })] }), _jsxs("label", { className: "flex items-center gap-2 text-sm", children: [_jsx(Switch, { checked: !!edit.has_attachment, onCheckedChange: (v) => setEdit({ ...edit, has_attachment: v }) }), " Met bijlage"] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Verwachte uitkomst" }), _jsx(Textarea, { rows: 6, className: "font-mono text-xs", value: edit.expectedText, onChange: (e) => setEdit({ ...edit, expectedText: e.target.value }) }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Bijvoorbeeld: is_order, known_sender, delivery_date, reference, en lines met quantity, unit, plants en unit_price." })] }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { onClick: saveEdit, children: "Opslaan" }), _jsx(Button, { variant: "outline", onClick: () => setEdit(null), children: "Annuleren" }), edit.id && (_jsx(Button, { variant: "destructive", onClick: async () => {
|
|
65
66
|
await remove({ data: { id: edit.id } });
|
|
66
67
|
setEdit(null);
|
|
67
68
|
void qc.invalidateQueries({ queryKey: ["mailbox-test-cases"] });
|
|
68
69
|
}, children: "Verwijderen" }))] })] }))] })] }));
|
|
69
70
|
}
|
|
71
|
+
/** Beheeronderdeel: alleen zichtbaar voor admin en superadmin. */
|
|
72
|
+
export function MailboxTestSetCard() {
|
|
73
|
+
const { isAdmin, isLoading } = useIsSuperadmin();
|
|
74
|
+
if (isLoading || !isAdmin)
|
|
75
|
+
return null;
|
|
76
|
+
return _jsx(MailboxTestSetCardInner, {});
|
|
77
|
+
}
|