@vicacha-devs/strapi-plugin-bookings 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 (82) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +23 -2
  3. package/dist/admin/App-BrB9n7EO.mjs +371 -0
  4. package/dist/admin/App-ZlqOsILc.js +371 -0
  5. package/dist/admin/SettingsPage-LR6F2vyx.js +410 -0
  6. package/dist/admin/SettingsPage-Xas3gvn4.mjs +410 -0
  7. package/dist/admin/ar-9_2mxMp2.js +339 -0
  8. package/dist/admin/ar-CrM4yxqb.mjs +339 -0
  9. package/dist/admin/de-D3NbAP6M.mjs +339 -0
  10. package/dist/admin/de-DBaO-D7Z.js +339 -0
  11. package/dist/admin/en-Cu-rn_xM.mjs +339 -0
  12. package/dist/admin/en-DAoI7qkk.js +339 -0
  13. package/dist/admin/es-DUqsu82s.js +339 -0
  14. package/dist/admin/es-Y0zfya4P.mjs +339 -0
  15. package/dist/admin/fr-BkLta_o8.js +339 -0
  16. package/dist/admin/fr-BrzKRqet.mjs +339 -0
  17. package/dist/admin/getTranslation-CZAJyMSt.mjs +5 -0
  18. package/dist/admin/getTranslation-Cd0_4UtW.js +4 -0
  19. package/dist/admin/id-BZz53ViW.mjs +339 -0
  20. package/dist/admin/id-ByxSagzq.js +339 -0
  21. package/dist/admin/index.js +1497 -0
  22. package/dist/admin/index.mjs +1492 -0
  23. package/dist/admin/pt-BSCDUkdd.js +339 -0
  24. package/dist/admin/pt-DUfISuZf.mjs +339 -0
  25. package/dist/admin/src/components/Initializer.d.ts +6 -0
  26. package/dist/admin/src/components/PluginIcon.d.ts +3 -0
  27. package/dist/admin/src/components/RRuleInput.d.ts +3 -0
  28. package/dist/admin/src/components/bookings/BookingSidePanel.d.ts +10 -0
  29. package/dist/admin/src/components/bookings/BookingsGridCanvas.d.ts +20 -0
  30. package/dist/admin/src/components/bookings/QuickCreateBookingModal.d.ts +11 -0
  31. package/dist/admin/src/index.d.ts +24 -0
  32. package/dist/admin/src/pages/App.d.ts +3 -0
  33. package/dist/admin/src/pages/CalendarPage.d.ts +3 -0
  34. package/dist/admin/src/pages/SettingsPage.d.ts +3 -0
  35. package/dist/admin/src/permissions.d.ts +29 -0
  36. package/dist/admin/src/pluginId.d.ts +1 -0
  37. package/dist/admin/src/translations/cmLabels.d.ts +1 -0
  38. package/dist/admin/src/translations/cmPlaceholders.d.ts +1 -0
  39. package/dist/admin/src/utils/getTranslation.d.ts +2 -0
  40. package/dist/admin/tr-_nhc9hk6.mjs +339 -0
  41. package/dist/admin/tr-r17l5F2K.js +339 -0
  42. package/dist/admin/ur-8edBd0Qo.mjs +339 -0
  43. package/dist/admin/ur-Dw_TAOZ3.js +339 -0
  44. package/dist/admin/zh-CeR0swEm.mjs +339 -0
  45. package/dist/admin/zh-D0z5sxxN.js +339 -0
  46. package/dist/server/index.js +3547 -0
  47. package/dist/server/index.mjs +3545 -0
  48. package/dist/server/src/bootstrap.d.ts +6 -0
  49. package/dist/server/src/config/index.d.ts +6 -0
  50. package/dist/server/src/content-types/booking/schema.json.d.ts +117 -0
  51. package/dist/server/src/content-types/index.d.ts +265 -0
  52. package/dist/server/src/content-types/resource/schema.json.d.ts +147 -0
  53. package/dist/server/src/controllers/admin.d.ts +30 -0
  54. package/dist/server/src/controllers/content-api.d.ts +32 -0
  55. package/dist/server/src/controllers/index.d.ts +28 -0
  56. package/dist/server/src/destroy.d.ts +5 -0
  57. package/dist/server/src/errors.d.ts +18 -0
  58. package/dist/server/src/index.d.ts +347 -0
  59. package/dist/server/src/register.d.ts +5 -0
  60. package/dist/server/src/routes/admin.d.ts +14 -0
  61. package/dist/server/src/routes/content-api.d.ts +9 -0
  62. package/dist/server/src/routes/index.d.ts +30 -0
  63. package/dist/server/src/services/availability.d.ts +8 -0
  64. package/dist/server/src/services/index.d.ts +12 -0
  65. package/dist/server/src/services/reservation.d.ts +6 -0
  66. package/dist/server/src/services/reservationHelpers.d.ts +41 -0
  67. package/dist/server/src/services/reservationHostCapacity.d.ts +16 -0
  68. package/dist/server/src/services/reservationMutations.d.ts +32 -0
  69. package/dist/server/src/services/reservationSources.d.ts +4 -0
  70. package/dist/server/src/services/reservationValidators.d.ts +27 -0
  71. package/dist/server/src/services/settings.d.ts +8 -0
  72. package/dist/server/src/types.d.ts +99 -0
  73. package/dist/shared/calendarSystems.d.ts +3 -0
  74. package/dist/shared/icalAndCsv.d.ts +16 -0
  75. package/dist/shared/index.d.ts +6 -0
  76. package/dist/shared/index.js +752 -0
  77. package/dist/shared/index.mjs +729 -0
  78. package/dist/shared/pluginId.d.ts +2 -0
  79. package/dist/shared/slotEngine.d.ts +19 -0
  80. package/dist/shared/slotTimezone.d.ts +45 -0
  81. package/dist/shared/types.d.ts +245 -0
  82. package/package.json +111 -3
@@ -0,0 +1,410 @@
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.js");
9
+ const getTranslation = require("./getTranslation-Cd0_4UtW.js");
10
+ const SLOT_NUMBER_FIELDS = [
11
+ {
12
+ name: "defaultSlotDurationMinutes",
13
+ labelId: "settings.defaultSlotDurationMinutes",
14
+ labelDefault: "Slot Duration (Minutes)",
15
+ hintId: "settings.defaultSlotDurationMinutesHint",
16
+ hintDefault: "Standard length of each bookable appointment slot.",
17
+ placeholderId: "settings.defaultSlotDurationMinutes.placeholder",
18
+ placeholderDefault: "e.g., 60",
19
+ min: 5,
20
+ fallback: 60
21
+ },
22
+ {
23
+ name: "defaultCapacityPerSlot",
24
+ labelId: "settings.defaultCapacityPerSlot",
25
+ labelDefault: "Default Capacity Per Slot",
26
+ hintId: "settings.defaultCapacityPerSlotHint",
27
+ hintDefault: "Concurrent reservations allowed per time slot.",
28
+ placeholderId: "settings.defaultCapacityPerSlot.placeholder",
29
+ placeholderDefault: "e.g., 1",
30
+ min: 1,
31
+ fallback: 1
32
+ },
33
+ {
34
+ name: "defaultBufferBeforeMinutes",
35
+ labelId: "settings.defaultBufferBeforeMinutes",
36
+ labelDefault: "Buffer Before (Minutes)",
37
+ hintId: "settings.defaultBufferBeforeMinutesHint",
38
+ hintDefault: "Preparation gap blocked before each booking starts.",
39
+ placeholderId: "settings.defaultBufferBeforeMinutes.placeholder",
40
+ placeholderDefault: "e.g., 0",
41
+ min: 0,
42
+ fallback: 0
43
+ },
44
+ {
45
+ name: "defaultBufferAfterMinutes",
46
+ labelId: "settings.defaultBufferAfterMinutes",
47
+ labelDefault: "Buffer After (Minutes)",
48
+ hintId: "settings.defaultBufferAfterMinutesHint",
49
+ hintDefault: "Cooldown gap blocked after each booking ends.",
50
+ placeholderId: "settings.defaultBufferAfterMinutes.placeholder",
51
+ placeholderDefault: "e.g., 0",
52
+ min: 0,
53
+ fallback: 0
54
+ },
55
+ {
56
+ name: "defaultMinLeadTimeHours",
57
+ labelId: "settings.defaultMinLeadTimeHours",
58
+ labelDefault: "Minimum Lead Time (Hours)",
59
+ hintId: "settings.defaultMinLeadTimeHoursHint",
60
+ hintDefault: "Minimum notice required before a slot can be booked.",
61
+ placeholderId: "settings.defaultMinLeadTimeHours.placeholder",
62
+ placeholderDefault: "e.g., 2",
63
+ min: 0,
64
+ fallback: 2
65
+ },
66
+ {
67
+ name: "defaultMaxAdvanceDays",
68
+ labelId: "settings.defaultMaxAdvanceDays",
69
+ labelDefault: "Max Advance Horizon (Days)",
70
+ hintId: "settings.defaultMaxAdvanceDaysHint",
71
+ hintDefault: "How far in advance visitors may schedule bookings.",
72
+ placeholderId: "settings.defaultMaxAdvanceDays.placeholder",
73
+ placeholderDefault: "e.g., 90",
74
+ min: 1,
75
+ fallback: 90
76
+ }
77
+ ];
78
+ const SettingsPage = () => {
79
+ const { formatMessage } = reactIntl.useIntl();
80
+ const { get, put } = admin.useFetchClient();
81
+ const { toggleNotification } = admin.useNotification();
82
+ const t = React.useCallback(
83
+ (id, defaultMessage) => formatMessage({ id: getTranslation.getTranslation(id), defaultMessage }),
84
+ [formatMessage]
85
+ );
86
+ const [settings, setSettings] = React.useState({
87
+ theme: "breeze",
88
+ defaultLocale: "es",
89
+ secondaryCalendarLanguage: "local",
90
+ defaultTimezone: "America/Bogota",
91
+ defaultSlotDurationMinutes: 60,
92
+ defaultBufferBeforeMinutes: 0,
93
+ defaultBufferAfterMinutes: 0,
94
+ defaultCapacityPerSlot: 1,
95
+ defaultMinLeadTimeHours: 2,
96
+ defaultMaxAdvanceDays: 90,
97
+ defaultRequiresApproval: false,
98
+ sendEmailNotifications: true,
99
+ secondaryCalendars: [],
100
+ sources: []
101
+ });
102
+ const [loading, setLoading] = React.useState(true);
103
+ const [loadError, setLoadError] = React.useState(false);
104
+ const [saving, setSaving] = React.useState(false);
105
+ React.useEffect(() => {
106
+ let isMounted = true;
107
+ const load = async () => {
108
+ setLoading(true);
109
+ try {
110
+ const res = await get(
111
+ `/${index.PLUGIN_ID}/settings`
112
+ );
113
+ if (!isMounted) return;
114
+ if (res.data?.data) {
115
+ setSettings(res.data.data);
116
+ setLoadError(false);
117
+ }
118
+ } catch {
119
+ if (!isMounted) return;
120
+ setLoadError(true);
121
+ toggleNotification({
122
+ type: "danger",
123
+ message: t("settings.loadError", "Failed to load bookings settings")
124
+ });
125
+ } finally {
126
+ if (isMounted) {
127
+ setLoading(false);
128
+ }
129
+ }
130
+ };
131
+ void load();
132
+ return () => {
133
+ isMounted = false;
134
+ };
135
+ }, [get, toggleNotification, t]);
136
+ const handleSave = async () => {
137
+ if (loadError || loading) return;
138
+ setSaving(true);
139
+ try {
140
+ const res = await put(
141
+ `/${index.PLUGIN_ID}/settings`,
142
+ settings
143
+ );
144
+ if (res.data?.data) {
145
+ setSettings(res.data.data);
146
+ }
147
+ toggleNotification({
148
+ type: "success",
149
+ message: t("settings.saved", "Bookings settings saved successfully")
150
+ });
151
+ } catch {
152
+ toggleNotification({
153
+ type: "danger",
154
+ message: t("settings.saveError", "Failed to save bookings settings")
155
+ });
156
+ } finally {
157
+ setSaving(false);
158
+ }
159
+ };
160
+ return /* @__PURE__ */ jsxRuntime.jsxs(admin.Layouts.Root, { children: [
161
+ /* @__PURE__ */ jsxRuntime.jsx(
162
+ admin.Layouts.Header,
163
+ {
164
+ title: t("settings.title", "Bookings & Availability Settings"),
165
+ subtitle: t(
166
+ "settings.subtitle",
167
+ "Configure default slot durations, capacity limits, buffer times, lead times, and reservation approval rules. Visual calendar themes and secondary calendars are managed centrally in Calendar Settings."
168
+ ),
169
+ primaryAction: /* @__PURE__ */ jsxRuntime.jsx(
170
+ designSystem.Button,
171
+ {
172
+ loading: saving,
173
+ disabled: loading || loadError || saving,
174
+ onClick: handleSave,
175
+ children: t("settings.save", "Save Settings")
176
+ }
177
+ )
178
+ }
179
+ ),
180
+ /* @__PURE__ */ jsxRuntime.jsx(admin.Layouts.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs.Root, { defaultValue: "slots", children: [
181
+ /* @__PURE__ */ jsxRuntime.jsxs(
182
+ designSystem.Tabs.List,
183
+ {
184
+ "aria-label": t("settings.title", "Bookings & Availability Settings"),
185
+ children: [
186
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "slots", children: t("settings.defaultsHeading", "Default Slot & Scheduling Rules") }),
187
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "approvals", children: t(
188
+ "settings.approvalsHeading",
189
+ "Approval Workflow & Email Notifications"
190
+ ) })
191
+ ]
192
+ }
193
+ ),
194
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: "slots", children: /* @__PURE__ */ jsxRuntime.jsx(
195
+ designSystem.Box,
196
+ {
197
+ background: "neutral0",
198
+ hasRadius: true,
199
+ shadow: "tableShadow",
200
+ padding: 6,
201
+ style: {
202
+ border: "1px solid rgba(128, 128, 128, 0.22)",
203
+ borderTopLeftRadius: 0,
204
+ borderTopRightRadius: 0
205
+ },
206
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
207
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", tag: "h2", children: t(
208
+ "settings.defaultsHeading",
209
+ "Default Slot & Scheduling Rules"
210
+ ) }),
211
+ /* @__PURE__ */ jsxRuntime.jsx(
212
+ "div",
213
+ {
214
+ style: {
215
+ display: "grid",
216
+ gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
217
+ gap: 16
218
+ },
219
+ children: SLOT_NUMBER_FIELDS.map((field) => /* @__PURE__ */ jsxRuntime.jsxs(
220
+ designSystem.Field.Root,
221
+ {
222
+ name: field.name,
223
+ hint: t(field.hintId, field.hintDefault),
224
+ children: [
225
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t(field.labelId, field.labelDefault) }),
226
+ /* @__PURE__ */ jsxRuntime.jsx(
227
+ designSystem.NumberInput,
228
+ {
229
+ placeholder: t(
230
+ field.placeholderId,
231
+ field.placeholderDefault
232
+ ),
233
+ value: settings[field.name],
234
+ onValueChange: (v) => {
235
+ const num = Number(v ?? field.fallback);
236
+ const safe = Number.isFinite(num) ? Math.max(field.min, Math.trunc(num)) : field.fallback;
237
+ setSettings((prev) => ({
238
+ ...prev,
239
+ [field.name]: safe
240
+ }));
241
+ }
242
+ }
243
+ ),
244
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
245
+ ]
246
+ },
247
+ field.name
248
+ ))
249
+ }
250
+ ),
251
+ /* @__PURE__ */ jsxRuntime.jsx(
252
+ "div",
253
+ {
254
+ style: {
255
+ display: "grid",
256
+ gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
257
+ gap: 16
258
+ },
259
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
260
+ designSystem.Field.Root,
261
+ {
262
+ name: "defaultTimezone",
263
+ hint: t(
264
+ "settings.defaultTimezoneHint",
265
+ "IANA timezone used to evaluate daily operating windows."
266
+ ),
267
+ children: [
268
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t(
269
+ "settings.defaultTimezone",
270
+ "Operating Hours Timezone (IANA)"
271
+ ) }),
272
+ /* @__PURE__ */ jsxRuntime.jsx(
273
+ designSystem.TextInput,
274
+ {
275
+ placeholder: t(
276
+ "settings.defaultTimezone.placeholder",
277
+ "e.g., America/Bogota"
278
+ ),
279
+ value: settings.defaultTimezone ?? "",
280
+ onChange: (e) => setSettings((prev) => ({
281
+ ...prev,
282
+ defaultTimezone: e.target.value
283
+ }))
284
+ }
285
+ ),
286
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
287
+ ]
288
+ }
289
+ )
290
+ }
291
+ )
292
+ ] })
293
+ }
294
+ ) }),
295
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: "approvals", children: /* @__PURE__ */ jsxRuntime.jsx(
296
+ designSystem.Box,
297
+ {
298
+ background: "neutral0",
299
+ hasRadius: true,
300
+ shadow: "tableShadow",
301
+ padding: 6,
302
+ style: {
303
+ border: "1px solid rgba(128, 128, 128, 0.22)",
304
+ borderTopLeftRadius: 0,
305
+ borderTopRightRadius: 0
306
+ },
307
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
308
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", tag: "h2", children: t(
309
+ "settings.approvalsHeading",
310
+ "Approval Workflow & Email Notifications"
311
+ ) }),
312
+ /* @__PURE__ */ jsxRuntime.jsxs(
313
+ "div",
314
+ {
315
+ style: {
316
+ display: "grid",
317
+ gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
318
+ gap: 16
319
+ },
320
+ children: [
321
+ /* @__PURE__ */ jsxRuntime.jsxs(
322
+ designSystem.Box,
323
+ {
324
+ padding: 4,
325
+ background: "neutral100",
326
+ hasRadius: true,
327
+ style: { border: "1px solid rgba(128, 128, 128, 0.18)" },
328
+ children: [
329
+ /* @__PURE__ */ jsxRuntime.jsx(
330
+ designSystem.Checkbox,
331
+ {
332
+ checked: settings.defaultRequiresApproval,
333
+ onCheckedChange: (checked) => setSettings((prev) => ({
334
+ ...prev,
335
+ defaultRequiresApproval: Boolean(checked)
336
+ })),
337
+ children: t(
338
+ "settings.requiresApproval",
339
+ "Require Manual Admin Approval"
340
+ )
341
+ }
342
+ ),
343
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: [
344
+ t(
345
+ "settings.requiresApprovalHintPrefix",
346
+ "Places new visitor reservations in"
347
+ ),
348
+ " ",
349
+ /* @__PURE__ */ jsxRuntime.jsx(
350
+ "code",
351
+ {
352
+ style: {
353
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
354
+ fontSize: "0.88em",
355
+ padding: "2px 6px",
356
+ borderRadius: 4,
357
+ background: "rgba(128, 128, 128, 0.16)",
358
+ border: "1px solid rgba(128, 128, 128, 0.25)"
359
+ },
360
+ children: "pending"
361
+ }
362
+ ),
363
+ " ",
364
+ t(
365
+ "settings.requiresApprovalHintSuffix",
366
+ "status until confirmed by staff."
367
+ )
368
+ ] }) })
369
+ ]
370
+ }
371
+ ),
372
+ /* @__PURE__ */ jsxRuntime.jsxs(
373
+ designSystem.Box,
374
+ {
375
+ padding: 4,
376
+ background: "neutral100",
377
+ hasRadius: true,
378
+ style: { border: "1px solid rgba(128, 128, 128, 0.18)" },
379
+ children: [
380
+ /* @__PURE__ */ jsxRuntime.jsx(
381
+ designSystem.Checkbox,
382
+ {
383
+ checked: settings.sendEmailNotifications,
384
+ onCheckedChange: (checked) => setSettings((prev) => ({
385
+ ...prev,
386
+ sendEmailNotifications: Boolean(checked)
387
+ })),
388
+ children: t(
389
+ "settings.sendEmailNotifications",
390
+ "Send Confirmation & Status Update Emails"
391
+ )
392
+ }
393
+ ),
394
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t(
395
+ "settings.sendEmailNotificationsHint",
396
+ "Automatically notifies visitors when their booking is created, approved, or rescheduled."
397
+ ) }) })
398
+ ]
399
+ }
400
+ )
401
+ ]
402
+ }
403
+ )
404
+ ] })
405
+ }
406
+ ) })
407
+ ] }) })
408
+ ] });
409
+ };
410
+ exports.SettingsPage = SettingsPage;