@oneclick.dev/cms-core-modules 0.0.61 → 0.0.63

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 (46) hide show
  1. package/dist/{ContentEditor-BAepN3Yd.js → ContentEditor-DKFCmfOs.js} +1 -1
  2. package/dist/{ContentEditor-BPjWW3d1.mjs → ContentEditor-owdOIage.mjs} +1 -1
  3. package/dist/NewReservationDialog.vue_vue_type_script_setup_true_lang-DRVxQswt.js +1 -0
  4. package/dist/{NewReservationDialog.vue_vue_type_script_setup_true_lang-BJitmbPE.mjs → NewReservationDialog.vue_vue_type_script_setup_true_lang-DkgDWC2i.mjs} +130 -125
  5. package/dist/{Overview-DtWvKB3W.mjs → Overview-DiBYtvEX.mjs} +124 -119
  6. package/dist/Overview-qP1guKjx.js +1 -0
  7. package/dist/ReservationDetailDialog.vue_vue_type_script_setup_true_lang-B7ks5mbf.mjs +2332 -0
  8. package/dist/ReservationDetailDialog.vue_vue_type_script_setup_true_lang-Vxubki_v.js +349 -0
  9. package/dist/{TableView-_2cP-w_7.js → TableView-BqhL_P45.js} +100 -100
  10. package/dist/{TableView-DlhHyuUZ.mjs → TableView-Dbl8qcUy.mjs} +14991 -14728
  11. package/dist/agenda-DFNJ8C1N.mjs +1136 -0
  12. package/dist/agenda-MjkwV63A.js +1 -0
  13. package/dist/floating-ui.dom-CBBY0Ism.js +1 -0
  14. package/dist/floating-ui.dom-xfqXu4GA.mjs +1138 -0
  15. package/dist/{index-DTago6vW-Bhr8E1Y6.js → index-CgfL8UKf-DAN7RkzR.js} +10 -10
  16. package/dist/{index-DTago6vW-CnomHQ_S.mjs → index-CgfL8UKf-DUUg9HDA.mjs} +904 -875
  17. package/dist/index-DBDq-h4j.js +245 -0
  18. package/dist/{index-BDaVYdkD.mjs → index-X0L4AHBR.mjs} +2406 -2394
  19. package/dist/index-YMaY4uuk-BgpTtr73.js +1 -0
  20. package/dist/{index-YMaY4uuk-BshejgNP.mjs → index-YMaY4uuk-C_xV5K9Z.mjs} +13 -14
  21. package/dist/index.cjs.js +1 -1
  22. package/dist/index.mjs +6 -6
  23. package/dist/orders-Bqa3Z3tH.mjs +356 -0
  24. package/dist/orders-D5GJOZXN.js +1 -0
  25. package/dist/src/appointments/components/edit/EventDialog/ApproveReservationDialog.vue.d.ts +8 -0
  26. package/dist/src/appointments/components/edit/EventDialog/BookingsList.vue.d.ts +39 -9
  27. package/dist/src/appointments/components/edit/EventDialog/CancelReservationDialog.vue.d.ts +2 -2
  28. package/dist/src/appointments/components/edit/EventDialog/RejectReservationDialog.vue.d.ts +8 -0
  29. package/dist/src/appointments/components/edit/EventDialog/ReservationDetailDialog.vue.d.ts +36 -8
  30. package/dist/src/appointments/components/edit/dashboard/BookingsList.vue.d.ts +46 -9
  31. package/dist/src/appointments/components/edit/dashboard/Timeline.vue.d.ts +19 -0
  32. package/dist/src/appointments/pages/edit/orders.vue.d.ts +39 -9
  33. package/package.json +1 -1
  34. package/dist/NewReservationDialog.vue_vue_type_script_setup_true_lang-D50uTpZY.js +0 -1
  35. package/dist/Overview-B_99j5eA.js +0 -1
  36. package/dist/ReservationDetailDialog.vue_vue_type_script_setup_true_lang-CI8YgHdU.js +0 -345
  37. package/dist/ReservationDetailDialog.vue_vue_type_script_setup_true_lang-P-MWwcVh.mjs +0 -2093
  38. package/dist/agenda-D81m29_4.mjs +0 -1135
  39. package/dist/agenda-uzPPxgsW.js +0 -1
  40. package/dist/floating-ui.dom-C82nbomj.js +0 -1
  41. package/dist/floating-ui.dom-ouSgPqty.mjs +0 -1133
  42. package/dist/index-DfV8-6ON.js +0 -245
  43. package/dist/index-YMaY4uuk-BxVT7IpO.js +0 -1
  44. package/dist/orders-Bh8w0ueq.mjs +0 -346
  45. package/dist/orders-Dt0zMz97.js +0 -1
  46. package/dist/src/appointments/components/edit/EventDialog/ResendConfirmationDialog.vue.d.ts +0 -4
@@ -0,0 +1,1136 @@
1
+ import { defineComponent as K, resolveComponent as N, openBlock as o, createElementBlock as u, createElementVNode as e, Fragment as X, renderList as Y, toDisplayString as v, normalizeStyle as q, normalizeClass as R, createVNode as d, withCtx as S, unref as b, createTextVNode as ne, createCommentVNode as M, ref as $, createBlock as Q, provide as Z, computed as U, onMounted as pe, onUnmounted as fe, inject as ie, nextTick as xe, onBeforeUnmount as ze, watch as re } from "vue";
2
+ import { o as ue, g as de } from "./DateFormatter-DsmlAuYV.mjs";
3
+ import { X as we, Search as Ee, Clock as ge, Users as he, ChevronLeft as ve, ChevronRight as ce, Asterisk as Ie, CalendarDays as Be } from "lucide-vue-next";
4
+ import { _ as Le } from "./EditLayout.vue_vue_type_script_setup_true_lang-CcysXzmW.mjs";
5
+ import { useModule as $e, useModuleRoute as Se, useFirebaseIntegration as Te, useModulePermissions as Ue } from "@oneclick.dev/cms-kit";
6
+ import { _ as je, F as Pe } from "./ReservationDetailDialog.vue_vue_type_script_setup_true_lang-B7ks5mbf.mjs";
7
+ import { _ as Ne } from "./_plugin-vue_export-helper-CHgC5LLL.mjs";
8
+ import { _ as be } from "./NewReservationDialog.vue_vue_type_script_setup_true_lang-DkgDWC2i.mjs";
9
+ const Oe = { class: "mb-6" }, Re = { class: "flex items-end gap-px h-24 bg-muted/30 rounded-lg p-2 overflow-visible" }, Fe = ["onClick"], Ae = { class: "absolute -top-8 left-1/2 -translate-x-1/2 bg-popover border shadow-md rounded px-2 py-1 text-xs whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none z-10" }, Ve = { class: "font-medium" }, We = { class: "text-muted-foreground" }, He = { class: "w-full flex-1 flex items-end justify-center" }, Qe = {
10
+ key: 1,
11
+ class: "text-[10px] mt-1"
12
+ }, Xe = {
13
+ key: 0,
14
+ class: "mt-2 text-sm text-muted-foreground flex items-center gap-2"
15
+ }, Ye = { class: "font-medium text-foreground" }, qe = { class: "font-medium text-foreground" }, Je = /* @__PURE__ */ K({
16
+ __name: "TimelineChart",
17
+ props: {
18
+ timeSlots: {},
19
+ slotStats: {},
20
+ selectedTimeSlot: {},
21
+ maxSpots: {}
22
+ },
23
+ emits: ["select", "clear"],
24
+ setup(f, { emit: k }) {
25
+ const y = k, T = (a) => {
26
+ y("select", a);
27
+ }, I = () => {
28
+ y("clear");
29
+ };
30
+ return (a, r) => {
31
+ const c = N("Button");
32
+ return o(), u("div", Oe, [
33
+ r[2] || (r[2] = e("h3", { class: "font-semibold text-sm mb-2" }, "Timeline", -1)),
34
+ e("div", Re, [
35
+ (o(!0), u(X, null, Y(f.timeSlots, (s) => (o(), u("div", {
36
+ key: s.startTime,
37
+ class: "flex-1 min-w-0 flex flex-col items-center cursor-pointer group h-full relative",
38
+ onClick: (w) => T(s.startTime)
39
+ }, [
40
+ e("div", Ae, [
41
+ e("div", Ve, v(s.startTime), 1),
42
+ e("div", We, v(f.slotStats[s.startTime]?.spots || 0) + " spots", 1)
43
+ ]),
44
+ e("div", He, [
45
+ e("div", {
46
+ class: R(["w-full transition-all duration-200", [
47
+ f.selectedTimeSlot === s.startTime ? "bg-primary" : f.slotStats[s.startTime]?.spots > 0 ? "bg-primary/60 group-hover:bg-primary/80" : "bg-muted-foreground/20 group-hover:bg-muted-foreground/30"
48
+ ]]),
49
+ style: q({
50
+ height: f.slotStats[s.startTime]?.spots > 0 ? `${f.slotStats[s.startTime].spots / f.maxSpots * 100}%` : "2px",
51
+ minHeight: f.slotStats[s.startTime]?.spots > 0 ? "4px" : "2px"
52
+ })
53
+ }, null, 6)
54
+ ]),
55
+ s.startTime.endsWith(":00") ? (o(), u("span", {
56
+ key: 0,
57
+ class: R(["text-[10px] text-muted-foreground mt-1 transition-colors truncate", { "text-primary font-medium": f.selectedTimeSlot === s.startTime }])
58
+ }, v(s.label), 3)) : (o(), u("span", Qe, " "))
59
+ ], 8, Fe))), 128))
60
+ ]),
61
+ f.selectedTimeSlot ? (o(), u("div", Xe, [
62
+ d(c, {
63
+ variant: "ghost",
64
+ size: "icon",
65
+ class: "h-6 w-6 p-0",
66
+ onClick: I
67
+ }, {
68
+ default: S(() => [
69
+ d(b(we), { size: 14 })
70
+ ]),
71
+ _: 1
72
+ }),
73
+ e("span", null, [
74
+ r[0] || (r[0] = ne(" Showing ", -1)),
75
+ e("span", Ye, v(f.slotStats[f.selectedTimeSlot]?.bookings || 0), 1),
76
+ r[1] || (r[1] = ne(" bookings at ", -1)),
77
+ e("span", qe, v(f.selectedTimeSlot), 1)
78
+ ])
79
+ ])) : M("", !0)
80
+ ]);
81
+ };
82
+ }
83
+ }), Ke = { class: "flex items-center justify-between mb-3" }, Ge = { class: "font-semibold" }, Ze = {
84
+ key: 0,
85
+ class: "text-muted-foreground font-normal"
86
+ }, et = { class: "relative mb-3" }, tt = {
87
+ key: 0,
88
+ class: "flex items-center justify-center py-8"
89
+ }, st = {
90
+ key: 1,
91
+ class: "text-center py-8 text-muted-foreground"
92
+ }, ot = {
93
+ key: 2,
94
+ class: "space-y-2 max-h-80 overflow-y-auto"
95
+ }, nt = ["onClick"], at = { class: "flex items-start justify-between" }, lt = { class: "flex-1" }, rt = { class: "font-medium" }, it = { class: "text-sm text-muted-foreground" }, ut = { class: "text-sm text-muted-foreground" }, dt = { class: "flex items-center gap-4" }, ct = { class: "flex items-center gap-2 mt-1 text-xs text-muted-foreground" }, mt = { class: "flex items-center gap-2 mt-1 text-xs text-muted-foreground" }, vt = { class: "text-right" }, pt = {
96
+ key: 0,
97
+ class: "inline-block px-2 py-1 text-xs rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400"
98
+ }, ft = {
99
+ key: 1,
100
+ class: "inline-block px-2 py-1 text-xs rounded-full bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400"
101
+ }, gt = {
102
+ key: 2,
103
+ class: "inline-block px-2 py-1 text-xs rounded-full bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400"
104
+ }, ht = {
105
+ key: 3,
106
+ class: "inline-block px-2 py-1 text-xs rounded-full bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400"
107
+ }, xt = {
108
+ key: 4,
109
+ class: "inline-block px-2 py-1 text-xs rounded-full bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400"
110
+ }, bt = {
111
+ key: 5,
112
+ class: "text-sm font-medium mt-1"
113
+ }, yt = /* @__PURE__ */ K({
114
+ __name: "BookingsList",
115
+ props: {
116
+ orders: {},
117
+ filteredOrders: {},
118
+ isLoading: { type: Boolean },
119
+ selectedTimeSlot: {},
120
+ searchQuery: {}
121
+ },
122
+ emits: ["update:searchQuery", "refresh"],
123
+ setup(f, { emit: k }) {
124
+ const y = k, T = $(null), I = (c) => {
125
+ y("update:searchQuery", c);
126
+ }, a = () => {
127
+ y("update:searchQuery", "");
128
+ }, r = () => {
129
+ y("refresh");
130
+ };
131
+ return (c, s) => {
132
+ const w = N("Input"), _ = N("Button");
133
+ return o(), u("div", null, [
134
+ e("div", Ke, [
135
+ e("h3", Ge, [
136
+ s[0] || (s[0] = ne(" Bookings ", -1)),
137
+ f.selectedTimeSlot || f.searchQuery ? (o(), u("span", Ze, " (" + v(f.filteredOrders.length) + " of " + v(f.orders.length) + ") ", 1)) : M("", !0)
138
+ ])
139
+ ]),
140
+ e("div", et, [
141
+ d(b(Ee), {
142
+ size: 16,
143
+ class: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"
144
+ }),
145
+ d(w, {
146
+ "model-value": f.searchQuery,
147
+ placeholder: "Search by name, email, or phone...",
148
+ class: "pl-9 pr-9",
149
+ "onUpdate:modelValue": I
150
+ }, null, 8, ["model-value"]),
151
+ f.searchQuery ? (o(), Q(_, {
152
+ key: 0,
153
+ variant: "ghost",
154
+ size: "icon",
155
+ class: "absolute right-1 top-1/2 -translate-y-1/2 h-7 w-7",
156
+ onClick: a
157
+ }, {
158
+ default: S(() => [
159
+ d(b(we), { size: 14 })
160
+ ]),
161
+ _: 1
162
+ })) : M("", !0)
163
+ ]),
164
+ f.isLoading ? (o(), u("div", tt, [...s[1] || (s[1] = [
165
+ e("div", { class: "animate-spin rounded-full h-8 w-8 border-b-2 border-primary" }, null, -1)
166
+ ])])) : f.filteredOrders.length === 0 ? (o(), u("div", st, v(f.selectedTimeSlot ? "No bookings for this time slot" : "No bookings for this event"), 1)) : (o(), u("div", ot, [
167
+ (o(!0), u(X, null, Y(f.filteredOrders, (h) => (o(), u("div", {
168
+ key: h.res_id || h.id,
169
+ class: "p-3 border rounded-lg hover:bg-muted/50 transition-colors",
170
+ onClick: (B) => b(T).openDialog(h)
171
+ }, [
172
+ e("div", at, [
173
+ e("div", lt, [
174
+ e("div", rt, v(h.customerInfo.firstName + " " + h.customerInfo.lastName || "Unknown Customer"), 1),
175
+ e("div", it, v(h.customerInfo.email), 1),
176
+ e("div", ut, v(h.customerInfo.phone), 1),
177
+ e("div", dt, [
178
+ e("div", ct, [
179
+ d(b(ge), { size: 12 }),
180
+ e("span", null, v(h.startTime) + " - " + v(h.endTime), 1)
181
+ ]),
182
+ e("div", mt, [
183
+ d(b(he), { size: 12 }),
184
+ e("span", null, v(h.spots), 1)
185
+ ])
186
+ ])
187
+ ]),
188
+ e("div", vt, [
189
+ h.reservationStatus === "needs_approval" ? (o(), u("span", pt, "Needs Approval")) : h.reservationStatus === "approved" ? (o(), u("span", ft, "Approved")) : h.reservationStatus === "rejected" ? (o(), u("span", gt, "Rejected")) : h.reservationStatus === "cancelled" ? (o(), u("span", ht, "Cancelled")) : (o(), u("span", xt, "Pending")),
190
+ h.reservationPrice || h.reservationPrice === 0 ? (o(), u("div", bt, " €" + v(h.reservationPrice.toFixed(2)), 1)) : M("", !0)
191
+ ])
192
+ ])
193
+ ], 8, nt))), 128))
194
+ ])),
195
+ d(je, {
196
+ ref_key: "reservationDetailDialog",
197
+ ref: T,
198
+ onCancelled: r,
199
+ onConfirmed: r,
200
+ onRejected: r
201
+ }, null, 512)
202
+ ]);
203
+ };
204
+ }
205
+ }), _t = { class: "flex items-center gap-4 mt-2 text-sm" }, kt = { class: "flex items-center gap-1" }, wt = {
206
+ key: 0,
207
+ class: "flex items-center gap-1"
208
+ }, $t = { class: "flex items-center gap-1" }, St = { class: "py-4" }, Tt = /* @__PURE__ */ K({
209
+ __name: "EventDialog",
210
+ props: {
211
+ resources: { default: () => [] }
212
+ },
213
+ setup(f, { expose: k }) {
214
+ const y = f, { config: T } = $e(), { params: I } = Se(), a = Te(T.project), r = $(!1), c = $(null), s = $([]), w = $(!1), _ = $(null), h = $("");
215
+ Z("event", c);
216
+ const B = U(() => {
217
+ if (!c.value) return [];
218
+ const p = c.value.resource?.interval || 60, n = [], [m, z] = c.value.startTime.split(":").map(Number), [A, C] = c.value.endTime.split(":").map(Number), O = m * 60 + z, t = A * 60 + C;
219
+ for (let i = O; i < t; i += p) {
220
+ const x = Math.floor(i / 60), g = i % 60, E = Math.min(i + p, t), P = Math.floor(E / 60), l = E % 60, V = `${x.toString().padStart(2, "0")}:${g.toString().padStart(2, "0")}`, H = `${P.toString().padStart(2, "0")}:${l.toString().padStart(2, "0")}`;
221
+ n.push({
222
+ startTime: V,
223
+ endTime: H,
224
+ label: V
225
+ });
226
+ }
227
+ return n;
228
+ }), D = (p) => {
229
+ const n = p.getFullYear(), m = String(p.getMonth() + 1).padStart(2, "0"), z = String(p.getDate()).padStart(2, "0");
230
+ return `${n}-${m}-${z}`;
231
+ }, W = U(() => {
232
+ const p = {};
233
+ return B.value.forEach((n) => {
234
+ p[n.startTime] = { bookings: 0, spots: 0, orders: [] };
235
+ }), s.value.forEach((n) => {
236
+ B.value.forEach((m) => {
237
+ n.startTime < m.endTime && n.endTime > m.startTime && (p[m.startTime].bookings++, p[m.startTime].spots += n.spots || 0, p[m.startTime].orders.push(n));
238
+ });
239
+ }), p;
240
+ }), L = U(() => Math.max(1, ...Object.values(W.value).map((p) => p.spots))), j = U(() => {
241
+ let p = s.value;
242
+ return _.value && (p = W.value[_.value]?.orders || []), h.value.trim() && (p = new Pe(p, {
243
+ keys: [
244
+ "customerInfo.firstName",
245
+ "customerInfo.lastName",
246
+ "customerInfo.email",
247
+ "customerInfo.phone"
248
+ ],
249
+ threshold: 0.3,
250
+ ignoreLocation: !0
251
+ }).search(h.value).map((m) => m.item)), p;
252
+ }), F = U(() => ({
253
+ spots: s.value.reduce((p, n) => p + (n.spots || 0), 0),
254
+ bookings: s.value.length
255
+ })), ee = (p) => {
256
+ _.value === p ? _.value = null : _.value = p;
257
+ }, J = () => {
258
+ _.value = null;
259
+ }, te = async (p) => {
260
+ r.value = !0, c.value = p, _.value = null, h.value = "", await G();
261
+ }, G = async () => {
262
+ if (c.value) {
263
+ w.value = !0, s.value = [];
264
+ try {
265
+ const p = I.value.id, n = D(new Date(c.value.date)), m = /* @__PURE__ */ new Set();
266
+ y.resources?.forEach((C) => {
267
+ const O = `${C.id}_${n}`;
268
+ m.add(O);
269
+ });
270
+ const z = await a.find(T.reservationsCollection, {
271
+ filters: [
272
+ { field: "agendaId", operator: "==", value: p },
273
+ { field: "status", operator: "==", value: "confirmed" },
274
+ { field: "flattenedReservationDates", operator: "array-contains-any", value: Array.from(m) }
275
+ ]
276
+ });
277
+ let A = [];
278
+ z.forEach((C) => {
279
+ const O = C.reservations?.filter((t) => t.date === n) || [];
280
+ console.log("dateReservations", O), O.forEach((t) => {
281
+ const i = y.resources.find((x) => x.id === t.resourceId);
282
+ (t.status === "approved" || t.status === "needs_approval") && A.push({
283
+ customerInfo: C.customerInfo,
284
+ amountDue: C.amountDue,
285
+ amountPaid: C.amountPaid,
286
+ status: C.status,
287
+ reservationStatus: t.status,
288
+ subtotal: C.subtotal,
289
+ total: C.total,
290
+ discount: C.discount,
291
+ id: C.id,
292
+ res_id: t.id,
293
+ resourceId: t.resourceId,
294
+ spots: t.spots,
295
+ date: n,
296
+ startTime: t.timeslot?.startTime,
297
+ endTime: t.timeslot?.endTime,
298
+ reservationPrice: t.totalPrice,
299
+ reservationBasePrice: t.basePrice,
300
+ reservationAddOnsPrice: t.addOnsPrice,
301
+ pricingOptionId: t.pricingOptionId,
302
+ pricingOption: t.pricingOption,
303
+ resourceName: i?.name || "Unknown",
304
+ resourceColor: i?.color
305
+ });
306
+ });
307
+ }), s.value = A.sort((C, O) => C.startTime?.localeCompare(O.startTime || "") || 0);
308
+ } catch (p) {
309
+ console.error("Error loading orders:", p), s.value = [];
310
+ } finally {
311
+ w.value = !1;
312
+ }
313
+ }
314
+ }, ae = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], se = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
315
+ return k({
316
+ openDialog: te
317
+ }), (p, n) => {
318
+ const m = N("DialogTitle"), z = N("DialogDescription"), A = N("DialogHeader"), C = N("Button"), O = N("DialogFooter"), t = N("DialogScrollContent"), i = N("Dialog");
319
+ return o(), Q(i, {
320
+ open: r.value,
321
+ "onUpdate:open": n[2] || (n[2] = (x) => r.value = x)
322
+ }, {
323
+ default: S(() => [
324
+ d(t, { class: "sm:max-w-3xl" }, {
325
+ default: S(() => [
326
+ d(A, null, {
327
+ default: S(() => [
328
+ c.value?.date ? (o(), Q(m, { key: 0 }, {
329
+ default: S(() => [
330
+ ne(v(ae[new Date(c.value.date).getUTCDay()]) + " " + v(se[new Date(c.value.date).getUTCMonth()]) + " " + v(new Date(c.value.date).getUTCDate()) + ", " + v(new Date(c.value.date).getUTCFullYear()), 1)
331
+ ]),
332
+ _: 1
333
+ })) : M("", !0),
334
+ d(z, null, {
335
+ default: S(() => [
336
+ e("div", _t, [
337
+ e("div", kt, [
338
+ d(b(ge), { size: 14 }),
339
+ e("span", null, v(c.value?.startTime) + " – " + v(c.value?.endTime), 1)
340
+ ]),
341
+ c.value?.resource ? (o(), u("div", wt, [
342
+ e("div", {
343
+ class: "w-4 h-4 rounded-full",
344
+ style: q({ backgroundColor: c.value.resource.color || "#6b7280" })
345
+ }, null, 4),
346
+ e("span", null, v(c.value.resource.name), 1)
347
+ ])) : M("", !0),
348
+ e("div", $t, [
349
+ d(b(he), { size: 14 }),
350
+ e("span", null, v(F.value.spots) + " spots in " + v(F.value.bookings) + " reservations", 1)
351
+ ])
352
+ ])
353
+ ]),
354
+ _: 1
355
+ })
356
+ ]),
357
+ _: 1
358
+ }),
359
+ e("div", St, [
360
+ B.value.length > 1 ? (o(), Q(Je, {
361
+ key: 0,
362
+ "time-slots": B.value,
363
+ "slot-stats": W.value,
364
+ "selected-time-slot": _.value,
365
+ "max-spots": L.value,
366
+ onSelect: ee,
367
+ onClear: J
368
+ }, null, 8, ["time-slots", "slot-stats", "selected-time-slot", "max-spots"])) : M("", !0),
369
+ d(yt, {
370
+ orders: s.value,
371
+ "filtered-orders": j.value,
372
+ "is-loading": w.value,
373
+ "selected-time-slot": _.value,
374
+ "search-query": h.value,
375
+ "onUpdate:searchQuery": n[0] || (n[0] = (x) => h.value = x),
376
+ onRefresh: G
377
+ }, null, 8, ["orders", "filtered-orders", "is-loading", "selected-time-slot", "search-query"])
378
+ ]),
379
+ d(O, null, {
380
+ default: S(() => [
381
+ d(C, {
382
+ variant: "outline",
383
+ onClick: n[1] || (n[1] = (x) => r.value = !1)
384
+ }, {
385
+ default: S(() => [...n[3] || (n[3] = [
386
+ ne("Close", -1)
387
+ ])]),
388
+ _: 1
389
+ })
390
+ ]),
391
+ _: 1
392
+ })
393
+ ]),
394
+ _: 1
395
+ })
396
+ ]),
397
+ _: 1
398
+ }, 8, ["open"]);
399
+ };
400
+ }
401
+ }), Dt = { class: "flex-1 border-r shadow-sm overflow-hidden min-h-[1536px]" }, Ct = { class: "relative h-full min-h-[1536px]" }, Mt = { class: "divide-y divide-input/80 h-full flex flex-col min-h-[1536px] border-y border-input/80" }, zt = { class: "absolute inset-0 pointer-events-none" }, Et = { class: "relative mr-3 h-full ml-2" }, It = ["onClick"], Bt = {
402
+ key: 0,
403
+ class: "absolute bottom-0 left-0 right-0 h-1 bg-black/20"
404
+ }, Lt = { class: "flex items-start justify-between gap-2 mb-1" }, Ut = { class: "font-semibold text-sm leading-tight line-clamp-1 flex-1" }, jt = { class: "flex items-center gap-1 shrink-0" }, Pt = ["title"], Nt = { class: "font-medium" }, ye = /* @__PURE__ */ K({
405
+ __name: "EventTimeline",
406
+ props: {
407
+ date: {},
408
+ events: {},
409
+ firstDay: { type: Boolean, default: !1 },
410
+ resources: { default: () => [] }
411
+ },
412
+ setup(f) {
413
+ const k = f, y = $(null), T = (r) => {
414
+ const [c, s] = r.split(":").map(Number);
415
+ return c * 60 + s;
416
+ };
417
+ U(() => !k.events || !k.resources ? [] : k.resources.map((r) => {
418
+ const s = k.events.filter((w) => w.resourceId === r.id).map((w) => {
419
+ const _ = T(w.startTime), B = T(w.endTime) - _, D = _ / 1440 * 100, W = B / 1440 * 100, L = (w.bookings ?? 0) > 0, j = w.maxBookings ? (w.bookings ?? 0) / w.maxBookings * 100 : 0;
420
+ return {
421
+ ...w,
422
+ top: `${D}%`,
423
+ height: `${W}%`,
424
+ color: w.resource?.color || "#3b82f6",
425
+ hasBookings: L,
426
+ fillPercentage: j,
427
+ isSmall: B < 60
428
+ };
429
+ });
430
+ return {
431
+ resource: r,
432
+ events: s
433
+ };
434
+ }));
435
+ const I = U(() => k.events ? k.events.map((r) => {
436
+ const c = T(r.startTime), w = T(r.endTime) - c, _ = c / 1440 * 100, h = w / 1440 * 100, B = (r.bookings ?? 0) > 0, D = r.maxBookings ? (r.bookings ?? 0) / r.maxBookings * 100 : 0;
437
+ return {
438
+ ...r,
439
+ top: `${_}%`,
440
+ height: `${h}%`,
441
+ color: r.resource?.color || "#3b82f6",
442
+ hasBookings: B,
443
+ fillPercentage: D,
444
+ isSmall: w < 60
445
+ };
446
+ }) : []), a = Array.from({ length: 24 }, (r, c) => ({
447
+ hour: c,
448
+ label: `${c.toString().padStart(2, "0")}:00`
449
+ }));
450
+ return (r, c) => (o(), u(X, null, [
451
+ e("div", Dt, [
452
+ e("div", Ct, [
453
+ e("div", Mt, [
454
+ (o(!0), u(X, null, Y(b(a), (s) => (o(), u("div", {
455
+ key: s.hour,
456
+ class: "flex-1 flex transition-all duration-200"
457
+ }, [...c[0] || (c[0] = [
458
+ e("div", { class: "flex-1 relative" }, [
459
+ e("div", { class: "absolute top-1/2 left-0 right-0 border-t border-dashed border-input/50" })
460
+ ], -1)
461
+ ])]))), 128))
462
+ ]),
463
+ e("div", zt, [
464
+ e("div", Et, [
465
+ (o(!0), u(X, null, Y(I.value, (s) => (o(), u("div", {
466
+ key: s.id,
467
+ style: q({
468
+ top: s.top,
469
+ height: s.height,
470
+ opacity: s.hasBookings ? "1" : "0.5"
471
+ }),
472
+ class: "event-card absolute left-2 right-2 rounded-lg pointer-events-auto cursor-pointer group/event transition-all duration-200 hover:shadow-xl overflow-hidden",
473
+ onClick: (w) => y.value?.openDialog(s)
474
+ }, [
475
+ e("div", {
476
+ style: q({ backgroundColor: s.color }),
477
+ class: "absolute inset-0 shadow-lg"
478
+ }, [
479
+ s.maxBookings ? (o(), u("div", Bt, [
480
+ e("div", {
481
+ class: "h-full bg-white/40 transition-all duration-300",
482
+ style: q({ width: `${s.fillPercentage}%` })
483
+ }, null, 4)
484
+ ])) : M("", !0)
485
+ ], 4),
486
+ e("div", {
487
+ class: R(["relative h-full p-3 flex flex-col", `${s.hasBookings ? "text-white" : "text-gray-600 dark:text-gray-100"}`])
488
+ }, [
489
+ e("div", Lt, [
490
+ e("h3", Ut, v(s.title), 1),
491
+ e("div", jt, [
492
+ s.resource ? (o(), u("div", {
493
+ key: 0,
494
+ class: "w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold bg-white/30 backdrop-blur-sm text-white border border-white/40",
495
+ title: s.resource.name
496
+ }, v(s.resource.avatarLabel || s.resource.name.charAt(0).toUpperCase()), 9, Pt)) : M("", !0),
497
+ e("div", {
498
+ class: R([
499
+ "flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium",
500
+ s.hasBookings ? "bg-white text-black backdrop-blur-sm" : "bg-black/10 backdrop-blur-sm"
501
+ ])
502
+ }, [
503
+ d(b(he), { size: 12 }),
504
+ e("span", null, v(s.bookings), 1)
505
+ ], 2)
506
+ ])
507
+ ]),
508
+ e("div", {
509
+ class: R(["flex items-center gap-2 text-xs opacity-90 mt-auto", { "-translate-x-1 -translate-y-2 scale-80 origin-[0_0]": s.isSmall }])
510
+ }, [
511
+ e("div", {
512
+ class: R(["flex items-center gap-1 px-2 py-0.5 rounded backdrop-blur-sm", { "bg-black/10": !s.isSmall }])
513
+ }, [
514
+ d(b(ge), { size: 10 }),
515
+ e("span", Nt, v(s.startTime) + " – " + v(s.endTime), 1)
516
+ ], 2)
517
+ ], 2)
518
+ ], 2),
519
+ c[1] || (c[1] = e("div", { class: "absolute inset-0 border-2 border-white/0 group-hover/event:border-white/30 rounded-lg transition-colors duration-200 pointer-events-none" }, null, -1))
520
+ ], 12, It))), 128))
521
+ ])
522
+ ])
523
+ ])
524
+ ]),
525
+ d(Tt, {
526
+ resources: f.resources,
527
+ ref_key: "eventDialog",
528
+ ref: y
529
+ }, null, 8, ["resources"])
530
+ ], 64));
531
+ }
532
+ }), Ot = { class: "sticky left-0 mt-auto z-10 divide-y divide-border/50 h-full flex flex-col min-h-[1536px] bg-input" }, Rt = { class: "flex-shrink-0 text-xs font-medium text-muted-foreground px-3 pb-3 border-r border-border/50 w-14" }, Ft = { class: "flex items-center gap-1.5" }, _e = /* @__PURE__ */ K({
533
+ __name: "Event24hSidebar",
534
+ setup(f) {
535
+ const k = Array.from({ length: 24 }, (y, T) => ({
536
+ hour: T,
537
+ label: `${T.toString().padStart(2, "0")}:00`
538
+ }));
539
+ return (y, T) => (o(), u("div", Ot, [
540
+ (o(!0), u(X, null, Y(b(k), (I) => (o(), u("div", {
541
+ key: I.hour,
542
+ class: "flex-1 flex transition-all duration-200"
543
+ }, [
544
+ e("div", Rt, [
545
+ e("div", Ft, [
546
+ e("span", {
547
+ class: R({ "-translate-y-1/2": I.hour !== 0 })
548
+ }, v(I.label), 3)
549
+ ])
550
+ ])
551
+ ]))), 128))
552
+ ]));
553
+ }
554
+ }), At = { class: "absolute top-0 w-full pointer-events-none" }, Vt = {
555
+ key: 0,
556
+ class: "absolute -right-2 -top-0.5 px-2 py-0.5 bg-red-500 text-white text-xs font-medium rounded shadow-lg"
557
+ }, ke = /* @__PURE__ */ K({
558
+ __name: "EventTimeIndicator",
559
+ props: {
560
+ currentDate: {
561
+ type: Object,
562
+ required: !1
563
+ }
564
+ },
565
+ setup(f) {
566
+ const k = $(Date.now());
567
+ let y;
568
+ pe(() => {
569
+ y = window.setInterval(() => {
570
+ k.value = Date.now();
571
+ }, 1e3);
572
+ }), fe(() => {
573
+ y && clearInterval(y);
574
+ });
575
+ const T = U(() => {
576
+ const a = new Date(k.value);
577
+ return `${(a.getHours() * 60 + a.getMinutes() + a.getSeconds() / 60) / 1440 * 100}%`;
578
+ }), I = U(() => new Date(k.value).getFullYear() + "-" + (new Date(k.value).getMonth() + 1).toString().padStart(2, "0") + "-" + new Date(k.value).getDate().toString().padStart(2, "0"));
579
+ return (a, r) => (o(), u("div", At, [
580
+ e("div", {
581
+ class: "absolute left-0 right-0 h-0.5 bg-red-500 z-30 pointer-events-none transition-[top] duration-300 ease-linear",
582
+ style: q({ top: T.value })
583
+ }, [
584
+ r[0] || (r[0] = e("div", { class: "absolute -left-2 -top-1.5 w-3 h-3 bg-red-500 rounded-full shadow-lg shadow-red-500/50" }, null, -1)),
585
+ f.currentDate && f.currentDate == I.value ? (o(), u("div", Vt, " Now ")) : M("", !0)
586
+ ], 4)
587
+ ]));
588
+ }
589
+ }), Wt = {
590
+ key: 0,
591
+ class: "relative flex flex-1 min-w-0"
592
+ }, Ht = {
593
+ key: 1,
594
+ class: "flex-1 min-w-0 relative"
595
+ }, Qt = {
596
+ key: 0,
597
+ class: "absolute top-0 right-0 z-10 px-3 py-1.5 bg-primary/90 text-primary-foreground text-xs font-medium rounded-bl-lg shadow-lg backdrop-blur-sm flex items-center gap-1.5 animate-pulse-subtle"
598
+ }, Xt = { class: "flex pb-4 min-w-[200px]" }, Yt = ["onClick"], qt = {
599
+ key: 0,
600
+ class: "absolute top-2 right-2 flex items-center gap-1 px-2 py-0.5 bg-primary/20 backdrop-blur-sm rounded-full border border-primary/30"
601
+ }, Jt = { class: "text-xs text-muted-foreground font-medium group-hover:text-foreground/70 transition-colors" }, Kt = {
602
+ key: 0,
603
+ class: "absolute bottom-0 left-0 w-full h-1 bg-orange-500"
604
+ }, Gt = /* @__PURE__ */ K({
605
+ __name: "EventView",
606
+ setup(f) {
607
+ const k = ie("activeDate", $(ue(de()))), y = ie("viewMode", $(1)), T = ie("events", $([])), I = ie("resources", $([])), a = $(null), r = $(!1), c = $(!1);
608
+ U(() => I.value.length > 1);
609
+ const s = U(() => {
610
+ const n = [], m = k.value;
611
+ for (let z = 0; z < y.value; z++)
612
+ n.push(m.add({ days: z }));
613
+ return n;
614
+ }), w = (n, m) => {
615
+ const z = `${n.year}-${String(n.month).padStart(2, "0")}-${String(n.day).padStart(2, "0")}`;
616
+ return T.value?.filter((A) => A.date === z) || [];
617
+ }, _ = (n) => {
618
+ const m = ue(de());
619
+ return n.year === m.year && n.month === m.month && n.day === m.day;
620
+ }, h = (n) => {
621
+ k.value = n, y.value = 1;
622
+ };
623
+ let B = null, D = null;
624
+ const W = () => {
625
+ a.value && (j(), a.value.scrollBy({ left: -300, behavior: "smooth" }), D = window.setTimeout(() => {
626
+ B = window.setInterval(() => {
627
+ a.value && a.value.scrollBy({ left: -20, behavior: "auto" });
628
+ }, 50);
629
+ }, 300));
630
+ }, L = () => {
631
+ a.value && (j(), a.value.scrollBy({ left: 300, behavior: "smooth" }), D = window.setTimeout(() => {
632
+ B = window.setInterval(() => {
633
+ a.value && a.value.scrollBy({ left: 20, behavior: "auto" });
634
+ }, 50);
635
+ }, 300));
636
+ }, j = () => {
637
+ D && (clearTimeout(D), D = null), B && (clearInterval(B), B = null);
638
+ }, F = () => {
639
+ if (!a.value) return;
640
+ const { scrollLeft: n, scrollWidth: m, clientWidth: z } = a.value;
641
+ r.value = n > 10, c.value = n < m - z - 10;
642
+ }, ee = (n) => {
643
+ a.value && Math.abs(n.deltaY) > Math.abs(n.deltaX) && (n.preventDefault(), a.value.scrollBy({ left: n.deltaY, behavior: "auto" }));
644
+ }, J = $(!1), te = $(0), G = $(0), ae = (n) => {
645
+ !a.value || y.value === 1 || n.target.closest(".event-card") || (J.value = !0, te.value = n.pageX, G.value = a.value.scrollLeft, a.value.style.userSelect = "none", n.preventDefault());
646
+ }, se = (n) => {
647
+ if (!J.value || !a.value) return;
648
+ const m = n.pageX, z = (te.value - m) * 1.2;
649
+ a.value.scrollLeft = G.value + z;
650
+ }, p = () => {
651
+ a.value && (J.value = !1, a.value.style.userSelect = "");
652
+ };
653
+ return pe(() => {
654
+ a.value && (a.value.addEventListener("scroll", F), a.value.addEventListener("wheel", ee, { passive: !1 }), xe(() => {
655
+ F(), setTimeout(F, 50), setTimeout(F, 150), setTimeout(F, 300), setTimeout(F, 500);
656
+ })), document.addEventListener("mousemove", se), document.addEventListener("mouseup", p);
657
+ }), ze(() => {
658
+ document.removeEventListener("mousemove", se), document.removeEventListener("mouseup", p);
659
+ }), re(y, () => {
660
+ y.value > 1 ? xe(() => {
661
+ setTimeout(() => {
662
+ if (!a.value) return;
663
+ const { scrollWidth: n, clientWidth: m } = a.value;
664
+ n > m && (c.value = !0, r.value = !1);
665
+ }, 100);
666
+ }) : a.value && (a.value.style.cursor = "");
667
+ }), fe(() => {
668
+ j(), a.value && (a.value.removeEventListener("scroll", F), a.value.removeEventListener("wheel", ee));
669
+ }), (n, m) => {
670
+ const z = N("Button"), A = N("TooltipTrigger"), C = N("TooltipContent"), O = N("Tooltip");
671
+ return b(y) === 1 ? (o(), u("div", Wt, [
672
+ d(_e),
673
+ d(ke, {
674
+ class: "h-full",
675
+ "current-date": b(k)
676
+ }, null, 8, ["current-date"]),
677
+ d(ye, {
678
+ date: b(k),
679
+ events: w(b(k)),
680
+ resources: b(I)
681
+ }, null, 8, ["date", "events", "resources"])
682
+ ])) : (o(), u("div", Ht, [
683
+ b(y) === 7 ? (o(), u("div", Qt, [
684
+ d(b(ve), { size: 12 }),
685
+ m[0] || (m[0] = e("span", null, "Scroll to view all days", -1)),
686
+ d(b(ce), { size: 12 })
687
+ ])) : M("", !0),
688
+ r.value ? (o(), Q(z, {
689
+ key: 1,
690
+ variant: "outline",
691
+ size: "icon",
692
+ onMousedown: W,
693
+ onMouseup: j,
694
+ onMouseleave: j,
695
+ onTouchstart: W,
696
+ onTouchend: j,
697
+ class: "sticky top-1/2 left-2 -translate-y-1/2 z-40 h-10 w-10 rounded-full shadow-lg bg-background/95 backdrop-blur-sm hover:bg-background border-2"
698
+ }, {
699
+ default: S(() => [
700
+ d(b(ve), { size: 20 })
701
+ ]),
702
+ _: 1
703
+ })) : M("", !0),
704
+ c.value ? (o(), Q(z, {
705
+ key: 2,
706
+ variant: "outline",
707
+ size: "icon",
708
+ onMousedown: L,
709
+ onMouseup: j,
710
+ onMouseleave: j,
711
+ onTouchstart: L,
712
+ onTouchend: j,
713
+ class: "sticky top-1/2 right-2 -translate-y-1/2 z-40 h-10 w-10 rounded-full shadow-lg bg-background/95 backdrop-blur-sm hover:bg-background border-2 float-right"
714
+ }, {
715
+ default: S(() => [
716
+ d(b(ce), { size: 20 })
717
+ ]),
718
+ _: 1
719
+ })) : M("", !0),
720
+ d(ke, { class: "h-[calc(100%-164px)] mt-[122px]" }),
721
+ e("div", {
722
+ class: R(["absolute right-0 top-0 bottom-0 w-8 bg-gradient-to-l from-background to-transparent z-10 pointer-events-none transition-opacity duration-300", c.value ? "opacity-100" : "opacity-0"])
723
+ }, null, 2),
724
+ e("div", {
725
+ ref_key: "scrollContainer",
726
+ ref: a,
727
+ class: "absolute inset-0 overflow-x-auto overflow-y-visible",
728
+ onScroll: F,
729
+ onMousedown: ae
730
+ }, [
731
+ e("div", Xt, [
732
+ d(_e),
733
+ m[5] || (m[5] = e("div", { class: "absolute w-14 h-[125px] bg-input" }, null, -1)),
734
+ (o(!0), u(X, null, Y(s.value, (t, i) => (o(), u("div", {
735
+ key: t.toString(),
736
+ class: R(["flex-shrink-0", { "min-w-[200px] w-[33.33%]": b(y) === 3, "min-w-[280px]": b(y) === 7 }])
737
+ }, [
738
+ e("div", {
739
+ onClick: (x) => h(t),
740
+ class: R([
741
+ "relative p-3 border cursor-pointer transition-all duration-200 group relative",
742
+ _(t) ? "bg-gradient-to-br from-primary/10 to-primary/5 border-primary/30 hover:from-primary/20 hover:to-primary/10 hover:border-primary/50 hover:shadow-md" : "bg-gradient-to-br from-muted/50 to-muted/30 border-border hover:from-accent/50 hover:to-accent/30 hover:border-accent-foreground/20 hover:shadow-md"
743
+ ])
744
+ }, [
745
+ _(t) ? (o(), u("div", qt, [...m[1] || (m[1] = [
746
+ e("div", { class: "w-1.5 h-1.5 bg-primary rounded-full animate-pulse" }, null, -1),
747
+ e("span", { class: "text-[9px] font-bold text-primary uppercase tracking-wide" }, "Today", -1)
748
+ ])])) : M("", !0),
749
+ e("div", {
750
+ class: R([
751
+ "text-xs font-semibold uppercase tracking-wider transition-colors",
752
+ _(t) ? "text-primary group-hover:text-primary/80" : "text-muted-foreground group-hover:text-foreground"
753
+ ])
754
+ }, v(new Date(t.year, t.month - 1, t.day).toLocaleDateString("en-US", { weekday: "short" })), 3),
755
+ e("div", {
756
+ class: R([
757
+ "text-2xl font-bold transition-colors",
758
+ _(t) ? "text-foreground" : "text-foreground group-hover:text-primary"
759
+ ])
760
+ }, v(t.day), 3),
761
+ e("div", Jt, v(new Date(t.year, t.month - 1, t.day).toLocaleDateString("en-US", { month: "long", year: "numeric" })), 1),
762
+ m[4] || (m[4] = e("div", { class: "mt-2 pt-2 border-t border-border/0 group-hover:border-border/50 transition-all" }, [
763
+ e("div", { class: "text-[10px] text-muted-foreground/0 group-hover:text-muted-foreground/100 uppercase tracking-wide transition-all" }, " Click to view ")
764
+ ], -1)),
765
+ d(O, null, {
766
+ default: S(() => [
767
+ d(A, { "as-child": "" }, {
768
+ default: S(() => [
769
+ w(t).filter((x) => x.isException).length > 0 ? (o(), Q(b(Ie), {
770
+ key: 0,
771
+ class: "absolute top-3 right-3 size-4 text-orange-500"
772
+ })) : M("", !0)
773
+ ]),
774
+ _: 2
775
+ }, 1024),
776
+ d(C, null, {
777
+ default: S(() => [...m[2] || (m[2] = [
778
+ e("p", null, " This day has exceptions applied to it. ", -1)
779
+ ])]),
780
+ _: 1
781
+ })
782
+ ]),
783
+ _: 2
784
+ }, 1024),
785
+ d(O, null, {
786
+ default: S(() => [
787
+ d(A, { "as-child": "" }, {
788
+ default: S(() => [
789
+ w(t).filter((x) => x.isException).length > 0 ? (o(), u("div", Kt)) : M("", !0)
790
+ ]),
791
+ _: 2
792
+ }, 1024),
793
+ d(C, null, {
794
+ default: S(() => [...m[3] || (m[3] = [
795
+ e("p", null, " This day has exceptions applied to it. ", -1)
796
+ ])]),
797
+ _: 1
798
+ })
799
+ ]),
800
+ _: 2
801
+ }, 1024)
802
+ ], 10, Yt),
803
+ d(ye, {
804
+ date: t,
805
+ events: w(t),
806
+ resources: b(I)
807
+ }, null, 8, ["date", "events", "resources"])
808
+ ], 2))), 128))
809
+ ])
810
+ ], 544)
811
+ ]));
812
+ };
813
+ }
814
+ }), Zt = /* @__PURE__ */ Ne(Gt, [["__scopeId", "data-v-99339cf2"]]), es = { class: "flex flex-col gap-2 md:gap-4 w-full h-full" }, ts = { class: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 px-1" }, ss = { class: "flex items-center justify-between sm:justify-start gap-4" }, os = { class: "flex flex-col" }, ns = { class: "flex items-center gap-2" }, as = { class: "text-lg sm:text-2xl font-bold tracking-tight truncate" }, ls = { class: "text-xs sm:text-sm text-muted-foreground ml-7 truncate" }, rs = { class: "flex items-center justify-between sm:justify-end gap-2" }, is = { class: "flex items-center gap-1 sm:mr-2" }, us = {
815
+ key: 0,
816
+ class: "flex items-center gap-2 px-1 overflow-x-auto pb-2 -mx-1 scrollbar-hide"
817
+ }, ds = ["onClick"], cs = { class: "flex gap-4 flex-1 min-h-0 md:min-h-[1700px]" }, ms = { class: "hidden md:flex flex-shrink-0 flex-col gap-4" }, vs = {
818
+ key: 0,
819
+ class: "rounded-md border p-3"
820
+ }, ps = { class: "space-y-1" }, fs = ["onClick"], gs = { class: "min-w-0 flex-1" }, hs = { class: "text-sm font-medium truncate" }, xs = {
821
+ key: 0,
822
+ class: "pt-2 mt-2 border-t"
823
+ }, bs = {
824
+ key: 0,
825
+ class: "mt-1 space-y-1"
826
+ }, ys = { class: "min-w-0 flex-1" }, _s = { class: "text-sm font-medium truncate text-muted-foreground" }, zs = /* @__PURE__ */ K({
827
+ __name: "agenda",
828
+ setup(f) {
829
+ const { hasPermission: k } = Ue(), { params: y } = Se(), { config: T } = $e(), I = Te(T.project), a = $(ue(de())), r = $(1), c = $(typeof window < "u" ? window.innerWidth : 1024), s = U(() => c.value < 768), w = () => {
830
+ c.value = window.innerWidth;
831
+ };
832
+ pe(() => {
833
+ window.addEventListener("resize", w);
834
+ }), fe(() => {
835
+ window.removeEventListener("resize", w);
836
+ }), re(s, (t) => {
837
+ t && r.value !== 1 && (r.value = 1);
838
+ }, { immediate: !0 });
839
+ const _ = $(null), h = $(/* @__PURE__ */ new Map()), B = U(() => _.value?.resources || []), D = U(() => B.value.filter((t) => t.isActive)), W = U(() => B.value.filter((t) => !t.isActive)), L = $(null), j = $(!1);
840
+ re(D, (t) => {
841
+ t.length > 0 && !L.value && (L.value = t[0].id);
842
+ }, { immediate: !0 });
843
+ const F = U(() => {
844
+ if (!L.value)
845
+ return D.value.length > 0 ? [D.value[0]] : [];
846
+ const t = D.value.find((i) => i.id === L.value);
847
+ return t ? [t] : D.value.length > 0 ? [D.value[0]] : [];
848
+ }), ee = U(() => _.value?.pricingOptions?.find((i) => i.isDefault)?.duration || 30), J = (t) => {
849
+ L.value = t;
850
+ };
851
+ re(a, () => {
852
+ O();
853
+ });
854
+ const te = U(() => {
855
+ const t = a.value, i = new Date(t.year, t.month - 1, t.day), x = i.toLocaleDateString("en-US", { weekday: "long" }).toUpperCase(), g = t.day, E = i.toLocaleDateString("en-US", { month: "short" }).toUpperCase();
856
+ return {
857
+ dayName: x,
858
+ day: g,
859
+ monthName: E,
860
+ full: `${x} ${g} ${E}`
861
+ };
862
+ }), G = () => {
863
+ a.value = a.value.subtract({ days: r.value });
864
+ }, ae = () => {
865
+ a.value = a.value.add({ days: r.value });
866
+ }, se = () => {
867
+ a.value = ue(de());
868
+ }, p = (t) => {
869
+ const [i, x] = t.split(":").map(Number);
870
+ return i * 60 + x;
871
+ }, n = (t, i) => (_.value?.exceptions || []).find((g) => i >= g.startDate && i <= g.endDate ? g.resourceIds === null ? !0 : g.resourceIds?.includes(t) : !1) || null, m = (t, i, x) => {
872
+ const g = n(t.id, x);
873
+ if (g)
874
+ return g.isClosed ? [] : g.timeslots.map((l) => ({
875
+ startTime: l.startTime,
876
+ endTime: l.endTime,
877
+ isException: !0
878
+ }));
879
+ const E = i.getDay(), P = t.openingHours?.[E] || [];
880
+ return P.length === 0 ? [] : P.map((l) => ({
881
+ startTime: l.start,
882
+ endTime: l.end,
883
+ isException: !1
884
+ }));
885
+ }, z = (t, i, x, g) => {
886
+ if (!_.value) return 0;
887
+ const E = h.value.get(i);
888
+ if (!E) return 0;
889
+ const P = E.filter((l) => l.resourceId === t).reduce((l, V) => {
890
+ const H = p(V.startTime), oe = p(V.endTime), le = p(x), me = p(g);
891
+ return H < me && oe > le ? l + (V.reserved || 0) : l;
892
+ }, 0);
893
+ return P > 0 && console.log(`Found ${P} total bookings for ${t} on ${i} ${x}-${g}`), P;
894
+ }, A = U(() => {
895
+ if (!_.value) return [];
896
+ h.value.size;
897
+ let t = [], i = [];
898
+ for (let g = 0; g < r.value; g++) {
899
+ const E = a.value.add({ days: g });
900
+ i.push(E);
901
+ }
902
+ const x = F.value.length > 0 ? F.value : [];
903
+ return x.length === 0 ? [] : (i.forEach((g) => {
904
+ let E = new Date(g.year, g.month - 1, g.day);
905
+ const P = `${g.year}-${String(g.month).padStart(2, "0")}-${String(g.day).padStart(2, "0")}`;
906
+ x.forEach((l) => {
907
+ const V = m(l, E, P);
908
+ t = t.concat(V.map((H, oe) => {
909
+ const le = z(l.id, P, H.startTime, H.endTime);
910
+ return {
911
+ id: `block-${P}-${l.id}-${oe}`,
912
+ title: _.value.serviceName,
913
+ date: P,
914
+ startTime: H.startTime,
915
+ endTime: H.endTime,
916
+ theme: l.color || "#3b82f6",
917
+ bookings: le,
918
+ maxBookings: l.capacity,
919
+ isException: H.isException || !1,
920
+ resourceId: l.id,
921
+ resource: l,
922
+ // Store interval and duration for booking slot calculation
923
+ interval: l.interval || 30,
924
+ serviceDuration: ee.value
925
+ };
926
+ }));
927
+ });
928
+ }), t);
929
+ }), C = async () => {
930
+ _.value = await I.get(T.agendaCollection, y.value.id);
931
+ }, O = async () => {
932
+ const t = y.value.id, i = a.value;
933
+ h.value.clear();
934
+ const x = [];
935
+ for (let g = 0; g < r.value; g++) {
936
+ const E = i.add({ days: g }), P = `${E.year}-${String(E.month).padStart(2, "0")}-${String(E.day).padStart(2, "0")}`, l = `${t}_${P}`;
937
+ x.push(
938
+ I.get(T.reservedSpotsCollection, l).then((V) => {
939
+ if (V) {
940
+ let H = [];
941
+ for (const oe of D.value) {
942
+ const le = V?.[oe.id] || {};
943
+ Object.entries(le).forEach(([me, De]) => {
944
+ const [Ce, Me] = me.split("-");
945
+ H.push({
946
+ resourceId: oe.id,
947
+ startTime: Ce,
948
+ endTime: Me,
949
+ reserved: De
950
+ });
951
+ });
952
+ }
953
+ h.value.set(P, H);
954
+ }
955
+ }).catch(() => {
956
+ })
957
+ );
958
+ }
959
+ await Promise.all(x), console.log("Loaded reserved spots:", h.value);
960
+ };
961
+ return C(), O(), re(r, () => {
962
+ O();
963
+ }), Z("agendaData", _), Z("activeDate", a), Z("viewMode", r), Z("events", A), Z("resources", F), Z("allResources", D), (t, i) => {
964
+ const x = N("Button"), g = N("SegmentedControlButton"), E = N("SegmentedControl"), P = N("Calendar");
965
+ return o(), Q(Le, null, {
966
+ default: S(() => [
967
+ e("div", es, [
968
+ e("div", ts, [
969
+ e("div", ss, [
970
+ e("div", os, [
971
+ e("div", ns, [
972
+ d(b(Be), {
973
+ size: 20,
974
+ class: "text-primary flex-shrink-0"
975
+ }),
976
+ e("h2", as, v(te.value.full), 1)
977
+ ]),
978
+ e("p", ls, v(_.value?.serviceName), 1)
979
+ ]),
980
+ s.value && b(k)("manage-reservations") ? (o(), Q(be, { key: 0 })) : M("", !0)
981
+ ]),
982
+ e("div", rs, [
983
+ e("div", is, [
984
+ d(x, {
985
+ variant: "outline",
986
+ size: "icon",
987
+ class: "size-8 sm:size-9",
988
+ onClick: G
989
+ }, {
990
+ default: S(() => [
991
+ d(b(ve), { size: 16 })
992
+ ]),
993
+ _: 1
994
+ }),
995
+ d(x, {
996
+ variant: "outline",
997
+ size: "sm",
998
+ class: "h-8 sm:h-9 px-2 sm:px-3 text-xs sm:text-sm",
999
+ onClick: se
1000
+ }, {
1001
+ default: S(() => [...i[3] || (i[3] = [
1002
+ ne(" Today ", -1)
1003
+ ])]),
1004
+ _: 1
1005
+ }),
1006
+ d(x, {
1007
+ variant: "outline",
1008
+ size: "icon",
1009
+ class: "size-8 sm:size-9",
1010
+ onClick: ae
1011
+ }, {
1012
+ default: S(() => [
1013
+ d(b(ce), { size: 16 })
1014
+ ]),
1015
+ _: 1
1016
+ })
1017
+ ]),
1018
+ s.value ? M("", !0) : (o(), Q(E, {
1019
+ key: 0,
1020
+ modelValue: r.value,
1021
+ "onUpdate:modelValue": i[0] || (i[0] = (l) => r.value = l)
1022
+ }, {
1023
+ default: S(() => [
1024
+ d(g, { value: 1 }, {
1025
+ default: S(() => [...i[4] || (i[4] = [
1026
+ e("span", { class: "whitespace-nowrap" }, "1 Day", -1)
1027
+ ])]),
1028
+ _: 1
1029
+ }),
1030
+ d(g, { value: 3 }, {
1031
+ default: S(() => [...i[5] || (i[5] = [
1032
+ e("span", { class: "whitespace-nowrap" }, "3 Days", -1)
1033
+ ])]),
1034
+ _: 1
1035
+ }),
1036
+ d(g, { value: 7 }, {
1037
+ default: S(() => [...i[6] || (i[6] = [
1038
+ e("span", { class: "whitespace-nowrap" }, "7 Days", -1)
1039
+ ])]),
1040
+ _: 1
1041
+ })
1042
+ ]),
1043
+ _: 1
1044
+ }, 8, ["modelValue"])),
1045
+ !s.value && b(k)("manage-reservations") ? (o(), Q(be, { key: 1 })) : M("", !0)
1046
+ ])
1047
+ ]),
1048
+ s.value && D.value.length > 0 ? (o(), u("div", us, [
1049
+ (o(!0), u(X, null, Y(D.value, (l) => (o(), u("button", {
1050
+ key: l.id,
1051
+ class: R(["flex items-center gap-2 px-3 py-1.5 rounded-full border text-sm whitespace-nowrap transition-colors flex-shrink-0", {
1052
+ "bg-primary text-primary-foreground border-primary": L.value === l.id,
1053
+ "bg-background hover:bg-muted": L.value !== l.id
1054
+ }]),
1055
+ onClick: (V) => J(l.id)
1056
+ }, [
1057
+ e("div", {
1058
+ class: "size-5 rounded-full flex items-center justify-center text-white text-[10px] font-medium",
1059
+ style: q({ backgroundColor: L.value === l.id ? "rgba(255,255,255,0.3)" : l.color || "#6b7280" })
1060
+ }, v(l.avatarLabel || l.name.charAt(0).toUpperCase()), 5),
1061
+ e("span", null, v(l.name), 1)
1062
+ ], 10, ds))), 128))
1063
+ ])) : M("", !0),
1064
+ e("div", cs, [
1065
+ e("div", ms, [
1066
+ d(P, {
1067
+ modelValue: a.value,
1068
+ "onUpdate:modelValue": i[1] || (i[1] = (l) => a.value = l),
1069
+ "weekday-format": "short",
1070
+ class: "rounded-md border"
1071
+ }, null, 8, ["modelValue"]),
1072
+ B.value.length > 0 ? (o(), u("div", vs, [
1073
+ i[7] || (i[7] = e("div", { class: "flex items-center justify-between mb-3" }, [
1074
+ e("span", { class: "text-sm font-medium" }, "Resources")
1075
+ ], -1)),
1076
+ e("div", ps, [
1077
+ (o(!0), u(X, null, Y(D.value, (l) => (o(), u("div", {
1078
+ key: l.id,
1079
+ class: R(["flex items-center gap-2 p-2 rounded-md hover:bg-muted cursor-pointer transition-colors", {
1080
+ "bg-muted ring-2 ring-primary/20": L.value === l.id,
1081
+ "opacity-50": L.value && L.value !== l.id
1082
+ }]),
1083
+ onClick: (V) => J(l.id)
1084
+ }, [
1085
+ e("div", {
1086
+ class: "size-7 rounded-full flex items-center justify-center text-white text-xs font-medium flex-shrink-0",
1087
+ style: q({ backgroundColor: l.color || "#6b7280" })
1088
+ }, v(l.avatarLabel || l.name.charAt(0).toUpperCase()), 5),
1089
+ e("div", gs, [
1090
+ e("div", hs, v(l.name), 1)
1091
+ ]),
1092
+ e("div", {
1093
+ class: R(["size-2 rounded-full flex-shrink-0", L.value === l.id ? "bg-primary" : "bg-muted-foreground/30"])
1094
+ }, null, 2)
1095
+ ], 10, fs))), 128)),
1096
+ W.value.length > 0 ? (o(), u("div", xs, [
1097
+ e("button", {
1098
+ class: "flex items-center gap-2 text-xs text-muted-foreground hover:text-foreground w-full py-1 transition-colors",
1099
+ onClick: i[2] || (i[2] = (l) => j.value = !j.value)
1100
+ }, [
1101
+ d(b(ce), {
1102
+ size: 14,
1103
+ class: R(["transition-transform", { "rotate-90": j.value }])
1104
+ }, null, 8, ["class"]),
1105
+ e("span", null, "Inactive (" + v(W.value.length) + ")", 1)
1106
+ ]),
1107
+ j.value ? (o(), u("div", bs, [
1108
+ (o(!0), u(X, null, Y(W.value, (l) => (o(), u("div", {
1109
+ key: l.id,
1110
+ class: "flex items-center gap-2 p-2 rounded-md opacity-50"
1111
+ }, [
1112
+ e("div", {
1113
+ class: "size-7 rounded-full flex items-center justify-center text-white text-xs font-medium flex-shrink-0 grayscale",
1114
+ style: q({ backgroundColor: l.color || "#6b7280" })
1115
+ }, v(l.avatarLabel || l.name.charAt(0).toUpperCase()), 5),
1116
+ e("div", ys, [
1117
+ e("div", _s, v(l.name), 1)
1118
+ ])
1119
+ ]))), 128))
1120
+ ])) : M("", !0)
1121
+ ])) : M("", !0)
1122
+ ])
1123
+ ])) : M("", !0)
1124
+ ]),
1125
+ d(Zt)
1126
+ ])
1127
+ ])
1128
+ ]),
1129
+ _: 1
1130
+ });
1131
+ };
1132
+ }
1133
+ });
1134
+ export {
1135
+ zs as default
1136
+ };