your-ai-workflow-firebase-os 2.0.1 → 2.0.3

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 (183) hide show
  1. package/dist/AccessNotice-BZ5Gt1nP.js +40 -0
  2. package/dist/AccessNotice-CN7kc70o.cjs +1 -0
  3. package/dist/{AddressField-R-HvndkG.js → AddressField-9Sqn8TvC.js} +3 -3
  4. package/dist/{AddressField-BkzFOo2t.cjs → AddressField-B7wtV8yA.cjs} +1 -1
  5. package/dist/Assets-DBMwZ3bN.cjs +1 -0
  6. package/dist/Assets-DT-NU_WO.js +296 -0
  7. package/dist/Attachments-Bl9_dfsu.js +46 -0
  8. package/dist/Attachments-UVK9SRXf.cjs +1 -0
  9. package/dist/Billing-0RIHayHy.cjs +1 -0
  10. package/dist/Billing-FNE2r3_d.js +379 -0
  11. package/dist/BookingCalendar-BP5kiv3d.cjs +1 -0
  12. package/dist/BookingCalendar-DZ2fEFja.js +309 -0
  13. package/dist/Button-4lzOE31p.js +48 -0
  14. package/dist/Button-5DlB2MCi.cjs +1 -0
  15. package/dist/CalendarView-BimoXy_k.cjs +1 -0
  16. package/dist/CalendarView-D-ykjpvI.js +664 -0
  17. package/dist/ConfirmModal-Di9GR-vV.cjs +1 -0
  18. package/dist/ConfirmModal-gKQEpd4d.js +113 -0
  19. package/dist/ContactPopup-BXnHrRwl.js +1114 -0
  20. package/dist/ContactPopup-lxmRMoIa.cjs +1 -0
  21. package/dist/CopyLink-BpEQWmfI.cjs +1 -0
  22. package/dist/CopyLink-CBAVfcm1.js +43 -0
  23. package/dist/DashboardNav-CXa_ci-_.cjs +1 -0
  24. package/dist/DashboardNav-Dmn7PVSp.js +886 -0
  25. package/dist/EmailAdmin-CjN_rvxT.js +318 -0
  26. package/dist/EmailAdmin-lAEBdY1s.cjs +1 -0
  27. package/dist/EventCard-46EquygT.cjs +1 -0
  28. package/dist/EventCard-B6xD-mk3.js +97 -0
  29. package/dist/FileViewerPopup-CX-J75TM.js +1283 -0
  30. package/dist/FileViewerPopup-D8-MmIoS.cjs +3 -0
  31. package/dist/FormNote-BivRNA3J.js +50 -0
  32. package/dist/FormNote-BtdTGpml.cjs +1 -0
  33. package/dist/FormsAdmin-B5PBCG2W.js +812 -0
  34. package/dist/FormsAdmin-BQCULvi5.cjs +1 -0
  35. package/dist/Inbox-BPk2ZkE5.js +779 -0
  36. package/dist/Inbox-DNrcBx0o.cjs +3 -0
  37. package/dist/Loader-Bu89fsbB.cjs +1 -0
  38. package/dist/Loader-D4gwgBOq.js +32 -0
  39. package/dist/ManagePlanButton-B0dwqZBd.cjs +1 -0
  40. package/dist/ManagePlanButton-BSrOHYze.js +29 -0
  41. package/dist/MyBookings-6qr0GgzO.cjs +1 -0
  42. package/dist/MyBookings-BQjGM2LQ.js +113 -0
  43. package/dist/PageTitle-CZhgmmDT.cjs +3 -0
  44. package/dist/PageTitle-D93YCiN8.js +1606 -0
  45. package/dist/PagesAdmin-BcHIcqM5.cjs +34 -0
  46. package/dist/PagesAdmin-D69P9nRb.js +5802 -0
  47. package/dist/PagesAdmin-DNwZOKjA.cjs +1 -0
  48. package/dist/PagesAdmin-HUITEcHx.js +3 -0
  49. package/dist/PaymentsAdmin-C2iCI9qC.js +1291 -0
  50. package/dist/PaymentsAdmin-CoXi2vCm.cjs +2 -0
  51. package/dist/{PhoneInputField-B3P_vUDW.cjs → PhoneInputField-BEwYZMB7.cjs} +1 -1
  52. package/dist/{PhoneInputField-BlYHb5e0.js → PhoneInputField-BG0L2djE.js} +2 -2
  53. package/dist/PhoneInputField-DfOtCIH_.js +2 -0
  54. package/dist/{PhoneInputField-CdNTvWXQ.cjs → PhoneInputField-jhWvto8C.cjs} +1 -1
  55. package/dist/Popup-DHYGFl2-.cjs +1 -0
  56. package/dist/Popup-xROLytgr.js +142 -0
  57. package/dist/ProviderMark-BBfaM5Yl.js +52 -0
  58. package/dist/ProviderMark-xLkUN3Fx.cjs +1 -0
  59. package/dist/PublishApp-Bm-6r3Td.js +595 -0
  60. package/dist/PublishApp-D4XJUkJa.cjs +2 -0
  61. package/dist/Said-CoC15awL.js +94 -0
  62. package/dist/Said-IqCNofdh.cjs +1 -0
  63. package/dist/ScheduleAdmin-BKfQkrR8.js +1853 -0
  64. package/dist/ScheduleAdmin-DwK36GAZ.cjs +1 -0
  65. package/dist/SchedulePicker--urIH2Eb.js +112 -0
  66. package/dist/SchedulePicker-nmqzUnUH.cjs +1 -0
  67. package/dist/Setup-CHLgd-ag.js +849 -0
  68. package/dist/Setup-CaDranTm.cjs +1374 -0
  69. package/dist/SetupPayments-CVIwh1eQ.js +411 -0
  70. package/dist/SetupPayments-HNXWA25X.cjs +1 -0
  71. package/dist/SignInAdmin-C94-A-0w.cjs +4 -0
  72. package/dist/SignInAdmin-Yxgv_8U4.js +766 -0
  73. package/dist/SupportBar-CDT0HwdP.cjs +1 -0
  74. package/dist/SupportBar-CN_JGC-9.js +117 -0
  75. package/dist/SystemTabContent-L3vGGF3P.cjs +1 -0
  76. package/dist/SystemTabContent-QdxxLILE.js +35 -0
  77. package/dist/TemplateDrive-DV8zNjYe.cjs +1 -0
  78. package/dist/TemplateDrive-NJY_AAvV.js +1197 -0
  79. package/dist/ThemeAdmin-BzFjJkLg.js +269 -0
  80. package/dist/ThemeAdmin-DVnPNxe7.cjs +1 -0
  81. package/dist/ThemeAdmin-DY7Vc4Sj.cjs +3 -0
  82. package/dist/ThemeAdmin-DnC-D2N3.js +2 -0
  83. package/dist/{ContactPopup-9J_YeJrb.js → TimeZoneField-DkI1Bkcz.js} +3382 -5513
  84. package/dist/TimeZoneField-qs7NPR30.cjs +12 -0
  85. package/dist/TransactionsAdmin-BsZ-oQWi.js +582 -0
  86. package/dist/TransactionsAdmin-CTSTiPld.cjs +1 -0
  87. package/dist/Trouble-9es_AI4F.cjs +1 -0
  88. package/dist/Trouble-oWt9fMsm.js +164 -0
  89. package/dist/Users-CTitWXyd.cjs +1 -0
  90. package/dist/Users-DJjQTWJF.js +1207 -0
  91. package/dist/aiModels-DIP9fn8T.cjs +1 -0
  92. package/dist/{aiModels-BHlEfuRJ.js → aiModels-DnDhNGup.js} +29 -61
  93. package/dist/arrivalRoads-BJ-35vkk.js +228 -0
  94. package/dist/arrivalRoads-qoU-B4jt.cjs +4 -0
  95. package/dist/{bake-D0gLVNTL.cjs → bake-n2wyFw0B.cjs} +1 -1
  96. package/dist/{bake-OErV2MLy.js → bake-naZeMu98.js} +14 -14
  97. package/dist/bookingPages-C7a3srPG.js +102 -0
  98. package/dist/bookingPages-DvbFbD9X.cjs +1 -0
  99. package/dist/components/CustomSelect.d.ts +7 -1
  100. package/dist/components/RegistrationFields.d.ts +6 -1
  101. package/dist/components/Reveal.d.ts +12 -0
  102. package/dist/components/ScrollToTop.d.ts +4 -0
  103. package/dist/contentFallback-C9MZjdq7.cjs +1 -0
  104. package/dist/contentFallback-CEDY0Pwp.js +96 -0
  105. package/dist/contentKey-Bwry4lDa.js +13 -0
  106. package/dist/contentKey-DJGYYnAE.cjs +1 -0
  107. package/dist/{dist-_zWHDDrc.js → dist-DUPvBnOA.js} +1 -1
  108. package/dist/email-BfnZnMwD.cjs +1 -0
  109. package/dist/email-Ddj8Dlu6.js +58 -0
  110. package/dist/{fileBytes-B0qxHYQL.cjs → fileBytes-BJPaiX9Y.cjs} +1 -1
  111. package/dist/{fileBytes-uhq3pGCS.js → fileBytes-bjgvCfWu.js} +2 -2
  112. package/dist/forms-Bvx9HTM6.js +75 -0
  113. package/dist/forms-CmNeTETW.cjs +1 -0
  114. package/dist/lib/ThemeContext.d.ts +0 -14
  115. package/dist/lib/bareImgWatch.d.ts +6 -1
  116. package/dist/lib/localEdits.d.ts +2 -0
  117. package/dist/lib/pageDesignLines.d.ts +1 -1
  118. package/dist/lib/paymentProducts.d.ts +8 -0
  119. package/dist/lib/payments.d.ts +11 -1
  120. package/dist/lib/people.d.ts +9 -0
  121. package/dist/lib/recordsKey.d.ts +24 -0
  122. package/dist/{lucide-react-DiyP8FA_.js → lucide-react-CA7GD7Nv.js} +8 -8
  123. package/dist/notices-B7iIrIEg.js +29 -0
  124. package/dist/notices-upMg8UVh.cjs +1 -0
  125. package/dist/openOnArrival-Buwqb86D.cjs +1 -0
  126. package/dist/openOnArrival-S2K6v-lB.js +35 -0
  127. package/dist/pageFiles--Ih60ITP.js +45 -0
  128. package/dist/pageFiles-UtBmlOcD.cjs +1 -0
  129. package/dist/pages/PagesAdmin.d.ts +69 -7
  130. package/dist/{pdf-DLuvpvHg.js → pdf-DRXcPGkr.js} +1 -1
  131. package/dist/{pdf.worker.min-C0gkd2Ec.js → pdf.worker.min-CfKZezeM.js} +1 -1
  132. package/dist/people-2jZE_pdI.js +102 -0
  133. package/dist/people-BpVvIr9-.cjs +1 -0
  134. package/dist/personName-CFw3pxuu.js +18 -0
  135. package/dist/personName-CbzN_i57.cjs +1 -0
  136. package/dist/publishSteps-C1cDFzzB.js +88 -0
  137. package/dist/publishSteps-SSm8afDw.cjs +1 -0
  138. package/dist/recordLock-DHVvI9bP.js +61 -0
  139. package/dist/recordLock-DWeIxiwh.cjs +1 -0
  140. package/dist/recordsKey-B7QrxdeU.cjs +1 -0
  141. package/dist/recordsKey-D5-wC0Aw.js +141 -0
  142. package/dist/registrationFields-CLeR2lQJ.js +181 -0
  143. package/dist/registrationFields-v4pOoRdn.cjs +1 -0
  144. package/dist/renderer.cjs.js +1 -1
  145. package/dist/renderer.es.js +1 -1
  146. package/dist/roles-D6VaHWfV.js +147 -0
  147. package/dist/roles-DQUFFBQe.cjs +1 -0
  148. package/dist/scheduleData-ATN8w5hI.js +727 -0
  149. package/dist/scheduleData-Cltj0ABZ.cjs +1 -0
  150. package/dist/server.cjs.js +6 -6
  151. package/dist/server.es.js +716 -715
  152. package/dist/serviceStatus-TQyZO_Y_.cjs +1 -0
  153. package/dist/serviceStatus-vS8AI7SZ.js +125 -0
  154. package/dist/tabAudience-BqpN6dsR.cjs +1 -0
  155. package/dist/tabAudience-CRyMvv0v.js +34 -0
  156. package/dist/transactions-BqMQDRx3.js +343 -0
  157. package/dist/transactions-CufFrdAM.cjs +1 -0
  158. package/dist/useIsPhone-BVGx_X3e.js +13 -0
  159. package/dist/useIsPhone-o63tNneA.cjs +1 -0
  160. package/dist/{validate-DzSJWuyL.js → validate-CmC_tLK-.js} +433 -351
  161. package/dist/validate-DZMwqSrb.cjs +103 -0
  162. package/dist/vite/validate.d.ts +14 -0
  163. package/dist/vite.cjs.js +1 -1
  164. package/dist/vite.es.js +1 -1
  165. package/dist/your-ai-workflow-firebase-os.cjs.js +15 -1431
  166. package/dist/your-ai-workflow-firebase-os.css +1 -1
  167. package/dist/your-ai-workflow-firebase-os.es.js +11695 -35911
  168. package/package.json +1 -1
  169. package/src/index.css +122 -2
  170. package/dist/ContactPopup-DF8qQCoY.cjs +0 -12
  171. package/dist/PhoneInputField-Btx07xvM.js +0 -2
  172. package/dist/aiModels-BIhoTNH0.cjs +0 -1
  173. package/dist/validate-e48WXJdP.cjs +0 -103
  174. /package/dist/{address-DI1YaCI4.cjs → address-Bsb8COq2.cjs} +0 -0
  175. /package/dist/{address-Ca1h_UZX.js → address-C2bHNxJU.js} +0 -0
  176. /package/dist/{dist-BLGlDv1e.cjs → dist-E4jTFPs7.cjs} +0 -0
  177. /package/dist/{lucide-react-BYniZ3lQ.cjs → lucide-react-BwV6L6Is.cjs} +0 -0
  178. /package/dist/{mediaKind-dk396a03.cjs → mediaKind-D0MWyv6b.cjs} +0 -0
  179. /package/dist/{mediaKind-De2Cx_kB.js → mediaKind-DmKMsjeY.js} +0 -0
  180. /package/dist/{pdf-CC5g01eC.cjs → pdf-jLjjhvjp.cjs} +0 -0
  181. /package/dist/{pdf.worker.min-pI_P-OCl.cjs → pdf.worker.min-bLgNWd7w.cjs} +0 -0
  182. /package/dist/{verifiedAccount-C1iCxopN.js → verifiedAccount-DRbRFJ6H.js} +0 -0
  183. /package/dist/{verifiedAccount-D3OeaOBo.cjs → verifiedAccount-DScyKk96.cjs} +0 -0
@@ -0,0 +1,1853 @@
1
+ import { a as e, t } from "./PageTitle-D93YCiN8.js";
2
+ import { Bt as n, C as r, Dt as i, Ei as a, En as o, F as s, G as c, H as l, Ht as u, Ii as d, J as f, Ji as p, L as m, Lt as h, Nt as g, P as _, R as v, Rt as y, S as b, Tn as x, U as S, Ui as C, Vt as w, _ as T, _t as E, ai as D, at as O, b as k, bt as ee, c as A, dr as j, ea as M, fn as te, h as N, i as P, k as ne, ka as re, mt as ie, nr as F, nt as I, o as L, ot as ae, qi as oe, s as R, sr as se, t as ce, tt as le, v as ue, vt as de, x as z, xn as fe, ya as pe, yt as me, z as he, zt as ge } from "./TimeZoneField-DkI1Bkcz.js";
3
+ import { t as _e } from "./DashboardNav-Dmn7PVSp.js";
4
+ import { p as ve } from "./verifiedAccount-DRbRFJ6H.js";
5
+ import { C as B, G as V, I as ye, _n as be, dn as xe, h as Se, o as H, on as U, vt as Ce, xn as we, yn as Te } from "./lucide-react-CA7GD7Nv.js";
6
+ import { n as Ee } from "./Loader-D4gwgBOq.js";
7
+ import { A as De, C as Oe, F as ke, I as Ae, L as W, M as je, N as Me, P as Ne, R as Pe, S as Fe, _ as Ie, a as Le, b as Re, c as ze, d as Be, f as Ve, g as He, j as Ue, k as We, l as Ge, m as G, n as Ke, o as qe, p as Je, r as Ye, t as Xe, u as Ze, x as Qe, z as $e } from "./scheduleData-ATN8w5hI.js";
8
+ import { r as et } from "./notices-B7iIrIEg.js";
9
+ import { t as tt } from "./ConfirmModal-gKQEpd4d.js";
10
+ import { r as nt } from "./email-Ddj8Dlu6.js";
11
+ import { a as rt, c as it, f as at, i as ot, l as st, m as ct, n as lt, p as ut, r as dt, s as ft, t as pt, u as mt } from "./bookingPages-C7a3srPG.js";
12
+ import { i as ht } from "./AccessNotice-BZ5Gt1nP.js";
13
+ import { n as gt } from "./SystemTabContent-QdxxLILE.js";
14
+ import { n as _t } from "./serviceStatus-vS8AI7SZ.js";
15
+ import { t as vt } from "./CalendarView-D-ykjpvI.js";
16
+ import { t as yt } from "./CopyLink-CBAVfcm1.js";
17
+ import { useEffect as K, useMemo as q, useRef as J, useState as Y } from "react";
18
+ import { Fragment as X, jsx as Z, jsxs as Q } from "react/jsx-runtime";
19
+ import { collection as bt, doc as xt, setDoc as St } from "firebase/firestore";
20
+ import { Link as Ct, useSearchParams as wt } from "react-router-dom";
21
+ //#region src/components/schedule/BlockedDatesField.tsx
22
+ var Tt = "w-[6.5rem] shrink-0", Et = "w-9 h-9 rounded-[var(--btn-radius,0.75rem)] border border-[var(--panel-border)] flex items-center justify-center shrink-0 text-foreground/45 hover:text-red-500 hover:border-red-500/40 hover:bg-red-500/[0.06] active:scale-[0.98] transition-all cursor-pointer", Dt = "date-field h-9 w-[10.5rem] shrink-0 px-3 text-[13px] font-semibold bg-transparent border border-[var(--panel-border)] text-foreground focus:outline-none focus:border-accent transition-colors", Ot = {
23
+ from: "09:00",
24
+ to: "13:00"
25
+ };
26
+ function kt(e, t) {
27
+ return {
28
+ upcoming: e.filter((e) => e.date >= t),
29
+ past: e.filter((e) => e.date < t)
30
+ };
31
+ }
32
+ function At({ row: e, onChange: t, onRemove: n }) {
33
+ let r = e.windows.length === 0, i = (n, r) => t({
34
+ ...e,
35
+ windows: e.windows.map((e, t) => t === n ? {
36
+ ...e,
37
+ ...r
38
+ } : e)
39
+ });
40
+ return /* @__PURE__ */ Q("div", {
41
+ className: "flex flex-col gap-2 py-2.5",
42
+ children: [/* @__PURE__ */ Q("div", {
43
+ className: "flex items-center gap-2 flex-wrap",
44
+ children: [
45
+ /* @__PURE__ */ Z("input", {
46
+ type: "date",
47
+ value: e.date,
48
+ "aria-label": "The date",
49
+ onChange: (n) => t({
50
+ ...e,
51
+ date: n.target.value
52
+ }),
53
+ className: Dt,
54
+ style: { borderRadius: "var(--input-radius, 0.75rem)" }
55
+ }),
56
+ /* @__PURE__ */ Z("div", {
57
+ className: "w-[11rem] shrink-0",
58
+ children: /* @__PURE__ */ Z(F, {
59
+ ariaLabel: `${e.date} — how much of it`,
60
+ value: r ? "all" : "some",
61
+ options: [{
62
+ value: "all",
63
+ label: "All day"
64
+ }, {
65
+ value: "some",
66
+ label: "Only some hours"
67
+ }],
68
+ onChange: (n) => t({
69
+ ...e,
70
+ windows: n === "all" ? [] : [Ot]
71
+ }),
72
+ className: "console-select",
73
+ compact: !0,
74
+ dense: !0,
75
+ portal: !0,
76
+ direction: "auto"
77
+ })
78
+ }),
79
+ /* @__PURE__ */ Z("button", {
80
+ type: "button",
81
+ title: `Remove ${e.date || "this date"}`,
82
+ "aria-label": `Remove ${e.date || "this date"}`,
83
+ onClick: n,
84
+ className: `${Et} ml-auto`,
85
+ children: /* @__PURE__ */ Z(H, { className: "w-3.5 h-3.5" })
86
+ })
87
+ ]
88
+ }), !r && /* @__PURE__ */ Q("div", {
89
+ className: "flex flex-col gap-2 sm:pl-[0.125rem]",
90
+ children: [e.windows.map((n, r) => /* @__PURE__ */ Q("div", {
91
+ className: "flex items-center gap-2",
92
+ children: [
93
+ /* @__PURE__ */ Z("div", {
94
+ className: Tt,
95
+ children: /* @__PURE__ */ Z(F, {
96
+ ariaLabel: `${e.date} from${r ? ` (${r + 1})` : ""}`,
97
+ value: n.from,
98
+ options: l,
99
+ onChange: (e) => i(r, { from: e }),
100
+ className: "console-select",
101
+ compact: !0,
102
+ portal: !0,
103
+ direction: "auto"
104
+ })
105
+ }),
106
+ /* @__PURE__ */ Z("span", {
107
+ className: "w-3 text-center text-foreground/40 text-[13px] shrink-0 select-none",
108
+ children: "–"
109
+ }),
110
+ /* @__PURE__ */ Z("div", {
111
+ className: Tt,
112
+ children: /* @__PURE__ */ Z(F, {
113
+ ariaLabel: `${e.date} to${r ? ` (${r + 1})` : ""}`,
114
+ value: n.to,
115
+ options: he,
116
+ onChange: (e) => i(r, { to: e }),
117
+ className: "console-select",
118
+ compact: !0,
119
+ portal: !0,
120
+ direction: "auto"
121
+ })
122
+ }),
123
+ e.windows.length > 1 && /* @__PURE__ */ Z("button", {
124
+ type: "button",
125
+ title: `Remove these hours on ${e.date}`,
126
+ "aria-label": `Remove ${e.date} hours ${r + 1}`,
127
+ onClick: () => t({
128
+ ...e,
129
+ windows: e.windows.filter((e, t) => t !== r)
130
+ }),
131
+ className: Et,
132
+ children: /* @__PURE__ */ Z(H, { className: "w-3.5 h-3.5" })
133
+ })
134
+ ]
135
+ }, r)), e.windows.length < 2 && /* @__PURE__ */ Z("button", {
136
+ type: "button",
137
+ onClick: () => t({
138
+ ...e,
139
+ windows: [...e.windows, {
140
+ from: "14:00",
141
+ to: "18:00"
142
+ }]
143
+ }),
144
+ className: "self-start h-6 px-1 text-[11.5px] font-semibold text-foreground/45 hover:text-accent transition-colors cursor-pointer",
145
+ children: "+ Add a second stretch"
146
+ })]
147
+ })]
148
+ });
149
+ }
150
+ function jt({ blocked: e, onChange: t, now: n }) {
151
+ let r = o(n ? n() : /* @__PURE__ */ new Date()), [i, a] = Y(!1), { upcoming: s, past: c } = kt(e, r), l = i ? [...c, ...s] : s, u = (n, r) => t(e.map((e) => e === n ? r : e));
152
+ return /* @__PURE__ */ Z(P, {
153
+ label: "Days away",
154
+ hint: "Dates this week's hours do not apply to — a holiday, a flight, an afternoon out. Nobody can book them, on any link on these hours.",
155
+ children: /* @__PURE__ */ Q("div", {
156
+ className: "flex flex-col divide-y divide-[var(--panel-border)]/60 rounded-2xl border border-[var(--panel-border)]/60 px-4 py-1",
157
+ children: [l.length === 0 ? /* @__PURE__ */ Z("p", {
158
+ className: `${R} py-3`,
159
+ children: "No days blocked out. Add one for a holiday or a day off."
160
+ }) : l.map((n, r) => /* @__PURE__ */ Z(At, {
161
+ row: n,
162
+ onChange: (e) => u(n, e),
163
+ onRemove: () => t(e.filter((e) => e !== n))
164
+ }, `${n.date}-${r}`)), /* @__PURE__ */ Q("div", {
165
+ className: "flex items-center justify-between gap-3 py-2.5",
166
+ children: [/* @__PURE__ */ Z(L, {
167
+ icon: V,
168
+ compact: !0,
169
+ title: "Add a day away",
170
+ onClick: () => t([...e, {
171
+ date: r,
172
+ windows: []
173
+ }]),
174
+ children: "Add a date"
175
+ }), c.length > 0 && /* @__PURE__ */ Z("button", {
176
+ type: "button",
177
+ onClick: () => a((e) => !e),
178
+ className: "h-6 px-1 text-[11.5px] font-semibold text-foreground/45 hover:text-accent transition-colors cursor-pointer",
179
+ children: i ? "Hide past dates" : `Show ${c.length} past date${c.length === 1 ? "" : "s"}`
180
+ })]
181
+ })]
182
+ })
183
+ });
184
+ }
185
+ //#endregion
186
+ //#region src/components/schedule/BookingQuestionsField.tsx
187
+ var Mt = (e) => s.find((t) => t.value === e)?.label || "Short text";
188
+ function Nt({ options: e, onChange: t }) {
189
+ return /* @__PURE__ */ Z(P, {
190
+ label: "Choices",
191
+ hint: "What people pick from.",
192
+ children: /* @__PURE__ */ Q("div", {
193
+ className: "flex flex-col gap-2",
194
+ children: [
195
+ e.length === 0 && /* @__PURE__ */ Z("span", {
196
+ className: "text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug px-1",
197
+ children: "No choices yet — add the first one."
198
+ }),
199
+ e.map((n, r) => /* @__PURE__ */ Q("div", {
200
+ className: "flex items-center gap-2",
201
+ children: [/* @__PURE__ */ Z("input", {
202
+ type: "text",
203
+ value: n,
204
+ "aria-label": `Choice ${r + 1}`,
205
+ placeholder: "e.g. At my place",
206
+ onChange: (n) => t(e.map((e, t) => t === r ? n.target.value : e)),
207
+ className: A
208
+ }), /* @__PURE__ */ Z(L, {
209
+ icon: H,
210
+ tone: "danger",
211
+ compact: !0,
212
+ title: `Remove choice ${r + 1}`,
213
+ onClick: () => t(e.filter((e, t) => t !== r)),
214
+ children: "Remove"
215
+ })]
216
+ }, r)),
217
+ /* @__PURE__ */ Z("div", { children: /* @__PURE__ */ Z(L, {
218
+ icon: V,
219
+ onClick: () => t([...e, ""]),
220
+ children: "Add choice"
221
+ }) })
222
+ ]
223
+ })
224
+ });
225
+ }
226
+ function Pt({ question: e, index: t, count: n, siblings: i, fixed: a, onChange: o, onMove: c, onRemove: l }) {
227
+ let [u, d] = Y(!e.label.trim()), f = e.label.trim() || "A new question";
228
+ return /* @__PURE__ */ Q("div", {
229
+ className: "rounded-2xl border border-[var(--panel-border)]",
230
+ children: [/* @__PURE__ */ Q("div", {
231
+ className: "flex items-center gap-1.5 sm:gap-2.5 pr-2.5 sm:pr-3.5",
232
+ children: [/* @__PURE__ */ Q("button", {
233
+ type: "button",
234
+ onClick: () => d((e) => !e),
235
+ "aria-expanded": u,
236
+ className: "flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3.5 text-left cursor-pointer",
237
+ children: [/* @__PURE__ */ Z("span", {
238
+ className: "text-[13px] font-semibold text-foreground/75 truncate",
239
+ children: f
240
+ }), /* @__PURE__ */ Q("span", {
241
+ className: "flex items-center gap-2.5 shrink-0",
242
+ children: [/* @__PURE__ */ Z("span", {
243
+ className: `${R} max-sm:hidden`,
244
+ children: a ? "Always asked" : `${Mt(e.type)}${e.required ? " · must be answered" : ""}`
245
+ }), /* @__PURE__ */ Z(U, { className: `w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${u ? "rotate-180" : ""}` })]
246
+ })]
247
+ }), !a && /* @__PURE__ */ Q("div", {
248
+ className: "flex items-center gap-1 sm:gap-1.5 shrink-0",
249
+ children: [
250
+ /* @__PURE__ */ Z(L, {
251
+ icon: be,
252
+ compact: !0,
253
+ disabled: t === 0,
254
+ title: `Move ${f} up`,
255
+ onClick: () => c(-1),
256
+ children: "Up"
257
+ }),
258
+ /* @__PURE__ */ Z(L, {
259
+ icon: we,
260
+ compact: !0,
261
+ disabled: t === n - 1,
262
+ title: `Move ${f} down`,
263
+ onClick: () => c(1),
264
+ children: "Down"
265
+ }),
266
+ /* @__PURE__ */ Z("span", { className: "max-sm:hidden w-px h-5 bg-[var(--panel-border)] mx-0.5" }),
267
+ /* @__PURE__ */ Z(L, {
268
+ icon: B,
269
+ tone: "danger",
270
+ compact: !0,
271
+ title: `Remove ${f}`,
272
+ onClick: l,
273
+ children: "Remove"
274
+ })
275
+ ]
276
+ })]
277
+ }), u && /* @__PURE__ */ Q("div", {
278
+ className: "px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4",
279
+ children: [
280
+ /* @__PURE__ */ Z(z, {
281
+ label: "What are you asking?",
282
+ hint: a ? "The words above the box. Every booking asks this one — you can only change how it is put." : "The words above the box, as the person booking reads them.",
283
+ value: e.label,
284
+ placeholder: a ? "e.g. Who is coming?" : "e.g. What is your phone number?",
285
+ onChange: (t) => o({
286
+ ...e,
287
+ label: t,
288
+ name: a ? e.name : ee(e, t, i)
289
+ })
290
+ }),
291
+ !a && /* @__PURE__ */ Q(X, { children: [/* @__PURE__ */ Z(T, {
292
+ label: "Kind of answer",
293
+ hint: "Sets the box they type into. The example below follows what you pick.",
294
+ value: e.type,
295
+ options: s,
296
+ allowEmpty: !1,
297
+ onChange: (t) => o({
298
+ ...e,
299
+ type: t,
300
+ options: t === "select" ? e.options : [],
301
+ placeholder: de(e, t)
302
+ })
303
+ }), /* @__PURE__ */ Z(r, {
304
+ label: "Must be answered",
305
+ hint: "On means they cannot book until it is filled in.",
306
+ hintWideOnly: !0,
307
+ enabled: e.required,
308
+ onChange: (t) => o({
309
+ ...e,
310
+ required: t
311
+ })
312
+ })] }),
313
+ e.type === "select" && /* @__PURE__ */ Z(Nt, {
314
+ options: e.options,
315
+ onChange: (t) => o({
316
+ ...e,
317
+ options: t
318
+ })
319
+ }),
320
+ me(e.type) && /* @__PURE__ */ Z(z, {
321
+ label: "Example answer",
322
+ hint: e.type === "tel" ? "Shown under the box — a phone box already starts with a dial code, so the example stands below it." : "Faint grey words inside the empty box.",
323
+ value: e.placeholder,
324
+ placeholder: _[e.type] || "e.g. +1 555 0123",
325
+ onChange: (t) => o({
326
+ ...e,
327
+ placeholder: t
328
+ })
329
+ })
330
+ ]
331
+ })]
332
+ });
333
+ }
334
+ function Ft({ questions: e, onChange: t }) {
335
+ let n = e.filter((e) => u(e.name)), r = e.filter((e) => !u(e.name)), i = (e) => t([...n, ...e]);
336
+ return /* @__PURE__ */ Z(P, {
337
+ label: "What does a booking ask for?",
338
+ children: /* @__PURE__ */ Q("div", {
339
+ className: "flex flex-col gap-3.5",
340
+ children: [
341
+ n.map((n) => /* @__PURE__ */ Z(Pt, {
342
+ question: n,
343
+ index: 0,
344
+ count: 1,
345
+ siblings: e,
346
+ fixed: !0,
347
+ onChange: (r) => t(e.map((e) => e.name === n.name ? r : e)),
348
+ onMove: () => {},
349
+ onRemove: () => {}
350
+ }, n.name)),
351
+ r.map((t, n) => /* @__PURE__ */ Z(Pt, {
352
+ question: t,
353
+ index: n,
354
+ count: r.length,
355
+ siblings: e,
356
+ onChange: (e) => i(r.map((t, r) => r === n ? e : t)),
357
+ onMove: (e) => {
358
+ let t = n + e;
359
+ if (t < 0 || t >= r.length) return;
360
+ let a = [...r];
361
+ [a[n], a[t]] = [a[t], a[n]], i(a);
362
+ },
363
+ onRemove: () => i(r.filter((e, t) => t !== n))
364
+ }, n)),
365
+ /* @__PURE__ */ Q("div", {
366
+ className: "flex flex-col items-start sm:flex-row sm:items-center gap-3 rounded-2xl border border-dashed border-[var(--panel-border)] px-4 py-3.5",
367
+ children: [/* @__PURE__ */ Z(L, {
368
+ icon: V,
369
+ title: "Add a question",
370
+ onClick: () => i([...r, O()]),
371
+ children: "Add a question"
372
+ }), r.length === 0 && /* @__PURE__ */ Z("p", {
373
+ className: "text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug",
374
+ children: "Nothing else is asked — just a name and an email."
375
+ })]
376
+ })
377
+ ]
378
+ })
379
+ });
380
+ }
381
+ var It = (e, t, n = 72) => e >= n && e <= Math.max(n, t * .45);
382
+ function $(e, t = 340) {
383
+ if (!e) return null;
384
+ let n = () => {
385
+ let t = e.getBoundingClientRect?.(), n = typeof window < "u" && window.innerHeight || 0;
386
+ t && n && It(t.top, n) || e.scrollIntoView?.({
387
+ behavior: "smooth",
388
+ block: "start"
389
+ });
390
+ };
391
+ return typeof setTimeout == "function" ? setTimeout(n, t) : (n(), null);
392
+ }
393
+ //#endregion
394
+ //#region src/lib/localEdits.ts
395
+ function Lt(e, t, n) {
396
+ let r = J(/* @__PURE__ */ new Set());
397
+ K(() => {
398
+ let i = new Set(e), a = [...r.current].filter((e) => !i.has(e) && !n.current.has(e));
399
+ e.forEach((e) => r.current.add(e)), a.length && (a.forEach((e) => r.current.delete(e)), t((e) => {
400
+ if (!a.some((t) => t in e)) return e;
401
+ let t = { ...e };
402
+ for (let e of a) delete t[e];
403
+ return t;
404
+ }));
405
+ }, [e.join("\0")]);
406
+ }
407
+ //#endregion
408
+ //#region src/components/schedule/BookingLinksCard.tsx
409
+ var Rt = "__new_payment__";
410
+ function zt() {
411
+ let [e, t] = Y([]);
412
+ return K(() => {
413
+ let e = pe(a, () => bt(re, a), (e) => {
414
+ let n = [];
415
+ e.forEach((e) => {
416
+ e.id !== "_settings" && n.push(M(e.id, e.data()));
417
+ }), t(n.filter((e) => e.kind === "once").sort((e, t) => (e.createdAt || 0) - (t.createdAt || 0)));
418
+ }, () => t([]));
419
+ return () => e();
420
+ }, []), e;
421
+ }
422
+ function Bt({ service: e, what: t, path: n, screen: r, children: i }) {
423
+ return e.loading ? null : e.configured ? e.on ? /* @__PURE__ */ Z(X, { children: i }) : null : /* @__PURE__ */ Q("div", {
424
+ className: "rounded-2xl border border-accent/25 bg-accent/[0.05] px-4 py-3.5 flex flex-wrap items-center justify-between gap-x-4 gap-y-2",
425
+ children: [/* @__PURE__ */ Q("span", {
426
+ className: "text-[13px] font-medium text-foreground/70",
427
+ children: [
428
+ "You do not have ",
429
+ t,
430
+ " set up yet."
431
+ ]
432
+ }), /* @__PURE__ */ Q(Ct, {
433
+ to: n,
434
+ className: "inline-flex items-center gap-1 text-[12px] font-bold text-accent hover:underline whitespace-nowrap",
435
+ children: [
436
+ "Set it up on the ",
437
+ r,
438
+ " screen",
439
+ /* @__PURE__ */ Z(Te, { className: "w-3 h-3" })
440
+ ]
441
+ })]
442
+ });
443
+ }
444
+ function Vt({ value: e, products: t, meetingName: n, canCreate: r, onChange: i, onCreate: a }) {
445
+ let [o, s] = Y(!1), [c, l] = Y(""), [u, d] = Y(""), [f, m] = Y(!1), h = [...t.map((e) => ({
446
+ value: e.id,
447
+ label: `${p(e)} — ${C(e).map((e) => e.amount).filter(Boolean).join(" + ") || "no price yet"}`
448
+ })), ...r ? [{
449
+ value: Rt,
450
+ label: "+ A new one-time payment"
451
+ }] : []], g = t.find((t) => t.id === e), _ = c.trim() && oe(c) === null ? "Just a number, like 25." : void 0;
452
+ return /* @__PURE__ */ Q("div", {
453
+ className: "flex flex-col gap-3",
454
+ children: [/* @__PURE__ */ Z(T, {
455
+ label: "Payment for this meeting",
456
+ hint: g ? "Taken on the booking page before the time is confirmed. Its price and its link are on the Payments screen." : r ? "Optional. A one-time payment taken on the booking page before the time is confirmed." : t.length ? "Optional. One of the payments your admin set up, taken on the booking page before the time is confirmed." : "Your admin has not set up a payment to charge for a meeting yet.",
457
+ value: o ? Rt : e,
458
+ placeholder: "No payment",
459
+ options: h,
460
+ onChange: (e) => {
461
+ if (e === "__new_payment__") {
462
+ s(!0);
463
+ return;
464
+ }
465
+ s(!1), i(e);
466
+ }
467
+ }), o && /* @__PURE__ */ Q("div", {
468
+ className: "rounded-2xl border border-[var(--panel-border)]/60 px-4 py-3.5 flex flex-col gap-3",
469
+ children: [/* @__PURE__ */ Z(z, {
470
+ label: "The price",
471
+ hint: `Just the number — 25 charges 25 in your Stripe account's currency. The payment is called ${n} and appears on the Payments screen too.`,
472
+ value: c,
473
+ onChange: (e) => {
474
+ l(e), u && d("");
475
+ },
476
+ placeholder: "25",
477
+ error: u || _
478
+ }), /* @__PURE__ */ Q("div", {
479
+ className: "flex items-center gap-2",
480
+ children: [/* @__PURE__ */ Z(L, {
481
+ icon: V,
482
+ busy: f,
483
+ onClick: async () => {
484
+ if (oe(c) === null) {
485
+ d("Just a number for the price, like 25.");
486
+ return;
487
+ }
488
+ d(""), m(!0);
489
+ let e = await a(n, c.trim());
490
+ if (m(!1), e) {
491
+ d(e);
492
+ return;
493
+ }
494
+ s(!1), l("");
495
+ },
496
+ children: "Create it"
497
+ }), /* @__PURE__ */ Z(L, {
498
+ onClick: () => {
499
+ s(!1), d(""), l("");
500
+ },
501
+ children: "Never mind"
502
+ })]
503
+ })]
504
+ })]
505
+ });
506
+ }
507
+ function Ht({ link: e, onChange: t }) {
508
+ return /* @__PURE__ */ Z(P, {
509
+ label: "Emails about bookings",
510
+ hint: "Sent the moment a time is taken. Every booking is in your Inbox and on the calendar regardless.",
511
+ children: /* @__PURE__ */ Q("div", {
512
+ className: "flex flex-col gap-3 rounded-2xl border border-[var(--panel-border)]/60 px-4 py-3.5",
513
+ children: [/* @__PURE__ */ Z(r, {
514
+ label: "Email me when someone books",
515
+ hint: "A note at your address — the sale alert, when they paid.",
516
+ hintWideOnly: !0,
517
+ enabled: e.notifyOwner,
518
+ onChange: (e) => t({ notifyOwner: e })
519
+ }), /* @__PURE__ */ Z(r, {
520
+ label: "Email them a confirmation",
521
+ hint: "Their receipt when they pay. For a free booking, a note that the time is theirs — to people who book signed in.",
522
+ hintWideOnly: !0,
523
+ enabled: e.confirmBooker,
524
+ onChange: (e) => t({ confirmBooker: e })
525
+ })]
526
+ })
527
+ });
528
+ }
529
+ var Ut = (e) => {
530
+ let t = {
531
+ ...je(Pe(), e),
532
+ createdAt: Date.now()
533
+ };
534
+ return {
535
+ ...t,
536
+ name: I(t),
537
+ description: le(t)
538
+ };
539
+ };
540
+ function Wt({ link: e, schedules: t, products: n, services: r, isAdmin: i = !0, onChange: a, onCreatePayment: o }) {
541
+ let s = t.find((t) => t.id === e.scheduleId), l = (t) => a({
542
+ ...e,
543
+ ...t
544
+ }), u = ke(e, s), d = s ? Me(e, s) : null, p = (t) => {
545
+ let n = {
546
+ ...e,
547
+ ...t
548
+ };
549
+ return {
550
+ ...t,
551
+ ...e.name.trim() === I(e) ? { name: I(n) } : {},
552
+ ...e.description.trim() === le(e) ? { description: le(n) } : {}
553
+ };
554
+ };
555
+ return /* @__PURE__ */ Q(X, { children: [
556
+ /* @__PURE__ */ Z(T, {
557
+ label: "Which hours is it booked in?",
558
+ hint: "Change the hours and every meeting booked in them changes with it — one holiday, entered once, closes them all.",
559
+ value: e.scheduleId,
560
+ options: t.map((e) => ({
561
+ value: e.id,
562
+ label: h(e)
563
+ })),
564
+ allowEmpty: !1,
565
+ onChange: (n) => {
566
+ let r = t.find((e) => e.id === n);
567
+ if (!r) return;
568
+ let i = !s || e.memberName.trim() === s.memberName.trim();
569
+ l(p({
570
+ scheduleId: r.id,
571
+ memberId: r.memberId,
572
+ ...i ? { memberName: r.memberName } : {}
573
+ }));
574
+ }
575
+ }),
576
+ /* @__PURE__ */ Z(z, {
577
+ label: "What is it called?",
578
+ hint: `Visitors read this on the booking page. It starts named after its length — call it whatever you like. Left blank it goes back to ${I(e)}.`,
579
+ value: e.name,
580
+ onChange: (e) => l({ name: e }),
581
+ placeholder: I(e)
582
+ }),
583
+ /* @__PURE__ */ Z(k, {
584
+ label: "A line or two about it",
585
+ hint: "Visitors read it under the name — what it is for, what to bring, what happens after. Emptied, the booking page simply shows none.",
586
+ value: e.description,
587
+ onChange: (e) => l({ description: e }),
588
+ placeholder: "A first conversation about what you need and how I can help."
589
+ }),
590
+ /* @__PURE__ */ Z(z, {
591
+ label: "The name visitors see",
592
+ value: e.memberName,
593
+ onChange: (e) => l(p({ memberName: e })),
594
+ placeholder: "Anna"
595
+ }),
596
+ /* @__PURE__ */ Z(T, {
597
+ label: "How long is one booking?",
598
+ value: String(e.slotMinutes),
599
+ options: f,
600
+ allowEmpty: !1,
601
+ onChange: (e) => l(p({ slotMinutes: Number(e) }))
602
+ }),
603
+ /* @__PURE__ */ Z(T, {
604
+ label: "How far ahead can people book?",
605
+ value: String(e.horizonDays),
606
+ options: S,
607
+ allowEmpty: !1,
608
+ onChange: (e) => l({ horizonDays: Number(e) })
609
+ }),
610
+ /* @__PURE__ */ Z(T, {
611
+ label: "How much notice do you need?",
612
+ value: String(e.noticeHours),
613
+ options: c,
614
+ allowEmpty: !1,
615
+ onChange: (e) => l({ noticeHours: Number(e) })
616
+ }),
617
+ /* @__PURE__ */ Z(Ft, {
618
+ questions: e.questions,
619
+ onChange: (e) => l({ questions: e })
620
+ }),
621
+ /* @__PURE__ */ Z(Bt, {
622
+ service: r.payments,
623
+ what: "Stripe",
624
+ path: "/payments",
625
+ screen: "Payments",
626
+ children: /* @__PURE__ */ Z(Vt, {
627
+ value: e.paymentId,
628
+ products: n,
629
+ meetingName: W(e),
630
+ canCreate: i,
631
+ onChange: (e) => l({ paymentId: e }),
632
+ onCreate: async (e, t) => {
633
+ let n = await o(e, t);
634
+ return n && n.startsWith("p_") ? (l({ paymentId: n }), null) : n || "The payment could not be made — make sure you are signed in as an admin and try again.";
635
+ }
636
+ })
637
+ }),
638
+ /* @__PURE__ */ Z(Bt, {
639
+ service: r.email,
640
+ what: "emails",
641
+ path: "/email",
642
+ screen: "Email",
643
+ children: /* @__PURE__ */ Z(Ht, {
644
+ link: e,
645
+ onChange: l
646
+ })
647
+ }),
648
+ /* @__PURE__ */ Z(P, {
649
+ label: "Booking link",
650
+ hint: d && !u && e.enabled ? "Send it to anyone. They see the free times in their own time zone, pick one and book — and pay first, when a payment is attached." : "The link opens once the meeting is complete and turned on.",
651
+ children: /* @__PURE__ */ Z(yt, {
652
+ title: W(e),
653
+ path: E(e.id)
654
+ })
655
+ }),
656
+ /* @__PURE__ */ Z("div", {
657
+ className: "pt-1",
658
+ children: u ? e.enabled ? /* @__PURE__ */ Q("span", {
659
+ className: "text-[11.5px] font-semibold text-amber-500",
660
+ children: ["Turned on, but not bookable yet — ", u]
661
+ }) : /* @__PURE__ */ Z("span", {
662
+ className: R,
663
+ children: u
664
+ }) : e.enabled ? /* @__PURE__ */ Z("span", {
665
+ className: "text-[11.5px] font-semibold text-emerald-500",
666
+ children: "Bookable — send the link, pick it on a page under Booking on this page, or add a Pick-a-time question to a form."
667
+ }) : /* @__PURE__ */ Z("span", {
668
+ className: R,
669
+ children: "Complete — flip the switch at the top of the row to offer it."
670
+ })
671
+ })
672
+ ] });
673
+ }
674
+ function Gt({ link: e, schedules: t, products: n, services: r, isAdmin: i = !0, open: a, fresh: o, error: s, onToggle: c, onChange: l, onRemove: u, onCreatePayment: d }) {
675
+ let f = t.find((t) => t.id === e.scheduleId), p = Ne(e, f), [m, h] = Y(!1), g = W(e), _ = J(null);
676
+ return K(() => {
677
+ if (!o) return;
678
+ let e = $(_.current);
679
+ return () => {
680
+ e && clearTimeout(e);
681
+ };
682
+ }, [o]), /* @__PURE__ */ Q("div", {
683
+ ref: _,
684
+ className: "scroll-mt-4 rounded-2xl border border-[var(--panel-border)]",
685
+ children: [
686
+ /* @__PURE__ */ Q("div", {
687
+ className: "flex items-center gap-2 sm:gap-2.5 pr-3",
688
+ children: [
689
+ /* @__PURE__ */ Q("button", {
690
+ type: "button",
691
+ onClick: c,
692
+ "aria-expanded": a,
693
+ className: "flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer",
694
+ children: [/* @__PURE__ */ Z("span", {
695
+ className: "text-[13px] font-semibold text-foreground/75 truncate",
696
+ children: Ae(e, f)
697
+ }), /* @__PURE__ */ Q("span", {
698
+ className: "flex items-center gap-2.5 shrink-0",
699
+ children: [/* @__PURE__ */ Z("span", {
700
+ className: "max-sm:hidden",
701
+ children: /* @__PURE__ */ Z(ue, {
702
+ state: p.state,
703
+ label: p.label
704
+ })
705
+ }), /* @__PURE__ */ Z(U, { className: `w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${a ? "rotate-180" : ""}` })]
706
+ })]
707
+ }),
708
+ /* @__PURE__ */ Z(b, {
709
+ enabled: e.enabled,
710
+ onChange: (t) => l({
711
+ ...e,
712
+ enabled: t
713
+ }),
714
+ label: `${g} — can be booked`
715
+ }),
716
+ /* @__PURE__ */ Z(L, {
717
+ icon: B,
718
+ tone: "danger",
719
+ compact: !0,
720
+ title: `Remove ${g}`,
721
+ onClick: () => h(!0),
722
+ children: "Remove"
723
+ })
724
+ ]
725
+ }),
726
+ /* @__PURE__ */ Z(tt, {
727
+ isOpen: m,
728
+ title: `Remove ${g}?`,
729
+ message: "Its booking link stops working and it leaves every page and form it was picked on. The hours it was booked in stay, and so do the bookings already taken.",
730
+ confirmText: "Yes, remove",
731
+ cancelText: "Keep it",
732
+ onCancel: () => h(!1),
733
+ onConfirm: () => {
734
+ h(!1), u();
735
+ }
736
+ }),
737
+ a && /* @__PURE__ */ Z("div", {
738
+ className: "px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4",
739
+ children: /* @__PURE__ */ Z(Wt, {
740
+ link: e,
741
+ schedules: t,
742
+ products: n,
743
+ services: r,
744
+ isAdmin: i,
745
+ onChange: l,
746
+ onCreatePayment: d
747
+ })
748
+ }),
749
+ s && /* @__PURE__ */ Z("p", {
750
+ className: "text-[12px] font-semibold text-red-500 px-4 pb-3",
751
+ children: s
752
+ })
753
+ ]
754
+ });
755
+ }
756
+ function Kt({ isAdmin: e = !0 } = {}) {
757
+ let { user: t } = j(), { loading: n, docs: r } = Re(), i = zt(), o = {
758
+ payments: _t("payments"),
759
+ email: _t("email")
760
+ }, [s, c] = Y({}), [l, u] = Y([]), [f, p] = Y(null), [m, h] = Y(null), [g, _] = Y({}), v = J(/* @__PURE__ */ new Map());
761
+ Lt(r.links.map((e) => e.id), c, v);
762
+ let b = t?.uid || "", x = q(() => [...e ? r.schedules : r.schedules.filter((e) => e.memberId === b)].sort((e, t) => Number(t.memberId === b) - Number(e.memberId === b)), [
763
+ r.schedules,
764
+ e,
765
+ b
766
+ ]), S = q(() => {
767
+ let t = new Map(r.links.map((e) => [e.id, e]));
768
+ for (let e of Object.values(s)) t.set(e.id, e);
769
+ for (let e of l) t.delete(e);
770
+ return [...t.values()].filter((t) => e || t.memberId === b).sort((e, t) => Number(t.memberId === b) - Number(e.memberId === b) || (e.createdAt || 0) - (t.createdAt || 0) || e.id.localeCompare(t.id));
771
+ }, [
772
+ r.links,
773
+ s,
774
+ l,
775
+ e,
776
+ b
777
+ ]), C = (e) => {
778
+ let t = v.current.get(e.id);
779
+ t && clearTimeout(t), v.current.set(e.id, setTimeout(async () => {
780
+ v.current.delete(e.id);
781
+ let t = await Ze(e);
782
+ _((n) => {
783
+ let r = { ...n };
784
+ return t ? r[e.id] = t : delete r[e.id], r;
785
+ });
786
+ }, 600));
787
+ }, w = (e) => {
788
+ c((t) => ({
789
+ ...t,
790
+ [e.id]: e
791
+ })), C(e);
792
+ }, T = () => {
793
+ let e = x.find((e) => e.memberId === b) || x[0];
794
+ if (!e) return;
795
+ let t = Ut(e);
796
+ c((e) => ({
797
+ ...e,
798
+ [t.id]: t
799
+ })), p(t.id), h(t.id), C(t);
800
+ }, E = async (e) => {
801
+ let t = v.current.get(e);
802
+ t && (clearTimeout(t), v.current.delete(e)), c((t) => {
803
+ let n = { ...t };
804
+ return delete n[e], n;
805
+ }), u((t) => [...t, e]), f === e && p(null);
806
+ let n = await ze(e);
807
+ n && (u((t) => t.filter((t) => t !== e)), _((t) => ({
808
+ ...t,
809
+ [e]: n
810
+ })));
811
+ }, D = async (e, t) => {
812
+ let n = {
813
+ ...d(`p_${Date.now().toString(36)}`),
814
+ kind: "once",
815
+ items: [{
816
+ name: e,
817
+ amount: t
818
+ }]
819
+ };
820
+ try {
821
+ let { id: e, ...t } = n;
822
+ return await St(xt(re, a, e), t), e;
823
+ } catch (e) {
824
+ return console.error("Could not make the payment", e), null;
825
+ }
826
+ };
827
+ return /* @__PURE__ */ Z(N, {
828
+ icon: Ce,
829
+ title: "Booking links",
830
+ description: "One per kind of meeting — pick the hours it is booked in, say how long it lasts and what it asks, and send the link.",
831
+ actions: !n && x.length > 0 ? ({ open: e }) => /* @__PURE__ */ Z(L, {
832
+ icon: V,
833
+ compact: !0,
834
+ title: "Add a booking link",
835
+ onClick: () => {
836
+ e(), T();
837
+ },
838
+ children: "Add a booking link"
839
+ }) : void 0,
840
+ children: /* @__PURE__ */ Z("div", {
841
+ className: "flex flex-col gap-3",
842
+ children: n ? /* @__PURE__ */ Z("p", {
843
+ className: R,
844
+ children: "Loading your booking links…"
845
+ }) : x.length === 0 ? /* @__PURE__ */ Z("p", {
846
+ className: `${R} px-1`,
847
+ children: "Add a schedule above first — a booking link is a meeting booked in somebody's hours, so there have to be hours to put it on."
848
+ }) : S.length === 0 ? /* @__PURE__ */ Q("p", {
849
+ className: `${R} px-1`,
850
+ children: [
851
+ "No booking link yet — press Add a booking link. It is what turns ",
852
+ y(x[0]),
853
+ " into something people can book."
854
+ ]
855
+ }) : S.map((t) => /* @__PURE__ */ Z(Gt, {
856
+ link: t,
857
+ schedules: x,
858
+ products: i,
859
+ services: o,
860
+ isAdmin: e,
861
+ open: f === t.id,
862
+ fresh: m === t.id,
863
+ error: g[t.id],
864
+ onToggle: () => p(f === t.id ? null : t.id),
865
+ onChange: w,
866
+ onRemove: () => E(t.id),
867
+ onCreatePayment: D
868
+ }, t.id))
869
+ })
870
+ });
871
+ }
872
+ var qt = "team", Jt = (e) => `m:${e}`, Yt = "__nobody__";
873
+ function Xt(e, t, n) {
874
+ return [
875
+ {
876
+ value: "me",
877
+ label: "My calendar"
878
+ },
879
+ {
880
+ value: qt,
881
+ label: "My team's calendar"
882
+ },
883
+ ...e.filter((e) => e.id !== n).map((e) => ({
884
+ value: Jt(e.id),
885
+ label: G(e) || e.email,
886
+ disabled: !t.has(e.id)
887
+ }))
888
+ ];
889
+ }
890
+ var Zt = (e) => e.startsWith("m:") ? e.slice(2) : "", Qt = /* @__PURE__ */ new Set(), $t = 3;
891
+ function en(e) {
892
+ let [t, n] = Y({}), r = J(/* @__PURE__ */ new Set()), i = J([]), a = J(0), o = J(!0);
893
+ return K(() => (o.current = !0, () => {
894
+ o.current = !1;
895
+ }), []), K(() => {
896
+ let t = () => {
897
+ for (; a.current < $t && i.current.length;) {
898
+ let e = i.current.shift();
899
+ a.current += 1, D(e, { quiet: !0 }).then((t) => {
900
+ t.paid && Qt.add(e), o.current && n((n) => ({
901
+ ...n,
902
+ [e]: t.paid
903
+ }));
904
+ }).catch(() => {}).finally(() => {
905
+ --a.current, o.current && t();
906
+ });
907
+ }
908
+ };
909
+ for (let t of e) {
910
+ let e = t.paymentSession;
911
+ !e || Qt.has(e) || r.current.has(e) || (r.current.add(e), i.current.push(e));
912
+ }
913
+ t();
914
+ }, [e]), q(() => {
915
+ let n = { ...t };
916
+ for (let t of e) t.paymentSession && Qt.has(t.paymentSession) && (n[t.paymentSession] = !0);
917
+ return n;
918
+ }, [t, e]);
919
+ }
920
+ function tn(e, t, n, r = "") {
921
+ if (!e.email) return Promise.resolve();
922
+ let i = fe(e, e.timeZone || n);
923
+ return nt(t, ne, e.id, {
924
+ when: `${i.day}, ${i.time}`,
925
+ memberName: e.memberName,
926
+ scheduleName: e.scheduleName,
927
+ reason: r.trim()
928
+ }).then(() => {}).catch(() => {});
929
+ }
930
+ function nn(e, t, n) {
931
+ let r = (e) => [...new Set(e.map((e) => String(e || "").trim()))].filter((e) => e && e !== n), i = r([
932
+ e.memberId,
933
+ ...t.map((e) => e.memberId),
934
+ ...e.copyIds.map((e) => e.split("__")[0])
935
+ ]);
936
+ return {
937
+ members: i,
938
+ bookers: r([e.uid, ...t.map((e) => e.uid)]).filter((e) => e !== "guest").filter((e) => !i.includes(e))
939
+ };
940
+ }
941
+ async function rn(e, t, n, r) {
942
+ if (e.own || e.heldOnly) return;
943
+ let i = {
944
+ title: "Meeting removed",
945
+ body: `${ie(e)} · ${g(new Date(e.start), r)}`
946
+ };
947
+ await tn(e, "booking_cancelled", r, "The meeting was removed from the calendar.");
948
+ let { members: a, bookers: o } = nn(e, t, n);
949
+ await et(a, {
950
+ ...i,
951
+ link: "/schedule"
952
+ }), await et(o, {
953
+ ...i,
954
+ link: "/my-bookings"
955
+ });
956
+ }
957
+ function an({ isAdmin: e }) {
958
+ let { user: t } = j(), n = t?.uid || "", r = i(), [a, o] = wt(), s = a.get("open") || a.get("booking") || "", { schedules: c } = Fe(), { members: l } = Oe(), u = q(() => new Set(c.map((e) => e.memberId)), [c]), d = q(() => Xt(l, u, n), [
959
+ l,
960
+ u,
961
+ n
962
+ ]), [f, p] = Y(null);
963
+ K(() => {
964
+ s && e && p((e) => e ?? "team");
965
+ }, [s, e]);
966
+ let m = f ?? "me", h = new Set(d.filter((e) => !e.disabled).map((e) => e.value)).has(m) ? m : "me", g = Zt(h), { loading: _, bookings: v, error: y } = He({
967
+ members: h === "team" ? void 0 : [g || n || Yt],
968
+ includePast: !0
969
+ }), b = en(v), S = Qe(q(() => (h === "team" ? l.map((e) => e.id) : [g || n]).filter(Boolean), [
970
+ h,
971
+ l,
972
+ g,
973
+ n
974
+ ]), q(() => {
975
+ let e = /* @__PURE__ */ new Date();
976
+ return new Date(Date.UTC(e.getUTCFullYear(), e.getUTCMonth() - 1, 1));
977
+ }, [])), [C, w] = Y(() => Date.now());
978
+ K(() => {
979
+ let e = setInterval(() => w(Date.now()), 6e4);
980
+ return () => clearInterval(e);
981
+ }, []);
982
+ let T = q(() => De(v), [v]), E = q(() => {
983
+ let e = v.map((e) => {
984
+ let t = T.get(e.id);
985
+ return t ? {
986
+ ...e,
987
+ ...t
988
+ } : e;
989
+ }), t = (e) => {
990
+ let t = l.find((t) => t.id === e);
991
+ return c.find((t) => t.memberId === e)?.memberName || (t ? G(t) : "");
992
+ }, n = Ue(S, v, C).map((e) => We(e, t(e.memberId)));
993
+ return n.length ? [...e, ...n] : e;
994
+ }, [
995
+ v,
996
+ T,
997
+ S,
998
+ C,
999
+ l,
1000
+ c
1001
+ ]);
1002
+ K(() => {
1003
+ if (!(_ || !n)) try {
1004
+ localStorage.setItem(`fbos_calendar_had_${n}`, E.length ? "1" : "0");
1005
+ } catch {}
1006
+ }, [
1007
+ _,
1008
+ n,
1009
+ E.length
1010
+ ]);
1011
+ let D = g || n, O = l.find((e) => e.id === D), k = c.find((e) => e.memberId === D)?.memberName || (O ? G(O) : "") || (D === n ? String(t?.displayName || "") : ""), ee = `fbos_calendar_had_${n}`, A = (() => {
1012
+ try {
1013
+ return localStorage.getItem(ee) === "1";
1014
+ } catch {
1015
+ return !1;
1016
+ }
1017
+ })();
1018
+ return _ && E.length === 0 ? A ? /* @__PURE__ */ Z(Ee, { className: "h-[420px] w-full" }) : null : E.length === 0 ? null : /* @__PURE__ */ Z(N, {
1019
+ icon: xe,
1020
+ title: "Calendar",
1021
+ description: h === "team" ? `Every booking made with your team, and the events they put on their own days — in your time, ${x(r)}.` : g ? `${k || "Their"} calendar, read as they read it — in your time, ${x(r)}.` : `Every booking made with you, under every schedule of yours — in your time, ${x(r)}.`,
1022
+ actions: e && d.length > 2 ? /* @__PURE__ */ Z(F, {
1023
+ ariaLabel: "Whose calendar",
1024
+ value: h,
1025
+ options: d,
1026
+ onChange: p,
1027
+ className: "console-select",
1028
+ compact: !0,
1029
+ dense: !0,
1030
+ portal: !0,
1031
+ direction: "auto"
1032
+ }) : void 0,
1033
+ children: _ ? /* @__PURE__ */ Z("p", {
1034
+ className: R,
1035
+ children: "Loading the calendar…"
1036
+ }) : y ? /* @__PURE__ */ Z("p", {
1037
+ className: "text-[12px] font-semibold text-red-500 px-1",
1038
+ children: y
1039
+ }) : /* @__PURE__ */ Z(vt, {
1040
+ bookings: E,
1041
+ zone: r,
1042
+ paid: b,
1043
+ openBookingId: s || void 0,
1044
+ onOpened: s ? () => o((e) => (e.delete("open"), e.delete("booking"), e), { replace: !0 }) : void 0,
1045
+ withMember: h === qt,
1046
+ me: n,
1047
+ onAccept: async (e) => {
1048
+ let t = await Xe(e.id);
1049
+ return t || tn(e, "booking_confirmed", r), t;
1050
+ },
1051
+ onCancel: async (e, i) => {
1052
+ let a = await Ye(e.id, {
1053
+ ids: e.copyIds,
1054
+ reason: i,
1055
+ side: "host",
1056
+ by: e.memberId === n ? k || String(t?.displayName || "") : e.memberName,
1057
+ byUid: n
1058
+ });
1059
+ return a || tn(e, "booking_cancelled", r, i), a;
1060
+ },
1061
+ onDelete: async (e) => (await rn(e, v, n, r), Le(e.id, e.copyIds)),
1062
+ canDelete: (t) => e || t.own && t.memberId === n,
1063
+ onRelease: (e) => qe(e.memberId, e.start),
1064
+ onColor: Ve,
1065
+ onAdd: h === "team" ? void 0 : (e) => Ke({
1066
+ ...e,
1067
+ memberId: D,
1068
+ memberName: k,
1069
+ timeZone: r
1070
+ })
1071
+ })
1072
+ });
1073
+ }
1074
+ //#endregion
1075
+ //#region src/components/schedule/BookingPagesCard.tsx
1076
+ function on(e, t) {
1077
+ if (!e.enabled) return {
1078
+ state: "off",
1079
+ label: "Off"
1080
+ };
1081
+ if (it(e, t)) return {
1082
+ state: "error",
1083
+ label: "Unfinished"
1084
+ };
1085
+ let n = e.schedules.length;
1086
+ return {
1087
+ state: "saved",
1088
+ label: n === 1 ? "1 meeting" : `${n} meetings`
1089
+ };
1090
+ }
1091
+ var sn = (e) => {
1092
+ let t = e.schedules.length;
1093
+ return `${ft(e)} — ${t === 0 ? "nothing on it yet" : t === 1 ? "1 meeting" : `${t} meetings`}`;
1094
+ };
1095
+ function cn({ page: e, schedules: t, onChange: n }) {
1096
+ return t.length ? /* @__PURE__ */ Z(P, {
1097
+ label: "Meetings on this page",
1098
+ hint: "They appear in the order you tick them. A meeting switched off above is kept off the page too.",
1099
+ children: /* @__PURE__ */ Z("div", {
1100
+ className: "flex flex-col gap-1.5",
1101
+ children: t.map((t) => {
1102
+ let r = e.schedules.includes(t.id);
1103
+ return /* @__PURE__ */ Q("button", {
1104
+ type: "button",
1105
+ role: "checkbox",
1106
+ "aria-checked": r,
1107
+ onClick: () => n(ut(e, t.id)),
1108
+ className: `flex items-center gap-3 px-3 py-2.5 rounded-xl border text-left transition-all cursor-pointer active:scale-[0.995] ${r ? "border-accent/45 bg-accent/[0.07]" : "border-[var(--panel-border)]/70 hover:border-accent/30 hover:bg-foreground/[0.03]"}`,
1109
+ children: [/* @__PURE__ */ Z("span", {
1110
+ "aria-hidden": !0,
1111
+ className: `w-[18px] h-[18px] rounded-[5px] border flex items-center justify-center shrink-0 transition-all ${r ? "border-accent bg-accent" : "border-foreground/25"}`,
1112
+ children: r && /* @__PURE__ */ Z("span", { className: "w-[7px] h-[7px] rounded-[2px] bg-[var(--button-fg,#fff)]" })
1113
+ }), /* @__PURE__ */ Z("span", {
1114
+ className: "flex-1 min-w-0 text-[13px] font-semibold text-foreground/80 truncate",
1115
+ children: te(t)
1116
+ })]
1117
+ }, t.id);
1118
+ })
1119
+ })
1120
+ }) : /* @__PURE__ */ Z(P, {
1121
+ label: "Meetings on this page",
1122
+ children: /* @__PURE__ */ Z("p", {
1123
+ className: `${R} px-1`,
1124
+ children: "Make a schedule above first — a page offers the meetings you have set up."
1125
+ })
1126
+ });
1127
+ }
1128
+ function ln({ page: e, taken: t, onRename: n }) {
1129
+ let [r, i] = Y(e.id), a = at(r), o = !!a && a !== e.id && t.includes(a);
1130
+ return /* @__PURE__ */ Z(z, {
1131
+ label: "Its address",
1132
+ prefix: "/meet/",
1133
+ value: r,
1134
+ onChange: i,
1135
+ onBlur: () => {
1136
+ if (!a || o || a === e.id) {
1137
+ i(e.id);
1138
+ return;
1139
+ }
1140
+ n(a);
1141
+ },
1142
+ placeholder: "anna-bell",
1143
+ error: o ? "Another page already has that address." : void 0,
1144
+ hint: "Change it and the old link stops working, so change it before you send it out."
1145
+ });
1146
+ }
1147
+ function un({ page: t, schedules: n, taken: r, open: i, fresh: a, error: o, onToggle: s, onChange: c, onRename: l, onRemove: u }) {
1148
+ let [d, f] = Y(!1), p = on(t, n), m = ft(t), h = it(t, n), g = J(null);
1149
+ return K(() => {
1150
+ if (!a) return;
1151
+ let e = $(g.current);
1152
+ return () => {
1153
+ e && clearTimeout(e);
1154
+ };
1155
+ }, [a]), /* @__PURE__ */ Q("div", {
1156
+ ref: g,
1157
+ className: "scroll-mt-4 rounded-2xl border border-[var(--panel-border)]",
1158
+ children: [
1159
+ /* @__PURE__ */ Q("div", {
1160
+ className: "flex items-center gap-2 sm:gap-2.5 pr-3",
1161
+ children: [
1162
+ /* @__PURE__ */ Q("button", {
1163
+ type: "button",
1164
+ onClick: s,
1165
+ "aria-expanded": i,
1166
+ className: "flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer",
1167
+ children: [/* @__PURE__ */ Z("span", {
1168
+ className: "text-[13px] font-semibold text-foreground/75 truncate",
1169
+ children: sn(t)
1170
+ }), /* @__PURE__ */ Q("span", {
1171
+ className: "flex items-center gap-2.5 shrink-0",
1172
+ children: [/* @__PURE__ */ Z("span", {
1173
+ className: "max-sm:hidden",
1174
+ children: /* @__PURE__ */ Z(ue, {
1175
+ state: p.state,
1176
+ label: p.label
1177
+ })
1178
+ }), /* @__PURE__ */ Z(U, { className: `w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${i ? "rotate-180" : ""}` })]
1179
+ })]
1180
+ }),
1181
+ /* @__PURE__ */ Z(b, {
1182
+ enabled: t.enabled,
1183
+ onChange: (e) => c({
1184
+ ...t,
1185
+ enabled: e
1186
+ }),
1187
+ label: `${m} — page is live`
1188
+ }),
1189
+ /* @__PURE__ */ Z(L, {
1190
+ icon: B,
1191
+ tone: "danger",
1192
+ compact: !0,
1193
+ title: `Remove ${m}`,
1194
+ onClick: () => f(!0),
1195
+ children: "Remove"
1196
+ })
1197
+ ]
1198
+ }),
1199
+ /* @__PURE__ */ Z(tt, {
1200
+ isOpen: d,
1201
+ title: `Remove ${m}?`,
1202
+ message: "Its link stops working. The meetings on it are untouched and keep their own links, and bookings already taken are kept.",
1203
+ confirmText: "Yes, remove",
1204
+ cancelText: "Keep it",
1205
+ onCancel: () => f(!1),
1206
+ onConfirm: () => {
1207
+ f(!1), u();
1208
+ }
1209
+ }),
1210
+ i && /* @__PURE__ */ Q("div", {
1211
+ className: "px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4",
1212
+ children: [
1213
+ /* @__PURE__ */ Z(z, {
1214
+ label: "Name on the page",
1215
+ value: t.title,
1216
+ onChange: (e) => c({
1217
+ ...t,
1218
+ title: e
1219
+ }),
1220
+ placeholder: "Anna Bell",
1221
+ hint: "Usually the name of whoever the page is for."
1222
+ }),
1223
+ /* @__PURE__ */ Z(e, {
1224
+ label: "Photo",
1225
+ hint: "Shown at the top of the page. A square picture of the person works best.",
1226
+ value: t.photo,
1227
+ onChange: (e) => c({
1228
+ ...t,
1229
+ photo: e
1230
+ })
1231
+ }),
1232
+ /* @__PURE__ */ Z(k, {
1233
+ label: "About this page",
1234
+ value: t.intro,
1235
+ onChange: (e) => c({
1236
+ ...t,
1237
+ intro: e
1238
+ }),
1239
+ rows: 3,
1240
+ placeholder: "I help small studios get their bookkeeping straight. Pick a time below and tell me what you need."
1241
+ }),
1242
+ /* @__PURE__ */ Z(cn, {
1243
+ page: t,
1244
+ schedules: n,
1245
+ onChange: c
1246
+ }),
1247
+ /* @__PURE__ */ Z(ln, {
1248
+ page: t,
1249
+ taken: r,
1250
+ onRename: l
1251
+ }),
1252
+ h ? /* @__PURE__ */ Z("p", {
1253
+ className: "text-[12px] font-semibold text-amber-500 px-1",
1254
+ children: h
1255
+ }) : /* @__PURE__ */ Z(yt, {
1256
+ title: m,
1257
+ path: st(t.id)
1258
+ })
1259
+ ]
1260
+ }),
1261
+ o && /* @__PURE__ */ Z("p", {
1262
+ className: "text-[12px] font-semibold text-red-500 px-4 pb-3",
1263
+ children: o
1264
+ })
1265
+ ]
1266
+ });
1267
+ }
1268
+ function dn({ schedules: e, myName: t, isAdmin: n = !0, meId: r = "" }) {
1269
+ let { loading: i, pages: a } = ot(), [o, s] = Y({}), [c, l] = Y([]), [u, d] = Y(null), [f, p] = Y(null), [m, h] = Y({}), g = J(/* @__PURE__ */ new Map());
1270
+ Lt(a.map((e) => e.id), s, g);
1271
+ let _ = new Map(a.map((e) => [e.id, e]));
1272
+ for (let e of Object.values(o)) _.set(e.id, e);
1273
+ for (let e of c) _.delete(e);
1274
+ let v = [..._.values()].sort((e, t) => (e.createdAt || 0) - (t.createdAt || 0) || e.id.localeCompare(t.id)), y = v.map((e) => e.id), b = mt(v, r, n), x = n ? e : e.filter((e) => e.memberId === r), S = (e) => {
1275
+ let t = g.current.get(e.id);
1276
+ t && clearTimeout(t), g.current.set(e.id, setTimeout(async () => {
1277
+ g.current.delete(e.id);
1278
+ let t = await dt(e);
1279
+ h((n) => {
1280
+ let r = { ...n };
1281
+ return t ? r[e.id] = t : delete r[e.id], r;
1282
+ });
1283
+ }, 600));
1284
+ }, C = (e) => {
1285
+ s((t) => ({
1286
+ ...t,
1287
+ [e.id]: e
1288
+ })), S(e);
1289
+ }, w = () => {
1290
+ let e = rt(ct(t || "my page", y), t, r);
1291
+ s((t) => ({
1292
+ ...t,
1293
+ [e.id]: e
1294
+ })), l((t) => t.filter((t) => t !== e.id)), d(e.id), p(e.id), S(e);
1295
+ }, T = async (e, t) => {
1296
+ let n = g.current.get(e.id);
1297
+ n && (clearTimeout(n), g.current.delete(e.id));
1298
+ let r = {
1299
+ ...e,
1300
+ id: t
1301
+ };
1302
+ s((n) => {
1303
+ let i = { ...n };
1304
+ return delete i[e.id], i[t] = r, i;
1305
+ }), l((n) => [...n.filter((e) => e !== t), e.id]), u === e.id && d(t);
1306
+ let i = await lt(e.id, r);
1307
+ i && h((e) => ({
1308
+ ...e,
1309
+ [t]: i
1310
+ }));
1311
+ }, E = async (e) => {
1312
+ let t = g.current.get(e);
1313
+ t && (clearTimeout(t), g.current.delete(e)), s((t) => {
1314
+ let n = { ...t };
1315
+ return delete n[e], n;
1316
+ }), l((t) => [...t, e]), u === e && d(null);
1317
+ let n = await pt(e);
1318
+ n && (l((t) => t.filter((t) => t !== e)), h((t) => ({
1319
+ ...t,
1320
+ [e]: n
1321
+ })));
1322
+ };
1323
+ return /* @__PURE__ */ Z(N, {
1324
+ icon: Ce,
1325
+ title: "Your booking pages",
1326
+ description: "One link with a photo, a line about you and every meeting you offer.",
1327
+ actions: ({ open: e }) => /* @__PURE__ */ Z(L, {
1328
+ icon: V,
1329
+ compact: !0,
1330
+ title: "Create a page",
1331
+ onClick: () => {
1332
+ e(), w();
1333
+ },
1334
+ children: "Create a page"
1335
+ }),
1336
+ children: /* @__PURE__ */ Z("div", {
1337
+ className: "flex flex-col gap-3",
1338
+ children: i ? /* @__PURE__ */ Z("p", {
1339
+ className: `${R} px-1`,
1340
+ children: "Loading pages…"
1341
+ }) : b.length === 0 ? /* @__PURE__ */ Z("p", {
1342
+ className: `${R} px-1`,
1343
+ children: "No pages yet. Create one to hand out a single link — a visitor sees your photo, what you do and every meeting you offer, and picks the one they want."
1344
+ }) : b.map((e) => /* @__PURE__ */ Z(un, {
1345
+ page: e,
1346
+ schedules: x,
1347
+ taken: y,
1348
+ open: u === e.id,
1349
+ fresh: f === e.id,
1350
+ error: m[e.id],
1351
+ onToggle: () => d((t) => t === e.id ? null : e.id),
1352
+ onChange: C,
1353
+ onRename: (t) => T(e, t),
1354
+ onRemove: () => E(e.id)
1355
+ }, e.id))
1356
+ })
1357
+ });
1358
+ }
1359
+ //#endregion
1360
+ //#region src/pages/ScheduleAdmin.tsx
1361
+ var fn = {
1362
+ from: "09:00",
1363
+ to: "17:00"
1364
+ }, pn = (e) => n(e) ? {
1365
+ state: "saved",
1366
+ label: "Ready"
1367
+ } : {
1368
+ state: "off",
1369
+ label: "In progress"
1370
+ }, mn = (e) => ({
1371
+ ...ae($e(), e.id, G(e), i()),
1372
+ name: "Working hours",
1373
+ enabled: !0,
1374
+ createdAt: Date.now()
1375
+ }), hn = "w-[6.5rem] shrink-0", gn = "w-9 h-9 rounded-[var(--btn-radius,0.75rem)] border border-[var(--panel-border)] flex items-center justify-center shrink-0 text-foreground/45 hover:text-red-500 hover:border-red-500/40 hover:bg-red-500/[0.06] active:scale-[0.98] transition-all cursor-pointer";
1376
+ function _n({ day: e, windows: t, onChange: n }) {
1377
+ let r = t.length > 0, i = (e, r) => n(t.map((t, n) => n === e ? {
1378
+ ...t,
1379
+ ...r
1380
+ } : t));
1381
+ return /* @__PURE__ */ Q("div", {
1382
+ className: "grid grid-cols-1 sm:grid-cols-[8.5rem_minmax(0,1fr)] items-start gap-x-4 gap-y-2 py-2.5",
1383
+ children: [/* @__PURE__ */ Q("div", {
1384
+ className: "flex items-center justify-between gap-3 h-9",
1385
+ children: [/* @__PURE__ */ Z("span", {
1386
+ className: `text-[13px] font-medium ${r ? "text-foreground/80" : "text-foreground/40"}`,
1387
+ children: v[e]
1388
+ }), /* @__PURE__ */ Z(b, {
1389
+ enabled: r,
1390
+ onChange: (e) => n(e ? [fn] : []),
1391
+ label: `${v[e]} — bookable`
1392
+ })]
1393
+ }), r && /* @__PURE__ */ Q("div", {
1394
+ className: "flex flex-col gap-2 min-w-0",
1395
+ children: [t.map((r, a) => /* @__PURE__ */ Q("div", {
1396
+ className: "flex items-center gap-2",
1397
+ children: [
1398
+ /* @__PURE__ */ Z("div", {
1399
+ className: hn,
1400
+ children: /* @__PURE__ */ Z(F, {
1401
+ ariaLabel: `${v[e]} from${a ? ` (${a + 1})` : ""}`,
1402
+ value: r.from,
1403
+ options: l,
1404
+ onChange: (e) => i(a, { from: e }),
1405
+ className: "console-select",
1406
+ compact: !0,
1407
+ portal: !0,
1408
+ direction: "auto"
1409
+ })
1410
+ }),
1411
+ /* @__PURE__ */ Z("span", {
1412
+ className: "w-3 text-center text-foreground/40 text-[13px] shrink-0 select-none",
1413
+ children: "–"
1414
+ }),
1415
+ /* @__PURE__ */ Z("div", {
1416
+ className: hn,
1417
+ children: /* @__PURE__ */ Z(F, {
1418
+ ariaLabel: `${v[e]} to${a ? ` (${a + 1})` : ""}`,
1419
+ value: r.to,
1420
+ options: he,
1421
+ onChange: (e) => i(a, { to: e }),
1422
+ className: "console-select",
1423
+ compact: !0,
1424
+ portal: !0,
1425
+ direction: "auto"
1426
+ })
1427
+ }),
1428
+ t.length > 1 && /* @__PURE__ */ Z("button", {
1429
+ type: "button",
1430
+ title: `Remove these hours on ${v[e]}`,
1431
+ "aria-label": `Remove ${v[e]} hours ${a + 1}`,
1432
+ onClick: () => n(t.filter((e, t) => t !== a)),
1433
+ className: gn,
1434
+ children: /* @__PURE__ */ Z(H, { className: "w-3.5 h-3.5" })
1435
+ })
1436
+ ]
1437
+ }, a)), t.length < 2 && /* @__PURE__ */ Z("button", {
1438
+ type: "button",
1439
+ onClick: () => n([...t, {
1440
+ from: "18:00",
1441
+ to: "20:00"
1442
+ }]),
1443
+ className: "self-start h-6 px-1 text-[11.5px] font-semibold text-foreground/45 hover:text-accent transition-colors cursor-pointer",
1444
+ children: "+ Add a second stretch"
1445
+ })]
1446
+ })]
1447
+ });
1448
+ }
1449
+ function vn({ schedule: e, onChange: t }) {
1450
+ let n = (n) => t({
1451
+ ...e,
1452
+ ...n
1453
+ }), r = ge(e);
1454
+ return /* @__PURE__ */ Q(X, { children: [
1455
+ /* @__PURE__ */ Z(z, {
1456
+ label: "What are these hours called?",
1457
+ hint: "Only you and your team read this — it is how a booking link names the hours it is booked in. Working hours, Evenings, Studio days.",
1458
+ value: e.name,
1459
+ onChange: (e) => n({ name: e }),
1460
+ placeholder: "Working hours"
1461
+ }),
1462
+ /* @__PURE__ */ Z(ce, {
1463
+ value: e.timeZone,
1464
+ onChange: (e) => n({ timeZone: e })
1465
+ }),
1466
+ /* @__PURE__ */ Z(P, {
1467
+ label: "When",
1468
+ hint: "The hours on each day, in this person's own time zone. Add a second stretch for a break in the middle. A time booked in any of their hours is taken here too.",
1469
+ children: /* @__PURE__ */ Z("div", {
1470
+ className: "flex flex-col divide-y divide-[var(--panel-border)]/60 rounded-2xl border border-[var(--panel-border)]/60 px-4 py-1",
1471
+ children: m.map((t) => /* @__PURE__ */ Z(_n, {
1472
+ day: t,
1473
+ windows: e.days[t] || [],
1474
+ onChange: (r) => n({ days: {
1475
+ ...e.days,
1476
+ [t]: r
1477
+ } })
1478
+ }, t))
1479
+ })
1480
+ }),
1481
+ /* @__PURE__ */ Z(jt, {
1482
+ blocked: e.blocked,
1483
+ onChange: (e) => n({ blocked: e })
1484
+ }),
1485
+ /* @__PURE__ */ Z("div", {
1486
+ className: "pt-1",
1487
+ children: r ? /* @__PURE__ */ Q("span", {
1488
+ className: "text-[11.5px] font-semibold text-amber-500",
1489
+ children: ["Not usable yet — ", r]
1490
+ }) : /* @__PURE__ */ Z("span", {
1491
+ className: "text-[11.5px] font-semibold text-emerald-500",
1492
+ children: "Ready — add a booking link below to let people book these hours, or ask for a page built on them."
1493
+ })
1494
+ })
1495
+ ] });
1496
+ }
1497
+ function yn({ schedule: e, open: t, stale: n, fresh: r, error: i, onToggle: a, onChange: o, onRemove: s }) {
1498
+ let c = pn(e), [l, u] = Y(!1), d = y(e), f = J(null);
1499
+ return K(() => {
1500
+ if (!r) return;
1501
+ let e = $(f.current);
1502
+ return () => {
1503
+ e && clearTimeout(e);
1504
+ };
1505
+ }, [r]), /* @__PURE__ */ Q("div", {
1506
+ ref: f,
1507
+ className: `scroll-mt-4 rounded-2xl border border-[var(--panel-border)] ${n ? "opacity-60" : ""}`,
1508
+ children: [
1509
+ /* @__PURE__ */ Q("div", {
1510
+ className: "flex items-center gap-2 sm:gap-2.5 pr-3",
1511
+ children: [/* @__PURE__ */ Q("button", {
1512
+ type: "button",
1513
+ onClick: a,
1514
+ "aria-expanded": t,
1515
+ className: "flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer",
1516
+ children: [/* @__PURE__ */ Z("span", {
1517
+ className: "text-[13px] font-semibold text-foreground/75 truncate",
1518
+ children: w(e)
1519
+ }), /* @__PURE__ */ Q("span", {
1520
+ className: "flex items-center gap-2.5 shrink-0",
1521
+ children: [n ? /* @__PURE__ */ Z("span", {
1522
+ className: `${R} max-sm:hidden`,
1523
+ children: "No longer on the team"
1524
+ }) : /* @__PURE__ */ Z("span", {
1525
+ className: "max-sm:hidden",
1526
+ children: /* @__PURE__ */ Z(ue, {
1527
+ state: c.state,
1528
+ label: c.label
1529
+ })
1530
+ }), /* @__PURE__ */ Z(U, { className: `w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${t ? "rotate-180" : ""}` })]
1531
+ })]
1532
+ }), /* @__PURE__ */ Z(L, {
1533
+ icon: B,
1534
+ tone: "danger",
1535
+ compact: !0,
1536
+ title: `Remove ${d}`,
1537
+ onClick: () => u(!0),
1538
+ children: "Remove"
1539
+ })]
1540
+ }),
1541
+ /* @__PURE__ */ Z(tt, {
1542
+ isOpen: l,
1543
+ title: `Remove ${d}?`,
1544
+ message: n ? "They are no longer on the team, so nobody can book them. Bookings already taken are kept." : "Every booking link booked in these hours stops working, and they leave every page and form they were picked on. Bookings already taken are kept.",
1545
+ confirmText: "Yes, remove",
1546
+ cancelText: "Keep it",
1547
+ onCancel: () => u(!1),
1548
+ onConfirm: () => {
1549
+ u(!1), s();
1550
+ }
1551
+ }),
1552
+ t && /* @__PURE__ */ Z("div", {
1553
+ className: "px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4",
1554
+ children: /* @__PURE__ */ Z(vn, {
1555
+ schedule: e,
1556
+ onChange: o
1557
+ })
1558
+ }),
1559
+ i && /* @__PURE__ */ Z("p", {
1560
+ className: "text-[12px] font-semibold text-red-500 px-4 pb-3",
1561
+ children: i
1562
+ })
1563
+ ]
1564
+ });
1565
+ }
1566
+ function bn({ name: e, schedules: t, stale: n, open: r, onToggle: i, onAdd: a, openScheduleId: o, freshId: s, errors: c, onToggleSchedule: l, onChange: u, onRemove: d }) {
1567
+ let f = n ? "No longer on the team" : t.length === 0 ? "No schedules yet" : `${t.length} schedule${t.length === 1 ? "" : "s"}`, p = J(null);
1568
+ return K(() => {
1569
+ if (!r) return;
1570
+ let e = $(p.current);
1571
+ return () => {
1572
+ e && clearTimeout(e);
1573
+ };
1574
+ }, [r]), /* @__PURE__ */ Q("div", {
1575
+ ref: p,
1576
+ className: "scroll-mt-4 rounded-2xl border border-[var(--panel-border)]",
1577
+ children: [/* @__PURE__ */ Q("button", {
1578
+ type: "button",
1579
+ onClick: i,
1580
+ "aria-expanded": r,
1581
+ className: "w-full flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer",
1582
+ children: [/* @__PURE__ */ Z("span", {
1583
+ className: "text-[13px] font-semibold text-foreground/75 truncate",
1584
+ children: e
1585
+ }), /* @__PURE__ */ Q("span", {
1586
+ className: "flex items-center gap-2.5 shrink-0",
1587
+ children: [/* @__PURE__ */ Z("span", {
1588
+ className: `${R} max-sm:hidden`,
1589
+ children: f
1590
+ }), /* @__PURE__ */ Z(U, { className: `w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${r ? "rotate-180" : ""}` })]
1591
+ })]
1592
+ }), r && /* @__PURE__ */ Q("div", {
1593
+ className: "px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-3",
1594
+ children: [t.map((e) => /* @__PURE__ */ Z(yn, {
1595
+ schedule: e,
1596
+ stale: n,
1597
+ fresh: s === e.id,
1598
+ open: o === e.id,
1599
+ error: c[e.id],
1600
+ onToggle: () => l(e.id),
1601
+ onChange: u,
1602
+ onRemove: () => d(e.id)
1603
+ }, e.id)), n ? t.length === 0 && /* @__PURE__ */ Q("p", {
1604
+ className: "text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug",
1605
+ children: [
1606
+ "No schedule yet for ",
1607
+ e,
1608
+ "."
1609
+ ]
1610
+ }) : /* @__PURE__ */ Q("div", {
1611
+ className: "flex flex-col items-start sm:flex-row sm:items-center gap-3 rounded-2xl border border-dashed border-[var(--panel-border)] px-4 py-3",
1612
+ children: [/* @__PURE__ */ Z(L, {
1613
+ icon: V,
1614
+ title: `Add a schedule for ${e}`,
1615
+ onClick: a,
1616
+ children: "Add a schedule"
1617
+ }), t.length === 0 && /* @__PURE__ */ Q("p", {
1618
+ className: "text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug",
1619
+ children: [
1620
+ "No schedule yet for ",
1621
+ e,
1622
+ "."
1623
+ ]
1624
+ })]
1625
+ })]
1626
+ })]
1627
+ });
1628
+ }
1629
+ var xn = (e) => ({
1630
+ id: e.uid,
1631
+ name: String(e.displayName || ""),
1632
+ email: String(e.email || ""),
1633
+ role: "admin"
1634
+ });
1635
+ function Sn({ isAdmin: e = !0 } = {}) {
1636
+ let { user: t } = j(), { loading: n, members: r } = Oe(), { loading: i, docs: a } = Re(), o = a.schedules, [s, c] = Y({}), [l, u] = Y([]), [d, f] = Y(null), [p, m] = Y(null), [h, g] = Y(null), [_, v] = Y({}), y = J(/* @__PURE__ */ new Map());
1637
+ Lt(o.map((e) => e.id), c, y);
1638
+ let b = q(() => {
1639
+ let e = new Map(o.map((e) => [e.id, e]));
1640
+ for (let t of Object.values(s)) e.set(t.id, t);
1641
+ for (let t of l) e.delete(t);
1642
+ return [...e.values()].sort((e, t) => (e.createdAt || 0) - (t.createdAt || 0) || e.id.localeCompare(t.id));
1643
+ }, [
1644
+ o,
1645
+ s,
1646
+ l
1647
+ ]), x = (e) => {
1648
+ let t = y.current.get(e.id);
1649
+ t && clearTimeout(t), y.current.set(e.id, setTimeout(async () => {
1650
+ y.current.delete(e.id);
1651
+ let t = await Be(e);
1652
+ v((n) => {
1653
+ let r = { ...n };
1654
+ return t ? r[e.id] = t : delete r[e.id], r;
1655
+ });
1656
+ }, 600));
1657
+ }, S = (e) => {
1658
+ c((t) => ({
1659
+ ...t,
1660
+ [e.id]: e
1661
+ })), x(e);
1662
+ }, C = q(() => t ? r.find((e) => e.id === t.uid) || xn(t) : null, [t, r]), w = q(() => C && !r.some((e) => e.id === C.id) ? [C, ...r] : r, [C, r]), T = J(!1), [E, D] = Y(""), O = q(() => a.schedules.filter((t) => a.legacyIds.includes(t.id) && (e || t.memberId === C?.id)), [
1663
+ a.schedules,
1664
+ a.legacyIds,
1665
+ e,
1666
+ C
1667
+ ]);
1668
+ K(() => {
1669
+ T.current || O.length === 0 || (T.current = !0, Je(O).then((e) => {
1670
+ e && D(e);
1671
+ }));
1672
+ }, [O]);
1673
+ let k = (e) => {
1674
+ let t = mn(e);
1675
+ c((e) => ({
1676
+ ...e,
1677
+ [t.id]: t
1678
+ })), f(t.id), m(t.id), C && e.id !== C.id && g(e.id), x(t);
1679
+ }, ee = () => {
1680
+ C && k(C);
1681
+ }, A = async (e) => {
1682
+ let t = y.current.get(e);
1683
+ t && (clearTimeout(t), y.current.delete(e)), c((t) => {
1684
+ let n = { ...t };
1685
+ return delete n[e], n;
1686
+ }), u((t) => [...t, e]), d === e && f(null);
1687
+ let n = await Ge(e);
1688
+ n && (u((t) => t.filter((t) => t !== e)), v((t) => ({
1689
+ ...t,
1690
+ [e]: n
1691
+ })));
1692
+ }, M = n || i, te = new Set(w.map((e) => e.id)), P = C ? b.filter((e) => e.memberId === C.id) : [], ne = q(() => {
1693
+ if (!C) return [];
1694
+ let e = /* @__PURE__ */ new Map();
1695
+ for (let t of b) {
1696
+ if (t.memberId === C.id) continue;
1697
+ let n = e.get(t.memberId);
1698
+ n ? n.push(t) : e.set(t.memberId, [t]);
1699
+ }
1700
+ let t = [];
1701
+ for (let n of w) n.id !== C.id && (t.push({
1702
+ id: n.id,
1703
+ name: G(n) || n.email,
1704
+ stale: !1,
1705
+ schedules: e.get(n.id) || []
1706
+ }), e.delete(n.id));
1707
+ for (let [n, r] of e) t.push({
1708
+ id: n,
1709
+ name: r[0].memberName.trim() || "Someone no longer on the team",
1710
+ stale: !0,
1711
+ schedules: r
1712
+ });
1713
+ return t;
1714
+ }, [
1715
+ b,
1716
+ w,
1717
+ C
1718
+ ]);
1719
+ return /* @__PURE__ */ Q(X, { children: [/* @__PURE__ */ Z(N, {
1720
+ icon: ye,
1721
+ title: "Your schedules",
1722
+ description: "When you are free — a name, a time zone, the week's hours and the days you are away. The base for anything booked on them.",
1723
+ actions: M ? void 0 : ({ open: e }) => /* @__PURE__ */ Z(L, {
1724
+ icon: V,
1725
+ compact: !0,
1726
+ title: "Add a schedule",
1727
+ onClick: () => {
1728
+ e(), ee();
1729
+ },
1730
+ children: "Add a schedule"
1731
+ }),
1732
+ children: /* @__PURE__ */ Q("div", {
1733
+ className: "flex flex-col gap-3",
1734
+ children: [M ? /* @__PURE__ */ Z("p", {
1735
+ className: R,
1736
+ children: "Loading your schedules…"
1737
+ }) : P.length === 0 ? /* @__PURE__ */ Z("p", {
1738
+ className: `${R} px-1`,
1739
+ children: "No hours of your own yet — press Add a schedule. Everything booked in them shares one availability, so a time taken once is gone from all of it."
1740
+ }) : P.map((e) => /* @__PURE__ */ Z(yn, {
1741
+ schedule: e,
1742
+ stale: !te.has(e.memberId),
1743
+ fresh: p === e.id,
1744
+ open: d === e.id,
1745
+ error: _[e.id],
1746
+ onToggle: () => f(d === e.id ? null : e.id),
1747
+ onChange: S,
1748
+ onRemove: () => A(e.id)
1749
+ }, e.id)), !!E && /* @__PURE__ */ Z("p", {
1750
+ className: "text-[12px] font-semibold text-red-500 px-1",
1751
+ children: E
1752
+ })]
1753
+ })
1754
+ }), e && /* @__PURE__ */ Z(N, {
1755
+ icon: Se,
1756
+ title: "Your team's schedules",
1757
+ description: "When everyone else is free — one folded row per person; open a name to add their hours or see what they keep.",
1758
+ children: /* @__PURE__ */ Z("div", {
1759
+ className: "flex flex-col gap-3",
1760
+ children: M ? /* @__PURE__ */ Z("p", {
1761
+ className: "text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug",
1762
+ children: "Loading your team's schedules…"
1763
+ }) : ne.length === 0 ? /* @__PURE__ */ Q("p", {
1764
+ className: "text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug px-1",
1765
+ children: [
1766
+ "Nobody else is marked Internal or Admin yet. Add them on the",
1767
+ " ",
1768
+ /* @__PURE__ */ Z(Ct, {
1769
+ to: "/users",
1770
+ className: "text-accent font-bold hover:underline",
1771
+ children: "Users screen"
1772
+ }),
1773
+ " and a folded row for them appears here."
1774
+ ]
1775
+ }) : ne.map((e) => /* @__PURE__ */ Z(bn, {
1776
+ name: e.name,
1777
+ schedules: e.schedules,
1778
+ stale: e.stale,
1779
+ open: h === e.id,
1780
+ onToggle: () => {
1781
+ let t = h !== e.id;
1782
+ g(t ? e.id : null), t && e.schedules.length && f(e.schedules[0].id);
1783
+ },
1784
+ onAdd: () => {
1785
+ let t = w.find((t) => t.id === e.id);
1786
+ t && k(t);
1787
+ },
1788
+ openScheduleId: d,
1789
+ freshId: p,
1790
+ errors: _,
1791
+ onToggleSchedule: (e) => f(d === e ? null : e),
1792
+ onChange: S,
1793
+ onRemove: A
1794
+ }, e.id))
1795
+ })
1796
+ })] });
1797
+ }
1798
+ function Cn() {
1799
+ let { user: e, userRole: n } = j(), r = n === "admin", { schedules: i } = Ie(), a = e && (e.displayName || e.email?.split("@")[0]) || "";
1800
+ return ve(n) ? /* @__PURE__ */ Q("main", {
1801
+ className: "flex-1 w-full max-w-7xl mx-auto p-4 pt-2 md:p-8 md:pt-4 z-10 flex flex-col min-h-screen",
1802
+ children: [/* @__PURE__ */ Q(se.div, {
1803
+ initial: {
1804
+ opacity: 0,
1805
+ y: 20
1806
+ },
1807
+ animate: {
1808
+ opacity: 1,
1809
+ y: 0
1810
+ },
1811
+ className: "mb-6",
1812
+ children: [/* @__PURE__ */ Z(t, { children: "Schedule" }), /* @__PURE__ */ Q("div", {
1813
+ className: "flex items-center gap-2 text-foreground/40 font-bold uppercase tracking-[0.2em] text-[11px]",
1814
+ children: [/* @__PURE__ */ Z("span", { className: "w-8 h-[1px] bg-foreground/10" }), "/schedule"]
1815
+ })]
1816
+ }), /* @__PURE__ */ Q("div", {
1817
+ className: "flex flex-col gap-6 flex-1 pb-16",
1818
+ children: [
1819
+ /* @__PURE__ */ Z(_e, {}),
1820
+ /* @__PURE__ */ Z(gt, { tab: "schedule" }),
1821
+ /* @__PURE__ */ Z("div", {
1822
+ className: "glass-panel border border-[var(--panel-border)] rounded-3xl p-4 sm:p-5 md:p-8 shadow-2xl relative bg-background flex flex-col fbos-tab-fill min-h-[600px]",
1823
+ children: /* @__PURE__ */ Q("div", {
1824
+ className: "flex flex-col gap-4",
1825
+ children: [
1826
+ /* @__PURE__ */ Z("div", {
1827
+ className: "flex flex-col gap-1.5 px-1",
1828
+ children: /* @__PURE__ */ Z("p", {
1829
+ className: "text-[13px] font-medium text-foreground/60 leading-relaxed",
1830
+ children: r ? "When you and your team are free, and everything built on it. A schedule is a week of hours in one person’s own time zone; a booking link turns those hours into a meeting people can book, with an address to send. The same hours are what a page you ask for is built on." : "When you are free, and what people can book in it. Your schedule is your week of hours; a booking link turns it into a meeting, with an address of its own to send — they pick a free time and it lands on your calendar. A booking page gathers your meetings under one address to hand out."
1831
+ })
1832
+ }),
1833
+ /* @__PURE__ */ Z(an, { isAdmin: r }),
1834
+ /* @__PURE__ */ Z(Sn, { isAdmin: r }),
1835
+ /* @__PURE__ */ Z(Kt, { isAdmin: r }),
1836
+ /* @__PURE__ */ Z(dn, {
1837
+ schedules: i,
1838
+ myName: a,
1839
+ isAdmin: r,
1840
+ meId: e?.uid || ""
1841
+ })
1842
+ ]
1843
+ })
1844
+ })
1845
+ ]
1846
+ })]
1847
+ }) : /* @__PURE__ */ Z("main", {
1848
+ className: "flex-1 w-full max-w-7xl mx-auto p-4 pt-2 md:p-8 md:pt-4 z-10 flex flex-col min-h-screen",
1849
+ children: /* @__PURE__ */ Z(ht, {})
1850
+ });
1851
+ }
1852
+ //#endregion
1853
+ export { Cn as ScheduleAdmin };