@flowselections/mailbox-orders 1.0.59 → 1.0.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist-lib/integrations/supabase/client.server.js +1 -1
  2. package/dist-lib/integrations/supabase/types.d.ts +1261 -0
  3. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  4. package/dist-lib/lib/ai-base-url.d.ts +7 -0
  5. package/dist-lib/lib/ai-base-url.d.ts.map +1 -0
  6. package/dist-lib/lib/ai-base-url.js +15 -0
  7. package/dist-lib/lib/mailbox-ai.server.d.ts.map +1 -1
  8. package/dist-lib/lib/mailbox-ai.server.js +5 -2
  9. package/dist-lib/lib/mailbox-filter-settings.functions.d.ts +2 -2
  10. package/dist-lib/lib/mailbox-filter-settings.functions.js +3 -3
  11. package/dist-lib/lib/mailbox.functions.d.ts +1 -1
  12. package/dist-lib/lib/mailbox.functions.js +6 -6
  13. package/package.json +1 -1
  14. package/dist-lib/components/CartAssignmentWizard.d.ts +0 -6
  15. package/dist-lib/components/CartAssignmentWizard.d.ts.map +0 -1
  16. package/dist-lib/components/CartAssignmentWizard.js +0 -199
  17. package/dist-lib/components/MailboxInboxPage.d.ts +0 -2
  18. package/dist-lib/components/MailboxInboxPage.d.ts.map +0 -1
  19. package/dist-lib/components/MailboxInboxPage.js +0 -120
  20. package/dist-lib/components/settings/ImapAccountsCard.d.ts +0 -2
  21. package/dist-lib/components/settings/ImapAccountsCard.d.ts.map +0 -1
  22. package/dist-lib/components/settings/ImapAccountsCard.js +0 -136
  23. package/dist-lib/components/settings/ImapProfilesCard.d.ts +0 -2
  24. package/dist-lib/components/settings/ImapProfilesCard.d.ts.map +0 -1
  25. package/dist-lib/components/settings/ImapProfilesCard.js +0 -101
  26. package/dist-lib/components/settings/MailboxSettingsCard.d.ts +0 -2
  27. package/dist-lib/components/settings/MailboxSettingsCard.d.ts.map +0 -1
  28. package/dist-lib/components/settings/MailboxSettingsCard.js +0 -85
  29. package/dist-lib/lib/imap.functions.d.ts +0 -32852
  30. package/dist-lib/lib/imap.functions.d.ts.map +0 -1
  31. package/dist-lib/lib/imap.functions.js +0 -235
  32. package/dist-lib/lib/mailbox-auto.server.d.ts +0 -9
  33. package/dist-lib/lib/mailbox-auto.server.d.ts.map +0 -1
  34. package/dist-lib/lib/mailbox-auto.server.js +0 -198
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Haalt een versie-segment (bv. `/v1beta` of `/v1`) van het eind van de
3
+ * base-URL af. De centrale tabel `ai_providers` mag de base-URL met of zonder
4
+ * versie opslaan; de provider-functies zetten zelf de juiste versie erachter.
5
+ */
6
+ export declare function stripVersionSuffix(baseUrl: string, versions: string[]): string;
7
+ //# sourceMappingURL=ai-base-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-base-url.d.ts","sourceRoot":"","sources":["../../src/lib/ai-base-url.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAS9E"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Haalt een versie-segment (bv. `/v1beta` of `/v1`) van het eind van de
3
+ * base-URL af. De centrale tabel `ai_providers` mag de base-URL met of zonder
4
+ * versie opslaan; de provider-functies zetten zelf de juiste versie erachter.
5
+ */
6
+ export function stripVersionSuffix(baseUrl, versions) {
7
+ let url = baseUrl.replace(/\/+$/, "");
8
+ for (const v of versions) {
9
+ if (url.toLowerCase().endsWith(`/${v}`)) {
10
+ url = url.slice(0, -(v.length + 1));
11
+ break;
12
+ }
13
+ }
14
+ return url;
15
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"mailbox-ai.server.d.ts","sourceRoot":"","sources":["../../src/lib/mailbox-ai.server.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAE9D,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AAEpE,OAAO,EAAE,6BAA6B,EAAE,CAAC;AAEzC,KAAK,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;AAE5C,eAAO,MAAM,qBAAqB,yBAAyB,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,GAAG,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,GAAG,IAAI,CAAC;IAC3D,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACrC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAChF;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACzC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,UAAU,EAAE;QACV,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB,CAAC;IACF,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,2FAA2F;AAC3F,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGrF;AA0JD,yFAAyF;AACzF,wBAAgB,gBAAgB,CAAC,GAAG,OAAa;;;;;;;EA4BhD;AA0HD,mDAAmD;AACnD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAI3D;AAID,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBACd,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM;CAMlE;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE;IACJ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,iBAAiB,EAAE,CAAC;IACpC,cAAc,EAAE,WAAW,EAAE,CAAC;IAC9B,iBAAiB,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,GACA,OAAO,CAAC;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,CA8ErD"}
1
+ {"version":3,"file":"mailbox-ai.server.d.ts","sourceRoot":"","sources":["../../src/lib/mailbox-ai.server.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  // Er wordt GEEN gebruik gemaakt van Lovable AI / de Lovable AI Gateway.
4
4
  import { resolveModuleAi, logAiCall } from "./ai-config.server.js";
5
5
  import { DEFAULT_MAILBOX_SYSTEM_PROMPT } from "./mailbox-ai-prompt.js";
6
+ import { stripVersionSuffix } from "./ai-base-url.js";
6
7
  export { DEFAULT_MAILBOX_SYSTEM_PROMPT };
7
8
  export const MAILBOX_AI_MODULE_KEY = "mailbox-bestellingen";
8
9
  /** Huidige vingerafdruk van de gekoppelde AI-agent, of null als AI niet beschikbaar is. */
@@ -11,7 +12,8 @@ export async function currentAiFingerprint(admin) {
11
12
  return res.ok ? res.config.fingerprint : null;
12
13
  }
13
14
  async function callGemini(cfg, system, user) {
14
- const url = `${cfg.baseUrl}/v1beta/models/${encodeURIComponent(cfg.modelSlug)}:generateContent?key=${encodeURIComponent(cfg.apiKey)}`;
15
+ const base = stripVersionSuffix(cfg.baseUrl, ["v1beta", "v1"]);
16
+ const url = `${base}/v1beta/models/${encodeURIComponent(cfg.modelSlug)}:generateContent?key=${encodeURIComponent(cfg.apiKey)}`;
15
17
  const res = await fetch(url, {
16
18
  method: "POST",
17
19
  headers: { "Content-Type": "application/json" },
@@ -61,7 +63,8 @@ async function callOpenAi(cfg, system, user) {
61
63
  };
62
64
  }
63
65
  async function callAnthropic(cfg, system, user) {
64
- const res = await fetch(`${cfg.baseUrl}/v1/messages`, {
66
+ const base = stripVersionSuffix(cfg.baseUrl, ["v1"]);
67
+ const res = await fetch(`${base}/v1/messages`, {
65
68
  method: "POST",
66
69
  headers: {
67
70
  "Content-Type": "application/json",
@@ -107,7 +107,7 @@ export declare const runTestCase: import("@tanstack/start-client-core").Optional
107
107
  }, Promise<{
108
108
  checks: Check[];
109
109
  passed: boolean;
110
- filter: import("../lib/mailbox-filter.js").FilterResult;
110
+ filter: import("./mailbox-filter.js").FilterResult;
111
111
  sender: string;
112
112
  forwarded: boolean;
113
113
  analyzed: boolean;
@@ -119,7 +119,7 @@ export declare const runTestCase: import("@tanstack/start-client-core").Optional
119
119
  } | {
120
120
  checks: Check[];
121
121
  passed: boolean;
122
- filter: import("../lib/mailbox-filter.js").FilterResult;
122
+ filter: import("./mailbox-filter.js").FilterResult;
123
123
  sender: string;
124
124
  forwarded: boolean;
125
125
  analyzed: boolean;
@@ -113,8 +113,8 @@ export const countLikelyFakeProposals = createServerFn({ method: "GET" })
113
113
  .handler(async () => {
114
114
  const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
115
115
  const admin = supabaseAdmin;
116
- const { loadFilterSettings } = await import("../lib/mailbox-ingest.server.js");
117
- const { classifyMessage } = await import("../lib/mailbox-filter.js");
116
+ const { loadFilterSettings } = await import("./mailbox-ingest.server.js");
117
+ const { classifyMessage } = await import("./mailbox-filter.js");
118
118
  const s = await loadFilterSettings(admin);
119
119
  let total = 0, known = 0, wouldSkip = 0, withSignals = 0;
120
120
  for (let from = 0; from < 20000; from += 1000) {
@@ -236,7 +236,7 @@ export const runTestCase = createServerFn({ method: "POST" })
236
236
  const { data: tc, error } = await admin.from("mailbox_test_cases").select("*").eq("id", data.id).maybeSingle();
237
237
  if (error || !tc)
238
238
  throw new Error("Voorbeeld niet gevonden.");
239
- const { dryRunAnalysis } = await import("../lib/mailbox-ingest.server.js");
239
+ const { dryRunAnalysis } = await import("./mailbox-ingest.server.js");
240
240
  const run = await dryRunAnalysis(admin, {
241
241
  subject: tc.subject ?? "",
242
242
  body: tc.body_text ?? "",
@@ -2,7 +2,7 @@ import { type ActiveMailboxStatus } from "./mailbox-active.js";
2
2
  export declare const getActiveOrdersMailbox: import("@tanstack/start-client-core").OptionalFetcher<undefined, undefined, Promise<ActiveMailboxStatus>>;
3
3
  export declare const syncMailboxNow: import("@tanstack/start-client-core").OptionalFetcher<undefined, (input: unknown) => {
4
4
  trigger: "realtime" | "manual";
5
- }, Promise<import("../lib/mailbox-ingest.server.js").IngestRunResult | {
5
+ }, Promise<import("./mailbox-ingest.server.js").IngestRunResult | {
6
6
  ok: false;
7
7
  error: string;
8
8
  processed: 0;
@@ -64,7 +64,7 @@ export const syncMailboxNow = createServerFn({ method: "POST" })
64
64
  if (userErr || !userData?.user) {
65
65
  return { ok: false, error: "unauthorized", processed: 0, inserted: 0, errors: 1 };
66
66
  }
67
- const { runIngest } = await import("../lib/mailbox-ingest.server.js");
67
+ const { runIngest } = await import("./mailbox-ingest.server.js");
68
68
  return await runIngest(data.trigger);
69
69
  }
70
70
  catch (e) {
@@ -95,7 +95,7 @@ export const reparseProposalNow = createServerFn({ method: "POST" })
95
95
  .inputValidator((input) => z.object({ proposalId: z.string().uuid() }).parse(input))
96
96
  .handler(async ({ data }) => {
97
97
  const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
98
- const { reparseProposal } = await import("../lib/mailbox-ingest.server.js");
98
+ const { reparseProposal } = await import("./mailbox-ingest.server.js");
99
99
  return reparseProposal(supabaseAdmin, data.proposalId);
100
100
  });
101
101
  /** Detecteert een gewijzigde AI-agent en herverwerkt openstaande voorstellen. */
@@ -103,7 +103,7 @@ export const refreshProposalsForAgentChange = createServerFn({ method: "POST" })
103
103
  .middleware([requireSupabaseAuth])
104
104
  .handler(async () => {
105
105
  const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
106
- const { reparseChangedAgentProposals } = await import("../lib/mailbox-ingest.server.js");
106
+ const { reparseChangedAgentProposals } = await import("./mailbox-ingest.server.js");
107
107
  return reparseChangedAgentProposals(supabaseAdmin);
108
108
  });
109
109
  // ─── Messages & Proposals ────────────────────────────────────────────────────
@@ -125,7 +125,7 @@ export const parseMessage = createServerFn({ method: "POST" })
125
125
  .inputValidator((input) => z.object({ messageId: z.string().uuid() }).parse(input))
126
126
  .handler(async ({ data }) => {
127
127
  const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
128
- const { createStubProposal } = await import("../lib/mailbox-ingest.server.js");
128
+ const { createStubProposal } = await import("./mailbox-ingest.server.js");
129
129
  const { data: msg, error: msgErr } = await supabaseAdmin
130
130
  .from("mailbox_messages").select("*").eq("id", data.messageId).single();
131
131
  if (msgErr || !msg)
@@ -1189,7 +1189,7 @@ export const analyzeMessageNow = createServerFn({ method: "POST" })
1189
1189
  .inputValidator((input) => z.object({ messageId: z.string().uuid() }).parse(input))
1190
1190
  .handler(async ({ data }) => {
1191
1191
  const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
1192
- const { createStubProposal } = await import("../lib/mailbox-ingest.server.js");
1192
+ const { createStubProposal } = await import("./mailbox-ingest.server.js");
1193
1193
  try {
1194
1194
  const res = await createStubProposal(supabaseAdmin, data.messageId, null, { force: true, trigger: "handmatig" });
1195
1195
  if (res.status === "busy")
@@ -1205,7 +1205,7 @@ export const countOutdatedProposals = createServerFn({ method: "GET" })
1205
1205
  .middleware([requireSupabaseAuth])
1206
1206
  .handler(async () => {
1207
1207
  const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
1208
- const { countOutdatedAgentProposals } = await import("../lib/mailbox-ingest.server.js");
1208
+ const { countOutdatedAgentProposals } = await import("./mailbox-ingest.server.js");
1209
1209
  return { count: await countOutdatedAgentProposals(supabaseAdmin) };
1210
1210
  });
1211
1211
  // ─── Stickervinkje: beschikbaarheid + standaardwaarden ─────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowselections/mailbox-orders",
3
- "version": "1.0.59",
3
+ "version": "1.0.61",
4
4
  "private": false,
5
5
  "sideEffects": false,
6
6
  "type": "module",
@@ -1,6 +0,0 @@
1
- export declare function CartAssignmentWizard({ orderId, open, onClose, }: {
2
- orderId: string | null;
3
- open: boolean;
4
- onClose: () => void;
5
- }): import("react").JSX.Element;
6
- //# sourceMappingURL=CartAssignmentWizard.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CartAssignmentWizard.d.ts","sourceRoot":"","sources":["../../src/components/CartAssignmentWizard.tsx"],"names":[],"mappings":"AA2CA,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EAAE,IAAI,EAAE,OAAO,GACvB,EAAE;IAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,+BAsUhE"}
@@ -1,199 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useMemo, useState } from "react";
3
- import { useQuery } from "@tanstack/react-query";
4
- import { useServerFn } from "@tanstack/react-start";
5
- import { Button, Badge, Card, CardContent, CardHeader, CardTitle, Input, Label, Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, toast, } from "@flowselections/core";
6
- import { Plus, Trash2, AlertTriangle, CheckCircle2 } from "lucide-react";
7
- import { planAndSaveAutoCarts, saveManualCarts } from "../lib/mailbox.functions.js";
8
- export function CartAssignmentWizard({ orderId, open, onClose, }) {
9
- const fetchPlan = useServerFn(planAndSaveAutoCarts);
10
- const fetchSave = useServerFn(saveManualCarts);
11
- const { data, isLoading, refetch } = useQuery({
12
- queryKey: ["cart-plan", orderId],
13
- enabled: !!orderId && open,
14
- queryFn: async () => {
15
- try {
16
- return await fetchPlan({ data: { orderId: orderId } });
17
- }
18
- catch (e) {
19
- toast.error(e?.message ?? "Indelen mislukt");
20
- return { autoCarts: [], remainders: [], existingManualCarts: [], nextCartNumber: 1 };
21
- }
22
- },
23
- });
24
- const autoCarts = Array.isArray(data?.autoCarts) ? data.autoCarts : [];
25
- const remainders = Array.isArray(data?.remainders) ? data.remainders : [];
26
- const existingManualCarts = Array.isArray(data?.existingManualCarts) ? data.existingManualCarts : [];
27
- // Pool met nog in te delen fusten per orderregel
28
- const [pool, setPool] = useState({});
29
- const [manual, setManual] = useState([]);
30
- useEffect(() => {
31
- const p = {};
32
- remainders.forEach((r) => { p[r.order_item_id] = r.crates_remaining; });
33
- setPool(p);
34
- // Bestaande handmatige karren herstellen — capaciteitsmeta uit remainders aanvullen.
35
- const remMeta = {};
36
- remainders.forEach((r) => { remMeta[r.order_item_id] = r; });
37
- setManual(existingManualCarts.map((c) => ({
38
- id: crypto.randomUUID(),
39
- items: c.items.map((i) => {
40
- const meta = i.order_item_id ? remMeta[i.order_item_id] : null;
41
- return {
42
- ...i,
43
- crates_per_layer: meta?.crates_per_layer ?? i.crates_per_layer ?? 1,
44
- layers_per_cart: meta?.layers_per_cart ?? i.layers_per_cart ?? 1,
45
- };
46
- }),
47
- })));
48
- }, [data]);
49
- const remByItem = useMemo(() => {
50
- const m = {};
51
- remainders.forEach((r) => { m[r.order_item_id] = r; });
52
- return m;
53
- }, [remainders]);
54
- const addCart = () => setManual((m) => [...m, { id: crypto.randomUUID(), items: [] }]);
55
- const addItemToCart = (cartId, orderItemId, crates) => {
56
- const rem = remByItem[orderItemId];
57
- if (!rem)
58
- return;
59
- const available = pool[orderItemId] ?? 0;
60
- const take = Math.max(0, Math.min(crates, available));
61
- if (take === 0)
62
- return;
63
- setPool((p) => ({ ...p, [orderItemId]: available - take }));
64
- setManual((carts) => carts.map((c) => {
65
- if (c.id !== cartId)
66
- return c;
67
- // merge in plaats van duplicate regel
68
- const existingIdx = c.items.findIndex((i) => i.order_item_id === orderItemId);
69
- if (existingIdx >= 0) {
70
- const next = [...c.items];
71
- next[existingIdx] = { ...next[existingIdx], crates: next[existingIdx].crates + take };
72
- return { ...c, items: next };
73
- }
74
- return {
75
- ...c,
76
- items: [...c.items, {
77
- order_item_id: orderItemId,
78
- product_id: rem.product_id,
79
- product_name: rem.product_name,
80
- crates: take,
81
- plants_per_crate: rem.plants_per_crate,
82
- crates_per_layer: rem.crates_per_layer,
83
- layers_per_cart: rem.layers_per_cart,
84
- }],
85
- };
86
- }));
87
- };
88
- const removeItem = (cartId, orderItemId) => {
89
- setManual((carts) => carts.map((c) => {
90
- if (c.id !== cartId)
91
- return c;
92
- const item = c.items.find((i) => i.order_item_id === orderItemId);
93
- if (!item)
94
- return c;
95
- setPool((p) => ({ ...p, [orderItemId]: (p[orderItemId] ?? 0) + item.crates }));
96
- return { ...c, items: c.items.filter((i) => i.order_item_id !== orderItemId) };
97
- }));
98
- };
99
- const removeCart = (cartId) => {
100
- setManual((carts) => {
101
- const c = carts.find((x) => x.id === cartId);
102
- if (c) {
103
- setPool((p) => {
104
- const np = { ...p };
105
- c.items.forEach((i) => {
106
- if (!i.order_item_id)
107
- return;
108
- np[i.order_item_id] = (np[i.order_item_id] ?? 0) + i.crates;
109
- });
110
- return np;
111
- });
112
- }
113
- return carts.filter((x) => x.id !== cartId);
114
- });
115
- };
116
- // Capaciteit per kar = max van betrokken artikelen (gemengde karren toegestaan,
117
- // pakken we de hoogste cratesPerCart als bovengrens; waarschuwing toont per item).
118
- const cartCapacity = (cart) => cart.items.length === 0
119
- ? 0
120
- : Math.max(...cart.items.map((i) => i.crates_per_layer * i.layers_per_cart));
121
- const cartUsed = (cart) => cart.items.reduce((s, i) => s + i.crates, 0);
122
- const totalRemainingInPool = Object.values(pool).reduce((s, n) => s + n, 0);
123
- const handleSave = async () => {
124
- if (totalRemainingInPool > 0) {
125
- toast.error(`Nog ${totalRemainingInPool} fust niet ingedeeld — verdeel alles over een kar voordat je opslaat`);
126
- return;
127
- }
128
- if (manual.some((c) => c.items.length === 0)) {
129
- toast.error("Lege karren niet toegestaan");
130
- return;
131
- }
132
- const overfull = manual.find((c) => cartUsed(c) > cartCapacity(c));
133
- if (overfull) {
134
- toast.error("Een kar overschrijdt de capaciteit");
135
- return;
136
- }
137
- try {
138
- await fetchSave({
139
- data: {
140
- orderId: orderId,
141
- carts: manual.map((c) => ({
142
- is_complete: cartUsed(c) >= cartCapacity(c),
143
- items: c.items.map((i) => ({
144
- order_item_id: i.order_item_id,
145
- product_id: i.product_id,
146
- product_name: i.product_name,
147
- crates: Math.max(1, Math.trunc(i.crates)),
148
- plants_per_crate: Math.max(1, Math.trunc(i.plants_per_crate || 1)),
149
- crates_per_layer: Math.max(1, Math.trunc(i.crates_per_layer || 1)),
150
- })),
151
- })),
152
- },
153
- });
154
- toast.success("Karindeling opgeslagen");
155
- onClose();
156
- }
157
- catch (e) {
158
- // requireSupabaseAuth en input-validatie gooien een Response; toString
159
- // daarvan is "[object Response]" — zet om in leesbare melding zodat
160
- // de React error-overlay niet wordt getriggerd.
161
- let msg = "Opslaan mislukt";
162
- if (e instanceof Response) {
163
- try {
164
- msg = (await e.text()) || `HTTP ${e.status}`;
165
- }
166
- catch {
167
- msg = `HTTP ${e.status}`;
168
- }
169
- if (e.status === 401)
170
- msg = "Sessie verlopen — log opnieuw in";
171
- }
172
- else if (e?.message) {
173
- msg = e.message;
174
- }
175
- toast.error(msg);
176
- console.error("saveManualCarts failed:", e);
177
- }
178
- };
179
- return (_jsx(Dialog, { open: open, onOpenChange: (o) => { if (!o)
180
- onClose(); }, children: _jsxs(DialogContent, { className: "max-w-[95vw] w-[95vw] h-[92vh] max-h-[92vh] overflow-y-auto p-6", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: "Karindeling" }) }), isLoading ? (_jsx("div", { className: "text-muted-foreground", children: "Karren worden berekend..." })) : (_jsxs("div", { className: "space-y-6", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "flex flex-row items-center justify-between", children: [_jsx(CardTitle, { className: "text-base", children: "Automatisch ingedeelde karren" }), _jsxs(Badge, { variant: "secondary", children: [autoCarts.length, " kar(ren)"] })] }), _jsx(CardContent, { children: autoCarts.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Geen volledige karren mogelijk." })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Kar #" }), _jsx(TableHead, { children: "Artikel" }), _jsx(TableHead, { className: "text-right", children: "Fusten" }), _jsx(TableHead, { className: "text-right", children: "Planten" }), _jsx(TableHead, { className: "text-right", children: "Bezetting" }), _jsx(TableHead, { children: "Status" })] }) }), _jsx(TableBody, { children: autoCarts.map((c) => (_jsxs(TableRow, { children: [_jsx(TableCell, { className: "font-mono", children: c.cart_number }), _jsx(TableCell, { children: c.product_name }), _jsx(TableCell, { className: "text-right", children: c.crates }), _jsx(TableCell, { className: "text-right", children: c.plants }), _jsx(TableCell, { className: "text-right", children: "100%" }), _jsx(TableCell, { children: _jsxs(Badge, { className: "gap-1", children: [_jsx(CheckCircle2, { className: "h-3 w-3" }), " Volledig"] }) })] }, c.cart_number))) })] })) })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: "Handmatig in te delen fusten" }) }), _jsx(CardContent, { className: "space-y-3", children: remainders.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Geen restant \u2014 alles past volledig op karren." })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Artikel" }), _jsx(TableHead, { className: "text-right", children: "Beschikbaar (fusten)" }), _jsx(TableHead, { className: "text-right", children: "Planten/fust" }), _jsx(TableHead, { className: "text-right", children: "Capaciteit/kar" })] }) }), _jsx(TableBody, { children: remainders.map((r) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: r.product_name }), _jsxs(TableCell, { className: "text-right font-mono", children: [pool[r.order_item_id] ?? 0, " / ", r.crates_remaining] }), _jsx(TableCell, { className: "text-right", children: r.plants_per_crate }), _jsx(TableCell, { className: "text-right", children: r.crates_per_layer * r.layers_per_cart })] }, r.order_item_id))) })] })) })] }), remainders.length > 0 && (_jsxs(Card, { children: [_jsxs(CardHeader, { className: "flex flex-row items-center justify-between", children: [_jsx(CardTitle, { className: "text-base", children: "Restant-karren samenstellen" }), _jsxs(Button, { size: "sm", onClick: addCart, children: [_jsx(Plus, { className: "h-3 w-3 mr-1" }), " Kar toevoegen"] })] }), _jsxs(CardContent, { className: "space-y-3", children: [manual.length === 0 && (_jsx("p", { className: "text-sm text-muted-foreground", children: "Voeg een kar toe om restant-fusten in te delen." })), manual.map((cart, idx) => {
181
- const used = cartUsed(cart);
182
- const cap = cartCapacity(cart);
183
- const pct = cap > 0 ? Math.round((used / cap) * 100) : 0;
184
- const over = cap > 0 && used > cap;
185
- return (_jsxs(Card, { className: over ? "border-destructive" : "", children: [_jsxs(CardHeader, { className: "flex flex-row items-center justify-between py-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("span", { className: "font-medium", children: ["Restant-kar ", idx + 1] }), _jsxs(Badge, { variant: over ? "destructive" : "secondary", children: [used, " / ", cap || "?", " fusten (", pct, "%)"] }), over && (_jsxs("span", { className: "text-xs text-destructive flex items-center gap-1", children: [_jsx(AlertTriangle, { className: "h-3 w-3" }), " Capaciteit overschreden"] }))] }), _jsx(Button, { variant: "ghost", size: "icon", onClick: () => removeCart(cart.id), children: _jsx(Trash2, { className: "h-4 w-4" }) })] }), _jsxs(CardContent, { className: "space-y-2", children: [cart.items.map((i) => (_jsxs("div", { className: "flex items-center justify-between text-sm", children: [_jsxs("div", { children: [_jsx("span", { className: "font-medium", children: i.product_name }), _jsxs("span", { className: "text-muted-foreground", children: [" \u00B7 ", i.crates, " fust (", i.crates * i.plants_per_crate, " planten)"] })] }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => removeItem(cart.id, i.order_item_id), children: _jsx(Trash2, { className: "h-3 w-3" }) })] }, i.order_item_id))), _jsx(AddItemRow, { remainders: remainders, pool: pool, onAdd: (itemId, crates) => addItemToCart(cart.id, itemId, crates) })] })] }, cart.id));
186
- })] })] }))] })), _jsxs(DialogFooter, { className: "gap-2", children: [_jsx(Button, { variant: "outline", onClick: onClose, children: "Annuleren" }), _jsxs(Button, { onClick: handleSave, disabled: isLoading || totalRemainingInPool > 0, children: ["Karindeling opslaan", totalRemainingInPool > 0 && (_jsxs(Badge, { variant: "destructive", className: "ml-2", children: ["Nog ", totalRemainingInPool, " fust in te delen"] }))] })] })] }) }));
187
- }
188
- function AddItemRow({ remainders, pool, onAdd, }) {
189
- const available = remainders.filter((r) => (pool[r.order_item_id] ?? 0) > 0);
190
- const [sel, setSel] = useState("");
191
- const [qty, setQty] = useState(1);
192
- if (available.length === 0)
193
- return null;
194
- return (_jsxs("div", { className: "flex items-end gap-2 pt-2 border-t", children: [_jsxs("div", { className: "flex-1", children: [_jsx(Label, { className: "text-xs", children: "Artikel" }), _jsxs(Select, { value: sel, onValueChange: setSel, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Kies restant-artikel..." }) }), _jsx(SelectContent, { children: available.map((r) => (_jsxs(SelectItem, { value: r.order_item_id, children: [r.product_name, " (", pool[r.order_item_id], " fust beschikbaar)"] }, r.order_item_id))) })] })] }), _jsxs("div", { className: "w-24", children: [_jsx(Label, { className: "text-xs", children: "Fusten" }), _jsx(Input, { type: "number", min: 1, value: qty, onChange: (e) => setQty(Math.max(1, Number(e.target.value) || 1)) })] }), _jsxs(Button, { size: "sm", disabled: !sel, onClick: () => { if (sel) {
195
- onAdd(sel, qty);
196
- setSel("");
197
- setQty(1);
198
- } }, children: [_jsx(Plus, { className: "h-3 w-3 mr-1" }), " Toevoegen"] })] }));
199
- }
@@ -1,2 +0,0 @@
1
- export declare function MailboxInboxPage(): import("react").JSX.Element;
2
- //# sourceMappingURL=MailboxInboxPage.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MailboxInboxPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxInboxPage.tsx"],"names":[],"mappings":"AA6BA,wBAAgB,gBAAgB,gCAuO/B"}
@@ -1,120 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useRef } from "react";
3
- import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
4
- import { useServerFn } from "@tanstack/react-start";
5
- import { Button, Badge, Card, CardContent, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, } from "@flowselections/core";
6
- import { Mail, Sparkles, AlertCircle, ExternalLink, RefreshCw } from "lucide-react";
7
- import { listMessages, parseMessage, getActiveOrdersMailbox, ingestEmailEvent, backfillRecentEvents, } from "../lib/mailbox.functions.js";
8
- import { supabase } from "../integrations/supabase/client.js";
9
- const AUTH_MODULE_URL = "https://auth.flowselections.com/e-mail-authenticatie";
10
- const STATUS_VARIANT = {
11
- new: "secondary",
12
- parsing: "outline",
13
- parsed: "default",
14
- failed: "destructive",
15
- ignored: "outline",
16
- converted: "default",
17
- };
18
- export function MailboxInboxPage() {
19
- const qc = useQueryClient();
20
- const fetchList = useServerFn(listMessages);
21
- const fetchParse = useServerFn(parseMessage);
22
- const fetchActive = useServerFn(getActiveOrdersMailbox);
23
- const fetchIngest = useServerFn(ingestEmailEvent);
24
- const fetchBackfill = useServerFn(backfillRecentEvents);
25
- const { data, isLoading } = useQuery({
26
- queryKey: ["mailbox-messages"],
27
- queryFn: () => fetchList(),
28
- });
29
- const { data: active, isSuccess: activeLoaded } = useQuery({
30
- queryKey: ["mailbox-active-account"],
31
- queryFn: () => fetchActive(),
32
- refetchInterval: 60000,
33
- retry: 1,
34
- });
35
- // Realtime: nieuwe events uit gedeelde authenticatiemodule
36
- const activeId = active?.connected ? active.id : null;
37
- useEffect(() => {
38
- if (!activeId)
39
- return;
40
- const channel = supabase
41
- .channel(`email_auth_events:${activeId}`)
42
- .on("postgres_changes", {
43
- event: "INSERT",
44
- schema: "public",
45
- table: "email_auth_events",
46
- filter: `connection_id=eq.${activeId}`,
47
- }, async (payload) => {
48
- const evId = payload?.new?.id;
49
- if (!evId)
50
- return;
51
- try {
52
- const res = await fetchIngest({ data: { eventId: evId } });
53
- if (res?.ok && (res.inserted ?? 0) > 0) {
54
- const app = res.autoApproved ?? 0;
55
- if (app > 0)
56
- toast.success(`Nieuwe e-mail — ${app} automatisch omgezet`);
57
- else
58
- toast.success("Nieuwe e-mail ontvangen");
59
- qc.invalidateQueries({ queryKey: ["mailbox-messages"] });
60
- qc.invalidateQueries({ queryKey: ["mailbox-proposals"] });
61
- }
62
- }
63
- catch {
64
- /* stille fout — backfill vangt het later op */
65
- }
66
- })
67
- .subscribe();
68
- return () => {
69
- void supabase.removeChannel(channel);
70
- };
71
- }, [activeId, fetchIngest, qc]);
72
- // Backfill bij eerste mount + iedere 60s (vangt gemiste events op)
73
- const didInitialBackfill = useRef(false);
74
- const backfillMut = useMutation({
75
- mutationFn: async () => {
76
- try {
77
- return await fetchBackfill();
78
- }
79
- catch {
80
- // 401's (token verlopen) en tijdelijke fouten stil opvangen
81
- return { ok: false, inserted: 0 };
82
- }
83
- },
84
- onSuccess: (res) => {
85
- if (res?.ok && (res.inserted ?? 0) > 0) {
86
- qc.invalidateQueries({ queryKey: ["mailbox-messages"] });
87
- qc.invalidateQueries({ queryKey: ["mailbox-proposals"] });
88
- }
89
- },
90
- onError: () => {
91
- /* stille fout — volgende interval probeert opnieuw */
92
- },
93
- });
94
- useEffect(() => {
95
- if (!activeId || didInitialBackfill.current)
96
- return;
97
- didInitialBackfill.current = true;
98
- backfillMut.mutate();
99
- const t = setInterval(() => backfillMut.mutate(), 60000);
100
- return () => clearInterval(t);
101
- // eslint-disable-next-line react-hooks/exhaustive-deps
102
- }, [activeId]);
103
- const parseMut = useMutation({
104
- mutationFn: (messageId) => fetchParse({ data: { messageId } }),
105
- onSuccess: (res) => {
106
- if (res?.ok) {
107
- toast.success("E-mail geparsed naar voorstel");
108
- qc.invalidateQueries({ queryKey: ["mailbox-messages"] });
109
- qc.invalidateQueries({ queryKey: ["mailbox-proposals"] });
110
- }
111
- else {
112
- toast.error(res?.error ?? "Parsen mislukt");
113
- }
114
- },
115
- onError: (e) => toast.error(e?.message ?? "Parsen mislukt"),
116
- });
117
- const items = Array.isArray(data?.items) ? data.items : [];
118
- const needsReauth = active?.connected && active.needs_reauth;
119
- return (_jsxs("div", { className: "p-6 space-y-6", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsxs("h1", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(Mail, { className: "h-6 w-6 text-primary" }), " Inbox"] }), _jsx("p", { className: "text-muted-foreground text-sm mt-1", children: "Binnenkomende bestel-e-mails \u2014 geleverd door de E-mail Authenticatie module" })] }), _jsxs(Button, { variant: "outline", onClick: () => backfillMut.mutate(), disabled: backfillMut.isPending || !active?.connected, title: "Haal achterstallige events op", children: [_jsx(RefreshCw, { className: `h-4 w-4 mr-2 ${backfillMut.isPending ? "animate-spin" : ""}` }), "Synchroniseer"] })] }), activeLoaded && !active?.connected ? (_jsx(Card, { children: _jsxs(CardContent, { className: "p-4 flex items-start gap-3 text-sm", children: [_jsx(AlertCircle, { className: "h-4 w-4 text-destructive mt-0.5" }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "font-medium", children: "Nog geen e-mailadres gekoppeld" }), _jsxs("div", { className: "text-muted-foreground", children: ["Koppel in de module ", _jsx("strong", { children: "E-mail Authenticatie" }), " een adres met doeleinde", " ", _jsx("code", { children: "orders" }), " en richting ", _jsx("code", { children: "receive" }), "."] })] }), _jsx(Button, { asChild: true, variant: "outline", size: "sm", children: _jsxs("a", { href: AUTH_MODULE_URL, target: "_blank", rel: "noreferrer", children: ["Open module ", _jsx(ExternalLink, { className: "h-3 w-3 ml-1" })] }) })] }) })) : needsReauth ? (_jsx(Card, { className: "border-destructive", children: _jsxs(CardContent, { className: "p-4 flex items-start gap-3 text-sm", children: [_jsx(AlertCircle, { className: "h-4 w-4 text-destructive mt-0.5" }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "font-medium", children: ["Heraanmelding vereist voor ", active.account_email] }), _jsx("div", { className: "text-muted-foreground", children: active.last_error ?? "De koppeling is verlopen. Log opnieuw in via de authenticatiemodule." })] }), _jsx(Button, { asChild: true, variant: "destructive", size: "sm", children: _jsxs("a", { href: `${AUTH_MODULE_URL}?focus=${active.id}`, target: "_blank", rel: "noreferrer", children: ["Opnieuw verbinden ", _jsx(ExternalLink, { className: "h-3 w-3 ml-1" })] }) })] }) })) : active?.connected ? (_jsx(Card, { children: _jsxs(CardContent, { className: "p-4 flex items-center gap-3 text-sm", children: [_jsx(Mail, { className: "h-4 w-4 text-primary" }), _jsx("span", { className: "text-muted-foreground", children: "Actieve mailbox:" }), _jsx("span", { className: "font-medium", children: active.account_email }), _jsx(Badge, { variant: "outline", className: "ml-2", children: active.provider }), active.status && active.status !== "ok" && active.status !== "verified" && (_jsx(Badge, { variant: "secondary", className: "ml-2", children: active.status }))] }) })) : null, _jsx(Card, { children: _jsx(CardContent, { className: "p-0", children: isLoading ? (_jsx("div", { className: "p-8 text-center text-muted-foreground", children: "Laden..." })) : items.length === 0 ? (_jsx("div", { className: "p-8 text-center text-muted-foreground", children: "Nog geen e-mails ontvangen. Nieuwe berichten verschijnen automatisch." })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Status" }), _jsx(TableHead, { children: "Afzender" }), _jsx(TableHead, { children: "Onderwerp" }), _jsx(TableHead, { children: "Ontvangen" }), _jsx(TableHead, { className: "text-right", children: "Actie" })] }) }), _jsx(TableBody, { children: items.map((m) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Badge, { variant: STATUS_VARIANT[m.status] ?? "secondary", children: m.status }) }), _jsxs(TableCell, { children: [_jsx("div", { className: "text-sm font-medium", children: m.from_name || m.from_email }), m.from_name && _jsx("div", { className: "text-xs text-muted-foreground", children: m.from_email })] }), _jsx(TableCell, { className: "max-w-md truncate", children: m.subject || "(geen onderwerp)" }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: m.received_at ? new Date(m.received_at).toLocaleString("nl-NL") : "-" }), _jsx(TableCell, { className: "text-right", children: m.status !== "converted" && (_jsxs(Button, { size: "sm", variant: "outline", disabled: parseMut.isPending, onClick: () => parseMut.mutate(m.id), children: [_jsx(Sparkles, { className: "h-3 w-3 mr-1" }), m.status === "parsed" ? "Opnieuw parsen" : "Parse"] })) })] }, m.id))) })] })) }) })] }));
120
- }
@@ -1,2 +0,0 @@
1
- export declare function ImapAccountsCard(): import("react").JSX.Element;
2
- //# sourceMappingURL=ImapAccountsCard.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ImapAccountsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/ImapAccountsCard.tsx"],"names":[],"mappings":"AAyCA,wBAAgB,gBAAgB,gCAwP/B"}