@vicacha-devs/strapi-plugin-inbox 0.0.0-stage → 1.1.0

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 (90) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +17 -2
  3. package/dist/admin/InboxHomePage-B5xUPD7Y.mjs +2153 -0
  4. package/dist/admin/InboxHomePage-BCHbPE2t.js +2171 -0
  5. package/dist/admin/LocalizationRoutingTab-CEXbHNe4.mjs +282 -0
  6. package/dist/admin/LocalizationRoutingTab-Dt6U-kXn.js +281 -0
  7. package/dist/admin/SettingsPage-Dif7Cq7I.mjs +819 -0
  8. package/dist/admin/SettingsPage-qB_efKCl.js +837 -0
  9. package/dist/admin/ar-CbjX4o07.mjs +268 -0
  10. package/dist/admin/ar-KedDMvsH.js +268 -0
  11. package/dist/admin/de-BrJIGJEV.mjs +268 -0
  12. package/dist/admin/de-rj5pqQ0S.js +268 -0
  13. package/dist/admin/en-BE8TARw0.mjs +268 -0
  14. package/dist/admin/en-CuTmgXZL.js +268 -0
  15. package/dist/admin/es-Berf1dRb.js +268 -0
  16. package/dist/admin/es-Ce4nMwC7.mjs +268 -0
  17. package/dist/admin/fr-CfdjWCiu.js +268 -0
  18. package/dist/admin/fr-Y3GKi6mQ.mjs +268 -0
  19. package/dist/admin/index-5e9dAMBs.mjs +822 -0
  20. package/dist/admin/index-DLfoIVZP.js +839 -0
  21. package/dist/admin/index.js +5 -0
  22. package/dist/admin/index.mjs +5 -0
  23. package/dist/admin/it-DXXnvX5J.mjs +268 -0
  24. package/dist/admin/it-DkJ3WwLA.js +268 -0
  25. package/dist/admin/pt-D7WKv-MR.js +268 -0
  26. package/dist/admin/pt-QDCJ6lOH.mjs +268 -0
  27. package/dist/admin/ru-DgYTw9aE.js +268 -0
  28. package/dist/admin/ru-DzP0H4fh.mjs +268 -0
  29. package/dist/admin/src/components/Initializer.d.ts +6 -0
  30. package/dist/admin/src/components/PluginIcon.d.ts +3 -0
  31. package/dist/admin/src/components/inbox/AlertBannersTab.d.ts +10 -0
  32. package/dist/admin/src/components/inbox/CaseworkDetailPanel.d.ts +15 -0
  33. package/dist/admin/src/components/inbox/CaseworkPayloadChecklistColumn.d.ts +12 -0
  34. package/dist/admin/src/components/inbox/CaseworkSubmissionsTab.d.ts +12 -0
  35. package/dist/admin/src/components/inbox/FormBuilderTab.d.ts +17 -0
  36. package/dist/admin/src/components/inbox/FormChecklistAndLocalePanels.d.ts +17 -0
  37. package/dist/admin/src/components/inbox/FormRoutingDrawer.d.ts +15 -0
  38. package/dist/admin/src/components/inbox/SubscribersTab.d.ts +10 -0
  39. package/dist/admin/src/components/settings/AntiSpamCaptchaTab.d.ts +9 -0
  40. package/dist/admin/src/components/settings/BridgesNotificationsTab.d.ts +8 -0
  41. package/dist/admin/src/components/settings/CaptchaProviderCard.d.ts +21 -0
  42. package/dist/admin/src/components/settings/LocalizationRoutingTab.d.ts +16 -0
  43. package/dist/admin/src/index.d.ts +21 -0
  44. package/dist/admin/src/pages/InboxHomePage.d.ts +3 -0
  45. package/dist/admin/src/pages/SettingsPage.d.ts +3 -0
  46. package/dist/admin/src/pluginId.d.ts +3 -0
  47. package/dist/admin/src/translations/cmLabels.d.ts +1 -0
  48. package/dist/admin/src/translations/cmPlaceholders.d.ts +1 -0
  49. package/dist/admin/src/utils/getTranslation.d.ts +3 -0
  50. package/dist/admin/tr-5q4NwTgF.mjs +268 -0
  51. package/dist/admin/tr-CT-24fLA.js +268 -0
  52. package/dist/admin/zh-CYhWM5Qr.mjs +268 -0
  53. package/dist/admin/zh-CmCHcNcd.js +268 -0
  54. package/dist/server/index.js +3108 -0
  55. package/dist/server/index.mjs +3108 -0
  56. package/dist/server/src/bootstrap.d.ts +5 -0
  57. package/dist/server/src/config/index.d.ts +5 -0
  58. package/dist/server/src/content-types/alert-banner/index.d.ts +73 -0
  59. package/dist/server/src/content-types/alert-banner/schema.json.d.ts +73 -0
  60. package/dist/server/src/content-types/index.d.ts +253 -0
  61. package/dist/server/src/content-types/submission/index.d.ts +111 -0
  62. package/dist/server/src/content-types/submission/schema.json.d.ts +126 -0
  63. package/dist/server/src/content-types/subscriber/index.d.ts +69 -0
  64. package/dist/server/src/content-types/subscriber/schema.json.d.ts +69 -0
  65. package/dist/server/src/controllers/caseworkHandlers.d.ts +10 -0
  66. package/dist/server/src/controllers/communityHandlers.d.ts +10 -0
  67. package/dist/server/src/controllers/formHandlers.d.ts +14 -0
  68. package/dist/server/src/controllers/inboxController.d.ts +40 -0
  69. package/dist/server/src/controllers/index.d.ts +2 -0
  70. package/dist/server/src/destroy.d.ts +5 -0
  71. package/dist/server/src/index.d.ts +2 -0
  72. package/dist/server/src/register.d.ts +5 -0
  73. package/dist/server/src/routes/admin.d.ts +12 -0
  74. package/dist/server/src/routes/content-api.d.ts +13 -0
  75. package/dist/server/src/routes/index.d.ts +26 -0
  76. package/dist/server/src/services/alertService.d.ts +16 -0
  77. package/dist/server/src/services/docHelper.d.ts +28 -0
  78. package/dist/server/src/services/formBuilderMapper.d.ts +22 -0
  79. package/dist/server/src/services/formBuilderSync.d.ts +13 -0
  80. package/dist/server/src/services/formService.d.ts +40 -0
  81. package/dist/server/src/services/index.d.ts +2 -0
  82. package/dist/server/src/services/settings.d.ts +9 -0
  83. package/dist/server/src/services/submissionEcosystemBridges.d.ts +21 -0
  84. package/dist/server/src/services/submissionFormBuilderBridge.d.ts +23 -0
  85. package/dist/server/src/services/submissionService.d.ts +58 -0
  86. package/dist/server/src/services/subscriberService.d.ts +22 -0
  87. package/dist/shared/index.d.ts +1 -0
  88. package/dist/shared/index.js +917 -0
  89. package/dist/shared/index.mjs +917 -0
  90. package/package.json +125 -3
@@ -0,0 +1,2153 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { Box, Flex, Typography, Button, Field, TextInput, SingleSelect, SingleSelectOption, NumberInput, Table, Thead, Tr, Th, Tbody, Td, Badge, Checkbox, Divider, Textarea, MultiSelect, MultiSelectOption, Main } from "@strapi/design-system";
3
+ import { useFetchClient } from "@strapi/strapi/admin";
4
+ import * as React from "react";
5
+ import { useIntl } from "react-intl";
6
+ import { A as ALERT_SEVERITIES, P as PLUGIN_ID, S as SUBMISSION_STATUSES, a as SUBMISSION_PRIORITIES, F as FORM_CATEGORIES, b as FORM_BUILDER_CMS_PLUGIN_ID, L as LOCALE_OPTIONS } from "./index-5e9dAMBs.mjs";
7
+ import { useNavigate } from "react-router-dom";
8
+ import { T as TOPIC_OPTIONS } from "./LocalizationRoutingTab-CEXbHNe4.mjs";
9
+ const STARTER_FORM_TEMPLATES = [
10
+ {
11
+ id: "general-contact",
12
+ name: "General Contact & Inquiry",
13
+ description: "Multi-language contact form with subject routing and anti-spam protection.",
14
+ form: {
15
+ title: "General Contact",
16
+ slug: "general-contact",
17
+ description: "Send us a message and our team will respond promptly.",
18
+ category: "contact",
19
+ active: true,
20
+ publishedAt: "2026-01-01T00:00:00.000Z",
21
+ translations: {
22
+ es: {
23
+ title: "Contacto General",
24
+ description: "Envíanos un mensaje y nuestro equipo te responderá pronto.",
25
+ submitButtonLabel: "Enviar mensaje",
26
+ successMessage: "Gracias por contactarnos. Hemos recibido tu mensaje."
27
+ },
28
+ en: {
29
+ title: "General Contact",
30
+ description: "Send us a message and our team will respond promptly.",
31
+ submitButtonLabel: "Send message",
32
+ successMessage: "Thank you for reaching out. We have received your message."
33
+ },
34
+ ar: {
35
+ title: "الاتصال العام",
36
+ description: "أرسل لنا رسالة وسيرد فريقنا في أقرب وقت.",
37
+ submitButtonLabel: "إرسال الرسالة",
38
+ successMessage: "شكراً لتواصلك معنا. لقد استلمنا رسالتك."
39
+ }
40
+ },
41
+ fields: [
42
+ {
43
+ id: "fld_full_name",
44
+ type: "text",
45
+ name: "fullName",
46
+ label: "Full Name",
47
+ required: true,
48
+ width: "half",
49
+ localizedLabels: {
50
+ es: "Nombre completo",
51
+ en: "Full Name",
52
+ ar: "الاسم الكامل"
53
+ },
54
+ validation: [{ type: "minLength", value: 2 }]
55
+ },
56
+ {
57
+ id: "fld_email",
58
+ type: "email",
59
+ name: "email",
60
+ label: "Email Address",
61
+ required: true,
62
+ width: "half",
63
+ localizedLabels: {
64
+ es: "Correo electrónico",
65
+ en: "Email Address",
66
+ ar: "البريد الإلكتروني"
67
+ }
68
+ },
69
+ {
70
+ id: "fld_phone",
71
+ type: "phone",
72
+ name: "phone",
73
+ label: "Phone / WhatsApp",
74
+ required: false,
75
+ width: "half",
76
+ localizedLabels: {
77
+ es: "Teléfono / WhatsApp",
78
+ en: "Phone / WhatsApp",
79
+ ar: "الهاتف / واتساب"
80
+ }
81
+ },
82
+ {
83
+ id: "fld_subject",
84
+ type: "select",
85
+ name: "subject",
86
+ label: "Subject",
87
+ required: true,
88
+ width: "half",
89
+ localizedLabels: {
90
+ es: "Asunto",
91
+ en: "Subject",
92
+ ar: "الموضوع"
93
+ },
94
+ options: [
95
+ {
96
+ value: "general",
97
+ label: "General Inquiry",
98
+ localizedLabels: {
99
+ es: "Consulta general",
100
+ en: "General Inquiry",
101
+ ar: "استفسار عام"
102
+ }
103
+ },
104
+ {
105
+ value: "visit",
106
+ label: "Guided Visit",
107
+ localizedLabels: {
108
+ es: "Visita guiada",
109
+ en: "Guided Visit",
110
+ ar: "زيارة إرشادية"
111
+ }
112
+ },
113
+ {
114
+ value: "support",
115
+ label: "Support & Assistance",
116
+ localizedLabels: {
117
+ es: "Apoyo y asistencia",
118
+ en: "Support & Assistance",
119
+ ar: "الدعم والمساعدة"
120
+ }
121
+ }
122
+ ]
123
+ },
124
+ {
125
+ id: "fld_message",
126
+ type: "textarea",
127
+ name: "message",
128
+ label: "Message",
129
+ required: true,
130
+ width: "full",
131
+ localizedLabels: {
132
+ es: "Mensaje",
133
+ en: "Message",
134
+ ar: "الرسالة"
135
+ },
136
+ validation: [
137
+ { type: "minLength", value: 10 },
138
+ { type: "maxLength", value: 2e3 }
139
+ ]
140
+ }
141
+ ],
142
+ settings: {
143
+ honeypotField: "_website_url",
144
+ rateLimitPerHour: 15,
145
+ captchaProvider: "none",
146
+ defaultPriority: "normal",
147
+ department: "general"
148
+ }
149
+ }
150
+ },
151
+ {
152
+ id: "service-desk-application",
153
+ name: "Service-Desk Casework & Document Checklist",
154
+ description: "Casework intake form with document verification checklist, booking bridge, and certificate bridge.",
155
+ form: {
156
+ title: "Formal Service Request",
157
+ slug: "service-request",
158
+ description: "Submit an official service application and required supporting documents.",
159
+ category: "service_desk",
160
+ active: true,
161
+ publishedAt: "2026-01-01T00:00:00.000Z",
162
+ translations: {
163
+ es: {
164
+ title: "Solicitud Formal de Servicio",
165
+ description: "Envía una solicitud oficial de servicio con los documentos requeridos.",
166
+ submitButtonLabel: "Radicar solicitud",
167
+ successMessage: "Tu solicitud ha sido radicada con éxito."
168
+ },
169
+ en: {
170
+ title: "Formal Service Request",
171
+ description: "Submit an official service application and required supporting documents.",
172
+ submitButtonLabel: "Submit application",
173
+ successMessage: "Your application has been registered."
174
+ },
175
+ ar: {
176
+ title: "طلب خدمة رسمي",
177
+ description: "قدم طلب خدمة رسمي مع المستندات المطلوبة.",
178
+ submitButtonLabel: "تقديم الطلب",
179
+ successMessage: "تم تسجيل طلبك بنجاح."
180
+ }
181
+ },
182
+ fields: [
183
+ {
184
+ id: "fld_applicant_name",
185
+ type: "text",
186
+ name: "applicantName",
187
+ label: "Applicant Full Name",
188
+ required: true,
189
+ width: "half",
190
+ localizedLabels: {
191
+ es: "Nombre completo del solicitante",
192
+ en: "Applicant Full Name",
193
+ ar: "الاسم الكامل لمقدم الطلب"
194
+ }
195
+ },
196
+ {
197
+ id: "fld_applicant_email",
198
+ type: "email",
199
+ name: "applicantEmail",
200
+ label: "Applicant Email",
201
+ required: true,
202
+ width: "half",
203
+ localizedLabels: {
204
+ es: "Correo del solicitante",
205
+ en: "Applicant Email",
206
+ ar: "البريد الإلكتروني لمقدم الطلب"
207
+ }
208
+ },
209
+ {
210
+ id: "fld_applicant_phone",
211
+ type: "phone",
212
+ name: "applicantPhone",
213
+ label: "Contact Phone",
214
+ required: true,
215
+ width: "half",
216
+ localizedLabels: {
217
+ es: "Teléfono de contacto",
218
+ en: "Contact Phone",
219
+ ar: "هاتف الاتصال"
220
+ }
221
+ },
222
+ {
223
+ id: "fld_preferred_date",
224
+ type: "date",
225
+ name: "preferredDate",
226
+ label: "Preferred Appointment Date",
227
+ required: false,
228
+ width: "half",
229
+ localizedLabels: {
230
+ es: "Fecha preferida de cita",
231
+ en: "Preferred Appointment Date",
232
+ ar: "تاريخ الموعد المفضل"
233
+ }
234
+ },
235
+ {
236
+ id: "fld_details",
237
+ type: "textarea",
238
+ name: "details",
239
+ label: "Case Details & Notes",
240
+ required: true,
241
+ width: "full",
242
+ localizedLabels: {
243
+ es: "Detalles del caso y observaciones",
244
+ en: "Case Details & Notes",
245
+ ar: "تفاصيل الطلب والملاحظات"
246
+ }
247
+ }
248
+ ],
249
+ checklistTemplate: [
250
+ {
251
+ id: "chk_id_document",
252
+ label: "Government ID / Passport Copy",
253
+ required: true,
254
+ verified: false,
255
+ localizedLabels: {
256
+ es: "Copia de documento de identidad / Pasaporte",
257
+ en: "Government ID / Passport Copy",
258
+ ar: "نسخة من بطاقة الهوية أو جواز السفر"
259
+ }
260
+ },
261
+ {
262
+ id: "chk_supporting_form",
263
+ label: "Signed Application Form",
264
+ required: true,
265
+ verified: false,
266
+ localizedLabels: {
267
+ es: "Formulario de solicitud firmado",
268
+ en: "Signed Application Form",
269
+ ar: "نموذج الطلب الموقع"
270
+ }
271
+ }
272
+ ],
273
+ settings: {
274
+ honeypotField: "_website_url",
275
+ rateLimitPerHour: 10,
276
+ captchaProvider: "none",
277
+ enableBookingBridge: true,
278
+ enableCertificateBridge: true,
279
+ defaultPriority: "normal",
280
+ department: "services"
281
+ }
282
+ }
283
+ }
284
+ ];
285
+ const cardBorderStyle$1 = {
286
+ border: "1px solid rgba(128, 128, 128, 0.2)"
287
+ };
288
+ const AlertBannersTab = ({
289
+ t,
290
+ alerts,
291
+ post,
292
+ onStatusMessage,
293
+ onReload
294
+ }) => {
295
+ const [showCreateForm, setShowCreateForm] = React.useState(false);
296
+ const [newAlertCode, setNewAlertCode] = React.useState("");
297
+ const [newAlertSeverity, setNewAlertSeverity] = React.useState("urgent");
298
+ const [newAlertPriority, setNewAlertPriority] = React.useState(100);
299
+ const [newAlertTitle, setNewAlertTitle] = React.useState("");
300
+ const [newAlertMessage, setNewAlertMessage] = React.useState("");
301
+ const [newAlertCtaLabel, setNewAlertCtaLabel] = React.useState("");
302
+ const [newAlertCtaUrl, setNewAlertCtaUrl] = React.useState("");
303
+ const handleCreateAlert = async () => {
304
+ if (!newAlertCode || !newAlertTitle || !newAlertMessage) return;
305
+ await post(`/${PLUGIN_ID}/alerts`, {
306
+ code: newAlertCode,
307
+ title: newAlertTitle,
308
+ message: newAlertMessage,
309
+ severity: newAlertSeverity,
310
+ active: true,
311
+ priority: newAlertPriority,
312
+ ctaLabel: newAlertCtaLabel || void 0,
313
+ ctaUrl: newAlertCtaUrl || void 0
314
+ });
315
+ setNewAlertCode("");
316
+ setNewAlertTitle("");
317
+ setNewAlertMessage("");
318
+ setNewAlertCtaLabel("");
319
+ setNewAlertCtaUrl("");
320
+ setShowCreateForm(false);
321
+ onStatusMessage("Site-wide alert banner saved");
322
+ await onReload();
323
+ };
324
+ return /* @__PURE__ */ jsxs(Box, { paddingTop: 5, children: [
325
+ /* @__PURE__ */ jsxs(
326
+ Flex,
327
+ {
328
+ justifyContent: "space-between",
329
+ alignItems: "center",
330
+ paddingBottom: 4,
331
+ wrap: "wrap",
332
+ gap: 3,
333
+ children: [
334
+ /* @__PURE__ */ jsx(Typography, { variant: "beta", tag: "h2", children: t("page.ui.alert_banners_list", "Site-Wide Alert Banners") }),
335
+ /* @__PURE__ */ jsx(
336
+ Button,
337
+ {
338
+ size: "S",
339
+ variant: showCreateForm ? "tertiary" : "default",
340
+ onClick: () => setShowCreateForm(!showCreateForm),
341
+ children: showCreateForm ? t("page.ui.cancel", "Cancel") : t("page.ui.new_alert_banner", "+ New Alert Banner")
342
+ }
343
+ )
344
+ ]
345
+ }
346
+ ),
347
+ showCreateForm ? /* @__PURE__ */ jsxs(
348
+ Box,
349
+ {
350
+ padding: 5,
351
+ marginBottom: 5,
352
+ background: "neutral0",
353
+ hasRadius: true,
354
+ shadow: "filterShadow",
355
+ style: cardBorderStyle$1,
356
+ children: [
357
+ /* @__PURE__ */ jsxs(
358
+ Flex,
359
+ {
360
+ justifyContent: "space-between",
361
+ alignItems: "center",
362
+ paddingBottom: 3,
363
+ wrap: "wrap",
364
+ gap: 2,
365
+ children: [
366
+ /* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h3", fontWeight: "bold", children: t(
367
+ "page.ui.publish_urgent_site_wide_alert_banner",
368
+ "Publish Site-Wide Alert Banner"
369
+ ) }),
370
+ /* @__PURE__ */ jsx(Button, { size: "S", onClick: handleCreateAlert, children: t("page.ui.save_alert_banner", "Save Alert Banner") })
371
+ ]
372
+ }
373
+ ),
374
+ /* @__PURE__ */ jsxs(
375
+ Box,
376
+ {
377
+ style: {
378
+ display: "grid",
379
+ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
380
+ gap: 16
381
+ },
382
+ children: [
383
+ /* @__PURE__ */ jsxs(Field.Root, { name: "code", required: true, children: [
384
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.alert_code", "Alert Code") }),
385
+ /* @__PURE__ */ jsx(
386
+ TextInput,
387
+ {
388
+ name: "code",
389
+ placeholder: t("placeholder.alert_code", "RAMADAN-1448-HILAL"),
390
+ value: newAlertCode,
391
+ onChange: (e) => setNewAlertCode(e.target.value)
392
+ }
393
+ )
394
+ ] }),
395
+ /* @__PURE__ */ jsxs(Field.Root, { name: "severity", required: true, children: [
396
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.severity_level", "Severity") }),
397
+ /* @__PURE__ */ jsx(
398
+ SingleSelect,
399
+ {
400
+ value: newAlertSeverity,
401
+ onChange: (val) => setNewAlertSeverity(String(val)),
402
+ children: ALERT_SEVERITIES.map((sev) => /* @__PURE__ */ jsx(SingleSelectOption, { value: sev, children: sev.toUpperCase() }, sev))
403
+ }
404
+ )
405
+ ] }),
406
+ /* @__PURE__ */ jsxs(Field.Root, { name: "priority", children: [
407
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.display_priority", "Priority") }),
408
+ /* @__PURE__ */ jsx(
409
+ NumberInput,
410
+ {
411
+ name: "priority",
412
+ value: newAlertPriority,
413
+ onValueChange: (val) => setNewAlertPriority(typeof val === "number" ? val : 100)
414
+ }
415
+ )
416
+ ] }),
417
+ /* @__PURE__ */ jsxs(Field.Root, { name: "title", required: true, children: [
418
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.headline_title", "Headline") }),
419
+ /* @__PURE__ */ jsx(
420
+ TextInput,
421
+ {
422
+ name: "title",
423
+ placeholder: t(
424
+ "placeholder.alert_headline",
425
+ "Moon-Sighting Announcement"
426
+ ),
427
+ value: newAlertTitle,
428
+ onChange: (e) => setNewAlertTitle(e.target.value)
429
+ }
430
+ )
431
+ ] }),
432
+ /* @__PURE__ */ jsxs(Field.Root, { name: "message", required: true, children: [
433
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.ticker_message", "Message") }),
434
+ /* @__PURE__ */ jsx(
435
+ TextInput,
436
+ {
437
+ name: "message",
438
+ placeholder: t(
439
+ "placeholder.alert_message",
440
+ "The first day of Ramadan will be..."
441
+ ),
442
+ value: newAlertMessage,
443
+ onChange: (e) => setNewAlertMessage(e.target.value)
444
+ }
445
+ )
446
+ ] }),
447
+ /* @__PURE__ */ jsxs(Field.Root, { name: "ctaLabel", children: [
448
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.cta_button_label_optional", "CTA Label") }),
449
+ /* @__PURE__ */ jsx(
450
+ TextInput,
451
+ {
452
+ name: "ctaLabel",
453
+ placeholder: t("placeholder.alert_cta_label", "View Schedule"),
454
+ value: newAlertCtaLabel,
455
+ onChange: (e) => setNewAlertCtaLabel(e.target.value)
456
+ }
457
+ )
458
+ ] }),
459
+ /* @__PURE__ */ jsxs(Field.Root, { name: "ctaUrl", children: [
460
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.cta_target_url_optional", "CTA URL") }),
461
+ /* @__PURE__ */ jsx(
462
+ TextInput,
463
+ {
464
+ name: "ctaUrl",
465
+ placeholder: t("placeholder.alert_cta_url", "/es/ramadan"),
466
+ value: newAlertCtaUrl,
467
+ onChange: (e) => setNewAlertCtaUrl(e.target.value)
468
+ }
469
+ )
470
+ ] })
471
+ ]
472
+ }
473
+ )
474
+ ]
475
+ }
476
+ ) : null,
477
+ /* @__PURE__ */ jsxs(Table, { colCount: 5, rowCount: alerts.length + 1, children: [
478
+ /* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
479
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.code", "Code") }) }),
480
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.severity", "Severity") }) }),
481
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.title", "Headline") }) }),
482
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.message", "Message") }) }),
483
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.secondary_calendar", "Hijri Date") }) })
484
+ ] }) }),
485
+ /* @__PURE__ */ jsx(Tbody, { children: alerts.map((banner) => /* @__PURE__ */ jsxs(Tr, { children: [
486
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: banner.code }) }),
487
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Badge, { children: banner.severity }) }),
488
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: banner.title }) }),
489
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: banner.message }) }),
490
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: banner.secondaryDateLabel || "-" }) })
491
+ ] }, banner.code)) })
492
+ ] })
493
+ ] });
494
+ };
495
+ function formatFieldKeyLabel(rawKey) {
496
+ return rawKey.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim().replace(/\b\w/g, (ch) => ch.toUpperCase());
497
+ }
498
+ const CaseworkPayloadChecklistColumn = ({
499
+ t,
500
+ shortLocale,
501
+ dataEntries,
502
+ form,
503
+ checklist,
504
+ onToggleChecklistItem
505
+ }) => {
506
+ const resolveFieldLabel = (key) => {
507
+ const matchedField = form?.fields?.find((f) => f.name === key);
508
+ if (matchedField) {
509
+ return matchedField.localizedLabels?.[shortLocale] || matchedField.label || formatFieldKeyLabel(key);
510
+ }
511
+ return formatFieldKeyLabel(key);
512
+ };
513
+ const resolveFieldValue = (key, val) => {
514
+ if (val === null || val === void 0 || val === "") return "-";
515
+ if (typeof val === "object") return JSON.stringify(val);
516
+ const strVal = String(val);
517
+ const matchedField = form?.fields?.find((f) => f.name === key);
518
+ const matchedOption = matchedField?.options?.find(
519
+ (o) => o.value === strVal
520
+ );
521
+ if (matchedOption) {
522
+ return matchedOption.localizedLabels?.[shortLocale] || matchedOption.label;
523
+ }
524
+ return strVal;
525
+ };
526
+ return /* @__PURE__ */ jsxs(Box, { style: { flex: "1 1 360px" }, children: [
527
+ /* @__PURE__ */ jsxs(Box, { paddingBottom: 4, children: [
528
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: t("page.ui.submitted_form_payload", "Submitted Form Payload") }),
529
+ /* @__PURE__ */ jsx(Box, { background: "neutral100", padding: 3, hasRadius: true, marginTop: 2, children: dataEntries.length === 0 ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: t(
530
+ "page.ui.no_payload_fields",
531
+ "No custom payload fields recorded."
532
+ ) }) : /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 0, children: dataEntries.map(([key, val], idx) => /* @__PURE__ */ jsxs(
533
+ Flex,
534
+ {
535
+ justifyContent: "space-between",
536
+ alignItems: "baseline",
537
+ gap: 3,
538
+ paddingTop: 2,
539
+ paddingBottom: 2,
540
+ style: {
541
+ borderBottom: idx < dataEntries.length - 1 ? "1px solid rgba(128, 128, 128, 0.14)" : "none"
542
+ },
543
+ children: [
544
+ /* @__PURE__ */ jsx(
545
+ Typography,
546
+ {
547
+ variant: "pi",
548
+ fontWeight: "bold",
549
+ textColor: "neutral600",
550
+ style: { textTransform: "capitalize" },
551
+ children: resolveFieldLabel(key)
552
+ }
553
+ ),
554
+ /* @__PURE__ */ jsx(
555
+ Typography,
556
+ {
557
+ variant: "pi",
558
+ fontWeight: "semiBold",
559
+ textColor: "neutral800",
560
+ style: { textAlign: "right" },
561
+ children: resolveFieldValue(key, val)
562
+ }
563
+ )
564
+ ]
565
+ },
566
+ key
567
+ )) }) })
568
+ ] }),
569
+ /* @__PURE__ */ jsxs(Box, { children: [
570
+ /* @__PURE__ */ jsxs(Typography, { variant: "sigma", textColor: "neutral600", children: [
571
+ t(
572
+ "page.ui.document_verification_checklist",
573
+ "Document Verification Checklist"
574
+ ),
575
+ " ",
576
+ "(",
577
+ checklist.filter((c) => c.verified).length,
578
+ "/",
579
+ checklist.length,
580
+ ")"
581
+ ] }),
582
+ /* @__PURE__ */ jsx(Box, { background: "neutral100", padding: 3, hasRadius: true, marginTop: 2, children: checklist.length === 0 ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: t(
583
+ "page.ui.no_checklist",
584
+ "No verification checklist attached to this form."
585
+ ) }) : /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: checklist.map((item) => /* @__PURE__ */ jsxs(
586
+ Flex,
587
+ {
588
+ justifyContent: "space-between",
589
+ alignItems: "center",
590
+ gap: 2,
591
+ children: [
592
+ /* @__PURE__ */ jsx(
593
+ Checkbox,
594
+ {
595
+ checked: Boolean(item.verified),
596
+ onCheckedChange: (checked) => onToggleChecklistItem(item.id, Boolean(checked)),
597
+ children: item.localizedLabels?.[shortLocale] || item.label
598
+ }
599
+ ),
600
+ /* @__PURE__ */ jsx(Badge, { active: Boolean(item.verified), children: item.verified ? t("page.ui.verified", "Verified") : item.required ? t("page.ui.required", "Required") : t("page.ui.optional", "Optional") })
601
+ ]
602
+ },
603
+ item.id
604
+ )) }) })
605
+ ] })
606
+ ] });
607
+ };
608
+ const CaseworkHeaderBar = ({
609
+ t,
610
+ submission,
611
+ onClose
612
+ }) => /* @__PURE__ */ jsxs(
613
+ Flex,
614
+ {
615
+ justifyContent: "space-between",
616
+ alignItems: "center",
617
+ paddingBottom: 3,
618
+ wrap: "wrap",
619
+ gap: 2,
620
+ children: [
621
+ /* @__PURE__ */ jsxs(Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
622
+ /* @__PURE__ */ jsxs(Typography, { variant: "delta", fontWeight: "bold", children: [
623
+ t("page.ui.casework_inspector", "Casework Inspector"),
624
+ ":",
625
+ " ",
626
+ submission.referenceCode
627
+ ] }),
628
+ /* @__PURE__ */ jsx(Badge, { children: submission.formSlug }),
629
+ submission.secondaryDate?.formatted ? /* @__PURE__ */ jsx(Badge, { children: submission.secondaryDate.formatted }) : null,
630
+ submission.linkedBookingId ? /* @__PURE__ */ jsxs(Badge, { active: true, children: [
631
+ t("page.ui.booking_badge", "Booking"),
632
+ ": ",
633
+ submission.linkedBookingId
634
+ ] }) : null,
635
+ submission.linkedCertificateNumber ? /* @__PURE__ */ jsxs(Badge, { active: true, children: [
636
+ t("page.ui.cert_badge", "Cert"),
637
+ ":",
638
+ " ",
639
+ submission.linkedCertificateNumber
640
+ ] }) : null
641
+ ] }),
642
+ /* @__PURE__ */ jsx(Button, { variant: "tertiary", size: "S", onClick: onClose, children: t("page.ui.close_inspector", "Close Inspector") })
643
+ ]
644
+ }
645
+ );
646
+ const CaseworkQuickBridges = ({
647
+ t,
648
+ bookingServiceSlug,
649
+ onBookingServiceSlugChange,
650
+ bookingDate,
651
+ onBookingDateChange,
652
+ bookingTime,
653
+ onBookingTimeChange,
654
+ onBookSlot,
655
+ certTemplateSlug,
656
+ onCertTemplateSlugChange,
657
+ certRecipient,
658
+ onCertRecipientChange,
659
+ requireVerifiedChecklist,
660
+ onRequireVerifiedChecklistChange,
661
+ onIssueCert
662
+ }) => /* @__PURE__ */ jsxs(Flex, { gap: 3, paddingTop: 3, wrap: "wrap", alignItems: "stretch", children: [
663
+ /* @__PURE__ */ jsxs(
664
+ Box,
665
+ {
666
+ background: "neutral100",
667
+ padding: 3,
668
+ hasRadius: true,
669
+ style: { flex: "1 1 180px" },
670
+ children: [
671
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.schedule_appointment", "Schedule Appointment") }),
672
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, paddingTop: 2, children: [
673
+ /* @__PURE__ */ jsx(
674
+ TextInput,
675
+ {
676
+ name: "bookingServiceSlug",
677
+ placeholder: t("placeholder.service_slug", "Service slug"),
678
+ value: bookingServiceSlug,
679
+ onChange: (e) => onBookingServiceSlugChange(e.target.value)
680
+ }
681
+ ),
682
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
683
+ /* @__PURE__ */ jsx(
684
+ TextInput,
685
+ {
686
+ name: "bookingDate",
687
+ type: "date",
688
+ value: bookingDate,
689
+ onChange: (e) => onBookingDateChange(e.target.value)
690
+ }
691
+ ),
692
+ /* @__PURE__ */ jsx(
693
+ TextInput,
694
+ {
695
+ name: "bookingTime",
696
+ placeholder: "10:00",
697
+ value: bookingTime,
698
+ onChange: (e) => onBookingTimeChange(e.target.value)
699
+ }
700
+ )
701
+ ] }),
702
+ /* @__PURE__ */ jsx(Button, { size: "S", variant: "secondary", onClick: onBookSlot, children: t("page.ui.book_slot", "Book Slot") })
703
+ ] })
704
+ ]
705
+ }
706
+ ),
707
+ /* @__PURE__ */ jsxs(
708
+ Box,
709
+ {
710
+ background: "neutral100",
711
+ padding: 3,
712
+ hasRadius: true,
713
+ style: { flex: "1 1 180px" },
714
+ children: [
715
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.issue_certificate", "Issue Certificate") }),
716
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, paddingTop: 2, children: [
717
+ /* @__PURE__ */ jsx(
718
+ TextInput,
719
+ {
720
+ name: "certTemplateSlug",
721
+ placeholder: t("placeholder.template_slug", "Template slug"),
722
+ value: certTemplateSlug,
723
+ onChange: (e) => onCertTemplateSlugChange(e.target.value)
724
+ }
725
+ ),
726
+ /* @__PURE__ */ jsx(
727
+ TextInput,
728
+ {
729
+ name: "certRecipient",
730
+ placeholder: t(
731
+ "placeholder.recipient_full_name",
732
+ "Recipient full name"
733
+ ),
734
+ value: certRecipient,
735
+ onChange: (e) => onCertRecipientChange(e.target.value)
736
+ }
737
+ ),
738
+ /* @__PURE__ */ jsx(
739
+ Checkbox,
740
+ {
741
+ checked: requireVerifiedChecklist,
742
+ onCheckedChange: (c) => onRequireVerifiedChecklistChange(Boolean(c)),
743
+ children: t(
744
+ "page.ui.require_verified_checklist",
745
+ "Require verified checklist"
746
+ )
747
+ }
748
+ ),
749
+ /* @__PURE__ */ jsx(Button, { size: "S", variant: "secondary", onClick: onIssueCert, children: t("page.ui.issue_cert", "Issue Cert") })
750
+ ] })
751
+ ]
752
+ }
753
+ )
754
+ ] });
755
+ const CaseworkDetailPanel = ({
756
+ t,
757
+ submission,
758
+ form,
759
+ post,
760
+ put,
761
+ onStatusMessage,
762
+ onReload,
763
+ onClose
764
+ }) => {
765
+ const { locale } = useIntl();
766
+ const shortLocale = (locale || "es").split("-")[0].toLowerCase();
767
+ const [status, setStatus] = React.useState(
768
+ submission.status
769
+ );
770
+ const [priority, setPriority] = React.useState(
771
+ submission.priority
772
+ );
773
+ const [department, setDepartment] = React.useState(
774
+ submission.department || "general"
775
+ );
776
+ const [assignedTo, setAssignedTo] = React.useState(
777
+ submission.assignedTo || ""
778
+ );
779
+ const [staffNotes, setStaffNotes] = React.useState(
780
+ submission.staffNotes || ""
781
+ );
782
+ const [checklist, setChecklist] = React.useState(
783
+ submission.checklistItems || []
784
+ );
785
+ const [bookingServiceSlug, setBookingServiceSlug] = React.useState(
786
+ form?.settings?.defaultBookingServiceSlug || "general-appointment"
787
+ );
788
+ const [bookingDate, setBookingDate] = React.useState(
789
+ (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
790
+ );
791
+ const [bookingTime, setBookingTime] = React.useState("10:00");
792
+ const [certTemplateSlug, setCertTemplateSlug] = React.useState(
793
+ form?.settings?.defaultCertificateTemplateId || "official-service-certificate"
794
+ );
795
+ const [certRecipient, setCertRecipient] = React.useState(
796
+ submission.applicantName || ""
797
+ );
798
+ const [requireVerifiedChecklist, setRequireVerifiedChecklist] = React.useState(true);
799
+ React.useEffect(() => {
800
+ setStatus(submission.status);
801
+ setPriority(submission.priority);
802
+ setDepartment(submission.department || "general");
803
+ setAssignedTo(submission.assignedTo || "");
804
+ setStaffNotes(submission.staffNotes || "");
805
+ setChecklist(submission.checklistItems || []);
806
+ setCertRecipient(submission.applicantName || "");
807
+ }, [submission]);
808
+ const handleToggleChecklistItem = async (itemId, verified) => {
809
+ const nextChecklist = checklist.map(
810
+ (item) => item.id === itemId ? {
811
+ ...item,
812
+ verified,
813
+ verifiedAt: verified ? (/* @__PURE__ */ new Date()).toISOString() : void 0
814
+ } : item
815
+ );
816
+ setChecklist(nextChecklist);
817
+ if (!submission.documentId) return;
818
+ await put(`/${PLUGIN_ID}/submissions/${submission.documentId}/casework`, {
819
+ checklistItems: nextChecklist
820
+ });
821
+ onStatusMessage(
822
+ `${t("page.ui.checklist_updated", "Checklist updated")}: ${submission.referenceCode}`
823
+ );
824
+ await onReload();
825
+ };
826
+ const handleSaveCasework = async () => {
827
+ if (!submission.documentId) return;
828
+ await put(`/${PLUGIN_ID}/submissions/${submission.documentId}/casework`, {
829
+ status,
830
+ priority,
831
+ department,
832
+ assignedTo,
833
+ staffNotes,
834
+ checklistItems: checklist
835
+ });
836
+ onStatusMessage(
837
+ `${t("page.ui.casework_saved", "Saved casework updates")}: ${submission.referenceCode}`
838
+ );
839
+ await onReload();
840
+ };
841
+ const handleCustomBooking = async () => {
842
+ if (!submission.documentId) return;
843
+ await post(
844
+ `/${PLUGIN_ID}/submissions/${submission.documentId}/schedule-booking`,
845
+ {
846
+ serviceSlug: bookingServiceSlug,
847
+ date: bookingDate,
848
+ startTime: bookingTime,
849
+ notes: staffNotes || `Casework Ref: ${submission.referenceCode}`
850
+ }
851
+ );
852
+ onStatusMessage(
853
+ `${t("page.ui.appointment_scheduled", "Appointment scheduled")} (${bookingDate} ${bookingTime})`
854
+ );
855
+ await onReload();
856
+ };
857
+ const handleCustomCertificate = async () => {
858
+ if (!submission.documentId) return;
859
+ try {
860
+ await post(
861
+ `/${PLUGIN_ID}/submissions/${submission.documentId}/issue-certificate`,
862
+ {
863
+ templateSlug: certTemplateSlug,
864
+ recipientName: certRecipient || submission.applicantName,
865
+ requireChecklistVerified: requireVerifiedChecklist
866
+ }
867
+ );
868
+ onStatusMessage(
869
+ `${t("page.ui.certificate_issued", "Certificate issued")}: ${submission.referenceCode}`
870
+ );
871
+ await onReload();
872
+ } catch (err) {
873
+ const fallbackError = t(
874
+ "page.ui.verify_checklist_error",
875
+ "Cannot issue certificate: verify required checklist items first"
876
+ );
877
+ onStatusMessage(err instanceof Error ? err.message : fallbackError);
878
+ }
879
+ };
880
+ const dataEntries = Object.entries(submission.data || {});
881
+ return /* @__PURE__ */ jsxs(
882
+ Box,
883
+ {
884
+ background: "neutral0",
885
+ padding: 5,
886
+ shadow: "filterShadow",
887
+ hasRadius: true,
888
+ marginBottom: 5,
889
+ children: [
890
+ /* @__PURE__ */ jsx(CaseworkHeaderBar, { t, submission, onClose }),
891
+ /* @__PURE__ */ jsx(Divider, {}),
892
+ /* @__PURE__ */ jsxs(Flex, { gap: 5, paddingTop: 4, alignItems: "flex-start", wrap: "wrap", children: [
893
+ /* @__PURE__ */ jsx(
894
+ CaseworkPayloadChecklistColumn,
895
+ {
896
+ t,
897
+ shortLocale,
898
+ dataEntries,
899
+ form,
900
+ checklist,
901
+ onToggleChecklistItem: handleToggleChecklistItem
902
+ }
903
+ ),
904
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1 1 400px" }, children: [
905
+ /* @__PURE__ */ jsxs(Flex, { gap: 3, wrap: "wrap", children: [
906
+ /* @__PURE__ */ jsx(Box, { style: { flex: "1 1 130px" }, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
907
+ /* @__PURE__ */ jsx(Field.Label, { children: t("page.ui.status", "Status") }),
908
+ /* @__PURE__ */ jsx(
909
+ SingleSelect,
910
+ {
911
+ value: status,
912
+ onChange: (v) => setStatus(v),
913
+ children: SUBMISSION_STATUSES.map((st) => /* @__PURE__ */ jsx(SingleSelectOption, { value: st, children: st }, st))
914
+ }
915
+ )
916
+ ] }) }),
917
+ /* @__PURE__ */ jsx(Box, { style: { flex: "1 1 130px" }, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
918
+ /* @__PURE__ */ jsx(Field.Label, { children: t("page.ui.priority", "Priority") }),
919
+ /* @__PURE__ */ jsx(
920
+ SingleSelect,
921
+ {
922
+ value: priority,
923
+ onChange: (v) => setPriority(v),
924
+ children: SUBMISSION_PRIORITIES.map((pr) => /* @__PURE__ */ jsx(SingleSelectOption, { value: pr, children: pr }, pr))
925
+ }
926
+ )
927
+ ] }) }),
928
+ /* @__PURE__ */ jsx(Box, { style: { flex: "1 1 150px" }, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
929
+ /* @__PURE__ */ jsx(Field.Label, { children: t("page.ui.assignee", "Assignee") }),
930
+ /* @__PURE__ */ jsx(
931
+ TextInput,
932
+ {
933
+ name: "assignedTo",
934
+ placeholder: t(
935
+ "placeholder.assignee_example",
936
+ "e.g. Sheikh Ahmad"
937
+ ),
938
+ value: assignedTo,
939
+ onChange: (e) => setAssignedTo(e.target.value)
940
+ }
941
+ )
942
+ ] }) })
943
+ ] }),
944
+ /* @__PURE__ */ jsxs(Box, { paddingTop: 3, paddingBottom: 3, children: [
945
+ /* @__PURE__ */ jsxs(Field.Root, { children: [
946
+ /* @__PURE__ */ jsx(Field.Label, { children: t("page.ui.internal_staff_notes", "Internal Staff Notes") }),
947
+ /* @__PURE__ */ jsx(
948
+ Textarea,
949
+ {
950
+ name: "staffNotes",
951
+ value: staffNotes,
952
+ onChange: (e) => setStaffNotes(e.target.value)
953
+ }
954
+ )
955
+ ] }),
956
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", paddingTop: 2, children: /* @__PURE__ */ jsx(Button, { size: "S", onClick: handleSaveCasework, children: t("page.ui.save_casework_notes", "Save Casework & Notes") }) })
957
+ ] }),
958
+ /* @__PURE__ */ jsx(Divider, {}),
959
+ /* @__PURE__ */ jsx(
960
+ CaseworkQuickBridges,
961
+ {
962
+ t,
963
+ bookingServiceSlug,
964
+ onBookingServiceSlugChange: setBookingServiceSlug,
965
+ bookingDate,
966
+ onBookingDateChange: setBookingDate,
967
+ bookingTime,
968
+ onBookingTimeChange: setBookingTime,
969
+ onBookSlot: handleCustomBooking,
970
+ certTemplateSlug,
971
+ onCertTemplateSlugChange: setCertTemplateSlug,
972
+ certRecipient,
973
+ onCertRecipientChange: setCertRecipient,
974
+ requireVerifiedChecklist,
975
+ onRequireVerifiedChecklistChange: setRequireVerifiedChecklist,
976
+ onIssueCert: handleCustomCertificate
977
+ }
978
+ )
979
+ ] })
980
+ ] })
981
+ ]
982
+ }
983
+ );
984
+ };
985
+ const matchesSubmissionFilters = (sub, statusFilter, priorityFilter, searchQuery) => {
986
+ if (statusFilter !== "all" && sub.status !== statusFilter) return false;
987
+ if (priorityFilter !== "all" && sub.priority !== priorityFilter) return false;
988
+ const q = searchQuery.trim().toLowerCase();
989
+ if (!q) return true;
990
+ const haystack = [
991
+ sub.referenceCode,
992
+ sub.formSlug,
993
+ sub.department,
994
+ sub.applicantName,
995
+ sub.applicantEmail
996
+ ].filter(Boolean).join(" ").toLowerCase();
997
+ return haystack.includes(q);
998
+ };
999
+ const SubmissionRow = ({
1000
+ t,
1001
+ sub,
1002
+ isSelected,
1003
+ onToggleInspect,
1004
+ onScheduleBooking,
1005
+ onIssueCertificate,
1006
+ onMarkCompleted
1007
+ }) => {
1008
+ const items = sub.checklistItems || [];
1009
+ const totalChecklist = items.length;
1010
+ const verifiedChecklist = items.filter((c) => c.verified).length;
1011
+ const linkedSummary = [sub.linkedBookingId, sub.linkedCertificateNumber].filter(Boolean).join(" • ");
1012
+ return /* @__PURE__ */ jsxs(Tr, { children: [
1013
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
1014
+ /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: sub.referenceCode }),
1015
+ linkedSummary ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: linkedSummary }) : null
1016
+ ] }) }),
1017
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", children: [
1018
+ /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: sub.applicantName || t("page.ui.anonymous", "Anonymous") }),
1019
+ sub.applicantEmail ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: sub.applicantEmail }) : null
1020
+ ] }) }),
1021
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
1022
+ /* @__PURE__ */ jsxs(Typography, { children: [
1023
+ sub.formSlug,
1024
+ " (",
1025
+ sub.department || "general",
1026
+ ")"
1027
+ ] }),
1028
+ totalChecklist > 0 ? /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral500", children: [
1029
+ t("page.ui.checklist", "Checklist"),
1030
+ ": ",
1031
+ verifiedChecklist,
1032
+ "/",
1033
+ totalChecklist,
1034
+ " ",
1035
+ t("page.ui.verified", "verified")
1036
+ ] }) : null
1037
+ ] }) }),
1038
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1039
+ /* @__PURE__ */ jsx(Badge, { children: sub.status }),
1040
+ /* @__PURE__ */ jsx(Badge, { children: sub.priority })
1041
+ ] }) }),
1042
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", children: [
1043
+ /* @__PURE__ */ jsx(Typography, { children: sub.submittedAt?.slice(0, 10) }),
1044
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: sub.secondaryDate?.formatted || "-" })
1045
+ ] }) }),
1046
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1047
+ /* @__PURE__ */ jsx(
1048
+ Button,
1049
+ {
1050
+ size: "S",
1051
+ variant: isSelected ? "default" : "tertiary",
1052
+ onClick: () => onToggleInspect(sub.referenceCode, isSelected),
1053
+ children: isSelected ? t("page.ui.hide_details", "Close") : t("page.ui.inspect", "Inspect")
1054
+ }
1055
+ ),
1056
+ /* @__PURE__ */ jsx(
1057
+ Button,
1058
+ {
1059
+ size: "S",
1060
+ variant: "secondary",
1061
+ onClick: () => onScheduleBooking(sub.documentId),
1062
+ children: t("page.ui.book_slot", "Book Slot")
1063
+ }
1064
+ ),
1065
+ /* @__PURE__ */ jsx(
1066
+ Button,
1067
+ {
1068
+ size: "S",
1069
+ variant: "secondary",
1070
+ onClick: () => onIssueCertificate(sub.documentId),
1071
+ children: t("page.ui.issue_cert", "Issue Cert")
1072
+ }
1073
+ ),
1074
+ /* @__PURE__ */ jsx(
1075
+ Button,
1076
+ {
1077
+ size: "S",
1078
+ variant: "tertiary",
1079
+ onClick: () => onMarkCompleted(sub.documentId),
1080
+ children: t("page.ui.complete", "Complete")
1081
+ }
1082
+ )
1083
+ ] }) })
1084
+ ] }, sub.referenceCode);
1085
+ };
1086
+ const CaseworkSubmissionsTab = ({
1087
+ t,
1088
+ submissions,
1089
+ forms = [],
1090
+ post,
1091
+ put,
1092
+ onStatusMessage,
1093
+ onReload
1094
+ }) => {
1095
+ const [searchQuery, setSearchQuery] = React.useState("");
1096
+ const [statusFilter, setStatusFilter] = React.useState("all");
1097
+ const [priorityFilter, setPriorityFilter] = React.useState("all");
1098
+ const [selectedRefCode, setSelectedRefCode] = React.useState(
1099
+ null
1100
+ );
1101
+ const selectedSubmission = React.useMemo(
1102
+ () => submissions.find((s) => s.referenceCode === selectedRefCode) || null,
1103
+ [submissions, selectedRefCode]
1104
+ );
1105
+ const selectedForm = React.useMemo(
1106
+ () => selectedSubmission ? forms.find((f) => f.slug === selectedSubmission.formSlug) || null : null,
1107
+ [forms, selectedSubmission]
1108
+ );
1109
+ const handleScheduleBooking = async (documentId) => {
1110
+ if (!documentId) return;
1111
+ await post(`/${PLUGIN_ID}/submissions/${documentId}/schedule-booking`, {
1112
+ serviceSlug: "general-appointment",
1113
+ date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
1114
+ startTime: "10:00"
1115
+ });
1116
+ onStatusMessage("Appointment scheduled via Bookings bridge");
1117
+ await onReload();
1118
+ };
1119
+ const handleIssueCertificate = async (documentId) => {
1120
+ if (!documentId) return;
1121
+ await post(`/${PLUGIN_ID}/submissions/${documentId}/issue-certificate`, {
1122
+ requireChecklistVerified: false
1123
+ });
1124
+ onStatusMessage("Certificate issued via Certificates bridge");
1125
+ await onReload();
1126
+ };
1127
+ const handleMarkCompleted = async (documentId) => {
1128
+ if (!documentId) return;
1129
+ await put(`/${PLUGIN_ID}/submissions/${documentId}/casework`, {
1130
+ status: "completed"
1131
+ });
1132
+ onStatusMessage("Submission marked as completed");
1133
+ await onReload();
1134
+ };
1135
+ const filteredSubmissions = React.useMemo(
1136
+ () => submissions.filter(
1137
+ (sub) => matchesSubmissionFilters(sub, statusFilter, priorityFilter, searchQuery)
1138
+ ),
1139
+ [submissions, statusFilter, priorityFilter, searchQuery]
1140
+ );
1141
+ return /* @__PURE__ */ jsxs(Box, { paddingTop: 5, children: [
1142
+ /* @__PURE__ */ jsxs(
1143
+ Flex,
1144
+ {
1145
+ justifyContent: "space-between",
1146
+ alignItems: "center",
1147
+ paddingBottom: 4,
1148
+ wrap: "wrap",
1149
+ gap: 3,
1150
+ children: [
1151
+ /* @__PURE__ */ jsx(Box, { style: { flex: "1 1 280px", maxWidth: 420 }, children: /* @__PURE__ */ jsx(
1152
+ TextInput,
1153
+ {
1154
+ name: "searchSubmissions",
1155
+ placeholder: t(
1156
+ "placeholder.search_submissions",
1157
+ "Search by reference code, applicant, or form..."
1158
+ ),
1159
+ value: searchQuery,
1160
+ onChange: (e) => setSearchQuery(e.target.value)
1161
+ }
1162
+ ) }),
1163
+ /* @__PURE__ */ jsxs(Flex, { gap: 3, wrap: "wrap", children: [
1164
+ /* @__PURE__ */ jsx(Box, { style: { minWidth: 170 }, children: /* @__PURE__ */ jsxs(
1165
+ SingleSelect,
1166
+ {
1167
+ value: statusFilter,
1168
+ onChange: (val) => setStatusFilter(String(val)),
1169
+ children: [
1170
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "all", children: t("page.ui.all_statuses", "Status: All") }),
1171
+ SUBMISSION_STATUSES.map((st) => /* @__PURE__ */ jsxs(SingleSelectOption, { value: st, children: [
1172
+ t("page.ui.status", "Status"),
1173
+ ": ",
1174
+ st
1175
+ ] }, st))
1176
+ ]
1177
+ }
1178
+ ) }),
1179
+ /* @__PURE__ */ jsx(Box, { style: { minWidth: 170 }, children: /* @__PURE__ */ jsxs(
1180
+ SingleSelect,
1181
+ {
1182
+ value: priorityFilter,
1183
+ onChange: (val) => setPriorityFilter(String(val)),
1184
+ children: [
1185
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "all", children: t("page.ui.all_priorities", "Priority: All") }),
1186
+ SUBMISSION_PRIORITIES.map((pr) => /* @__PURE__ */ jsxs(SingleSelectOption, { value: pr, children: [
1187
+ t("page.ui.priority", "Priority"),
1188
+ ": ",
1189
+ pr
1190
+ ] }, pr))
1191
+ ]
1192
+ }
1193
+ ) })
1194
+ ] })
1195
+ ]
1196
+ }
1197
+ ),
1198
+ selectedSubmission ? /* @__PURE__ */ jsx(
1199
+ CaseworkDetailPanel,
1200
+ {
1201
+ t,
1202
+ submission: selectedSubmission,
1203
+ form: selectedForm,
1204
+ post,
1205
+ put,
1206
+ onStatusMessage,
1207
+ onReload,
1208
+ onClose: () => setSelectedRefCode(null)
1209
+ }
1210
+ ) : null,
1211
+ /* @__PURE__ */ jsxs(Table, { colCount: 6, rowCount: filteredSubmissions.length + 1, children: [
1212
+ /* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
1213
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.ref_code", "Reference") }) }),
1214
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.applicant", "Applicant") }) }),
1215
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.form_dept", "Form & Dept") }) }),
1216
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.status_priority", "Status") }) }),
1217
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.date_secondary", "Submitted (Hijri)") }) }),
1218
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.actions", "Actions") }) })
1219
+ ] }) }),
1220
+ /* @__PURE__ */ jsx(Tbody, { children: filteredSubmissions.map((sub) => /* @__PURE__ */ jsx(
1221
+ SubmissionRow,
1222
+ {
1223
+ t,
1224
+ sub,
1225
+ isSelected: selectedRefCode === sub.referenceCode,
1226
+ onToggleInspect: (refCode, selected) => setSelectedRefCode(selected ? null : refCode),
1227
+ onScheduleBooking: handleScheduleBooking,
1228
+ onIssueCertificate: handleIssueCertificate,
1229
+ onMarkCompleted: handleMarkCompleted
1230
+ },
1231
+ sub.referenceCode
1232
+ )) })
1233
+ ] })
1234
+ ] });
1235
+ };
1236
+ const SUPPORTED_FORM_LOCALES = ["es", "en", "ar"];
1237
+ const FormChecklistAndLocalePanels = ({
1238
+ t,
1239
+ checklistItems,
1240
+ newChecklistLabel,
1241
+ onNewChecklistLabelChange,
1242
+ onAddChecklistItem,
1243
+ onRemoveChecklistItem,
1244
+ onUpdateChecklistItemLabel,
1245
+ activeLocale,
1246
+ onActiveLocaleChange,
1247
+ translations,
1248
+ onUpdateTranslationField
1249
+ }) => {
1250
+ const currentTranslation = translations[activeLocale] || {};
1251
+ return /* @__PURE__ */ jsxs(Flex, { gap: 5, paddingTop: 4, wrap: "wrap", alignItems: "flex-start", children: [
1252
+ /* @__PURE__ */ jsxs(
1253
+ Box,
1254
+ {
1255
+ padding: 4,
1256
+ background: "neutral100",
1257
+ hasRadius: true,
1258
+ style: { flex: "1 1 340px" },
1259
+ children: [
1260
+ /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [
1261
+ /* @__PURE__ */ jsxs(Typography, { variant: "sigma", textColor: "neutral600", children: [
1262
+ t(
1263
+ "page.ui.required_verification_documents",
1264
+ "Required Verification Documents"
1265
+ ),
1266
+ " ",
1267
+ "(",
1268
+ checklistItems.length,
1269
+ ")"
1270
+ ] }),
1271
+ /* @__PURE__ */ jsx(Badge, { children: activeLocale.toUpperCase() })
1272
+ ] }),
1273
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, paddingTop: 2, children: [
1274
+ checklistItems.map((item) => {
1275
+ const displayLabel = item.localizedLabels?.[activeLocale] ?? item.label;
1276
+ return /* @__PURE__ */ jsxs(
1277
+ Flex,
1278
+ {
1279
+ justifyContent: "space-between",
1280
+ alignItems: "center",
1281
+ gap: 2,
1282
+ padding: 2,
1283
+ background: "neutral0",
1284
+ hasRadius: true,
1285
+ children: [
1286
+ /* @__PURE__ */ jsx(Box, { style: { flex: 1 }, children: onUpdateChecklistItemLabel ? /* @__PURE__ */ jsx(
1287
+ TextInput,
1288
+ {
1289
+ name: `chk_${item.id}`,
1290
+ value: displayLabel,
1291
+ onChange: (e) => onUpdateChecklistItemLabel(item.id, e.target.value)
1292
+ }
1293
+ ) : /* @__PURE__ */ jsx(Typography, { variant: "omega", children: displayLabel }) }),
1294
+ /* @__PURE__ */ jsx(
1295
+ Button,
1296
+ {
1297
+ size: "S",
1298
+ variant: "danger-light",
1299
+ onClick: () => onRemoveChecklistItem(item.id),
1300
+ children: t("page.ui.remove", "Remove")
1301
+ }
1302
+ )
1303
+ ]
1304
+ },
1305
+ item.id
1306
+ );
1307
+ }),
1308
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, paddingTop: 2, children: [
1309
+ /* @__PURE__ */ jsx(Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(
1310
+ TextInput,
1311
+ {
1312
+ name: "newChecklistLabel",
1313
+ placeholder: t(
1314
+ "placeholder.add_required_document",
1315
+ "Add required document (e.g., Valid National ID)..."
1316
+ ),
1317
+ value: newChecklistLabel,
1318
+ onChange: (e) => onNewChecklistLabelChange(e.target.value)
1319
+ }
1320
+ ) }),
1321
+ /* @__PURE__ */ jsx(Button, { size: "S", variant: "secondary", onClick: onAddChecklistItem, children: t("page.ui.add_item", "+ Add") })
1322
+ ] })
1323
+ ] })
1324
+ ]
1325
+ }
1326
+ ),
1327
+ /* @__PURE__ */ jsxs(
1328
+ Box,
1329
+ {
1330
+ padding: 4,
1331
+ background: "neutral100",
1332
+ hasRadius: true,
1333
+ style: { flex: "1 1 360px" },
1334
+ children: [
1335
+ /* @__PURE__ */ jsxs(
1336
+ Flex,
1337
+ {
1338
+ justifyContent: "space-between",
1339
+ alignItems: "center",
1340
+ paddingBottom: 2,
1341
+ children: [
1342
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: t(
1343
+ "page.ui.form_localization_header",
1344
+ "Form Localization (es / en / ar)"
1345
+ ) }),
1346
+ /* @__PURE__ */ jsx(Flex, { gap: 1, children: SUPPORTED_FORM_LOCALES.map((loc) => /* @__PURE__ */ jsx(
1347
+ Button,
1348
+ {
1349
+ size: "S",
1350
+ variant: activeLocale === loc ? "default" : "tertiary",
1351
+ onClick: () => onActiveLocaleChange(loc),
1352
+ children: loc.toUpperCase()
1353
+ },
1354
+ loc
1355
+ )) })
1356
+ ]
1357
+ }
1358
+ ),
1359
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
1360
+ /* @__PURE__ */ jsx(
1361
+ TextInput,
1362
+ {
1363
+ name: "localizedTitle",
1364
+ placeholder: `${t("placeholder.localized_title", "Localized title")} (${activeLocale})`,
1365
+ value: currentTranslation.title || "",
1366
+ onChange: (e) => onUpdateTranslationField("title", e.target.value)
1367
+ }
1368
+ ),
1369
+ /* @__PURE__ */ jsx(
1370
+ TextInput,
1371
+ {
1372
+ name: "localizedDescription",
1373
+ placeholder: `${t("placeholder.localized_description", "Localized description")} (${activeLocale})`,
1374
+ value: currentTranslation.description || "",
1375
+ onChange: (e) => onUpdateTranslationField("description", e.target.value)
1376
+ }
1377
+ ),
1378
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1379
+ /* @__PURE__ */ jsx(Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(
1380
+ TextInput,
1381
+ {
1382
+ name: "localizedSubmit",
1383
+ placeholder: `${t("placeholder.localized_submit_label", "Submit label")} (${activeLocale})`,
1384
+ value: currentTranslation.submitButtonLabel || "",
1385
+ onChange: (e) => onUpdateTranslationField("submitButtonLabel", e.target.value)
1386
+ }
1387
+ ) }),
1388
+ /* @__PURE__ */ jsx(Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(
1389
+ TextInput,
1390
+ {
1391
+ name: "localizedSuccess",
1392
+ placeholder: `${t("placeholder.localized_success_message", "Success message")} (${activeLocale})`,
1393
+ value: currentTranslation.successMessage || "",
1394
+ onChange: (e) => onUpdateTranslationField("successMessage", e.target.value)
1395
+ }
1396
+ ) })
1397
+ ] }),
1398
+ /* @__PURE__ */ jsx(Flex, { gap: 1, paddingTop: 1, children: SUPPORTED_FORM_LOCALES.map(
1399
+ (loc) => translations[loc]?.title ? /* @__PURE__ */ jsxs(Badge, { children: [
1400
+ loc.toUpperCase(),
1401
+ " ",
1402
+ t("page.ui.ready", "Ready")
1403
+ ] }, loc) : null
1404
+ ) })
1405
+ ] })
1406
+ ]
1407
+ }
1408
+ )
1409
+ ] });
1410
+ };
1411
+ const FormRoutingDrawer = ({
1412
+ t,
1413
+ form,
1414
+ post,
1415
+ onStatusMessage,
1416
+ onReload,
1417
+ onClose
1418
+ }) => {
1419
+ const [editCategory, setEditCategory] = React.useState(
1420
+ form.category || "contact"
1421
+ );
1422
+ const [editDepartment, setEditDepartment] = React.useState(
1423
+ form.settings?.department || "general"
1424
+ );
1425
+ const [editPriority, setEditPriority] = React.useState(
1426
+ form.settings?.defaultPriority || "normal"
1427
+ );
1428
+ const [editBookingBridge, setEditBookingBridge] = React.useState(
1429
+ Boolean(form.settings?.enableBookingBridge)
1430
+ );
1431
+ const [editCertBridge, setEditCertBridge] = React.useState(
1432
+ Boolean(form.settings?.enableCertificateBridge)
1433
+ );
1434
+ const [editChecklistItems, setEditChecklistItems] = React.useState(form.checklistTemplate || []);
1435
+ const [newChecklistLabel, setNewChecklistLabel] = React.useState("");
1436
+ const [activeLocale, setActiveLocale] = React.useState("es");
1437
+ const [translations, setTranslations] = React.useState(form.translations || {});
1438
+ React.useEffect(() => {
1439
+ setEditCategory(form.category || "contact");
1440
+ setEditDepartment(form.settings?.department || "general");
1441
+ setEditPriority(form.settings?.defaultPriority || "normal");
1442
+ setEditBookingBridge(Boolean(form.settings?.enableBookingBridge));
1443
+ setEditCertBridge(Boolean(form.settings?.enableCertificateBridge));
1444
+ setEditChecklistItems(form.checklistTemplate || []);
1445
+ setTranslations(form.translations || {});
1446
+ setNewChecklistLabel("");
1447
+ }, [form]);
1448
+ const updateTranslationField = (key, value) => {
1449
+ setTranslations((prev) => ({
1450
+ ...prev,
1451
+ [activeLocale]: {
1452
+ ...prev[activeLocale],
1453
+ [key]: value
1454
+ }
1455
+ }));
1456
+ };
1457
+ const handleAddChecklistItem = () => {
1458
+ const trimmed = newChecklistLabel.trim();
1459
+ if (!trimmed) return;
1460
+ setEditChecklistItems([
1461
+ ...editChecklistItems,
1462
+ {
1463
+ id: `chk_${Date.now()}`,
1464
+ label: trimmed,
1465
+ required: true,
1466
+ verified: false,
1467
+ localizedLabels: {
1468
+ [activeLocale]: trimmed
1469
+ }
1470
+ }
1471
+ ]);
1472
+ setNewChecklistLabel("");
1473
+ };
1474
+ const handleUpdateChecklistItemLabel = (id, value) => {
1475
+ setEditChecklistItems(
1476
+ (prev) => prev.map((item) => {
1477
+ if (item.id !== id) return item;
1478
+ return {
1479
+ ...item,
1480
+ label: activeLocale === "es" || !item.label ? value : item.label,
1481
+ localizedLabels: {
1482
+ ...item.localizedLabels,
1483
+ [activeLocale]: value
1484
+ }
1485
+ };
1486
+ })
1487
+ );
1488
+ };
1489
+ const handleRemoveChecklistItem = (id) => {
1490
+ setEditChecklistItems(editChecklistItems.filter((item) => item.id !== id));
1491
+ };
1492
+ const handleSave = async () => {
1493
+ await post(`/${PLUGIN_ID}/forms`, {
1494
+ ...form,
1495
+ category: editCategory,
1496
+ checklistTemplate: editChecklistItems,
1497
+ translations,
1498
+ settings: {
1499
+ ...form.settings,
1500
+ department: editDepartment,
1501
+ defaultPriority: editPriority,
1502
+ enableBookingBridge: editBookingBridge,
1503
+ enableCertificateBridge: editCertBridge
1504
+ }
1505
+ });
1506
+ onStatusMessage(
1507
+ `Saved routing, checklist & translations (es/en/ar) on Form Builder form "${form.title}"`
1508
+ );
1509
+ onClose();
1510
+ await onReload();
1511
+ };
1512
+ return /* @__PURE__ */ jsxs(
1513
+ Box,
1514
+ {
1515
+ padding: 5,
1516
+ marginBottom: 5,
1517
+ background: "neutral0",
1518
+ hasRadius: true,
1519
+ shadow: "filterShadow",
1520
+ style: { border: "1px solid rgba(128, 128, 128, 0.22)" },
1521
+ children: [
1522
+ /* @__PURE__ */ jsxs(
1523
+ Flex,
1524
+ {
1525
+ justifyContent: "space-between",
1526
+ alignItems: "center",
1527
+ paddingBottom: 4,
1528
+ wrap: "wrap",
1529
+ gap: 2,
1530
+ children: [
1531
+ /* @__PURE__ */ jsxs(Box, { children: [
1532
+ /* @__PURE__ */ jsxs(Typography, { variant: "delta", tag: "h3", fontWeight: "bold", children: [
1533
+ t(
1534
+ "page.ui.routing_checklist_localization",
1535
+ "Routing, Checklist & Localization"
1536
+ ),
1537
+ " ",
1538
+ "— ",
1539
+ form.slug
1540
+ ] }),
1541
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t(
1542
+ "page.ui.routing_drawer_subtitle",
1543
+ "Stored directly on Form Builder CMS (`settings.inbox`). Configure casework routing, document checklist, and es/en/ar translations."
1544
+ ) })
1545
+ ] }),
1546
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1547
+ /* @__PURE__ */ jsx(Button, { size: "S", variant: "tertiary", onClick: onClose, children: t("page.ui.close", "Close") }),
1548
+ /* @__PURE__ */ jsx(Button, { size: "S", onClick: handleSave, children: t("page.ui.save_form_config", "Save Form Config") })
1549
+ ] })
1550
+ ]
1551
+ }
1552
+ ),
1553
+ /* @__PURE__ */ jsxs(Flex, { gap: 4, wrap: "wrap", children: [
1554
+ /* @__PURE__ */ jsx(Box, { style: { flex: "1 1 200px" }, children: /* @__PURE__ */ jsxs(Field.Root, { name: "editCategory", children: [
1555
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.workflow_category", "Workflow Category") }),
1556
+ /* @__PURE__ */ jsx(
1557
+ SingleSelect,
1558
+ {
1559
+ value: editCategory,
1560
+ onChange: (val) => setEditCategory(String(val)),
1561
+ children: FORM_CATEGORIES.map((cat) => /* @__PURE__ */ jsx(SingleSelectOption, { value: cat, children: cat }, cat))
1562
+ }
1563
+ )
1564
+ ] }) }),
1565
+ /* @__PURE__ */ jsx(Box, { style: { flex: "1 1 200px" }, children: /* @__PURE__ */ jsxs(Field.Root, { name: "editDepartment", children: [
1566
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.target_department", "Target Department") }),
1567
+ /* @__PURE__ */ jsx(
1568
+ TextInput,
1569
+ {
1570
+ name: "editDepartment",
1571
+ value: editDepartment,
1572
+ onChange: (e) => setEditDepartment(e.target.value),
1573
+ placeholder: t(
1574
+ "placeholder.target_department",
1575
+ "e.g., imamate, nikah_family, general"
1576
+ )
1577
+ }
1578
+ )
1579
+ ] }) }),
1580
+ /* @__PURE__ */ jsx(Box, { style: { flex: "1 1 200px" }, children: /* @__PURE__ */ jsxs(Field.Root, { name: "editPriority", children: [
1581
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.default_priority", "Default Priority") }),
1582
+ /* @__PURE__ */ jsx(
1583
+ SingleSelect,
1584
+ {
1585
+ value: editPriority,
1586
+ onChange: (val) => setEditPriority(String(val)),
1587
+ children: SUBMISSION_PRIORITIES.map((pr) => /* @__PURE__ */ jsx(SingleSelectOption, { value: pr, children: pr }, pr))
1588
+ }
1589
+ )
1590
+ ] }) })
1591
+ ] }),
1592
+ /* @__PURE__ */ jsxs(Flex, { gap: 6, paddingTop: 4, paddingBottom: 4, wrap: "wrap", children: [
1593
+ /* @__PURE__ */ jsx(
1594
+ Checkbox,
1595
+ {
1596
+ checked: editBookingBridge,
1597
+ onCheckedChange: (checked) => setEditBookingBridge(Boolean(checked)),
1598
+ children: t(
1599
+ "checkbox.enable_1_click_booking",
1600
+ "Enable 1-Click Appointment Booking"
1601
+ )
1602
+ }
1603
+ ),
1604
+ /* @__PURE__ */ jsx(
1605
+ Checkbox,
1606
+ {
1607
+ checked: editCertBridge,
1608
+ onCheckedChange: (checked) => setEditCertBridge(Boolean(checked)),
1609
+ children: t(
1610
+ "checkbox.enable_1_click_certificate",
1611
+ "Enable 1-Click Certificate Issuance"
1612
+ )
1613
+ }
1614
+ )
1615
+ ] }),
1616
+ /* @__PURE__ */ jsx(Divider, {}),
1617
+ /* @__PURE__ */ jsx(
1618
+ FormChecklistAndLocalePanels,
1619
+ {
1620
+ t,
1621
+ checklistItems: editChecklistItems,
1622
+ newChecklistLabel,
1623
+ onNewChecklistLabelChange: setNewChecklistLabel,
1624
+ onAddChecklistItem: handleAddChecklistItem,
1625
+ onRemoveChecklistItem: handleRemoveChecklistItem,
1626
+ onUpdateChecklistItemLabel: handleUpdateChecklistItemLabel,
1627
+ activeLocale,
1628
+ onActiveLocaleChange: setActiveLocale,
1629
+ translations,
1630
+ onUpdateTranslationField: updateTranslationField
1631
+ }
1632
+ )
1633
+ ]
1634
+ }
1635
+ );
1636
+ };
1637
+ const drawerCardStyle = {
1638
+ border: "1px solid rgba(128, 128, 128, 0.22)"
1639
+ };
1640
+ const FormBuilderTab = ({
1641
+ t,
1642
+ forms,
1643
+ post,
1644
+ onStatusMessage,
1645
+ onReload
1646
+ }) => {
1647
+ const navigate = useNavigate();
1648
+ const [editingFormSlug, setEditingFormSlug] = React.useState(
1649
+ null
1650
+ );
1651
+ const [showTemplates, setShowTemplates] = React.useState(false);
1652
+ const selectedForm = React.useMemo(
1653
+ () => forms.find((f) => f.slug === editingFormSlug) || null,
1654
+ [forms, editingFormSlug]
1655
+ );
1656
+ const handleCreateTemplate = async (templateId) => {
1657
+ await post(`/${PLUGIN_ID}/forms/from-template`, { templateId });
1658
+ onStatusMessage(`Created form from "${templateId}" in Visual Form Builder`);
1659
+ setShowTemplates(false);
1660
+ await onReload();
1661
+ };
1662
+ const handleSyncFormBuilder = async () => {
1663
+ const res = await post(`/${PLUGIN_ID}/forms/sync-builder`, {});
1664
+ const info = res?.data?.data;
1665
+ onStatusMessage(
1666
+ `Refreshed Visual Form Builder (${info?.forms?.length ?? 0} forms)`
1667
+ );
1668
+ await onReload();
1669
+ };
1670
+ const handleOpenInVisualBuilder = async (form) => {
1671
+ if (form.formBuilderId) {
1672
+ navigate(
1673
+ `/plugins/${FORM_BUILDER_CMS_PLUGIN_ID}/builder/${form.formBuilderId}`
1674
+ );
1675
+ return;
1676
+ }
1677
+ const res = await post(`/${PLUGIN_ID}/forms/sync-builder`, {});
1678
+ const syncedForms = res?.data?.data?.forms || [];
1679
+ const matched = syncedForms.find((f) => f.slug === form.slug);
1680
+ if (matched?.formBuilderId) {
1681
+ navigate(
1682
+ `/plugins/${FORM_BUILDER_CMS_PLUGIN_ID}/builder/${matched.formBuilderId}`
1683
+ );
1684
+ } else {
1685
+ navigate(`/plugins/${FORM_BUILDER_CMS_PLUGIN_ID}`);
1686
+ }
1687
+ };
1688
+ return /* @__PURE__ */ jsxs(Box, { paddingTop: 5, children: [
1689
+ /* @__PURE__ */ jsxs(
1690
+ Flex,
1691
+ {
1692
+ justifyContent: "space-between",
1693
+ alignItems: "center",
1694
+ paddingBottom: 4,
1695
+ wrap: "wrap",
1696
+ gap: 3,
1697
+ children: [
1698
+ /* @__PURE__ */ jsxs(Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
1699
+ /* @__PURE__ */ jsx(Typography, { variant: "beta", tag: "h2", children: t("page.ui.active_forms", "Forms & Service-Desk Workflows") }),
1700
+ /* @__PURE__ */ jsx(Badge, { children: t("page.ui.formcraft_visual_builder", "FormCraft Visual Builder") })
1701
+ ] }),
1702
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, wrap: "wrap", children: [
1703
+ /* @__PURE__ */ jsx(
1704
+ Button,
1705
+ {
1706
+ variant: "tertiary",
1707
+ size: "S",
1708
+ onClick: () => setShowTemplates(!showTemplates),
1709
+ children: showTemplates ? t("page.ui.hide_templates", "Hide Templates") : t("page.ui.starter_templates", "Starter Templates")
1710
+ }
1711
+ ),
1712
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "S", onClick: handleSyncFormBuilder, children: t("page.ui.sync_form_builder", "Refresh Forms") }),
1713
+ /* @__PURE__ */ jsx(
1714
+ Button,
1715
+ {
1716
+ variant: "default",
1717
+ size: "S",
1718
+ onClick: () => navigate(`/plugins/${FORM_BUILDER_CMS_PLUGIN_ID}/builder/new`),
1719
+ children: t("page.ui.new_visual_form", "+ New Visual Form")
1720
+ }
1721
+ )
1722
+ ] })
1723
+ ]
1724
+ }
1725
+ ),
1726
+ showTemplates ? /* @__PURE__ */ jsx(
1727
+ Box,
1728
+ {
1729
+ padding: 4,
1730
+ marginBottom: 4,
1731
+ background: "neutral100",
1732
+ hasRadius: true,
1733
+ style: drawerCardStyle,
1734
+ children: /* @__PURE__ */ jsxs(
1735
+ Flex,
1736
+ {
1737
+ justifyContent: "space-between",
1738
+ alignItems: "center",
1739
+ wrap: "wrap",
1740
+ gap: 3,
1741
+ children: [
1742
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t(
1743
+ "page.ui.seed_starter_form_hint",
1744
+ "Quickly seed a pre-configured multilingual mosque form:"
1745
+ ) }),
1746
+ /* @__PURE__ */ jsx(Flex, { gap: 2, wrap: "wrap", children: STARTER_FORM_TEMPLATES.map((tpl) => /* @__PURE__ */ jsxs(
1747
+ Button,
1748
+ {
1749
+ size: "S",
1750
+ variant: "secondary",
1751
+ onClick: () => handleCreateTemplate(tpl.id),
1752
+ children: [
1753
+ "+ ",
1754
+ tpl.name
1755
+ ]
1756
+ },
1757
+ tpl.id
1758
+ )) })
1759
+ ]
1760
+ }
1761
+ )
1762
+ }
1763
+ ) : null,
1764
+ selectedForm ? /* @__PURE__ */ jsx(
1765
+ FormRoutingDrawer,
1766
+ {
1767
+ t,
1768
+ form: selectedForm,
1769
+ post,
1770
+ onStatusMessage,
1771
+ onReload,
1772
+ onClose: () => setEditingFormSlug(null)
1773
+ }
1774
+ ) : null,
1775
+ /* @__PURE__ */ jsxs(Table, { colCount: 6, rowCount: forms.length + 1, children: [
1776
+ /* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
1777
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.title", "Form") }) }),
1778
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.category", "Category & Dept") }) }),
1779
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.fields", "Fields & Locales") }) }),
1780
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.checklist", "Checklist") }) }),
1781
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.submissions", "Submissions") }) }),
1782
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.actions", "Actions") }) })
1783
+ ] }) }),
1784
+ /* @__PURE__ */ jsx(Tbody, { children: forms.map((form) => {
1785
+ const localeKeys = Object.keys(form.translations || {});
1786
+ return /* @__PURE__ */ jsxs(Tr, { children: [
1787
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
1788
+ /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: form.title }),
1789
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral500", children: [
1790
+ "/",
1791
+ form.slug
1792
+ ] })
1793
+ ] }) }),
1794
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
1795
+ /* @__PURE__ */ jsx(Badge, { children: form.category }),
1796
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: form.settings?.department || "general" })
1797
+ ] }) }),
1798
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
1799
+ /* @__PURE__ */ jsxs(Typography, { children: [
1800
+ (form.fields || []).length,
1801
+ " ",
1802
+ t("page.ui.fields_label", "fields")
1803
+ ] }),
1804
+ localeKeys.length > 0 ? /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral500", children: [
1805
+ t("page.ui.locales_label", "Locales"),
1806
+ ":",
1807
+ " ",
1808
+ localeKeys.join(", ").toUpperCase()
1809
+ ] }) : null
1810
+ ] }) }),
1811
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: (form.checklistTemplate || []).length }) }),
1812
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: form.submissionCount || 0 }) }),
1813
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, wrap: "wrap", children: [
1814
+ /* @__PURE__ */ jsx(
1815
+ Button,
1816
+ {
1817
+ size: "S",
1818
+ variant: "secondary",
1819
+ onClick: () => handleOpenInVisualBuilder(form),
1820
+ children: t(
1821
+ "page.ui.design_fields",
1822
+ "Design Fields (Drag & Drop)"
1823
+ )
1824
+ }
1825
+ ),
1826
+ /* @__PURE__ */ jsx(
1827
+ Button,
1828
+ {
1829
+ size: "S",
1830
+ variant: editingFormSlug === form.slug ? "default" : "tertiary",
1831
+ onClick: () => setEditingFormSlug(
1832
+ editingFormSlug === form.slug ? null : form.slug
1833
+ ),
1834
+ children: t(
1835
+ "page.ui.casework_checklist",
1836
+ "Routing, Checklist & i18n"
1837
+ )
1838
+ }
1839
+ )
1840
+ ] }) })
1841
+ ] }, form.slug);
1842
+ }) })
1843
+ ] })
1844
+ ] });
1845
+ };
1846
+ const cardBorderStyle = {
1847
+ border: "1px solid rgba(128, 128, 128, 0.2)"
1848
+ };
1849
+ const SubscribersTab = ({
1850
+ t,
1851
+ subscribers,
1852
+ post,
1853
+ onStatusMessage,
1854
+ onReload
1855
+ }) => {
1856
+ const [showAddForm, setShowAddForm] = React.useState(false);
1857
+ const [newSubEmail, setNewSubEmail] = React.useState("");
1858
+ const [newSubName, setNewSubName] = React.useState("");
1859
+ const [newSubLocale, setNewSubLocale] = React.useState("es");
1860
+ const [newSubTopics, setNewSubTopics] = React.useState([
1861
+ "announcements",
1862
+ "events"
1863
+ ]);
1864
+ const handleAddSubscriber = async () => {
1865
+ if (!newSubEmail.trim()) return;
1866
+ await post(`/api/${PLUGIN_ID}/subscribers`, {
1867
+ email: newSubEmail.trim(),
1868
+ fullName: newSubName.trim(),
1869
+ locale: newSubLocale,
1870
+ topics: newSubTopics.length > 0 ? newSubTopics : ["announcements"]
1871
+ });
1872
+ setNewSubEmail("");
1873
+ setNewSubName("");
1874
+ setShowAddForm(false);
1875
+ onStatusMessage(`Subscriber "${newSubEmail.trim()}" added`);
1876
+ await onReload();
1877
+ };
1878
+ return /* @__PURE__ */ jsxs(Box, { paddingTop: 5, children: [
1879
+ /* @__PURE__ */ jsxs(
1880
+ Flex,
1881
+ {
1882
+ justifyContent: "space-between",
1883
+ alignItems: "center",
1884
+ paddingBottom: 4,
1885
+ wrap: "wrap",
1886
+ gap: 3,
1887
+ children: [
1888
+ /* @__PURE__ */ jsx(Typography, { variant: "beta", tag: "h2", children: t("page.ui.subscribers_list", "Community Subscribers") }),
1889
+ /* @__PURE__ */ jsx(
1890
+ Button,
1891
+ {
1892
+ size: "S",
1893
+ variant: showAddForm ? "tertiary" : "default",
1894
+ onClick: () => setShowAddForm(!showAddForm),
1895
+ children: showAddForm ? t("page.ui.cancel", "Cancel") : t("page.ui.add_subscriber", "+ Add Subscriber")
1896
+ }
1897
+ )
1898
+ ]
1899
+ }
1900
+ ),
1901
+ showAddForm ? /* @__PURE__ */ jsx(
1902
+ Box,
1903
+ {
1904
+ padding: 5,
1905
+ marginBottom: 5,
1906
+ background: "neutral0",
1907
+ hasRadius: true,
1908
+ shadow: "filterShadow",
1909
+ style: cardBorderStyle,
1910
+ children: /* @__PURE__ */ jsxs(
1911
+ Box,
1912
+ {
1913
+ style: {
1914
+ display: "grid",
1915
+ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
1916
+ gap: 16,
1917
+ alignItems: "end"
1918
+ },
1919
+ children: [
1920
+ /* @__PURE__ */ jsxs(Field.Root, { name: "newSubEmail", required: true, children: [
1921
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.subscriber_email", "Email") }),
1922
+ /* @__PURE__ */ jsx(
1923
+ TextInput,
1924
+ {
1925
+ name: "newSubEmail",
1926
+ type: "email",
1927
+ placeholder: t(
1928
+ "placeholder.subscriber_email",
1929
+ "fatima@example.org"
1930
+ ),
1931
+ value: newSubEmail,
1932
+ onChange: (e) => setNewSubEmail(e.target.value)
1933
+ }
1934
+ )
1935
+ ] }),
1936
+ /* @__PURE__ */ jsxs(Field.Root, { name: "newSubName", children: [
1937
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.full_name", "Full Name") }),
1938
+ /* @__PURE__ */ jsx(
1939
+ TextInput,
1940
+ {
1941
+ name: "newSubName",
1942
+ placeholder: t("placeholder.subscriber_name", "Fatima Zahra"),
1943
+ value: newSubName,
1944
+ onChange: (e) => setNewSubName(e.target.value)
1945
+ }
1946
+ )
1947
+ ] }),
1948
+ /* @__PURE__ */ jsxs(Field.Root, { name: "newSubLocale", children: [
1949
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.preferred_locale", "Locale") }),
1950
+ /* @__PURE__ */ jsx(
1951
+ SingleSelect,
1952
+ {
1953
+ value: newSubLocale,
1954
+ onChange: (val) => setNewSubLocale(String(val)),
1955
+ children: LOCALE_OPTIONS.map((opt) => /* @__PURE__ */ jsx(SingleSelectOption, { value: opt.value, children: opt.label }, opt.value))
1956
+ }
1957
+ )
1958
+ ] }),
1959
+ /* @__PURE__ */ jsxs(Field.Root, { name: "newSubTopics", children: [
1960
+ /* @__PURE__ */ jsx(Field.Label, { children: t("field.topics", "Topics") }),
1961
+ /* @__PURE__ */ jsx(
1962
+ MultiSelect,
1963
+ {
1964
+ name: "newSubTopics",
1965
+ withTags: true,
1966
+ placeholder: t(
1967
+ "placeholder.subscriber_topics",
1968
+ "Select topics..."
1969
+ ),
1970
+ value: newSubTopics,
1971
+ onChange: (nextValues) => setNewSubTopics(
1972
+ nextValues.length > 0 ? nextValues : ["announcements"]
1973
+ ),
1974
+ onClear: () => setNewSubTopics(["announcements"]),
1975
+ children: TOPIC_OPTIONS.map((opt) => /* @__PURE__ */ jsx(MultiSelectOption, { value: opt.value, children: opt.label }, opt.value))
1976
+ }
1977
+ )
1978
+ ] }),
1979
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Button, { onClick: handleAddSubscriber, children: t("page.ui.save_subscriber", "Save Subscriber") }) })
1980
+ ]
1981
+ }
1982
+ )
1983
+ }
1984
+ ) : null,
1985
+ /* @__PURE__ */ jsxs(Table, { colCount: 5, rowCount: subscribers.length + 1, children: [
1986
+ /* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
1987
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.email", "Email") }) }),
1988
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.name", "Name") }) }),
1989
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.locale", "Locale") }) }),
1990
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.topics", "Topics") }) }),
1991
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("page.ui.status", "Status") }) })
1992
+ ] }) }),
1993
+ /* @__PURE__ */ jsx(Tbody, { children: subscribers.map((sub) => /* @__PURE__ */ jsxs(Tr, { children: [
1994
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: sub.email }) }),
1995
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: sub.fullName || "-" }) }),
1996
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Badge, { children: sub.locale }) }),
1997
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: (sub.topics || []).join(", ") }) }),
1998
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Badge, { children: sub.status }) })
1999
+ ] }, sub.email)) })
2000
+ ] })
2001
+ ] });
2002
+ };
2003
+ const InboxHomePage = () => {
2004
+ const { formatMessage } = useIntl();
2005
+ const t = (id, defaultMessage) => formatMessage({ id: `${PLUGIN_ID}.${id}`, defaultMessage });
2006
+ const { get, post, put } = useFetchClient();
2007
+ const [activeTab, setActiveTab] = React.useState("submissions");
2008
+ const [forms, setForms] = React.useState([]);
2009
+ const [submissions, setSubmissions] = React.useState([]);
2010
+ const [subscribers, setSubscribers] = React.useState([]);
2011
+ const [alerts, setAlerts] = React.useState([]);
2012
+ const [statusMessage, setStatusMessage] = React.useState("");
2013
+ const loadAll = async () => {
2014
+ try {
2015
+ const [formsRes, subsRes, subscRes, alertsRes] = await Promise.all([
2016
+ get(`/${PLUGIN_ID}/forms?activeOnly=false&admin=true`),
2017
+ get(`/${PLUGIN_ID}/submissions`),
2018
+ get(`/${PLUGIN_ID}/subscribers`),
2019
+ get(`/${PLUGIN_ID}/alerts`)
2020
+ ]);
2021
+ setForms(formsRes?.data?.data || []);
2022
+ setSubmissions(subsRes?.data?.data || []);
2023
+ setSubscribers(subscRes?.data?.data || []);
2024
+ setAlerts(alertsRes?.data?.data || []);
2025
+ } catch {
2026
+ }
2027
+ };
2028
+ React.useEffect(() => {
2029
+ void loadAll();
2030
+ }, []);
2031
+ return /* @__PURE__ */ jsx(Main, { children: /* @__PURE__ */ jsxs(Box, { padding: 8, children: [
2032
+ /* @__PURE__ */ jsxs(
2033
+ Flex,
2034
+ {
2035
+ justifyContent: "space-between",
2036
+ alignItems: "center",
2037
+ paddingBottom: 4,
2038
+ wrap: "wrap",
2039
+ gap: 3,
2040
+ children: [
2041
+ /* @__PURE__ */ jsxs(Box, { children: [
2042
+ /* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: t("page.ui.inbox_service_desk", "Inbox & Service Desk") }),
2043
+ /* @__PURE__ */ jsx(Typography, { variant: "epsilon", textColor: "neutral600", children: t(
2044
+ "page.ui.inbox_service_desk_subtitle",
2045
+ "Casework submissions, visual forms, subscribers, and site-wide alert banners"
2046
+ ) })
2047
+ ] }),
2048
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, wrap: "wrap", children: [
2049
+ /* @__PURE__ */ jsxs(
2050
+ Button,
2051
+ {
2052
+ variant: activeTab === "submissions" ? "default" : "tertiary",
2053
+ onClick: () => setActiveTab("submissions"),
2054
+ children: [
2055
+ t("page.ui.casework_inbox", "Casework Inbox"),
2056
+ " (",
2057
+ submissions.length,
2058
+ ")"
2059
+ ]
2060
+ }
2061
+ ),
2062
+ /* @__PURE__ */ jsxs(
2063
+ Button,
2064
+ {
2065
+ variant: activeTab === "forms" ? "default" : "tertiary",
2066
+ onClick: () => setActiveTab("forms"),
2067
+ children: [
2068
+ t("page.ui.form_builder", "Form Builder"),
2069
+ " (",
2070
+ forms.length,
2071
+ ")"
2072
+ ]
2073
+ }
2074
+ ),
2075
+ /* @__PURE__ */ jsxs(
2076
+ Button,
2077
+ {
2078
+ variant: activeTab === "subscribers" ? "default" : "tertiary",
2079
+ onClick: () => setActiveTab("subscribers"),
2080
+ children: [
2081
+ t("page.ui.subscribers", "Subscribers"),
2082
+ " (",
2083
+ subscribers.length,
2084
+ ")"
2085
+ ]
2086
+ }
2087
+ ),
2088
+ /* @__PURE__ */ jsxs(
2089
+ Button,
2090
+ {
2091
+ variant: activeTab === "alerts" ? "default" : "tertiary",
2092
+ onClick: () => setActiveTab("alerts"),
2093
+ children: [
2094
+ t("page.ui.alert_banners", "Alert Banners"),
2095
+ " (",
2096
+ alerts.length,
2097
+ ")"
2098
+ ]
2099
+ }
2100
+ )
2101
+ ] })
2102
+ ]
2103
+ }
2104
+ ),
2105
+ statusMessage ? /* @__PURE__ */ jsx(Box, { padding: 3, marginBottom: 4, background: "success100", hasRadius: true, children: /* @__PURE__ */ jsx(Typography, { textColor: "success700", fontWeight: "semiBold", children: statusMessage }) }) : null,
2106
+ /* @__PURE__ */ jsx(Divider, {}),
2107
+ activeTab === "submissions" && /* @__PURE__ */ jsx(
2108
+ CaseworkSubmissionsTab,
2109
+ {
2110
+ t,
2111
+ submissions,
2112
+ forms,
2113
+ post,
2114
+ put,
2115
+ onStatusMessage: setStatusMessage,
2116
+ onReload: loadAll
2117
+ }
2118
+ ),
2119
+ activeTab === "forms" && /* @__PURE__ */ jsx(
2120
+ FormBuilderTab,
2121
+ {
2122
+ t,
2123
+ forms,
2124
+ post,
2125
+ onStatusMessage: setStatusMessage,
2126
+ onReload: loadAll
2127
+ }
2128
+ ),
2129
+ activeTab === "subscribers" && /* @__PURE__ */ jsx(
2130
+ SubscribersTab,
2131
+ {
2132
+ t,
2133
+ subscribers,
2134
+ post,
2135
+ onStatusMessage: setStatusMessage,
2136
+ onReload: loadAll
2137
+ }
2138
+ ),
2139
+ activeTab === "alerts" && /* @__PURE__ */ jsx(
2140
+ AlertBannersTab,
2141
+ {
2142
+ t,
2143
+ alerts,
2144
+ post,
2145
+ onStatusMessage: setStatusMessage,
2146
+ onReload: loadAll
2147
+ }
2148
+ )
2149
+ ] }) });
2150
+ };
2151
+ export {
2152
+ InboxHomePage
2153
+ };