@flowselections/floriday-afhandeling-module 1.0.12 → 1.0.14

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 (80) hide show
  1. package/dist-lib/components/afhandeling/AutoProcessStatus.d.ts +12 -0
  2. package/dist-lib/components/afhandeling/AutoProcessStatus.d.ts.map +1 -0
  3. package/dist-lib/components/afhandeling/AutoProcessStatus.js +103 -0
  4. package/dist-lib/components/afhandeling/ControleLijstPrint.d.ts +3 -1
  5. package/dist-lib/components/afhandeling/ControleLijstPrint.d.ts.map +1 -1
  6. package/dist-lib/components/afhandeling/ControleLijstPrint.js +56 -17
  7. package/dist-lib/components/afhandeling/DagDetailDialog.d.ts.map +1 -1
  8. package/dist-lib/components/afhandeling/DagDetailDialog.js +96 -4
  9. package/dist-lib/components/afhandeling/LeveringenPage.js +1 -1
  10. package/dist-lib/components/afhandeling/VervoerdersPage.d.ts.map +1 -1
  11. package/dist-lib/components/afhandeling/VervoerdersPage.js +2 -1
  12. package/dist-lib/components/afhandeling/WeekAgendaView.d.ts +3 -1
  13. package/dist-lib/components/afhandeling/WeekAgendaView.d.ts.map +1 -1
  14. package/dist-lib/components/afhandeling/WeekAgendaView.js +58 -17
  15. package/dist-lib/components/pickstation/KioskControle.d.ts +2 -0
  16. package/dist-lib/components/pickstation/KioskControle.d.ts.map +1 -0
  17. package/dist-lib/components/pickstation/KioskControle.js +7 -0
  18. package/dist-lib/components/pickstation/PakbonTemplate.d.ts +2 -1
  19. package/dist-lib/components/pickstation/PakbonTemplate.d.ts.map +1 -1
  20. package/dist-lib/components/pickstation/PakbonTemplate.js +20 -17
  21. package/dist-lib/components/pickstation/PickstationPage.d.ts +2 -0
  22. package/dist-lib/components/pickstation/PickstationPage.d.ts.map +1 -0
  23. package/dist-lib/components/pickstation/PickstationPage.js +266 -0
  24. package/dist-lib/components/settings/AfhandelingSettingsCard.d.ts.map +1 -1
  25. package/dist-lib/components/settings/AfhandelingSettingsCard.js +14 -2
  26. package/dist-lib/hooks/useOrderPlanning.d.ts.map +1 -1
  27. package/dist-lib/hooks/useOrderPlanning.js +28 -11
  28. package/dist-lib/index.d.ts +4 -0
  29. package/dist-lib/index.d.ts.map +1 -1
  30. package/dist-lib/index.js +4 -0
  31. package/dist-lib/integrations/supabase/auth-middleware.d.ts +1243 -63
  32. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  33. package/dist-lib/integrations/supabase/client.d.ts +1243 -63
  34. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  35. package/dist-lib/integrations/supabase/client.server.d.ts +1243 -63
  36. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  37. package/dist-lib/integrations/supabase/types.d.ts +1264 -56
  38. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  39. package/dist-lib/lib/afhandelingSettings.functions.d.ts +2483 -111
  40. package/dist-lib/lib/afhandelingSettings.functions.d.ts.map +1 -1
  41. package/dist-lib/lib/afhandelingSettings.functions.js +28 -1
  42. package/dist-lib/lib/carrierPlanning.d.ts +25 -0
  43. package/dist-lib/lib/carrierPlanning.d.ts.map +1 -0
  44. package/dist-lib/lib/carrierPlanning.js +65 -0
  45. package/dist-lib/lib/carrierSignupMail.server.d.ts +0 -2
  46. package/dist-lib/lib/carrierSignupMail.server.d.ts.map +1 -1
  47. package/dist-lib/lib/carrierSignupMail.server.js +53 -216
  48. package/dist-lib/lib/carriers.functions.d.ts +5920 -20
  49. package/dist-lib/lib/carriers.functions.d.ts.map +1 -1
  50. package/dist-lib/lib/carriers.functions.js +5 -0
  51. package/dist-lib/lib/cartAssignments.functions.d.ts +5920 -20
  52. package/dist-lib/lib/cartAssignments.functions.d.ts.map +1 -1
  53. package/dist-lib/lib/cartControl.functions.d.ts +11843 -40
  54. package/dist-lib/lib/cartControl.functions.d.ts.map +1 -1
  55. package/dist-lib/lib/cartControl.functions.js +4 -1
  56. package/dist-lib/lib/cartRescheduling.d.ts.map +1 -1
  57. package/dist-lib/lib/cartRescheduling.js +8 -6
  58. package/dist-lib/lib/countries.d.ts +2 -0
  59. package/dist-lib/lib/countries.d.ts.map +1 -1
  60. package/dist-lib/lib/countries.js +51 -0
  61. package/dist-lib/lib/deliveryNotePrint.d.ts +26 -0
  62. package/dist-lib/lib/deliveryNotePrint.d.ts.map +1 -0
  63. package/dist-lib/lib/deliveryNotePrint.js +172 -0
  64. package/dist-lib/lib/floriday.functions.d.ts +1251 -63
  65. package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
  66. package/dist-lib/lib/floriday.functions.js +126 -8
  67. package/dist-lib/lib/floridayAutoProcess.d.ts +30 -0
  68. package/dist-lib/lib/floridayAutoProcess.d.ts.map +1 -0
  69. package/dist-lib/lib/floridayAutoProcess.js +70 -0
  70. package/dist-lib/lib/pickstationI18n.d.ts +46 -0
  71. package/dist-lib/lib/pickstationI18n.d.ts.map +1 -1
  72. package/dist-lib/lib/pickstationI18n.js +251 -0
  73. package/dist-lib/lib/pickstationOrders.server.d.ts.map +1 -1
  74. package/dist-lib/lib/pickstationOrders.server.js +56 -19
  75. package/dist-lib/lib/pickstationTypes.d.ts +2 -0
  76. package/dist-lib/lib/pickstationTypes.d.ts.map +1 -1
  77. package/dist-lib/lib/planning.d.ts +34 -0
  78. package/dist-lib/lib/planning.d.ts.map +1 -1
  79. package/dist-lib/lib/planning.js +84 -0
  80. package/package.json +15 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"carrierPlanning.d.ts","sourceRoot":"","sources":["../../src/lib/carrierPlanning.ts"],"names":[],"mappings":"AAEA,OAAO,EAAyB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAItE,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACjC,cAAc,CAAC,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IAC1C,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAUzD;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,EAAE,CAanE;AAED,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAK/D;AAED,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,mBAAmB,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAU3F;AAED,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,mBAAmB,EAClE,QAAQ,EAAE,CAAC,EAAE,EACb,MAAM,EAAE,kBAAkB,GACzB,CAAC,GAAG,IAAI,CAiCV"}
@@ -0,0 +1,65 @@
1
+ import { matchesServiceArea } from "./geo/euServiceAreas";
2
+ import { countryCode } from "./countries";
3
+ import { DEFAULT_PICKUP_MOMENT } from "./planning";
4
+ const DEFAULT_WEEKDAYS = [1, 2, 3, 4, 5];
5
+ export function sanitizeWeekdays(input) {
6
+ if (!Array.isArray(input))
7
+ return DEFAULT_WEEKDAYS;
8
+ const clean = Array.from(new Set(input
9
+ .map((n) => Math.floor(Number(n)))
10
+ .filter((n) => Number.isFinite(n) && n >= 1 && n <= 7))).sort((a, b) => a - b);
11
+ return clean.length > 0 ? clean : DEFAULT_WEEKDAYS;
12
+ }
13
+ export function normalizePickupMoments(raw) {
14
+ if (!Array.isArray(raw) || raw.length === 0)
15
+ return [DEFAULT_PICKUP_MOMENT];
16
+ return raw.map((m) => {
17
+ const r = (m ?? {});
18
+ return {
19
+ signup_days: Math.max(0, Math.floor(Number(r.signup_days ?? DEFAULT_PICKUP_MOMENT.signup_days) || 0)),
20
+ signup_time: String(r.signup_time ?? DEFAULT_PICKUP_MOMENT.signup_time),
21
+ pickup_days: Math.max(0, Math.floor(Number(r.pickup_days ?? DEFAULT_PICKUP_MOMENT.pickup_days) || 0)),
22
+ pickup_time: String(r.pickup_time ?? DEFAULT_PICKUP_MOMENT.pickup_time),
23
+ delivery_days: Math.max(0, Math.floor(Number(r.delivery_days ?? DEFAULT_PICKUP_MOMENT.delivery_days) || 0)),
24
+ delivery_time: String(r.delivery_time ?? DEFAULT_PICKUP_MOMENT.delivery_time),
25
+ };
26
+ });
27
+ }
28
+ export function carrierLeadDaysFromMoments(raw) {
29
+ return normalizePickupMoments(raw).reduce((max, moment) => Math.max(max, moment.signup_days, moment.pickup_days, moment.delivery_days), 0);
30
+ }
31
+ export function normalizePlanningCarriers(carriers) {
32
+ return carriers.map((carrier) => ({
33
+ ...carrier,
34
+ service_countries: carrier.service_countries ?? [],
35
+ service_provinces: carrier.service_provinces ?? [],
36
+ service_cities: carrier.service_cities ?? [],
37
+ pickup_moments: normalizePickupMoments(carrier.pickup_moments),
38
+ pickup_weekdays: sanitizeWeekdays(carrier.pickup_weekdays),
39
+ delivery_weekdays: sanitizeWeekdays(carrier.delivery_weekdays),
40
+ }));
41
+ }
42
+ export function selectCarrierForTarget(carriers, target) {
43
+ const normalized = normalizePlanningCarriers(carriers);
44
+ const sorted = [...normalized].sort((a, b) => (a.sort_order ?? 9999) - (b.sort_order ?? 9999));
45
+ if (target.carrierId) {
46
+ const explicit = sorted.find((carrier) => carrier.id === target.carrierId);
47
+ if (explicit)
48
+ return explicit;
49
+ }
50
+ const matchTarget = {
51
+ country: countryCode(target.country) ?? target.country ?? null,
52
+ province: target.province ?? null,
53
+ city: target.city ?? null,
54
+ };
55
+ for (const carrier of sorted) {
56
+ if (matchesServiceArea({
57
+ countries: carrier.service_countries ?? [],
58
+ provinces: carrier.service_provinces ?? [],
59
+ cities: carrier.service_cities ?? [],
60
+ }, matchTarget)) {
61
+ return carrier;
62
+ }
63
+ }
64
+ return sorted.find((carrier) => carrier.is_default) ?? sorted[0] ?? null;
65
+ }
@@ -37,7 +37,6 @@ export interface SignupMailOrderRow {
37
37
  customerName: string;
38
38
  deliveryType: string;
39
39
  cartCount: number | null;
40
- plantCount: number | null;
41
40
  }
42
41
  export interface SignupMailInput {
43
42
  carrierName: string;
@@ -51,6 +50,5 @@ export declare function buildCarrierSignupMail(input: SignupMailInput): {
51
50
  html: string;
52
51
  text: string;
53
52
  totalCarts: number;
54
- totalPlants: number;
55
53
  };
56
54
  //# sourceMappingURL=carrierSignupMail.server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"carrierSignupMail.server.d.ts","sourceRoot":"","sources":["../../src/lib/carrierSignupMail.server.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,gBAAgB,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC/B;AAGD,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,IAAI,CAAC;IACrB,MAAM,EAAE,qBAAqB,EAAE,CAAC;CACjC;AAgJD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,eAAe,GAAG;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB,CAoGA"}
1
+ {"version":3,"file":"carrierSignupMail.server.d.ts","sourceRoot":"","sources":["../../src/lib/carrierSignupMail.server.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,gBAAgB,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC/B;AAGD,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,IAAI,CAAC;IACrB,MAAM,EAAE,qBAAqB,EAAE,CAAC;CACjC;AAyBD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,eAAe,GAAG;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB,CAuDA"}
@@ -1,229 +1,66 @@
1
1
  // Server-only HTML/text builder for carrier signup digest e-mails.
2
- function fmtDate(d) {
3
- return d.toLocaleDateString("nl-NL", {
4
- weekday: "long",
5
- day: "2-digit",
6
- month: "long",
7
- year: "numeric",
8
- });
9
- }
10
- function fmtDateTime(d) {
11
- return d.toLocaleString("nl-NL", {
12
- weekday: "short",
13
- day: "2-digit",
14
- month: "short",
15
- hour: "2-digit",
16
- minute: "2-digit",
17
- });
18
- }
19
- function fmtIsoDate(s) {
20
- if (!s)
21
- return "Onbekend";
22
- const d = new Date(s);
23
- if (Number.isNaN(d.getTime()))
24
- return s;
25
- return d.toLocaleDateString("nl-NL", { day: "2-digit", month: "long", year: "numeric" });
2
+ function escape(s) {
3
+ return String(s)
4
+ .replace(/&/g, "&amp;")
5
+ .replace(/</g, "&lt;")
6
+ .replace(/>/g, "&gt;")
7
+ .replace(/"/g, "&quot;");
26
8
  }
27
- function val(s) {
28
- const v = (s ?? "").trim();
29
- return v === "" ? "Onbekend" : escape(v);
9
+ function fmtDdMmYyyy(d) {
10
+ const dd = String(d.getDate()).padStart(2, "0");
11
+ const mm = String(d.getMonth() + 1).padStart(2, "0");
12
+ const yy = d.getFullYear();
13
+ return `${dd}-${mm}-${yy}`;
30
14
  }
31
- function renderAddress(a) {
15
+ function formatFullAddress(a) {
32
16
  if (!a)
33
- return `<div style="color:#6b7280;">Onbekend</div>`;
34
- const streetLine = [a.street, a.houseNumber].filter(Boolean).join(" ").trim();
35
- const cityLine = [a.postalCode, a.city].filter(Boolean).join(" ").trim();
36
- const lines = [];
37
- if (a.name && a.name.trim())
38
- lines.push(`<strong>${escape(a.name)}</strong>`);
39
- if (streetLine)
40
- lines.push(escape(streetLine));
41
- if (cityLine)
42
- lines.push(escape(cityLine));
43
- if (a.province && a.province.trim())
44
- lines.push(escape(a.province));
45
- if (a.country && a.country.trim())
46
- lines.push(escape(a.country));
47
- if (lines.length === 0)
48
- return `<div style="color:#6b7280;">Onbekend</div>`;
49
- return lines.map((l) => `<div>${l}</div>`).join("");
50
- }
51
- function renderDefinitionList(rows) {
52
- return `<table style="border-collapse:collapse;font-size:13px;width:100%;">${rows
53
- .map((r) => `
54
- <tr>
55
- <td style="padding:2px 12px 2px 0;color:#6b7280;width:140px;vertical-align:top;">${escape(r.label)}</td>
56
- <td style="padding:2px 0;vertical-align:top;">${r.value}</td>
57
- </tr>`)
58
- .join("")}</table>`;
59
- }
60
- function renderItemsTable(items) {
61
- if (!items || items.length === 0) {
62
- return `<div style="color:#6b7280;font-size:13px;">Geen artikelen geregistreerd.</div>`;
63
- }
64
- const rows = items
65
- .map((it) => `
66
- <tr>
67
- <td style="padding:6px 8px;border-bottom:1px solid #e5e7eb;">${escape(it.name)}</td>
68
- <td style="padding:6px 8px;border-bottom:1px solid #e5e7eb;text-align:right;">${it.quantity ?? "—"}</td>
69
- <td style="padding:6px 8px;border-bottom:1px solid #e5e7eb;">${escape(it.unit ?? "")}</td>
70
- </tr>`)
71
- .join("");
72
- return `<table style="border-collapse:collapse;width:100%;font-size:13px;">
73
- <thead><tr style="background:#f3f4f6;text-align:left;">
74
- <th style="padding:6px 8px;">Artikel</th>
75
- <th style="padding:6px 8px;text-align:right;width:90px;">Aantal</th>
76
- <th style="padding:6px 8px;width:100px;">Eenheid</th>
77
- </tr></thead>
78
- <tbody>${rows}</tbody>
79
- </table>`;
80
- }
81
- function renderOrderBlock(o) {
82
- const orderRows = renderDefinitionList([
83
- { label: "Ordernummer", value: `<strong>${val(o.orderNumber)}</strong>` },
84
- { label: "Besteldatum", value: escape(fmtIsoDate(o.orderDate)) },
85
- { label: "Gewenste leverdatum", value: escape(fmtIsoDate(o.deliveryDate)) },
86
- { label: "Type levering", value: val(o.deliveryType) },
87
- { label: "Karren", value: String(o.cartCount ?? "—") },
88
- { label: "Planten", value: String(o.plantCount ?? "—") },
89
- ]);
90
- const customerRows = renderDefinitionList([
91
- { label: "Klantnaam", value: val(o.customer.name) },
92
- { label: "E-mailadres", value: val(o.customer.email) },
93
- ]);
94
- const pickupHtml = o.pickupLocations && o.pickupLocations.length > 0
95
- ? o.pickupLocations.map((p) => `<div>${escape(p)}</div>`).join("")
96
- : `<div style="color:#6b7280;">Onbekend</div>`;
97
- const notesHtml = o.notes && o.notes.trim()
98
- ? `<div style="background:#fffbeb;border:1px solid #fde68a;border-radius:6px;padding:10px 12px;font-size:13px;white-space:pre-wrap;">${escape(o.notes)}</div>`
99
- : "";
100
- return `
101
- <div style="border:1px solid #e5e7eb;border-radius:8px;padding:16px;margin-bottom:20px;">
102
- <h3 style="margin:0 0 12px 0;font-size:16px;">Order ${escape(o.orderNumber)}</h3>
103
-
104
- <div style="margin-bottom:14px;">
105
- <div style="font-weight:bold;font-size:13px;margin-bottom:6px;color:#111827;">Ordergegevens</div>
106
- ${orderRows}
107
- </div>
108
-
109
- <div style="margin-bottom:14px;">
110
- <div style="font-weight:bold;font-size:13px;margin-bottom:6px;color:#111827;">Klantgegevens</div>
111
- ${customerRows}
112
- </div>
113
-
114
- <table style="width:100%;border-collapse:collapse;margin-bottom:14px;">
115
- <tr>
116
- <td style="vertical-align:top;width:50%;padding-right:8px;">
117
- <div style="font-weight:bold;font-size:13px;margin-bottom:6px;color:#111827;">Afleverlocatie</div>
118
- <div style="font-size:13px;">${renderAddress(o.deliveryLocation)}</div>
119
- </td>
120
- <td style="vertical-align:top;width:50%;padding-left:8px;">
121
- <div style="font-weight:bold;font-size:13px;margin-bottom:6px;color:#111827;">Ophaallocatie</div>
122
- <div style="font-size:13px;">${pickupHtml}</div>
123
- </td>
124
- </tr>
125
- </table>
126
-
127
- <div style="margin-bottom:14px;">
128
- <div style="font-weight:bold;font-size:13px;margin-bottom:6px;color:#111827;">Bestelde artikelen</div>
129
- ${renderItemsTable(o.items)}
130
- </div>
131
-
132
- ${notesHtml ? `<div><div style="font-weight:bold;font-size:13px;margin-bottom:6px;color:#111827;">Opmerkingen</div>${notesHtml}</div>` : ""}
133
- </div>`;
17
+ return "—";
18
+ const street = [a.street, a.houseNumber].filter(Boolean).join(" ").trim();
19
+ const city = [a.postalCode, a.city].filter(Boolean).join(" ").trim();
20
+ const parts = [street, city].filter((v) => v && v.trim() !== "");
21
+ return parts.length > 0 ? parts.join(", ") : "—";
134
22
  }
135
23
  export function buildCarrierSignupMail(input) {
136
24
  const totalCarts = input.orders.reduce((s, o) => s + (o.cartCount ?? 0), 0);
137
- const totalPlants = input.orders.reduce((s, o) => s + (o.plantCount ?? 0), 0);
138
- const subject = `Aanmelden karren ${input.carrierName} — ${input.pickupDate.toLocaleDateString("nl-NL", { day: "2-digit", month: "2-digit", year: "numeric" })} ${input.pickupTime}`;
139
- const summaryRows = input.orders
25
+ const orderCount = input.orders.length;
26
+ const subject = `Aanmelden karren ${input.carrierName} — ${fmtDdMmYyyy(input.pickupDate)} ${input.pickupTime}`;
27
+ const rows = input.orders
140
28
  .map((o) => `
141
- <tr>
142
- <td style="padding:6px 8px;border-bottom:1px solid #e5e7eb;">${escape(o.orderNumber)}</td>
143
- <td style="padding:6px 8px;border-bottom:1px solid #e5e7eb;">${escape(o.customer.name)}</td>
144
- <td style="padding:6px 8px;border-bottom:1px solid #e5e7eb;">${escape(o.deliveryType)}</td>
145
- <td style="padding:6px 8px;border-bottom:1px solid #e5e7eb;text-align:right;">${o.cartCount ?? "—"}</td>
146
- <td style="padding:6px 8px;border-bottom:1px solid #e5e7eb;text-align:right;">${o.plantCount ?? "—"}</td>
147
- </tr>`)
29
+ <tr>
30
+ <td style="padding:6px 8px;border:1px solid #d1d5db;">${escape(o.orderNumber)}</td>
31
+ <td style="padding:6px 8px;border:1px solid #d1d5db;">${escape(o.customer.name)}</td>
32
+ <td style="padding:6px 8px;border:1px solid #d1d5db;">${escape(o.deliveryDate ?? "—")}</td>
33
+ <td style="padding:6px 8px;border:1px solid #d1d5db;text-align:right;">${o.cartCount ?? "—"}</td>
34
+ <td style="padding:6px 8px;border:1px solid #d1d5db;">${escape(formatFullAddress(o.deliveryLocation))}</td>
35
+ </tr>`)
148
36
  .join("");
149
- const orderBlocks = input.orders.map(renderOrderBlock).join("");
150
37
  const html = `<!doctype html>
151
- <html lang="nl"><body style="font-family:Arial,sans-serif;color:#111;background:#f9fafb;margin:0;padding:24px;">
152
- <div style="max-width:760px;margin:0 auto;background:#ffffff;padding:24px;border-radius:8px;">
153
- <h2 style="margin:0 0 8px 0;">Aanmelden karren — ${escape(input.carrierName)}</h2>
154
- <p style="margin:0 0 20px 0;color:#374151;font-size:14px;">
155
- Ophaalmoment: <strong>${escape(fmtDate(input.pickupDate))} om ${escape(input.pickupTime)}</strong><br/>
156
- Aanmelddeadline: <strong>${escape(fmtDateTime(input.signupDeadline))}</strong>
157
- </p>
38
+ <html lang="nl"><body style="font-family:Arial,sans-serif;color:#111;margin:0;padding:24px;">
39
+ <h2 style="margin:0 0 16px 0;">Aanmelden karren</h2>
40
+ <p style="margin:0 0 12px 0;">Beste ${escape(input.carrierName)},</p>
41
+ <p style="margin:0 0 12px 0;">Graag aanmelden voor ophalen op <strong>${fmtDdMmYyyy(input.pickupDate)} om ${escape(input.pickupTime)}</strong>.</p>
42
+ <p style="margin:0 0 16px 0;"><strong>${orderCount} order${orderCount === 1 ? "" : "s"} · ${totalCarts} karren</strong></p>
158
43
 
159
- <div style="font-weight:bold;font-size:14px;margin-bottom:6px;">Overzicht</div>
160
- <table style="border-collapse:collapse;width:100%;font-size:13px;margin-bottom:24px;">
161
- <thead><tr style="background:#f3f4f6;text-align:left;">
162
- <th style="padding:6px 8px;">Order</th>
163
- <th style="padding:6px 8px;">Klant</th>
164
- <th style="padding:6px 8px;">Type</th>
165
- <th style="padding:6px 8px;text-align:right;">Karren</th>
166
- <th style="padding:6px 8px;text-align:right;">Planten</th>
167
- </tr></thead>
168
- <tbody>${summaryRows}</tbody>
169
- <tfoot><tr style="font-weight:bold;background:#f9fafb;">
170
- <td colspan="3" style="padding:6px 8px;text-align:right;">Totaal</td>
171
- <td style="padding:6px 8px;text-align:right;">${totalCarts}</td>
172
- <td style="padding:6px 8px;text-align:right;">${totalPlants}</td>
173
- </tr></tfoot>
174
- </table>
175
-
176
- ${orderBlocks}
177
-
178
- <p style="margin-top:16px;font-size:12px;color:#6b7280;">
179
- Automatisch verzonden door Flowselections Afhandeling.
180
- </p>
181
- </div>
44
+ <table style="border-collapse:collapse;font-size:13px;">
45
+ <thead>
46
+ <tr style="background:#f3f4f6;text-align:left;">
47
+ <th style="padding:6px 8px;border:1px solid #d1d5db;">Order</th>
48
+ <th style="padding:6px 8px;border:1px solid #d1d5db;">Klant</th>
49
+ <th style="padding:6px 8px;border:1px solid #d1d5db;">Leverdatum</th>
50
+ <th style="padding:6px 8px;border:1px solid #d1d5db;text-align:right;">Karren</th>
51
+ <th style="padding:6px 8px;border:1px solid #d1d5db;">Plaats</th>
52
+ </tr>
53
+ </thead>
54
+ <tbody>${rows}</tbody>
55
+ </table>
182
56
  </body></html>`;
183
- const textOrders = input.orders
184
- .map((o) => {
185
- const addr = o.deliveryLocation
186
- ? [
187
- o.deliveryLocation.name,
188
- [o.deliveryLocation.street, o.deliveryLocation.houseNumber].filter(Boolean).join(" "),
189
- [o.deliveryLocation.postalCode, o.deliveryLocation.city].filter(Boolean).join(" "),
190
- o.deliveryLocation.province,
191
- o.deliveryLocation.country,
192
- ]
193
- .filter((v) => v && String(v).trim())
194
- .join(", ")
195
- : "Onbekend";
196
- const items = (o.items ?? [])
197
- .map((it) => ` - ${it.name}: ${it.quantity ?? "-"} ${it.unit ?? ""}`.trim())
198
- .join("\n");
199
- return [
200
- `Order ${o.orderNumber}`,
201
- ` Besteldatum: ${fmtIsoDate(o.orderDate)}`,
202
- ` Leverdatum: ${fmtIsoDate(o.deliveryDate)}`,
203
- ` Type: ${o.deliveryType}`,
204
- ` Karren: ${o.cartCount ?? "-"} | Planten: ${o.plantCount ?? "-"}`,
205
- ` Klant: ${o.customer.name}` +
206
- (o.customer.email ? ` <${o.customer.email}>` : ""),
207
- ` Afleverlocatie: ${addr}`,
208
- ` Ophaallocatie: ${(o.pickupLocations ?? []).join(", ") || "Onbekend"}`,
209
- items ? ` Artikelen:\n${items}` : ` Artikelen: -`,
210
- o.notes ? ` Opmerkingen: ${o.notes}` : "",
211
- ]
212
- .filter(Boolean)
213
- .join("\n");
214
- })
215
- .join("\n\n");
216
- const text = `Aanmelden karren — ${input.carrierName}\n` +
217
- `Ophaalmoment: ${fmtDate(input.pickupDate)} ${input.pickupTime}\n` +
218
- `Aanmelddeadline: ${fmtDateTime(input.signupDeadline)}\n\n` +
219
- textOrders +
220
- `\n\nTotaal: ${totalCarts} karren, ${totalPlants} planten.`;
221
- return { subject, html, text, totalCarts, totalPlants };
222
- }
223
- function escape(s) {
224
- return String(s)
225
- .replace(/&/g, "&amp;")
226
- .replace(/</g, "&lt;")
227
- .replace(/>/g, "&gt;")
228
- .replace(/"/g, "&quot;");
57
+ const textRows = input.orders
58
+ .map((o) => `- ${o.orderNumber} | ${o.customer.name} | ${o.deliveryDate ?? "—"} | ${o.cartCount ?? "—"} karren | ${formatFullAddress(o.deliveryLocation)}`)
59
+ .join("\n");
60
+ const text = `Aanmelden karren\n\n` +
61
+ `Beste ${input.carrierName},\n\n` +
62
+ `Graag aanmelden voor ophalen op ${fmtDdMmYyyy(input.pickupDate)} om ${input.pickupTime}.\n\n` +
63
+ `${orderCount} order${orderCount === 1 ? "" : "s"} · ${totalCarts} karren\n\n` +
64
+ textRows;
65
+ return { subject, html, text, totalCarts };
229
66
  }