@vicacha-devs/strapi-plugin-calendar 0.0.0-stage → 1.0.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.md +21 -0
  2. package/README.md +163 -2
  3. package/dist/admin/CalendarPage-CVqowKst.cjs +1015 -0
  4. package/dist/admin/CalendarPage-Dq6YfSXF.js +1015 -0
  5. package/dist/admin/SettingsPage-7SecVQEi.js +2088 -0
  6. package/dist/admin/SettingsPage-D0aCDb9w.cjs +2088 -0
  7. package/dist/admin/ar-O6QL_nJZ.js +331 -0
  8. package/dist/admin/ar-yKsEpX_y.cjs +331 -0
  9. package/dist/admin/de-BpDxjctz.js +331 -0
  10. package/dist/admin/de-ryVtwWOz.cjs +331 -0
  11. package/dist/admin/en-BHYSUqXv.cjs +331 -0
  12. package/dist/admin/en-BoRq-9QD.js +331 -0
  13. package/dist/admin/es-BZ7WX8Ev.js +331 -0
  14. package/dist/admin/es-T5v93hXW.cjs +331 -0
  15. package/dist/admin/fr-BnDr9DC8.js +331 -0
  16. package/dist/admin/fr-DTdTwx7e.cjs +331 -0
  17. package/dist/admin/index-DO0QbnXX.cjs +3223 -0
  18. package/dist/admin/index-USqxqyAm.js +3216 -0
  19. package/dist/admin/index.cjs +9 -0
  20. package/dist/admin/index.js +9 -0
  21. package/dist/admin/index.mjs +9 -0
  22. package/dist/admin/it-BkJNzy27.cjs +331 -0
  23. package/dist/admin/it-DkdUInap.js +331 -0
  24. package/dist/admin/nl-C2NFORLS.js +331 -0
  25. package/dist/admin/nl-CjnlbeUM.cjs +331 -0
  26. package/dist/admin/pl-BJArPgCQ.cjs +331 -0
  27. package/dist/admin/pl-mv5eXA8W.js +331 -0
  28. package/dist/admin/pt-CSYqSGnz.cjs +331 -0
  29. package/dist/admin/pt-WpvZGj3b.js +331 -0
  30. package/dist/admin/src/components/CalendarSidePanel.d.ts +13 -0
  31. package/dist/admin/src/components/Initializer.d.ts +6 -0
  32. package/dist/admin/src/components/PluginIcon.d.ts +3 -0
  33. package/dist/admin/src/components/RRuleInput.d.ts +20 -0
  34. package/dist/admin/src/components/calendar/CalendarToolbar.d.ts +32 -0
  35. package/dist/admin/src/components/calendar/FullCalendarCanvas.d.ts +21 -0
  36. package/dist/admin/src/components/calendar/FullCalendarDayCell.d.ts +11 -0
  37. package/dist/admin/src/components/calendar/OccurrenceDetailDrawer.d.ts +15 -0
  38. package/dist/admin/src/components/calendar/QuickCreatePanel.d.ts +29 -0
  39. package/dist/admin/src/components/calendar/QuickCreateSubcomponents.d.ts +40 -0
  40. package/dist/admin/src/components/calendar/calendarPageHelpers.d.ts +52 -0
  41. package/dist/admin/src/components/calendar/calendarThemeStyles.d.ts +2 -0
  42. package/dist/admin/src/components/settings/CalendarThemeSection.d.ts +9 -0
  43. package/dist/admin/src/components/settings/CalendarViewsSection.d.ts +10 -0
  44. package/dist/admin/src/components/settings/CollectionSourcesSection.d.ts +12 -0
  45. package/dist/admin/src/components/settings/CompanionSuiteSettingsSection.d.ts +29 -0
  46. package/dist/admin/src/components/settings/SecondaryCalendarsSection.d.ts +11 -0
  47. package/dist/admin/src/fields/rruleField.d.ts +19 -0
  48. package/dist/admin/src/index.d.ts +18 -0
  49. package/dist/admin/src/pages/CalendarPage.d.ts +3 -0
  50. package/dist/admin/src/pages/SettingsPage.d.ts +3 -0
  51. package/dist/admin/src/pages/calendarPageSupport.d.ts +8 -0
  52. package/dist/admin/tr-BhZKvFoK.js +331 -0
  53. package/dist/admin/tr-zUVxuw9X.cjs +331 -0
  54. package/dist/package.json +3 -0
  55. package/dist/server/index.cjs +2585 -0
  56. package/dist/server/index.js +2585 -0
  57. package/dist/server/index.mjs +2585 -0
  58. package/dist/server/src/bootstrap.d.ts +5 -0
  59. package/dist/server/src/config/index.d.ts +7 -0
  60. package/dist/server/src/controllers/admin.d.ts +15 -0
  61. package/dist/server/src/controllers/content-api.d.ts +10 -0
  62. package/dist/server/src/controllers/index.d.ts +21 -0
  63. package/dist/server/src/destroy.d.ts +5 -0
  64. package/dist/server/src/index.d.ts +85 -0
  65. package/dist/server/src/register.d.ts +5 -0
  66. package/dist/server/src/routes/admin.d.ts +17 -0
  67. package/dist/server/src/routes/content-api.d.ts +10 -0
  68. package/dist/server/src/routes/index.d.ts +28 -0
  69. package/dist/server/src/services/builtinSources.d.ts +3 -0
  70. package/dist/server/src/services/ical.d.ts +6 -0
  71. package/dist/server/src/services/index.d.ts +23 -0
  72. package/dist/server/src/services/occurrence.d.ts +6 -0
  73. package/dist/server/src/services/occurrenceDates.d.ts +7 -0
  74. package/dist/server/src/services/quickCreateHelpers.d.ts +20 -0
  75. package/dist/server/src/services/registry.d.ts +19 -0
  76. package/dist/server/src/services/settings.d.ts +6 -0
  77. package/dist/server/src/types.d.ts +98 -0
  78. package/dist/shared/calendarSystems.d.ts +41 -0
  79. package/dist/shared/icalGenerator.d.ts +18 -0
  80. package/dist/shared/index.cjs +1612 -0
  81. package/dist/shared/index.d.ts +6 -0
  82. package/dist/shared/index.js +1612 -0
  83. package/dist/shared/index.mjs +1612 -0
  84. package/dist/shared/localization.d.ts +14 -0
  85. package/dist/shared/pluginId.d.ts +2 -0
  86. package/dist/shared/rruleEngine.d.ts +22 -0
  87. package/dist/shared/themePalettes.d.ts +27 -0
  88. package/dist/shared/themePresets.d.ts +32 -0
  89. package/dist/shared/types.d.ts +311 -0
  90. package/package.json +120 -3
@@ -0,0 +1,2088 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const designSystem = require("@strapi/design-system");
5
+ const admin = require("@strapi/strapi/admin");
6
+ const react = require("react");
7
+ const reactIntl = require("react-intl");
8
+ const index = require("./index-DO0QbnXX.cjs");
9
+ const styledComponents = require("styled-components");
10
+ const CalendarThemeSection = ({
11
+ t,
12
+ settings,
13
+ onPatchSettings
14
+ }) => {
15
+ const styledTheme = styledComponents.useTheme();
16
+ const strapiNeutral0 = styledTheme?.colors?.neutral0;
17
+ const activeTheme = settings.theme ?? "breeze";
18
+ const configuredColorScheme = settings.colorScheme ?? "auto";
19
+ const effectiveColorScheme = index.detectEffectiveColorScheme(
20
+ configuredColorScheme,
21
+ strapiNeutral0
22
+ );
23
+ const activePalette = settings.themePalette ?? "default";
24
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
25
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", tag: "h2", children: t("settings.section.theme", "Calendar Theme & Visual Style") }),
26
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 1, paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t(
27
+ "settings.themeHint",
28
+ "Select a modern FullCalendar stock theme (Breezy, Monarch, Forma, Pulse, Classic), design system (Shadcn, MUI), or heritage palette, plus accent swatch and light/dark mode."
29
+ ) }) }),
30
+ /* @__PURE__ */ jsxRuntime.jsx(
31
+ designSystem.Box,
32
+ {
33
+ padding: 4,
34
+ background: "neutral100",
35
+ hasRadius: true,
36
+ style: {
37
+ border: "1px solid rgba(128, 128, 128, 0.18)",
38
+ marginBottom: 20
39
+ },
40
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
41
+ "div",
42
+ {
43
+ style: {
44
+ display: "grid",
45
+ gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
46
+ gap: 16,
47
+ alignItems: "center"
48
+ },
49
+ children: [
50
+ /* @__PURE__ */ jsxRuntime.jsxs(
51
+ designSystem.Field.Root,
52
+ {
53
+ hint: t(
54
+ "settings.paletteHint",
55
+ "Primary accent swatch applied to event pills, selected dates, and active view buttons."
56
+ ),
57
+ children: [
58
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.paletteLabel", "Accent Color Palette") }),
59
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, alignItems: "center", wrap: "wrap", paddingTop: 1, children: Object.values(index.CALENDAR_COLOR_PALETTES).map((pal) => {
60
+ const isSelected = activePalette === pal.id;
61
+ const swatchColor = pal.id === "default" ? index.CALENDAR_THEME_PRESETS[activeTheme]?.primaryColor ?? "#0284C7" : effectiveColorScheme === "dark" ? pal.darkPrimary : pal.lightPrimary;
62
+ return /* @__PURE__ */ jsxRuntime.jsx(
63
+ "button",
64
+ {
65
+ type: "button",
66
+ title: pal.label,
67
+ "aria-label": pal.label,
68
+ onClick: () => onPatchSettings({
69
+ themePalette: pal.id,
70
+ primaryColor: swatchColor
71
+ }),
72
+ style: {
73
+ width: 26,
74
+ height: 26,
75
+ borderRadius: "999px",
76
+ background: swatchColor,
77
+ border: isSelected ? "2px solid #FFFFFF" : "1px solid rgba(128,128,128,0.35)",
78
+ boxShadow: isSelected ? `0 0 0 2px ${swatchColor}` : "none",
79
+ cursor: "pointer",
80
+ padding: 0,
81
+ transition: "transform 0.12s ease",
82
+ transform: isSelected ? "scale(1.12)" : "scale(1)"
83
+ }
84
+ },
85
+ pal.id
86
+ );
87
+ }) }),
88
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
89
+ ]
90
+ }
91
+ ),
92
+ /* @__PURE__ */ jsxRuntime.jsxs(
93
+ designSystem.Field.Root,
94
+ {
95
+ hint: t(
96
+ "settings.colorSchemeHint",
97
+ "Choose whether the calendar canvas follows Strapi's light/dark theme or forces a specific mode."
98
+ ),
99
+ children: [
100
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t(
101
+ "settings.colorSchemeLabel",
102
+ "Calendar Appearance (Color Scheme)"
103
+ ) }),
104
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", wrap: "wrap", paddingTop: 1, children: [
105
+ /* @__PURE__ */ jsxRuntime.jsx(
106
+ designSystem.Button,
107
+ {
108
+ size: "S",
109
+ variant: configuredColorScheme === "auto" ? "default" : "tertiary",
110
+ onClick: () => onPatchSettings({ colorScheme: "auto" }),
111
+ children: t("calendar.scheme.auto", "Auto (Match Strapi Theme)")
112
+ }
113
+ ),
114
+ /* @__PURE__ */ jsxRuntime.jsx(
115
+ designSystem.Button,
116
+ {
117
+ size: "S",
118
+ variant: configuredColorScheme === "light" ? "default" : "tertiary",
119
+ onClick: () => onPatchSettings({ colorScheme: "light" }),
120
+ children: t("calendar.scheme.light", "Light")
121
+ }
122
+ ),
123
+ /* @__PURE__ */ jsxRuntime.jsx(
124
+ designSystem.Button,
125
+ {
126
+ size: "S",
127
+ variant: configuredColorScheme === "dark" ? "default" : "tertiary",
128
+ onClick: () => onPatchSettings({ colorScheme: "dark" }),
129
+ children: t("calendar.scheme.dark", "Dark")
130
+ }
131
+ )
132
+ ] }),
133
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
134
+ ]
135
+ }
136
+ )
137
+ ]
138
+ }
139
+ )
140
+ }
141
+ ),
142
+ /* @__PURE__ */ jsxRuntime.jsx(
143
+ "div",
144
+ {
145
+ style: {
146
+ display: "grid",
147
+ gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
148
+ gap: 14
149
+ },
150
+ children: Object.values(index.CALENDAR_THEME_PRESETS).map((preset) => {
151
+ const isSelected = activeTheme === preset.id;
152
+ const preview = index.resolveCalendarTheme(
153
+ preset.id,
154
+ effectiveColorScheme,
155
+ activePalette,
156
+ strapiNeutral0
157
+ );
158
+ return /* @__PURE__ */ jsxRuntime.jsxs(
159
+ "button",
160
+ {
161
+ type: "button",
162
+ onClick: () => onPatchSettings({
163
+ theme: preset.id,
164
+ primaryColor: preview.primaryColor
165
+ }),
166
+ style: {
167
+ textAlign: "left",
168
+ padding: "14px 16px",
169
+ borderRadius: preview.containerRadius ?? "8px",
170
+ cursor: "pointer",
171
+ background: preview.cellBg,
172
+ color: preview.cellText,
173
+ border: isSelected ? `2px solid ${preview.primaryColor}` : `1px solid ${preview.borderColor}`,
174
+ boxShadow: isSelected ? `0 0 0 2px ${preview.headerBg}` : preview.containerShadow ?? "none",
175
+ transition: "all 0.15s ease"
176
+ },
177
+ children: [
178
+ /* @__PURE__ */ jsxRuntime.jsxs(
179
+ "div",
180
+ {
181
+ style: {
182
+ display: "flex",
183
+ justifyContent: "space-between",
184
+ alignItems: "center",
185
+ marginBottom: 8
186
+ },
187
+ children: [
188
+ /* @__PURE__ */ jsxRuntime.jsx(
189
+ "span",
190
+ {
191
+ style: {
192
+ fontWeight: 700,
193
+ fontSize: 13,
194
+ color: preview.cellText
195
+ },
196
+ children: t(`settings.theme.${preset.id}.label`, preset.label)
197
+ }
198
+ ),
199
+ /* @__PURE__ */ jsxRuntime.jsx(
200
+ "span",
201
+ {
202
+ style: {
203
+ display: "inline-flex",
204
+ alignItems: "center",
205
+ gap: 4
206
+ },
207
+ children: /* @__PURE__ */ jsxRuntime.jsx(
208
+ "span",
209
+ {
210
+ style: {
211
+ width: 20,
212
+ height: 20,
213
+ borderRadius: preset.id === "forma" ? "3px" : "999px",
214
+ background: preview.todayNumberBg,
215
+ color: preview.todayNumberText,
216
+ fontSize: 10,
217
+ fontWeight: 700,
218
+ display: "inline-flex",
219
+ alignItems: "center",
220
+ justifyContent: "center"
221
+ },
222
+ children: "16"
223
+ }
224
+ )
225
+ }
226
+ )
227
+ ]
228
+ }
229
+ ),
230
+ /* @__PURE__ */ jsxRuntime.jsx(
231
+ "div",
232
+ {
233
+ style: {
234
+ marginBottom: 8,
235
+ padding: "4px 8px",
236
+ fontSize: 11,
237
+ fontWeight: 600,
238
+ borderRadius: preset.eventRadius ?? "5px",
239
+ background: preset.eventStyle === "solid" ? preview.primaryColor : `${preview.primaryColor}22`,
240
+ color: preset.eventStyle === "solid" ? "#FFFFFF" : preview.cellText,
241
+ borderLeft: preset.eventStyle === "accent-bar" ? `5px solid ${preview.primaryColor}` : `1px solid ${preview.primaryColor}55`
242
+ },
243
+ children: t(
244
+ "settings.theme.previewSampleEvent",
245
+ "09:00 · Community Event"
246
+ )
247
+ }
248
+ ),
249
+ /* @__PURE__ */ jsxRuntime.jsx(
250
+ "div",
251
+ {
252
+ style: {
253
+ fontSize: 11,
254
+ color: preview.cellMutedText,
255
+ lineHeight: 1.4
256
+ },
257
+ children: t(
258
+ `settings.theme.${preset.id}.description`,
259
+ preset.description
260
+ )
261
+ }
262
+ )
263
+ ]
264
+ },
265
+ preset.id
266
+ );
267
+ })
268
+ }
269
+ )
270
+ ] });
271
+ };
272
+ const GRID_3_COL$1 = {
273
+ display: "grid",
274
+ gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
275
+ gap: 16
276
+ };
277
+ const GRID_2_COL$1 = {
278
+ display: "grid",
279
+ gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
280
+ gap: 16
281
+ };
282
+ const SUB_BOX_STYLE$1 = {
283
+ border: "1px solid rgba(128, 128, 128, 0.18)"
284
+ };
285
+ const VIEW_CHECKBOXES = [
286
+ ["monthView", "view.month", "Month"],
287
+ ["weekView", "view.week", "Week"],
288
+ ["dayView", "view.day", "Day"],
289
+ ["agendaView", "view.agenda", "Agenda"],
290
+ ["yearView", "view.year", "Year"]
291
+ ];
292
+ const BEHAVIOR_CHECKBOXES = [
293
+ ["showWeekends", "settings.showWeekends", "Show Weekends"],
294
+ ["weekNumbers", "settings.weekNumbers", "Show Week Numbers"],
295
+ ["timeFormat24h", "settings.timeFormat24h", "24-Hour Time Format"],
296
+ [
297
+ "showCreateButton",
298
+ "settings.showCreateButton",
299
+ "Enable Quick-Create & Slot Selection"
300
+ ]
301
+ ];
302
+ const CalendarViewsSection = ({
303
+ t,
304
+ settings,
305
+ onPatchSettings,
306
+ mode = "all"
307
+ }) => {
308
+ const showTheme = mode === "all" || mode === "theme";
309
+ const showGeneral = mode === "all" || mode === "general";
310
+ const renderSelect = (label, hint, placeholder, value, options, onChange) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { hint: t(hint[0], hint[1]), children: [
311
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t(label[0], label[1]) }),
312
+ /* @__PURE__ */ jsxRuntime.jsx(
313
+ designSystem.SingleSelect,
314
+ {
315
+ placeholder: t(placeholder[0], placeholder[1]),
316
+ value,
317
+ onChange: (val) => onChange(String(val)),
318
+ children: options.map(([optVal, optIdOrLabel, optDef]) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: optVal, children: optDef ? t(optIdOrLabel, optDef) : optIdOrLabel }, optVal))
319
+ }
320
+ ),
321
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
322
+ ] });
323
+ const renderText = (label, hint, placeholder, value, onChange) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { hint: t(hint[0], hint[1]), children: [
324
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t(label[0], label[1]) }),
325
+ /* @__PURE__ */ jsxRuntime.jsx(
326
+ designSystem.TextInput,
327
+ {
328
+ value,
329
+ onChange: (e) => onChange(e.target.value),
330
+ placeholder: t(placeholder[0], placeholder[1])
331
+ }
332
+ ),
333
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
334
+ ] });
335
+ const extraLocales = index.SUPPORTED_CALENDAR_LOCALES.filter(
336
+ (loc) => !["es", "en", "ar", "tr"].includes(loc.code)
337
+ ).map((loc) => [
338
+ loc.code,
339
+ `${loc.nativeName} — ${loc.label} (${loc.code.toUpperCase()})`
340
+ ]);
341
+ return /* @__PURE__ */ jsxRuntime.jsx(
342
+ designSystem.Box,
343
+ {
344
+ padding: 5,
345
+ background: "neutral0",
346
+ hasRadius: true,
347
+ shadow: "tableShadow",
348
+ style: { border: "1px solid rgba(128, 128, 128, 0.22)" },
349
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 5, children: [
350
+ showTheme && /* @__PURE__ */ jsxRuntime.jsx(
351
+ CalendarThemeSection,
352
+ {
353
+ t,
354
+ settings,
355
+ onPatchSettings
356
+ }
357
+ ),
358
+ showTheme && showGeneral && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}),
359
+ showGeneral && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
360
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
361
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", tag: "h2", children: t(
362
+ "settings.section.general",
363
+ "Language, TimeGrid & Schedule Configuration"
364
+ ) }),
365
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 1, paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t(
366
+ "settings.generalHint",
367
+ "Configure the primary local language, optional Arabic/Hijri secondary calendar display, timezone, and daily operating hours."
368
+ ) }) }),
369
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: GRID_3_COL$1, children: [
370
+ renderSelect(
371
+ ["settings.defaultLocale", "Primary Calendar Language"],
372
+ [
373
+ "settings.defaultLocaleHint",
374
+ "Language for month names, weekdays, and toolbar buttons."
375
+ ],
376
+ [
377
+ "settings.defaultLocale.placeholder",
378
+ "Select primary language"
379
+ ],
380
+ settings.defaultLocale || "auto",
381
+ [
382
+ ["es", "settings.locale.es", "Español — Spanish (ES)"],
383
+ ["en", "settings.locale.en", "English (EN)"],
384
+ ["ar", "settings.locale.ar", "العربية — Arabic (AR)"],
385
+ ["tr", "settings.locale.tr", "Türkçe — Turkish (TR)"],
386
+ [
387
+ "auto",
388
+ "settings.locale.auto",
389
+ "Auto (Match Strapi Admin UI)"
390
+ ],
391
+ ...extraLocales
392
+ ],
393
+ (defaultLocale) => onPatchSettings({ defaultLocale })
394
+ ),
395
+ renderSelect(
396
+ [
397
+ "settings.secondaryCalendarLanguage",
398
+ "Secondary Hijri / Arabic Date Display"
399
+ ],
400
+ [
401
+ "settings.secondaryCalendarLanguageHint",
402
+ "Choose whether Hijri dates appear in local language, Arabic script, or hidden."
403
+ ],
404
+ [
405
+ "settings.secondaryCalendarLanguage.placeholder",
406
+ "Select Hijri display mode"
407
+ ],
408
+ settings.secondaryCalendarLanguage || "local",
409
+ [
410
+ [
411
+ "local",
412
+ "settings.secondaryCalendarLanguage.local",
413
+ "Local Language (e.g. 16 Rabiʻ II)"
414
+ ],
415
+ [
416
+ "ar",
417
+ "settings.secondaryCalendarLanguage.ar",
418
+ "Arabic Script — العربية (e.g. ١٦ ربيع الآخر)"
419
+ ],
420
+ [
421
+ "off",
422
+ "settings.secondaryCalendarLanguage.off",
423
+ "Off (Gregorian Calendar Only)"
424
+ ]
425
+ ],
426
+ (val) => onPatchSettings({
427
+ secondaryCalendarLanguage: val
428
+ })
429
+ ),
430
+ renderSelect(
431
+ ["settings.direction", "Layout Direction"],
432
+ [
433
+ "settings.directionHint",
434
+ "Grid column order (LTR or RTL for Arabic)."
435
+ ],
436
+ ["settings.direction.placeholder", "Select layout direction"],
437
+ settings.direction || "auto",
438
+ [
439
+ [
440
+ "auto",
441
+ "settings.direction.auto",
442
+ "Auto (LTR / RTL by Language)"
443
+ ],
444
+ ["ltr", "settings.direction.ltr", "Left-to-Right (LTR)"],
445
+ ["rtl", "settings.direction.rtl", "Right-to-Left (RTL)"]
446
+ ],
447
+ (val) => onPatchSettings({
448
+ direction: val
449
+ })
450
+ ),
451
+ renderSelect(
452
+ ["settings.defaultView", "Default Calendar View"],
453
+ [
454
+ "settings.defaultViewHint",
455
+ "Initial view displayed when opening the calendar."
456
+ ],
457
+ ["settings.defaultView.placeholder", "Select default view"],
458
+ settings.defaultView || "dayGridMonth",
459
+ [
460
+ [
461
+ "dayGridMonth",
462
+ "settings.defaultView.month",
463
+ "Month Grid"
464
+ ],
465
+ [
466
+ "timeGridWeek",
467
+ "settings.defaultView.week",
468
+ "Week (TimeGrid)"
469
+ ],
470
+ [
471
+ "timeGridDay",
472
+ "settings.defaultView.day",
473
+ "Day (TimeGrid)"
474
+ ],
475
+ ["listMonth", "settings.defaultView.agenda", "Agenda List"],
476
+ [
477
+ "multiMonthYear",
478
+ "settings.defaultView.year",
479
+ "Full Year (3x4 Grid)"
480
+ ],
481
+ [
482
+ "multiMonthYearStacked",
483
+ "settings.defaultView.yearStacked",
484
+ "Year (Stacked Months)"
485
+ ],
486
+ [
487
+ "dayGridYear",
488
+ "settings.defaultView.dayGridYear",
489
+ "Year (Continuous Grid)"
490
+ ]
491
+ ],
492
+ (val) => onPatchSettings({ defaultView: val })
493
+ ),
494
+ renderSelect(
495
+ ["settings.firstDayOfWeek", "First Day of Week"],
496
+ [
497
+ "settings.firstDayHint",
498
+ "Starting weekday column in Month and Week views."
499
+ ],
500
+ [
501
+ "settings.firstDayOfWeek.placeholder",
502
+ "Select first day of week"
503
+ ],
504
+ String(settings.firstDayOfWeek ?? 1),
505
+ [
506
+ ["1", "settings.firstDay.monday", "Monday (1)"],
507
+ ["0", "settings.firstDay.sunday", "Sunday (0)"],
508
+ ["6", "settings.firstDay.saturday", "Saturday (6)"]
509
+ ],
510
+ (val) => onPatchSettings({
511
+ firstDayOfWeek: Number.parseInt(val, 10)
512
+ })
513
+ ),
514
+ renderSelect(
515
+ ["settings.weekNumberCalculation", "Week Calculation"],
516
+ [
517
+ "settings.weekCalcHint",
518
+ "Standard used when computing week numbers."
519
+ ],
520
+ [
521
+ "settings.weekNumberCalculation.placeholder",
522
+ "Select week calculation mode"
523
+ ],
524
+ settings.weekNumberCalculation || "ISO",
525
+ [
526
+ ["ISO", "settings.weekCalc.iso", "ISO 8601 (Monday)"],
527
+ ["local", "settings.weekCalc.local", "Locale Default"]
528
+ ],
529
+ (val) => onPatchSettings({
530
+ weekNumberCalculation: val
531
+ })
532
+ ),
533
+ renderText(
534
+ ["settings.defaultTimezone", "Default Timezone (IANA)"],
535
+ [
536
+ "settings.timezoneHint",
537
+ "IANA timezone identifier (e.g., UTC or America/New_York)."
538
+ ],
539
+ ["settings.defaultTimezone.placeholder", "e.g., UTC"],
540
+ settings.defaultTimezone || "UTC",
541
+ (defaultTimezone) => onPatchSettings({ defaultTimezone })
542
+ ),
543
+ renderText(
544
+ ["settings.startHour", "Daily Start Hour"],
545
+ [
546
+ "settings.startHourHint",
547
+ "Earliest visible time slot in Week/Day TimeGrid (HH:MM:SS)."
548
+ ],
549
+ ["settings.startHour.placeholder", "e.g., 07:00:00"],
550
+ settings.startHour || "07:00:00",
551
+ (startHour) => onPatchSettings({ startHour })
552
+ ),
553
+ renderText(
554
+ ["settings.endHour", "Daily End Hour"],
555
+ [
556
+ "settings.endHourHint",
557
+ "Latest visible time slot in Week/Day TimeGrid (HH:MM:SS)."
558
+ ],
559
+ ["settings.endHour.placeholder", "e.g., 21:00:00"],
560
+ settings.endHour || "21:00:00",
561
+ (endHour) => onPatchSettings({ endHour })
562
+ )
563
+ ] }),
564
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { ...GRID_2_COL$1, marginTop: 16 }, children: [
565
+ renderSelect(
566
+ ["settings.slotDuration", "TimeGrid Slot Duration"],
567
+ [
568
+ "settings.slotDurationHint",
569
+ "Time interval for rows in Week and Day TimeGrid views."
570
+ ],
571
+ ["settings.slotDuration.placeholder", "Select slot interval"],
572
+ settings.slotDuration || "00:30:00",
573
+ [
574
+ [
575
+ "00:15:00",
576
+ "settings.slotDuration.15m",
577
+ "15 min (00:15:00)"
578
+ ],
579
+ [
580
+ "00:30:00",
581
+ "settings.slotDuration.30m",
582
+ "30 min (00:30:00)"
583
+ ],
584
+ [
585
+ "01:00:00",
586
+ "settings.slotDuration.60m",
587
+ "60 min (01:00:00)"
588
+ ]
589
+ ],
590
+ (slotDuration) => onPatchSettings({ slotDuration })
591
+ ),
592
+ renderText(
593
+ ["settings.feedTitle", "Public iCal (.ics) Feed Title"],
594
+ [
595
+ "settings.feedTitleHint",
596
+ "Calendar title exported in /api/calendar/feed.ics for Google/Apple/Outlook subscriptions."
597
+ ],
598
+ [
599
+ "settings.feedTitle.placeholder",
600
+ "e.g., Organization — General Calendar"
601
+ ],
602
+ settings.feedTitle || t(
603
+ "settings.defaultFeedTitle",
604
+ "Organization — General Calendar"
605
+ ),
606
+ (feedTitle) => onPatchSettings({ feedTitle })
607
+ )
608
+ ] })
609
+ ] }),
610
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}),
611
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: GRID_2_COL$1, children: [
612
+ [
613
+ "settings.enabledViewsGroup",
614
+ "Enabled Calendar View Tabs",
615
+ VIEW_CHECKBOXES
616
+ ],
617
+ [
618
+ "settings.gridBehaviorGroup",
619
+ "Grid Display & Interaction Options",
620
+ BEHAVIOR_CHECKBOXES
621
+ ]
622
+ ].map(([groupId, groupDef, items]) => /* @__PURE__ */ jsxRuntime.jsx(
623
+ designSystem.Box,
624
+ {
625
+ padding: 4,
626
+ background: "neutral100",
627
+ hasRadius: true,
628
+ style: SUB_BOX_STYLE$1,
629
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 3, children: [
630
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral700", children: t(groupId, groupDef) }),
631
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 4, wrap: "wrap", children: items.map(([key, id, def]) => /* @__PURE__ */ jsxRuntime.jsx(
632
+ designSystem.Checkbox,
633
+ {
634
+ checked: key === "timeFormat24h" ? settings.timeFormat24h !== false : Boolean(settings[key]),
635
+ onCheckedChange: (c) => onPatchSettings({ [key]: Boolean(c) }),
636
+ children: t(id, def)
637
+ },
638
+ key
639
+ )) })
640
+ ] })
641
+ },
642
+ groupId
643
+ )) })
644
+ ] })
645
+ ] })
646
+ }
647
+ );
648
+ };
649
+ const CARD_BORDER_STYLE = {
650
+ border: "1px solid rgba(128, 128, 128, 0.22)"
651
+ };
652
+ const SUB_CARD_BORDER_STYLE = {
653
+ border: "1px solid rgba(128, 128, 128, 0.18)"
654
+ };
655
+ const GRID_3_STYLE = {
656
+ display: "grid",
657
+ gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
658
+ gap: 16
659
+ };
660
+ const GRID_2_STYLE = {
661
+ display: "grid",
662
+ gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
663
+ gap: 16
664
+ };
665
+ const TITLE_CANDIDATES = "title,name,customerName,visitorName,headline,subject,fullName,slug".split(
666
+ ","
667
+ );
668
+ const START_CANDIDATES = "startDate,preferredDate,date,scheduledAt,releasedAt,publishedAt,createdAt,updatedAt".split(
669
+ ","
670
+ );
671
+ const CollectionSourcesSection = ({
672
+ t,
673
+ sources,
674
+ contentTypes,
675
+ onAddOrUpdateSource,
676
+ onToggleSourceEnabled,
677
+ onRemoveSource
678
+ }) => {
679
+ const [isFormOpen, setIsFormOpen] = react.useState(true);
680
+ const [editingSourceId, setEditingSourceId] = react.useState(null);
681
+ const [newSourceUid, setNewSourceUid] = react.useState("plugin::events.event");
682
+ const [newSourceLabel, setNewSourceLabel] = react.useState(
683
+ () => t("settings.defaultSourceLabel", "Events")
684
+ );
685
+ const [newSourceColor, setNewSourceColor] = react.useState("#0284C7");
686
+ const [newTitleField, setNewTitleField] = react.useState("title");
687
+ const [newStartField, setNewStartField] = react.useState("startDate");
688
+ const [newEndField, setNewEndField] = react.useState("endDate");
689
+ const [newRRuleField, setNewRRuleField] = react.useState("recurrence");
690
+ const selectCollectionDefaults = (ct) => {
691
+ setEditingSourceId(null);
692
+ setNewSourceUid(ct.uid);
693
+ setNewSourceLabel(ct.displayName || ct.uid);
694
+ const fieldNames = ct.fields.map((f) => f.name);
695
+ const findMatch = (candidates) => fieldNames.find((n) => candidates.includes(n));
696
+ const bestTitle = findMatch(TITLE_CANDIDATES) ?? ct.fields.find((f) => ["string", "text", "uid"].includes(f.type))?.name ?? ct.fields[0]?.name ?? "title";
697
+ const bestStart = findMatch(START_CANDIDATES) ?? ct.fields.find((f) => f.type === "datetime" || f.type === "date")?.name ?? ct.fields[0]?.name ?? "startDate";
698
+ setNewTitleField(bestTitle);
699
+ setNewStartField(bestStart);
700
+ setNewEndField(
701
+ findMatch(["endDate", "finishDate", "expiresAt"]) ?? "endDate"
702
+ );
703
+ setNewRRuleField(
704
+ findMatch(["recurrence", "rrule", "recurrenceRule"]) ?? "recurrence"
705
+ );
706
+ };
707
+ react.useEffect(() => {
708
+ if (contentTypes.length === 0) return;
709
+ const preferred = contentTypes.find((ct) => ct.uid === newSourceUid) ?? contentTypes.find((ct) => ct.uid === "plugin::events.event") ?? contentTypes.find((ct) => !sources.some((s) => s.uid === ct.uid)) ?? contentTypes[0];
710
+ if (preferred) selectCollectionDefaults(preferred);
711
+ }, [contentTypes]);
712
+ const selectedCtFields = react.useMemo(() => {
713
+ const found = contentTypes.find((ct) => ct.uid === newSourceUid);
714
+ const base = found?.fields ? [...found.fields] : [];
715
+ const ensureField = (name, fallbackType) => {
716
+ if (name && !base.some((f) => f.name === name)) {
717
+ base.push({ name, type: fallbackType });
718
+ }
719
+ };
720
+ ensureField(newTitleField || "title", "string");
721
+ ensureField(newStartField || "startDate", "datetime");
722
+ return base;
723
+ }, [contentTypes, newSourceUid, newTitleField, newStartField]);
724
+ const handleEditSource = (src) => {
725
+ setEditingSourceId(src.id);
726
+ setNewSourceUid(src.uid);
727
+ setNewSourceLabel(src.label);
728
+ setNewSourceColor(src.color || "#0284C7");
729
+ setNewTitleField(src.fields.title || "title");
730
+ setNewStartField(src.fields.startDate || "startDate");
731
+ setNewEndField(src.fields.endDate || "");
732
+ setNewRRuleField(src.fields.rrule || "");
733
+ setIsFormOpen(true);
734
+ };
735
+ const handleSaveSource = () => {
736
+ if (!newSourceUid || !newTitleField || !newStartField) return;
737
+ const existing = sources.find(
738
+ (s) => s.id === editingSourceId || s.uid === newSourceUid
739
+ );
740
+ const idSlug = (newSourceLabel || newSourceUid).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
741
+ const nextSource = {
742
+ ...existing,
743
+ id: existing?.id || idSlug || `source-${Date.now()}`,
744
+ label: newSourceLabel.trim() || newSourceUid,
745
+ uid: newSourceUid,
746
+ color: /^#[0-9a-fA-F]{3,8}$/.test(newSourceColor.trim()) ? newSourceColor.trim() : "#0284C7",
747
+ enabled: existing?.enabled ?? true,
748
+ fields: {
749
+ ...existing?.fields,
750
+ title: newTitleField,
751
+ startDate: newStartField,
752
+ endDate: newEndField.trim() || void 0,
753
+ rrule: newRRuleField.trim() || void 0
754
+ }
755
+ };
756
+ setEditingSourceId(null);
757
+ onAddOrUpdateSource(nextSource);
758
+ };
759
+ const renderTextField = (label, hint, placeholder, value, onChange) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { hint: t(hint[0], hint[1]), children: [
760
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t(label[0], label[1]) }),
761
+ /* @__PURE__ */ jsxRuntime.jsx(
762
+ designSystem.TextInput,
763
+ {
764
+ value,
765
+ onChange: (e) => onChange(e.target.value),
766
+ placeholder: t(placeholder[0], placeholder[1])
767
+ }
768
+ ),
769
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
770
+ ] });
771
+ const renderFieldSelect = (label, hint, placeholder, value, onChange) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { required: true, hint: t(hint[0], hint[1]), children: [
772
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t(label[0], label[1]) }),
773
+ /* @__PURE__ */ jsxRuntime.jsx(
774
+ designSystem.SingleSelect,
775
+ {
776
+ placeholder: t(placeholder[0], placeholder[1]),
777
+ value,
778
+ onChange: (val) => onChange(String(val)),
779
+ children: selectedCtFields.map((f) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.SingleSelectOption, { value: f.name, children: [
780
+ f.name,
781
+ " (",
782
+ f.type,
783
+ ")"
784
+ ] }, f.name))
785
+ }
786
+ ),
787
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
788
+ ] });
789
+ return /* @__PURE__ */ jsxRuntime.jsx(
790
+ designSystem.Box,
791
+ {
792
+ padding: 5,
793
+ background: "neutral0",
794
+ hasRadius: true,
795
+ shadow: "tableShadow",
796
+ style: CARD_BORDER_STYLE,
797
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
798
+ /* @__PURE__ */ jsxRuntime.jsxs(
799
+ designSystem.Flex,
800
+ {
801
+ justifyContent: "space-between",
802
+ alignItems: "flex-start",
803
+ wrap: "wrap",
804
+ gap: 3,
805
+ children: [
806
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: 1, minWidth: 280 }, children: [
807
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", tag: "h2", children: t("settings.section.sources", "Mapped Collection Sources") }),
808
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t(
809
+ "settings.sourcesHint",
810
+ "Connects Strapi Collection Types (such as Events or Bookings) so their records are automatically plotted on the unified calendar. Each mapping defines which fields represent the item title, start/end dates, and optional recurrence rules."
811
+ ) }) })
812
+ ] }),
813
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
814
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { active: true, children: [
815
+ sources.length,
816
+ " ",
817
+ t("settings.mappedCount", "Mapped")
818
+ ] }),
819
+ /* @__PURE__ */ jsxRuntime.jsx(
820
+ designSystem.Button,
821
+ {
822
+ variant: isFormOpen ? "tertiary" : "secondary",
823
+ size: "S",
824
+ onClick: () => setIsFormOpen((prev) => !prev),
825
+ children: isFormOpen ? t("common.hideForm", "Hide Mapping Form") : `+ ${t("settings.addSourceToggle", "Map Collection Type")}`
826
+ }
827
+ )
828
+ ] })
829
+ ]
830
+ }
831
+ ),
832
+ sources.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
833
+ designSystem.Box,
834
+ {
835
+ padding: 4,
836
+ background: "neutral100",
837
+ hasRadius: true,
838
+ style: SUB_CARD_BORDER_STYLE,
839
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral600", children: t(
840
+ "settings.noSources",
841
+ "No collection types are mapped yet. Use the form below to plot Events, Bookings, or Articles on the calendar."
842
+ ) })
843
+ }
844
+ ) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: sources.map((src) => /* @__PURE__ */ jsxRuntime.jsx(
845
+ designSystem.Box,
846
+ {
847
+ padding: 4,
848
+ background: "neutral100",
849
+ hasRadius: true,
850
+ style: {
851
+ ...SUB_CARD_BORDER_STYLE,
852
+ borderLeft: `4px solid ${src.color || "#0284C7"}`
853
+ },
854
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
855
+ designSystem.Flex,
856
+ {
857
+ justifyContent: "space-between",
858
+ alignItems: "center",
859
+ wrap: "wrap",
860
+ gap: 3,
861
+ children: [
862
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
863
+ /* @__PURE__ */ jsxRuntime.jsx(
864
+ "span",
865
+ {
866
+ style: {
867
+ display: "inline-block",
868
+ width: 14,
869
+ height: 14,
870
+ borderRadius: "50%",
871
+ background: src.color
872
+ }
873
+ }
874
+ ),
875
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: src.label }),
876
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "neutral200", textColor: "neutral800", children: src.uid }),
877
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
878
+ t("settings.badge.title", "Title"),
879
+ ": ",
880
+ src.fields.title,
881
+ " ·",
882
+ " ",
883
+ t("settings.badge.start", "Start"),
884
+ ":",
885
+ " ",
886
+ src.fields.startDate,
887
+ src.fields.endDate ? ` · ${t("settings.badge.end", "End")}: ${src.fields.endDate}` : ""
888
+ ] })
889
+ ] }),
890
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", children: [
891
+ /* @__PURE__ */ jsxRuntime.jsx(
892
+ designSystem.Checkbox,
893
+ {
894
+ checked: src.enabled,
895
+ onCheckedChange: (checked) => onToggleSourceEnabled(src.id, Boolean(checked)),
896
+ children: t("settings.sourceEnabled", "Enabled")
897
+ }
898
+ ),
899
+ /* @__PURE__ */ jsxRuntime.jsx(
900
+ designSystem.Button,
901
+ {
902
+ variant: "tertiary",
903
+ size: "S",
904
+ onClick: () => handleEditSource(src),
905
+ children: t("common.edit", "Edit")
906
+ }
907
+ ),
908
+ /* @__PURE__ */ jsxRuntime.jsx(
909
+ designSystem.Button,
910
+ {
911
+ variant: "danger-light",
912
+ size: "S",
913
+ onClick: () => onRemoveSource(src.id),
914
+ children: t("common.remove", "Remove")
915
+ }
916
+ )
917
+ ] })
918
+ ]
919
+ }
920
+ )
921
+ },
922
+ src.id
923
+ )) }),
924
+ isFormOpen && /* @__PURE__ */ jsxRuntime.jsx(
925
+ designSystem.Box,
926
+ {
927
+ padding: 5,
928
+ background: "neutral100",
929
+ hasRadius: true,
930
+ style: SUB_CARD_BORDER_STYLE,
931
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
932
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral700", children: t(
933
+ "settings.addSourceTitle",
934
+ "Configure Collection Type Mapping"
935
+ ) }),
936
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: GRID_3_STYLE, children: [
937
+ /* @__PURE__ */ jsxRuntime.jsxs(
938
+ designSystem.Field.Root,
939
+ {
940
+ hint: t(
941
+ "settings.collectionTypeHint",
942
+ "Select which Strapi Collection Type provides the dated entries."
943
+ ),
944
+ children: [
945
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.collectionType", "Strapi Collection Type") }),
946
+ contentTypes.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
947
+ designSystem.SingleSelect,
948
+ {
949
+ placeholder: t(
950
+ "settings.collectionType.placeholder",
951
+ "Select Strapi Collection Type"
952
+ ),
953
+ value: newSourceUid || contentTypes[0]?.uid || "plugin::events.event",
954
+ onChange: (val) => {
955
+ const uid = String(val);
956
+ const found = contentTypes.find((c) => c.uid === uid);
957
+ if (found) {
958
+ selectCollectionDefaults(found);
959
+ } else {
960
+ setNewSourceUid(uid);
961
+ }
962
+ },
963
+ children: contentTypes.map((ct) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.SingleSelectOption, { value: ct.uid, children: [
964
+ ct.displayName,
965
+ " (",
966
+ ct.uid,
967
+ ")"
968
+ ] }, ct.uid))
969
+ }
970
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
971
+ designSystem.TextInput,
972
+ {
973
+ value: newSourceUid,
974
+ onChange: (e) => setNewSourceUid(e.target.value),
975
+ placeholder: t(
976
+ "settings.collectionTypeUid.placeholder",
977
+ "e.g., plugin::events.event"
978
+ )
979
+ }
980
+ ),
981
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
982
+ ]
983
+ }
984
+ ),
985
+ renderTextField(
986
+ ["settings.sourceLabel", "Calendar Filter Label"],
987
+ [
988
+ "settings.sourceLabelHint",
989
+ "Human-readable label shown on calendar filter chips."
990
+ ],
991
+ ["settings.sourceLabel.placeholder", "e.g., Events"],
992
+ newSourceLabel,
993
+ setNewSourceLabel
994
+ ),
995
+ renderTextField(
996
+ ["settings.sourceColor", "Event Badge Color (Hex)"],
997
+ [
998
+ "settings.sourceColorHint",
999
+ "Hex color accent applied to calendar chips for this source."
1000
+ ],
1001
+ ["settings.sourceColor.placeholder", "e.g., #0284C7"],
1002
+ newSourceColor,
1003
+ setNewSourceColor
1004
+ )
1005
+ ] }),
1006
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: GRID_2_STYLE, children: [
1007
+ renderFieldSelect(
1008
+ ["settings.field.title", "Title Field"],
1009
+ [
1010
+ "settings.field.titleHint",
1011
+ "Attribute displayed as the calendar event title."
1012
+ ],
1013
+ ["settings.field.title.placeholder", "Select title field"],
1014
+ newTitleField || "title",
1015
+ setNewTitleField
1016
+ ),
1017
+ renderFieldSelect(
1018
+ ["settings.field.startDate", "Start Date Field"],
1019
+ [
1020
+ "settings.field.startDateHint",
1021
+ "Date or DateTime field used to place the entry on the grid."
1022
+ ],
1023
+ [
1024
+ "settings.field.startDate.placeholder",
1025
+ "Select start date field"
1026
+ ],
1027
+ newStartField || "startDate",
1028
+ setNewStartField
1029
+ ),
1030
+ renderTextField(
1031
+ ["settings.field.endDate", "End Date Field (Optional)"],
1032
+ [
1033
+ "settings.field.endDateHint",
1034
+ "Optional end Date/DateTime attribute for multi-hour or multi-day spans."
1035
+ ],
1036
+ ["settings.field.endDate.placeholder", "e.g., endDate"],
1037
+ newEndField,
1038
+ setNewEndField
1039
+ ),
1040
+ renderTextField(
1041
+ ["settings.field.rrule", "Recurrence Field (Optional)"],
1042
+ [
1043
+ "settings.field.rruleHint",
1044
+ "Optional RFC 5545 RRULE field for repeating schedules."
1045
+ ],
1046
+ ["settings.field.rrule.placeholder", "e.g., recurrence"],
1047
+ newRRuleField,
1048
+ setNewRRuleField
1049
+ )
1050
+ ] }),
1051
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Button, { variant: "default", onClick: handleSaveSource, children: [
1052
+ "+ ",
1053
+ t("settings.addSourceButton", "Save Collection Source")
1054
+ ] }) })
1055
+ ] })
1056
+ }
1057
+ )
1058
+ ] })
1059
+ }
1060
+ );
1061
+ };
1062
+ const CARD_STYLE = {
1063
+ border: "1px solid rgba(128, 128, 128, 0.22)"
1064
+ };
1065
+ const SUB_BOX_STYLE = {
1066
+ border: "1px solid rgba(128, 128, 128, 0.18)"
1067
+ };
1068
+ const GRID_2_COL = {
1069
+ display: "grid",
1070
+ gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
1071
+ gap: 16
1072
+ };
1073
+ const GRID_3_COL = {
1074
+ display: "grid",
1075
+ gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
1076
+ gap: 16
1077
+ };
1078
+ const BOOKING_NUMBER_FIELDS = [
1079
+ {
1080
+ key: "defaultSlotDurationMinutes",
1081
+ labelId: "settings.bookingsSlotDuration",
1082
+ labelDefault: "Slot Duration (Minutes)",
1083
+ hintId: "settings.bookingsSlotDurationHint",
1084
+ hintDefault: "Standard length of each bookable appointment slot.",
1085
+ min: 5,
1086
+ fallback: 60
1087
+ },
1088
+ {
1089
+ key: "defaultCapacityPerSlot",
1090
+ labelId: "settings.bookingsCapacityPerSlot",
1091
+ labelDefault: "Default Capacity Per Slot",
1092
+ hintId: "settings.bookingsCapacityPerSlotHint",
1093
+ hintDefault: "Concurrent reservations allowed per time slot.",
1094
+ min: 1,
1095
+ fallback: 1
1096
+ },
1097
+ {
1098
+ key: "defaultBufferBeforeMinutes",
1099
+ labelId: "settings.bookingsBufferBefore",
1100
+ labelDefault: "Buffer Before (Minutes)",
1101
+ hintId: "settings.bookingsBufferBeforeHint",
1102
+ hintDefault: "Preparation gap blocked before each booking starts.",
1103
+ min: 0,
1104
+ fallback: 0
1105
+ },
1106
+ {
1107
+ key: "defaultBufferAfterMinutes",
1108
+ labelId: "settings.bookingsBufferAfter",
1109
+ labelDefault: "Buffer After (Minutes)",
1110
+ hintId: "settings.bookingsBufferAfterHint",
1111
+ hintDefault: "Cooldown gap blocked after each booking ends.",
1112
+ min: 0,
1113
+ fallback: 0
1114
+ },
1115
+ {
1116
+ key: "defaultMinLeadTimeHours",
1117
+ labelId: "settings.bookingsMinLeadHours",
1118
+ labelDefault: "Minimum Lead Time (Hours)",
1119
+ hintId: "settings.bookingsMinLeadHoursHint",
1120
+ hintDefault: "Minimum notice required before a slot can be booked.",
1121
+ min: 0,
1122
+ fallback: 2
1123
+ },
1124
+ {
1125
+ key: "defaultMaxAdvanceDays",
1126
+ labelId: "settings.bookingsMaxAdvanceDays",
1127
+ labelDefault: "Max Advance Horizon (Days)",
1128
+ hintId: "settings.bookingsMaxAdvanceDaysHint",
1129
+ hintDefault: "How far in advance visitors may schedule bookings.",
1130
+ min: 1,
1131
+ fallback: 90
1132
+ }
1133
+ ];
1134
+ const SettingCheckboxCard = ({ checked, onChange, label, hint }) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, background: "neutral100", hasRadius: true, style: SUB_BOX_STYLE, children: [
1135
+ /* @__PURE__ */ jsxRuntime.jsx(
1136
+ designSystem.Checkbox,
1137
+ {
1138
+ checked,
1139
+ onCheckedChange: (c) => onChange(Boolean(c)),
1140
+ children: label
1141
+ }
1142
+ ),
1143
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: hint }) })
1144
+ ] });
1145
+ const CompanionSuiteSettingsSection = ({
1146
+ t,
1147
+ mode,
1148
+ eventsSettings,
1149
+ bookingsSettings,
1150
+ onPatchEvents,
1151
+ onPatchBookings
1152
+ }) => {
1153
+ if (mode === "events") {
1154
+ if (!eventsSettings) {
1155
+ return /* @__PURE__ */ jsxRuntime.jsx(
1156
+ designSystem.Box,
1157
+ {
1158
+ padding: 5,
1159
+ background: "neutral0",
1160
+ hasRadius: true,
1161
+ shadow: "tableShadow",
1162
+ style: CARD_STYLE,
1163
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral600", children: t(
1164
+ "settings.eventsUnavailable",
1165
+ "Events & RSVPs plugin settings are loading or not installed."
1166
+ ) })
1167
+ }
1168
+ );
1169
+ }
1170
+ return /* @__PURE__ */ jsxRuntime.jsx(
1171
+ designSystem.Box,
1172
+ {
1173
+ padding: 5,
1174
+ background: "neutral0",
1175
+ hasRadius: true,
1176
+ shadow: "tableShadow",
1177
+ style: CARD_STYLE,
1178
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 5, children: [
1179
+ /* @__PURE__ */ jsxRuntime.jsxs(
1180
+ designSystem.Flex,
1181
+ {
1182
+ justifyContent: "space-between",
1183
+ alignItems: "center",
1184
+ wrap: "wrap",
1185
+ gap: 2,
1186
+ children: [
1187
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
1188
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", tag: "h2", children: t(
1189
+ "settings.eventsHeading",
1190
+ "Events, RSVP Capacity & Waitlist Automation"
1191
+ ) }),
1192
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t(
1193
+ "settings.eventsHint",
1194
+ "Configure default RSVP seat capacity, guest limits per registration, automatic FIFO waitlist promotion, and public Events iCal (.ics) feed."
1195
+ ) }) })
1196
+ ] }),
1197
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { active: true, children: [
1198
+ t("settings.badge.timezone", "Timezone"),
1199
+ ":",
1200
+ " ",
1201
+ eventsSettings.defaultTimezone || "UTC"
1202
+ ] })
1203
+ ]
1204
+ }
1205
+ ),
1206
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: GRID_2_COL, children: [
1207
+ /* @__PURE__ */ jsxRuntime.jsxs(
1208
+ designSystem.Field.Root,
1209
+ {
1210
+ hint: t(
1211
+ "settings.eventsDefaultCapacityHint",
1212
+ "Default seat capacity for newly created RSVP events."
1213
+ ),
1214
+ children: [
1215
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.eventsDefaultCapacity", "Default Event Capacity") }),
1216
+ /* @__PURE__ */ jsxRuntime.jsx(
1217
+ designSystem.NumberInput,
1218
+ {
1219
+ value: eventsSettings.defaultCapacity || 100,
1220
+ onValueChange: (val) => onPatchEvents({
1221
+ defaultCapacity: val && val >= 1 ? val : 100
1222
+ })
1223
+ }
1224
+ ),
1225
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
1226
+ ]
1227
+ }
1228
+ ),
1229
+ /* @__PURE__ */ jsxRuntime.jsxs(
1230
+ designSystem.Field.Root,
1231
+ {
1232
+ hint: t(
1233
+ "settings.eventsMaxGuestsHint",
1234
+ "Maximum seats a single RSVP submission may reserve."
1235
+ ),
1236
+ children: [
1237
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.eventsMaxGuests", "Max Guests per Registration") }),
1238
+ /* @__PURE__ */ jsxRuntime.jsx(
1239
+ designSystem.NumberInput,
1240
+ {
1241
+ value: eventsSettings.defaultMaxGuestsPerRegistration || 5,
1242
+ onValueChange: (val) => onPatchEvents({
1243
+ defaultMaxGuestsPerRegistration: val && val >= 1 ? val : 5
1244
+ })
1245
+ }
1246
+ ),
1247
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
1248
+ ]
1249
+ }
1250
+ )
1251
+ ] }),
1252
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: GRID_2_COL, children: [
1253
+ /* @__PURE__ */ jsxRuntime.jsx(
1254
+ SettingCheckboxCard,
1255
+ {
1256
+ checked: eventsSettings.waitlistEnabledByDefault,
1257
+ onChange: (waitlistEnabledByDefault) => onPatchEvents({ waitlistEnabledByDefault }),
1258
+ label: t(
1259
+ "settings.eventsWaitlist",
1260
+ "Enable Waitlist & Automatic Promotion"
1261
+ ),
1262
+ hint: t(
1263
+ "settings.eventsWaitlistHint",
1264
+ "Automatically promotes waitlisted attendees in FIFO order when a confirmed attendee cancels."
1265
+ )
1266
+ }
1267
+ ),
1268
+ /* @__PURE__ */ jsxRuntime.jsx(
1269
+ SettingCheckboxCard,
1270
+ {
1271
+ checked: eventsSettings.sendRsvpEmails,
1272
+ onChange: (sendRsvpEmails) => onPatchEvents({ sendRsvpEmails }),
1273
+ label: t(
1274
+ "settings.eventsSendEmails",
1275
+ "Send Confirmation & Waitlist Promotion Emails"
1276
+ ),
1277
+ hint: t(
1278
+ "settings.eventsSendEmailsHint",
1279
+ "Dispatches confirmation and waitlist promotion emails via the Strapi Email plugin."
1280
+ )
1281
+ }
1282
+ )
1283
+ ] }),
1284
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}),
1285
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: GRID_2_COL, children: [
1286
+ /* @__PURE__ */ jsxRuntime.jsxs(
1287
+ designSystem.Field.Root,
1288
+ {
1289
+ hint: t(
1290
+ "settings.defaultTimezoneHint",
1291
+ "IANA timezone identifier used for event recurrence and iCal exports."
1292
+ ),
1293
+ children: [
1294
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.defaultTimezone", "Events Timezone (IANA)") }),
1295
+ /* @__PURE__ */ jsxRuntime.jsx(
1296
+ designSystem.TextInput,
1297
+ {
1298
+ value: eventsSettings.defaultTimezone || "UTC",
1299
+ onChange: (e) => onPatchEvents({ defaultTimezone: e.target.value })
1300
+ }
1301
+ ),
1302
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
1303
+ ]
1304
+ }
1305
+ ),
1306
+ /* @__PURE__ */ jsxRuntime.jsxs(
1307
+ designSystem.Field.Root,
1308
+ {
1309
+ hint: t(
1310
+ "settings.eventsFeedTitleHint",
1311
+ "Calendar name shown when users subscribe in Google, Apple, or Outlook Calendar."
1312
+ ),
1313
+ children: [
1314
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.eventsFeedTitle", "Events iCal (.ics) Feed Title") }),
1315
+ /* @__PURE__ */ jsxRuntime.jsx(
1316
+ designSystem.TextInput,
1317
+ {
1318
+ value: eventsSettings.feedTitle || "Organization — Events Calendar",
1319
+ onChange: (e) => onPatchEvents({ feedTitle: e.target.value })
1320
+ }
1321
+ ),
1322
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
1323
+ ]
1324
+ }
1325
+ )
1326
+ ] })
1327
+ ] })
1328
+ }
1329
+ );
1330
+ }
1331
+ if (!bookingsSettings) {
1332
+ return /* @__PURE__ */ jsxRuntime.jsx(
1333
+ designSystem.Box,
1334
+ {
1335
+ padding: 5,
1336
+ background: "neutral0",
1337
+ hasRadius: true,
1338
+ shadow: "tableShadow",
1339
+ style: CARD_STYLE,
1340
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral600", children: t(
1341
+ "settings.bookingsUnavailable",
1342
+ "Bookings & Availability plugin settings are loading or not installed."
1343
+ ) })
1344
+ }
1345
+ );
1346
+ }
1347
+ return /* @__PURE__ */ jsxRuntime.jsx(
1348
+ designSystem.Box,
1349
+ {
1350
+ padding: 5,
1351
+ background: "neutral0",
1352
+ hasRadius: true,
1353
+ shadow: "tableShadow",
1354
+ style: CARD_STYLE,
1355
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 5, children: [
1356
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
1357
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", tag: "h2", children: t(
1358
+ "settings.bookingsHeading",
1359
+ "Bookings, Slot Duration & Approval Workflow"
1360
+ ) }),
1361
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t(
1362
+ "settings.bookingsHint",
1363
+ "Configure default appointment slot durations, capacity limits, preparation buffers, lead times, and manual approval rules."
1364
+ ) }) })
1365
+ ] }),
1366
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: GRID_3_COL, children: BOOKING_NUMBER_FIELDS.map((field) => /* @__PURE__ */ jsxRuntime.jsxs(
1367
+ designSystem.Field.Root,
1368
+ {
1369
+ hint: t(field.hintId, field.hintDefault),
1370
+ children: [
1371
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t(field.labelId, field.labelDefault) }),
1372
+ /* @__PURE__ */ jsxRuntime.jsx(
1373
+ designSystem.NumberInput,
1374
+ {
1375
+ value: bookingsSettings[field.key],
1376
+ onValueChange: (v) => onPatchBookings({
1377
+ [field.key]: Math.max(
1378
+ field.min,
1379
+ Number(v ?? field.fallback)
1380
+ )
1381
+ })
1382
+ }
1383
+ ),
1384
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
1385
+ ]
1386
+ },
1387
+ field.key
1388
+ )) }),
1389
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}),
1390
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: GRID_2_COL, children: [
1391
+ /* @__PURE__ */ jsxRuntime.jsx(
1392
+ SettingCheckboxCard,
1393
+ {
1394
+ checked: bookingsSettings.defaultRequiresApproval,
1395
+ onChange: (defaultRequiresApproval) => onPatchBookings({ defaultRequiresApproval }),
1396
+ label: t(
1397
+ "settings.bookingsRequiresApproval",
1398
+ "Require Manual Admin Approval"
1399
+ ),
1400
+ hint: t(
1401
+ "settings.bookingsRequiresApprovalHint",
1402
+ "Places new visitor reservations in pending status until confirmed by staff."
1403
+ )
1404
+ }
1405
+ ),
1406
+ /* @__PURE__ */ jsxRuntime.jsx(
1407
+ SettingCheckboxCard,
1408
+ {
1409
+ checked: bookingsSettings.sendEmailNotifications,
1410
+ onChange: (sendEmailNotifications) => onPatchBookings({ sendEmailNotifications }),
1411
+ label: t(
1412
+ "settings.bookingsSendEmails",
1413
+ "Send Confirmation & Status Update Emails"
1414
+ ),
1415
+ hint: t(
1416
+ "settings.bookingsSendEmailsHint",
1417
+ "Automatically notifies visitors when their booking is created, approved, or rescheduled."
1418
+ )
1419
+ }
1420
+ )
1421
+ ] })
1422
+ ] })
1423
+ }
1424
+ );
1425
+ };
1426
+ const SecondaryCalendarsSection = ({
1427
+ t,
1428
+ secondaryCalendars,
1429
+ onAddOrUpdateCalendar,
1430
+ onToggleCalendarEnabled,
1431
+ onRemoveCalendar
1432
+ }) => {
1433
+ const [isFormOpen, setIsFormOpen] = react.useState(true);
1434
+ const [newCalPreset, setNewCalPreset] = react.useState("islamic-umalqura");
1435
+ const [newCalId, setNewCalId] = react.useState("hijri");
1436
+ const [newCalLabel, setNewCalLabel] = react.useState("Hijri (Umm al-Qura)");
1437
+ const [newCalLocale, setNewCalLocale] = react.useState("local");
1438
+ const [newCalOverrideField, setNewCalOverrideField] = react.useState("hijriDate");
1439
+ const [newCalDayOffset, setNewCalDayOffset] = react.useState(0);
1440
+ const handleEditCalendarSystem = (cal) => {
1441
+ setNewCalPreset(cal.intlCalendar || "islamic-umalqura");
1442
+ setNewCalId(cal.id || "hijri");
1443
+ setNewCalLabel(cal.label || "Hijri (Umm al-Qura)");
1444
+ setNewCalLocale(cal.locale || "local");
1445
+ setNewCalOverrideField(cal.overrideField || "hijriDate");
1446
+ setNewCalDayOffset(cal.dayOffset ?? 0);
1447
+ setIsFormOpen(true);
1448
+ };
1449
+ const handleAddCalendarSystem = () => {
1450
+ if (!newCalId.trim() || !newCalPreset) return;
1451
+ const cleanId = newCalId.trim().toLowerCase().replace(/[^a-z0-9-_]/g, "");
1452
+ if (!cleanId) return;
1453
+ const nextEntry = {
1454
+ id: cleanId,
1455
+ label: newCalLabel.trim() || cleanId,
1456
+ intlCalendar: newCalPreset,
1457
+ locale: newCalLocale && newCalLocale !== "local" ? newCalLocale.trim() : void 0,
1458
+ dayOffset: newCalDayOffset || 0,
1459
+ overrideField: newCalOverrideField.trim() || void 0,
1460
+ enabled: true
1461
+ };
1462
+ onAddOrUpdateCalendar(nextEntry);
1463
+ };
1464
+ return /* @__PURE__ */ jsxRuntime.jsx(
1465
+ designSystem.Box,
1466
+ {
1467
+ padding: 5,
1468
+ background: "neutral0",
1469
+ hasRadius: true,
1470
+ shadow: "tableShadow",
1471
+ style: { border: "1px solid rgba(128, 128, 128, 0.22)" },
1472
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
1473
+ /* @__PURE__ */ jsxRuntime.jsxs(
1474
+ designSystem.Flex,
1475
+ {
1476
+ justifyContent: "space-between",
1477
+ alignItems: "flex-start",
1478
+ wrap: "wrap",
1479
+ gap: 3,
1480
+ children: [
1481
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: 1, minWidth: 280 }, children: [
1482
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", tag: "h2", children: t(
1483
+ "settings.section.secondaryCalendars",
1484
+ "Secondary & Alternative Calendar Systems (Intl / Custom)"
1485
+ ) }),
1486
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t(
1487
+ "settings.secondaryCalendarsHint",
1488
+ "Display optional secondary dates (such as Hijri Umm al-Qura) alongside Gregorian dates in day cells. Supports local language or Arabic script and moon-sighting day offsets (-2 to +2 days)."
1489
+ ) }) })
1490
+ ] }),
1491
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
1492
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { active: true, children: [
1493
+ secondaryCalendars.length,
1494
+ " ",
1495
+ t("settings.configuredCount", "Configured")
1496
+ ] }),
1497
+ /* @__PURE__ */ jsxRuntime.jsx(
1498
+ designSystem.Button,
1499
+ {
1500
+ variant: isFormOpen ? "tertiary" : "secondary",
1501
+ size: "S",
1502
+ onClick: () => setIsFormOpen((prev) => !prev),
1503
+ children: isFormOpen ? t("common.hideForm", "Hide Form") : `+ ${t("settings.addCalendar", "Add Calendar System")}`
1504
+ }
1505
+ )
1506
+ ] })
1507
+ ]
1508
+ }
1509
+ ),
1510
+ secondaryCalendars.map((cal) => /* @__PURE__ */ jsxRuntime.jsx(
1511
+ designSystem.Box,
1512
+ {
1513
+ padding: 4,
1514
+ background: "neutral100",
1515
+ hasRadius: true,
1516
+ style: {
1517
+ border: "1px solid rgba(128, 128, 128, 0.18)",
1518
+ borderLeft: "4px solid #0284C7"
1519
+ },
1520
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1521
+ designSystem.Flex,
1522
+ {
1523
+ justifyContent: "space-between",
1524
+ alignItems: "center",
1525
+ wrap: "wrap",
1526
+ gap: 3,
1527
+ children: [
1528
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
1529
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: cal.label }),
1530
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: cal.intlCalendar }),
1531
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: cal.locale === "ar" || cal.locale === "ar-SA" ? t(
1532
+ "settings.badge.arabicScript",
1533
+ "Arabic Script (العربية)"
1534
+ ) : t("settings.badge.localLanguage", "Local Language") }),
1535
+ cal.overrideField && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "neutral200", textColor: "neutral800", children: [
1536
+ t("settings.badge.overrideField", "Override field"),
1537
+ ":",
1538
+ " ",
1539
+ cal.overrideField
1540
+ ] }),
1541
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "warning100", textColor: "warning700", children: [
1542
+ t("settings.badge.offset", "Offset"),
1543
+ ":",
1544
+ " ",
1545
+ (cal.dayOffset ?? 0) > 0 ? `+${cal.dayOffset}` : cal.dayOffset ?? 0,
1546
+ "d"
1547
+ ] })
1548
+ ] }),
1549
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", children: [
1550
+ /* @__PURE__ */ jsxRuntime.jsx(
1551
+ designSystem.Checkbox,
1552
+ {
1553
+ checked: cal.enabled,
1554
+ onCheckedChange: (checked) => onToggleCalendarEnabled(cal.id, Boolean(checked)),
1555
+ children: t("settings.calendarEnabled", "Enabled")
1556
+ }
1557
+ ),
1558
+ /* @__PURE__ */ jsxRuntime.jsx(
1559
+ designSystem.Button,
1560
+ {
1561
+ variant: "tertiary",
1562
+ size: "S",
1563
+ onClick: () => handleEditCalendarSystem(cal),
1564
+ children: t("common.edit", "Edit")
1565
+ }
1566
+ ),
1567
+ /* @__PURE__ */ jsxRuntime.jsx(
1568
+ designSystem.Button,
1569
+ {
1570
+ variant: "danger-light",
1571
+ size: "S",
1572
+ onClick: () => onRemoveCalendar(cal.id),
1573
+ children: t("common.remove", "Remove")
1574
+ }
1575
+ )
1576
+ ] })
1577
+ ]
1578
+ }
1579
+ )
1580
+ },
1581
+ cal.id
1582
+ )),
1583
+ isFormOpen && /* @__PURE__ */ jsxRuntime.jsx(
1584
+ designSystem.Box,
1585
+ {
1586
+ padding: 5,
1587
+ background: "neutral100",
1588
+ hasRadius: true,
1589
+ style: { border: "1px solid rgba(128, 128, 128, 0.18)" },
1590
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
1591
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral700", children: t(
1592
+ "settings.configureCalendarTitle",
1593
+ "Configure Secondary Calendar System"
1594
+ ) }),
1595
+ /* @__PURE__ */ jsxRuntime.jsxs(
1596
+ "div",
1597
+ {
1598
+ style: {
1599
+ display: "grid",
1600
+ gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
1601
+ gap: 16
1602
+ },
1603
+ children: [
1604
+ /* @__PURE__ */ jsxRuntime.jsxs(
1605
+ designSystem.Field.Root,
1606
+ {
1607
+ hint: t(
1608
+ "settings.calendarPresetHint",
1609
+ "Unicode CLDR calendar identifier used by Intl.DateTimeFormat."
1610
+ ),
1611
+ children: [
1612
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.calendarPreset", "Calendar System (CLDR)") }),
1613
+ /* @__PURE__ */ jsxRuntime.jsx(
1614
+ designSystem.SingleSelect,
1615
+ {
1616
+ placeholder: t(
1617
+ "settings.calendarPreset.placeholder",
1618
+ "Select CLDR calendar system"
1619
+ ),
1620
+ value: newCalPreset || "islamic-umalqura",
1621
+ onChange: (val) => {
1622
+ const strVal = String(val);
1623
+ setNewCalPreset(strVal);
1624
+ const match = index.SUPPORTED_INTL_CALENDARS.find(
1625
+ (c) => c.intlCalendar === strVal
1626
+ );
1627
+ if (match) {
1628
+ setNewCalId(match.id.split("-")[0]);
1629
+ setNewCalLabel(match.defaultLabel);
1630
+ }
1631
+ },
1632
+ children: index.SUPPORTED_INTL_CALENDARS.filter(
1633
+ (c) => c.id !== "gregory"
1634
+ ).map((cal) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.SingleSelectOption, { value: cal.intlCalendar, children: [
1635
+ cal.defaultLabel,
1636
+ " (",
1637
+ cal.intlCalendar,
1638
+ ")"
1639
+ ] }, cal.id))
1640
+ }
1641
+ ),
1642
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
1643
+ ]
1644
+ }
1645
+ ),
1646
+ /* @__PURE__ */ jsxRuntime.jsxs(
1647
+ designSystem.Field.Root,
1648
+ {
1649
+ hint: t(
1650
+ "settings.calendarIdHint",
1651
+ "Unique slug key for this calendar overlay."
1652
+ ),
1653
+ children: [
1654
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.calendarId", "ID Key") }),
1655
+ /* @__PURE__ */ jsxRuntime.jsx(
1656
+ designSystem.TextInput,
1657
+ {
1658
+ value: newCalId,
1659
+ onChange: (e) => setNewCalId(e.target.value),
1660
+ placeholder: t(
1661
+ "settings.calendarId.placeholder",
1662
+ "e.g., hijri"
1663
+ )
1664
+ }
1665
+ ),
1666
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
1667
+ ]
1668
+ }
1669
+ ),
1670
+ /* @__PURE__ */ jsxRuntime.jsxs(
1671
+ designSystem.Field.Root,
1672
+ {
1673
+ hint: t(
1674
+ "settings.calendarLabelHint",
1675
+ "Badge label displayed in calendar headers and tooltips."
1676
+ ),
1677
+ children: [
1678
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.calendarLabel", "Display Label") }),
1679
+ /* @__PURE__ */ jsxRuntime.jsx(
1680
+ designSystem.TextInput,
1681
+ {
1682
+ value: newCalLabel,
1683
+ onChange: (e) => setNewCalLabel(e.target.value),
1684
+ placeholder: t(
1685
+ "settings.calendarLabel.placeholder",
1686
+ "e.g., Hijri (Umm al-Qura)"
1687
+ )
1688
+ }
1689
+ ),
1690
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
1691
+ ]
1692
+ }
1693
+ ),
1694
+ /* @__PURE__ */ jsxRuntime.jsxs(
1695
+ designSystem.Field.Root,
1696
+ {
1697
+ hint: t(
1698
+ "settings.calendarScriptHint",
1699
+ "Locale used to render month names and numerals."
1700
+ ),
1701
+ children: [
1702
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.calendarScript", "Language / Script Override") }),
1703
+ /* @__PURE__ */ jsxRuntime.jsxs(
1704
+ designSystem.SingleSelect,
1705
+ {
1706
+ placeholder: t(
1707
+ "settings.calendarScript.placeholder",
1708
+ "Select script override"
1709
+ ),
1710
+ value: newCalLocale || "local",
1711
+ onChange: (val) => {
1712
+ setNewCalLocale(String(val));
1713
+ },
1714
+ children: [
1715
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "local", children: t(
1716
+ "settings.calendarScript.local",
1717
+ "Follow Calendar Language (Local)"
1718
+ ) }),
1719
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "ar-SA", children: t(
1720
+ "settings.calendarScript.ar",
1721
+ "Arabic Script — العربية (ar-SA)"
1722
+ ) }),
1723
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "es", children: t("settings.calendarScript.es", "Español (es)") }),
1724
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "en", children: t("settings.calendarScript.en", "English (en)") })
1725
+ ]
1726
+ }
1727
+ ),
1728
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
1729
+ ]
1730
+ }
1731
+ ),
1732
+ /* @__PURE__ */ jsxRuntime.jsxs(
1733
+ designSystem.Field.Root,
1734
+ {
1735
+ hint: t(
1736
+ "settings.overrideFieldHint",
1737
+ "Optional entry field that overrides calculated dates."
1738
+ ),
1739
+ children: [
1740
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.overrideField", "Document Override Field") }),
1741
+ /* @__PURE__ */ jsxRuntime.jsx(
1742
+ designSystem.TextInput,
1743
+ {
1744
+ value: newCalOverrideField,
1745
+ onChange: (e) => setNewCalOverrideField(e.target.value),
1746
+ placeholder: t(
1747
+ "settings.overrideField.placeholder",
1748
+ "e.g., hijriDate"
1749
+ )
1750
+ }
1751
+ ),
1752
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
1753
+ ]
1754
+ }
1755
+ ),
1756
+ /* @__PURE__ */ jsxRuntime.jsxs(
1757
+ designSystem.Field.Root,
1758
+ {
1759
+ hint: t(
1760
+ "settings.dayOffsetHint",
1761
+ "Moon-sighting adjustment in days (-2 to +2)."
1762
+ ),
1763
+ children: [
1764
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.dayOffset", "Lunar Day Offset (-2 to +2)") }),
1765
+ /* @__PURE__ */ jsxRuntime.jsx(
1766
+ designSystem.NumberInput,
1767
+ {
1768
+ placeholder: t("settings.dayOffset.placeholder", "e.g., 0"),
1769
+ value: newCalDayOffset,
1770
+ onValueChange: (val) => setNewCalDayOffset(typeof val === "number" ? val : 0)
1771
+ }
1772
+ ),
1773
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
1774
+ ]
1775
+ }
1776
+ )
1777
+ ]
1778
+ }
1779
+ ),
1780
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Button, { variant: "default", onClick: handleAddCalendarSystem, children: [
1781
+ "+ ",
1782
+ t("settings.saveCalendar", "Save Calendar System")
1783
+ ] }) })
1784
+ ] })
1785
+ }
1786
+ )
1787
+ ] })
1788
+ }
1789
+ );
1790
+ };
1791
+ const SettingsPage = () => {
1792
+ const { formatMessage } = reactIntl.useIntl();
1793
+ const { get, put, post } = admin.useFetchClient();
1794
+ const t = (id, defaultMessage) => formatMessage({ id: `${index.PLUGIN_ID}.${id}`, defaultMessage });
1795
+ const [settings, setSettings] = react.useState(null);
1796
+ const [contentTypes, setContentTypes] = react.useState([]);
1797
+ const [eventsSettings, setEventsSettings] = react.useState(null);
1798
+ const [bookingsSettings, setBookingsSettings] = react.useState(null);
1799
+ const [saving, setSaving] = react.useState(false);
1800
+ const [savedBanner, setSavedBanner] = react.useState(null);
1801
+ const [bannerIsError, setBannerIsError] = react.useState(false);
1802
+ react.useEffect(() => {
1803
+ Promise.all([
1804
+ get(`/${index.PLUGIN_ID}/settings`),
1805
+ get(`/${index.PLUGIN_ID}/content-types`),
1806
+ get(
1807
+ "/events/settings"
1808
+ ).catch(() => null),
1809
+ get(
1810
+ "/bookings/settings"
1811
+ ).catch(() => null)
1812
+ ]).then(([settingsRes, ctRes, eventsRes, bookingsRes]) => {
1813
+ if (settingsRes?.data?.data) {
1814
+ setSettings(settingsRes.data.data);
1815
+ }
1816
+ if (Array.isArray(ctRes?.data?.data)) {
1817
+ setContentTypes(ctRes.data.data);
1818
+ }
1819
+ if (eventsRes?.data?.data) {
1820
+ setEventsSettings(eventsRes.data.data);
1821
+ }
1822
+ if (bookingsRes?.data?.data) {
1823
+ setBookingsSettings(bookingsRes.data.data);
1824
+ }
1825
+ }).catch(() => {
1826
+ });
1827
+ }, [get]);
1828
+ const handleSave = async () => {
1829
+ if (!settings) return;
1830
+ setSaving(true);
1831
+ setSavedBanner(null);
1832
+ setBannerIsError(false);
1833
+ try {
1834
+ let companionFailed = false;
1835
+ const [res, eventsRes, bookingsRes] = await Promise.all([
1836
+ put(`/${index.PLUGIN_ID}/settings`, settings),
1837
+ eventsSettings ? put(
1838
+ "/events/settings",
1839
+ eventsSettings
1840
+ ).catch(() => {
1841
+ companionFailed = true;
1842
+ return null;
1843
+ }) : Promise.resolve(null),
1844
+ bookingsSettings ? put(
1845
+ "/bookings/settings",
1846
+ bookingsSettings
1847
+ ).catch(() => {
1848
+ companionFailed = true;
1849
+ return null;
1850
+ }) : Promise.resolve(null)
1851
+ ]);
1852
+ if (res?.data?.data) {
1853
+ setSettings(res.data.data);
1854
+ }
1855
+ if (eventsRes?.data?.data) {
1856
+ setEventsSettings(eventsRes.data.data);
1857
+ }
1858
+ if (bookingsRes?.data?.data) {
1859
+ setBookingsSettings(bookingsRes.data.data);
1860
+ }
1861
+ if (companionFailed) {
1862
+ setBannerIsError(true);
1863
+ setSavedBanner(
1864
+ t(
1865
+ "settings.savedPartial",
1866
+ "Calendar settings saved, but companion plugin settings could not be updated."
1867
+ )
1868
+ );
1869
+ } else {
1870
+ setSavedBanner(
1871
+ t(
1872
+ "settings.saved",
1873
+ "Calendar, Events, and Bookings settings saved successfully."
1874
+ )
1875
+ );
1876
+ }
1877
+ } catch {
1878
+ setBannerIsError(true);
1879
+ setSavedBanner(t("settings.error", "Could not save settings."));
1880
+ } finally {
1881
+ setSaving(false);
1882
+ }
1883
+ };
1884
+ const handleResetSettings = async () => {
1885
+ setSaving(true);
1886
+ setBannerIsError(false);
1887
+ try {
1888
+ const res = await post(
1889
+ `/${index.PLUGIN_ID}/clear-settings`,
1890
+ {}
1891
+ );
1892
+ if (res?.data?.data) {
1893
+ setSettings(res.data.data);
1894
+ }
1895
+ setSavedBanner(t("settings.resetSuccess", "Settings reset to defaults."));
1896
+ } catch {
1897
+ setBannerIsError(true);
1898
+ setSavedBanner(t("settings.error", "Could not reset settings."));
1899
+ } finally {
1900
+ setSaving(false);
1901
+ }
1902
+ };
1903
+ const handleAddOrUpdateSource = (nextSource) => {
1904
+ if (!settings) return;
1905
+ const existing = settings.sources ?? [];
1906
+ const updated = existing.some(
1907
+ (s) => s.id === nextSource.id || s.uid === nextSource.uid
1908
+ ) ? existing.map(
1909
+ (s) => s.id === nextSource.id || s.uid === nextSource.uid ? nextSource : s
1910
+ ) : [...existing, nextSource];
1911
+ setSettings({
1912
+ ...settings,
1913
+ sources: updated
1914
+ });
1915
+ };
1916
+ const toggleSourceEnabled = (sourceId, enabled) => {
1917
+ if (!settings) return;
1918
+ setSettings({
1919
+ ...settings,
1920
+ sources: settings.sources.map(
1921
+ (src) => src.id === sourceId ? { ...src, enabled } : src
1922
+ )
1923
+ });
1924
+ };
1925
+ const removeSource = (sourceId) => {
1926
+ if (!settings) return;
1927
+ setSettings({
1928
+ ...settings,
1929
+ sources: settings.sources.filter((src) => src.id !== sourceId)
1930
+ });
1931
+ };
1932
+ const handleAddOrUpdateCalendar = (nextEntry) => {
1933
+ if (!settings) return;
1934
+ const existing = settings.secondaryCalendars ?? [];
1935
+ const nextList = existing.some((c) => c.id === nextEntry.id) ? existing.map((c) => c.id === nextEntry.id ? nextEntry : c) : [...existing, nextEntry];
1936
+ setSettings({
1937
+ ...settings,
1938
+ secondaryCalendars: nextList
1939
+ });
1940
+ };
1941
+ const toggleCalendarEnabled = (calId, enabled) => {
1942
+ if (!settings) return;
1943
+ setSettings({
1944
+ ...settings,
1945
+ secondaryCalendars: (settings.secondaryCalendars ?? []).map(
1946
+ (cal) => cal.id === calId ? { ...cal, enabled } : cal
1947
+ )
1948
+ });
1949
+ };
1950
+ const removeCalendarSystem = (calId) => {
1951
+ if (!settings) return;
1952
+ setSettings({
1953
+ ...settings,
1954
+ secondaryCalendars: (settings.secondaryCalendars ?? []).filter(
1955
+ (cal) => cal.id !== calId
1956
+ )
1957
+ });
1958
+ };
1959
+ if (!settings) {
1960
+ return /* @__PURE__ */ jsxRuntime.jsx(admin.Layouts.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(admin.Layouts.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 6, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: t("settings.loading", "Loading Calendar settings...") }) }) }) });
1961
+ }
1962
+ return /* @__PURE__ */ jsxRuntime.jsxs(admin.Layouts.Root, { children: [
1963
+ /* @__PURE__ */ jsxRuntime.jsx(
1964
+ admin.Layouts.Header,
1965
+ {
1966
+ title: t("settings.title", "Calendar, Events & Bookings Settings"),
1967
+ subtitle: t(
1968
+ "settings.subtitle",
1969
+ "Configure visual themes, primary local language, Arabic/Hijri calendar overlay, collection sources, RSVP event rules, and booking slot policies."
1970
+ ),
1971
+ primaryAction: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
1972
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", onClick: handleResetSettings, children: t("settings.reset", "Reset Defaults") }),
1973
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "default", loading: saving, onClick: handleSave, children: t("common.save", "Save Settings") })
1974
+ ] })
1975
+ }
1976
+ ),
1977
+ /* @__PURE__ */ jsxRuntime.jsx(admin.Layouts.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
1978
+ savedBanner && /* @__PURE__ */ jsxRuntime.jsx(
1979
+ designSystem.Box,
1980
+ {
1981
+ padding: 3,
1982
+ background: bannerIsError ? "danger100" : "success100",
1983
+ hasRadius: true,
1984
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1985
+ designSystem.Typography,
1986
+ {
1987
+ variant: "omega",
1988
+ fontWeight: "bold",
1989
+ textColor: bannerIsError ? "danger700" : "success700",
1990
+ children: savedBanner
1991
+ }
1992
+ )
1993
+ }
1994
+ ),
1995
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs.Root, { defaultValue: "theme", children: [
1996
+ /* @__PURE__ */ jsxRuntime.jsxs(
1997
+ designSystem.Tabs.List,
1998
+ {
1999
+ "aria-label": t(
2000
+ "settings.title",
2001
+ "Calendar, Events & Bookings Settings"
2002
+ ),
2003
+ children: [
2004
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "theme", children: t("settings.tab.theme", "Theme & Appearance") }),
2005
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "general", children: t("settings.tab.general", "General & Views") }),
2006
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs.Trigger, { value: "sources", children: [
2007
+ t("settings.tab.sources", "Collection Sources"),
2008
+ " (",
2009
+ settings.sources?.length ?? 0,
2010
+ ")"
2011
+ ] }),
2012
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs.Trigger, { value: "secondary", children: [
2013
+ t("settings.tab.secondaryCalendars", "Secondary Calendars"),
2014
+ " (",
2015
+ settings.secondaryCalendars?.length ?? 0,
2016
+ ")"
2017
+ ] }),
2018
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "events", children: t("settings.tab.events", "Events & RSVPs") }),
2019
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "bookings", children: t("settings.tab.bookings", "Bookings & Availability") })
2020
+ ]
2021
+ }
2022
+ ),
2023
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: "theme", children: /* @__PURE__ */ jsxRuntime.jsx(
2024
+ CalendarViewsSection,
2025
+ {
2026
+ mode: "theme",
2027
+ t,
2028
+ settings,
2029
+ onPatchSettings: (patch) => setSettings({ ...settings, ...patch })
2030
+ }
2031
+ ) }),
2032
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: "general", children: /* @__PURE__ */ jsxRuntime.jsx(
2033
+ CalendarViewsSection,
2034
+ {
2035
+ mode: "general",
2036
+ t,
2037
+ settings,
2038
+ onPatchSettings: (patch) => setSettings({ ...settings, ...patch })
2039
+ }
2040
+ ) }),
2041
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: "sources", children: /* @__PURE__ */ jsxRuntime.jsx(
2042
+ CollectionSourcesSection,
2043
+ {
2044
+ t,
2045
+ sources: settings.sources,
2046
+ contentTypes,
2047
+ onAddOrUpdateSource: handleAddOrUpdateSource,
2048
+ onToggleSourceEnabled: toggleSourceEnabled,
2049
+ onRemoveSource: removeSource
2050
+ }
2051
+ ) }),
2052
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: "secondary", children: /* @__PURE__ */ jsxRuntime.jsx(
2053
+ SecondaryCalendarsSection,
2054
+ {
2055
+ t,
2056
+ secondaryCalendars: settings.secondaryCalendars ?? [],
2057
+ onAddOrUpdateCalendar: handleAddOrUpdateCalendar,
2058
+ onToggleCalendarEnabled: toggleCalendarEnabled,
2059
+ onRemoveCalendar: removeCalendarSystem
2060
+ }
2061
+ ) }),
2062
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: "events", children: /* @__PURE__ */ jsxRuntime.jsx(
2063
+ CompanionSuiteSettingsSection,
2064
+ {
2065
+ mode: "events",
2066
+ t,
2067
+ eventsSettings,
2068
+ bookingsSettings,
2069
+ onPatchEvents: (patch) => eventsSettings && setEventsSettings({ ...eventsSettings, ...patch }),
2070
+ onPatchBookings: (patch) => bookingsSettings && setBookingsSettings({ ...bookingsSettings, ...patch })
2071
+ }
2072
+ ) }),
2073
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: "bookings", children: /* @__PURE__ */ jsxRuntime.jsx(
2074
+ CompanionSuiteSettingsSection,
2075
+ {
2076
+ mode: "bookings",
2077
+ t,
2078
+ eventsSettings,
2079
+ bookingsSettings,
2080
+ onPatchEvents: (patch) => eventsSettings && setEventsSettings({ ...eventsSettings, ...patch }),
2081
+ onPatchBookings: (patch) => bookingsSettings && setBookingsSettings({ ...bookingsSettings, ...patch })
2082
+ }
2083
+ ) })
2084
+ ] })
2085
+ ] }) })
2086
+ ] });
2087
+ };
2088
+ exports.SettingsPage = SettingsPage;