your-ai-workflow-firebase-os 2.0.9 → 2.0.10

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 (77) hide show
  1. package/dist/{Assets-COH4Ji57.js → Assets-BKXpQmMS.js} +2 -2
  2. package/dist/{Assets-D7fDckSi.cjs → Assets-DoZlHuud.cjs} +1 -1
  3. package/dist/{Billing-kk4ZMd3z.js → Billing-A6rwfQRT.js} +2 -2
  4. package/dist/{Billing-DkuJdls5.cjs → Billing-CBxVy-CG.cjs} +1 -1
  5. package/dist/{CopyLink-C5lKLyOU.cjs → CopyLink-D6QTWSoK.cjs} +1 -1
  6. package/dist/{CopyLink-CNjDLzOl.js → CopyLink-kROJG9Qf.js} +1 -1
  7. package/dist/{DashboardNav-GgEUpyTa.cjs → DashboardNav-Bc619nqn.cjs} +1 -1
  8. package/dist/{DashboardNav-CEd8gGPm.js → DashboardNav-CxS3Qnl-.js} +1 -1
  9. package/dist/{EmailAdmin-pbQ-f9Ge.js → EmailAdmin-DbWK_5Kw.js} +4 -4
  10. package/dist/{EmailAdmin-d_gWd48U.cjs → EmailAdmin-sa9C5jOw.cjs} +1 -1
  11. package/dist/{EventCard-DAsGsicK.cjs → EventCard-D57elnQo.cjs} +1 -1
  12. package/dist/{EventCard-BSGLYD64.js → EventCard-DnoR91KN.js} +1 -1
  13. package/dist/{FormsAdmin-5KTTp6zo.cjs → FormsAdmin-Ck7ssCHd.cjs} +1 -1
  14. package/dist/{FormsAdmin-BNI63vEk.js → FormsAdmin-DOes2Ajy.js} +4 -4
  15. package/dist/{Inbox-DjslBakx.cjs → Inbox-ChBLxjCi.cjs} +1 -1
  16. package/dist/{Inbox-D9Y5K8Se.js → Inbox-CyteB2LL.js} +2 -2
  17. package/dist/{MyBookings-CkEioQIj.cjs → MyBookings-B424zfVj.cjs} +1 -1
  18. package/dist/{MyBookings-B4DndHV6.js → MyBookings-DLQefkDS.js} +3 -3
  19. package/dist/{PageTitle-DQkvCB11.cjs → PageTitle-BL50s4qY.cjs} +1 -1
  20. package/dist/{PageTitle-DCoUQWw6.js → PageTitle-CkZriz8K.js} +1 -1
  21. package/dist/{PagesAdmin-YdYgmuEB.cjs → PagesAdmin-1U73GM_o.cjs} +1 -1
  22. package/dist/PagesAdmin-8smM_SDx.cjs +1 -0
  23. package/dist/{PagesAdmin-DzLJWKBJ.js → PagesAdmin-CORR24DJ.js} +8 -8
  24. package/dist/{PagesAdmin-D0qgoZtW.js → PagesAdmin-hhVAwuuy.js} +1 -1
  25. package/dist/{PaymentsAdmin-C3cEOeIs.js → PaymentsAdmin-CoaSATtY.js} +9 -9
  26. package/dist/{PaymentsAdmin-B5l-f0mp.cjs → PaymentsAdmin-DdP5FeXc.cjs} +1 -1
  27. package/dist/{ProviderMark--adeeajP.cjs → ProviderMark-BCQRu5Gs.cjs} +1 -1
  28. package/dist/{ProviderMark-BvEMlZAm.js → ProviderMark-Celkjuth.js} +1 -1
  29. package/dist/{PublishApp-Bc82Ijkq.cjs → PublishApp-CYHX36oo.cjs} +1 -1
  30. package/dist/{PublishApp-B9Fo6xN0.js → PublishApp-Dagc4TYm.js} +4 -4
  31. package/dist/{ScheduleAdmin-bk3GgxKP.js → ScheduleAdmin-D8siv7ZQ.js} +4 -4
  32. package/dist/{ScheduleAdmin-Dh_hW6p4.cjs → ScheduleAdmin-ohFzK-5E.cjs} +1 -1
  33. package/dist/{SchedulePicker-CN0755Ek.cjs → SchedulePicker-BpPGI5VZ.cjs} +1 -1
  34. package/dist/{SchedulePicker-DO4PewPJ.js → SchedulePicker-sZIZec9L.js} +1 -1
  35. package/dist/{Setup-_G-s5y5Q.js → Setup-DOGI-_8f.js} +2 -2
  36. package/dist/{Setup-R4r6_tbV.cjs → Setup-DiFnnzdd.cjs} +1 -1
  37. package/dist/{SetupPayments-CuFk9REC.cjs → SetupPayments-BLq0W5DU.cjs} +1 -1
  38. package/dist/{SetupPayments-CkolcOtv.js → SetupPayments-ICqCoZeQ.js} +3 -3
  39. package/dist/{SignInAdmin-BLEn0rId.js → SignInAdmin-CQzPqUui.js} +5 -5
  40. package/dist/{SignInAdmin-B1yLLaQu.cjs → SignInAdmin-JnhCefKY.cjs} +1 -1
  41. package/dist/{SupportBar-DI_XbEsG.js → SupportBar-0nIiQp-_.js} +105 -104
  42. package/dist/SupportBar-DR52UpBq.cjs +1 -0
  43. package/dist/{TemplateDrive-DNBwL0oy.js → TemplateDrive-6aV9Hmh3.js} +2 -2
  44. package/dist/{TemplateDrive-BJN-ReA_.cjs → TemplateDrive-ElNPzwv3.cjs} +1 -1
  45. package/dist/ThemeAdmin-B4CIxIjh.cjs +1 -0
  46. package/dist/ThemeAdmin-B9VnH5xH.js +2 -0
  47. package/dist/{ThemeAdmin-DkgmjW3g.cjs → ThemeAdmin-BhaTfgKX.cjs} +1 -1
  48. package/dist/{ThemeAdmin-Cnqefrz6.js → ThemeAdmin-C_8phTKX.js} +3 -3
  49. package/dist/{TransactionsAdmin-C5wQRR1g.cjs → TransactionsAdmin-BiV8VgD0.cjs} +1 -1
  50. package/dist/{TransactionsAdmin-Brs-CEcG.js → TransactionsAdmin-DAENRmVO.js} +3 -3
  51. package/dist/{Users-B16L9cKI.cjs → Users-Ayu_S4cd.cjs} +1 -1
  52. package/dist/{Users-CbI4K_Le.js → Users-CNRVFf3-.js} +5 -5
  53. package/dist/{appIcons-CCArfCDe.js → appIcons-DfjKL0tw.js} +1 -1
  54. package/dist/{appIcons-C90OKlV5.cjs → appIcons-Xjk-LuQ5.cjs} +1 -1
  55. package/dist/{arrivalRoads-Cc6AZM-d.cjs → arrivalRoads-1OeHArA0.cjs} +0 -0
  56. package/dist/{arrivalRoads-CGXm9Ntm.js → arrivalRoads-BZ4SWRAw.js} +0 -0
  57. package/dist/components/TutorialVideo.d.ts +3 -1
  58. package/dist/index.d.ts +1 -0
  59. package/dist/{paidSessions-D-zHC4oG.cjs → paidSessions-BK9qlIyL.cjs} +1 -1
  60. package/dist/{paidSessions-B8e5RHi4.js → paidSessions-C9392hZH.js} +2 -2
  61. package/dist/{recordsKey-C4E2vOti.cjs → recordsKey-B3lWGd8C.cjs} +1 -1
  62. package/dist/{recordsKey-Cd216nq1.js → recordsKey-CJL-dAYF.js} +1 -1
  63. package/dist/{roles-BBDIJzox.cjs → roles-BmnoAilb.cjs} +1 -1
  64. package/dist/{roles-DiwP6-WQ.js → roles-D3T8p-hA.js} +2 -2
  65. package/dist/server.cjs.js +1 -1
  66. package/dist/server.es.js +1 -1
  67. package/dist/vite.cjs.js +1 -1
  68. package/dist/vite.es.js +1 -1
  69. package/dist/your-ai-workflow-firebase-os.cjs.js +13 -13
  70. package/dist/your-ai-workflow-firebase-os.es.js +2184 -2189
  71. package/package.json +1 -1
  72. package/scripts/postinstall.js +2 -1
  73. package/src/pages/Home.tsx +11 -14
  74. package/dist/PagesAdmin-KUxCI1Mr.cjs +0 -1
  75. package/dist/SupportBar-DLWruzQb.cjs +0 -1
  76. package/dist/ThemeAdmin-CoE_c5-P.cjs +0 -1
  77. package/dist/ThemeAdmin-DI7QaZ-0.js +0 -2
@@ -1,27 +1,27 @@
1
- import { _ as e, o as t, t as n } from "./PageTitle-DCoUQWw6.js";
1
+ import { _ as e, o as t, t as n } from "./PageTitle-CkZriz8K.js";
2
2
  import { $n as r, Ar as i, At as a, Cr as o, Dr as s, Er as c, Ft as l, Jn as u, Qn as d, S as f, Sr as p, Tr as m, Vn as h, Zr as g, _, b as v, br as y, cr as b, dr as x, g as S, gr as C, h as w, i as T, ii as E, ir as D, kr as O, m as k, n as A, nt as j, o as M, or as N, qr as ee, r as P, s as F, sr as I, ui as L, v as R, wr as z, x as te, xr as B, y as V, yr as ne } from "./TimeZoneField-oIMwb5_X.js";
3
- import { j as re, t as ie, w as ae } from "./DashboardNav-CEd8gGPm.js";
3
+ import { j as re, t as ie, w as ae } from "./DashboardNav-CxS3Qnl-.js";
4
4
  import { Ln as H, jt as oe } from "./schedule-C13m_kiO.js";
5
5
  import { n as U, t as W } from "./chevron-down--LwXEv9w.js";
6
6
  import { t as se } from "./arrow-left-DdRja6es.js";
7
7
  import { t as ce } from "./arrow-right-C6OLl8Zh.js";
8
- import { t as le } from "./SupportBar-DI_XbEsG.js";
9
- import { An as ue, Fi as de, Ni as fe, Pi as pe, _n as me, fr as he, pr as ge } from "./PagesAdmin-DzLJWKBJ.js";
8
+ import { t as le } from "./SupportBar-0nIiQp-_.js";
9
+ import { An as ue, Fi as de, Ni as fe, Pi as pe, _n as me, fr as he, pr as ge } from "./PagesAdmin-CORR24DJ.js";
10
10
  import { t as _e } from "./link-2-CtDUJiNU.js";
11
11
  import { r as ve } from "./x-hax8aKt8.js";
12
12
  import { t as G } from "./plus-BKrt0Qx5.js";
13
13
  import { t as ye } from "./power-BrOGO3tj.js";
14
14
  import { i as be, n as xe } from "./Said-BvSRaEfZ.js";
15
15
  import { t as K } from "./trash-6Wj66gJi.js";
16
- import { l as Se, n as Ce, o as we } from "./roles-DiwP6-WQ.js";
16
+ import { l as Se, n as Ce, o as we } from "./roles-D3T8p-hA.js";
17
17
  import { r as Te } from "./transactions-ycKW6zHa.js";
18
18
  import { t as Ee } from "./ConfirmModal-BW9e6Y7d.js";
19
- import { u as De } from "./recordsKey-Cd216nq1.js";
20
- import { a as Oe, n as ke, t as Ae } from "./Setup-_G-s5y5Q.js";
19
+ import { u as De } from "./recordsKey-CJL-dAYF.js";
20
+ import { a as Oe, n as ke, t as Ae } from "./Setup-DOGI-_8f.js";
21
21
  import { r as je } from "./serviceSwitches-CZHwvVfP.js";
22
22
  import { i as Me, n as Ne } from "./serviceStatus-C9izcuQz.js";
23
- import { ConnectCard as Pe, StripeSetupSteps as Fe } from "./SetupPayments-CkolcOtv.js";
24
- import { t as Ie } from "./CopyLink-CNjDLzOl.js";
23
+ import { ConnectCard as Pe, StripeSetupSteps as Fe } from "./SetupPayments-ICqCoZeQ.js";
24
+ import { t as Ie } from "./CopyLink-kROJG9Qf.js";
25
25
  import { l as Le, s as Re } from "./publishSteps-Cf5pSB_H.js";
26
26
  import { useCallback as ze, useEffect as q, useRef as J, useState as Y } from "react";
27
27
  import { Fragment as X, jsx as Z, jsxs as Q } from "react/jsx-runtime";
@@ -1,2 +1,2 @@
1
- require(`./chunk-CiTBaPhY.cjs`);const e=require(`./PageTitle-DQkvCB11.cjs`),t=require(`./TimeZoneField-Ckn1pKAL.cjs`),n=require(`./DashboardNav-GgEUpyTa.cjs`),r=require(`./schedule-BAea6q8_.cjs`),i=require(`./chevron-down-lyDK1rfL.cjs`),a=require(`./arrow-left-C39sNUA7.cjs`),o=require(`./arrow-right-CGvbxks5.cjs`),s=require(`./SupportBar-DLWruzQb.cjs`),c=require(`./PagesAdmin-YdYgmuEB.cjs`),l=require(`./link-2-C7A-6PW6.cjs`),u=require(`./x-Ci8c5p6T.cjs`),d=require(`./plus-zsWFCu4F.cjs`),f=require(`./power-Bs_nchQG.cjs`),p=require(`./Said-W3KFi5uX.cjs`),m=require(`./trash-D-CpYHCs.cjs`),h=require(`./roles-BBDIJzox.cjs`),g=require(`./transactions-CIU2NcKh.cjs`),_=require(`./ConfirmModal-BUNtss4a.cjs`),v=require(`./recordsKey-C4E2vOti.cjs`),y=require(`./Setup-R4r6_tbV.cjs`),b=require(`./serviceSwitches-mhJbQBrV.cjs`),x=require(`./serviceStatus-Cde96_OO.cjs`),S=require(`./SetupPayments-CuFk9REC.cjs`),C=require(`./CopyLink-C5lKLyOU.cjs`),w=require(`./publishSteps-DvWlF0p_.cjs`);let T=require(`react`),E=require(`react/jsx-runtime`),D=require(`firebase/firestore`),O=require(`react-router-dom`);var k={name:`plug`,size:24,node:[[`path`,{d:`M12 22v-5`,key:`1ega77`}],[`path`,{d:`M15 8V2`,key:`18g5xt`}],[`path`,{d:`M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z`,key:`1xoxul`}],[`path`,{d:`M9 8V2`,key:`14iosj`}]]};k.node;var A=i.n(k),j={name:`tag`,size:24,node:[[`path`,{d:`M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z`,key:`vktsd0`}],[`circle`,{cx:`7.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`kqv944`}]]};j.node;var M=i.n(j),N={name:`triangle-alert`,size:24,node:[[`path`,{d:`m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3`,key:`wmoenq`}],[`path`,{d:`M12 9v4`,key:`juzpu7`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]],aliases:[`alert-triangle`]};N.node;var P=i.n(N),F={name:`workflow`,size:24,node:[[`rect`,{width:`8`,height:`8`,x:`3`,y:`3`,rx:`2`,key:`by2w9f`}],[`path`,{d:`M7 11v4a2 2 0 0 0 2 2h4`,key:`xkn7yn`}],[`rect`,{width:`8`,height:`8`,x:`13`,y:`13`,rx:`2`,key:`1cgmvn`}]]};F.node;var I=i.n(F);function L({product:e,live:n,open:r,onToggle:o,onChange:s,forPage:c,onAddToPage:l}){let u=t=>s({...e,...t});if(!t.wr(e,n))return(0,E.jsx)(`div`,{className:`rounded-2xl border border-[var(--panel-border)] opacity-50`,"aria-disabled":`true`,children:(0,E.jsxs)(`div`,{className:`w-full flex items-center justify-between gap-3 px-4 py-3`,children:[(0,E.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/60 truncate`,children:t.Er(e)}),(0,E.jsx)(t._,{state:`off`,label:`Finish it above first`})]})});let f=t.Cr(e),p=e.kind===`subscription`;return(0,E.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]`,children:[(0,E.jsxs)(`button`,{type:`button`,onClick:o,"aria-expanded":r,className:`w-full flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer`,children:[(0,E.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:t.Er(e)}),(0,E.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[(0,E.jsx)(t._,{state:f?`off`:`saved`,label:f?`Question left`:`Ready for pages`}),(0,E.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${r?`rotate-180`:``}`})]})]}),r&&(0,E.jsxs)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4`,children:[(0,E.jsx)(t.y,{label:`How will this payment work?`,hint:p?`Start to finish, in your own words — what someone does, pays, and gets. Worth saying if you care: what they tell you before paying (never their email — Stripe asks for that), what each plan unlocks, and what happens the moment they subscribe. Whatever you skip, your assistant decides.`:`Start to finish, in your own words — what someone does, pays, and gets. Worth saying if you care: what they tell you before paying (never their email — Stripe asks for that) and what happens after they pay. Whatever you skip, your assistant decides.`,value:e.how,onChange:e=>u({how:e}),placeholder:p?`People pick a plan and pay, and their member area unlocks the same minute — Basic gets the videos, Pro gets the videos and a monthly call.`:`People choose a session, tell me their phone number and what they need, and pay — then they see a thank-you, and I get in touch within a day.`}),(0,E.jsxs)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:[`The buyer’s receipt and your sale email are switched on your`,` `,(0,E.jsx)(O.Link,{to:`/email`,className:`text-accent font-semibold hover:underline`,children:`Email screen`}),`, for every payment at once.`]}),(0,E.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3 pt-1`,children:[f?(0,E.jsx)(`span`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:f}):c?(0,E.jsx)(`span`,{className:`text-[11.5px] font-semibold text-emerald-500`,children:`Ready to add to pages — add it to ${c.title} and go back.`}):(0,E.jsxs)(`span`,{className:`text-[11.5px] font-semibold text-emerald-500`,children:[`Ready to add to pages — open a page on the`,` `,(0,E.jsx)(O.Link,{to:`/pages`,className:`font-bold hover:underline`,children:`Pages screen`}),` and add it under Payments.`]}),!f&&c&&l?(0,E.jsx)(t.o,{icon:e.pageIds.includes(c.id)?a.t:d.t,onClick:()=>l(e.id),children:e.pageIds.includes(c.id)?`Back to ${c.title}`:`Add to ${c.title}`}):(0,E.jsx)(`span`,{})]})]})]})}function R({products:e,live:n,openId:r,onToggle:i,onChange:a,forPage:o,onAddToPage:s}){return e===null?(0,E.jsx)(`p`,{className:t.s,children:`Loading your payments…`}):e.length===0?(0,E.jsx)(`p`,{className:`${t.s} px-1`,children:`Nothing here yet. Describe what you sell in the card above — each payment you add appears here with one question: how it works, start to finish.`}):(0,E.jsx)(`div`,{className:`flex flex-col gap-3`,children:e.map(e=>(0,E.jsx)(L,{product:e,live:n,open:r===e.id,onToggle:()=>i(e.id),onChange:a,forPage:o,onAddToPage:s},e.id))})}var z=e=>c.pr(`pay-${t.xr(e)}`)||`pay-${e.id}`,B=e=>{let n=t.gr(e).map(e=>e.amount.trim()).filter(Boolean).join(` + `);return`${t.xr(e)}${n?` — ${n}`:``}`};function V(e,n,r){return[c.An(n,r),`This page is the page of my payment link for ${t.xr(e)} — everyone I send ${n.path} to lands here and pays here.`,...t.Tr(e,n.path)].join(`
1
+ require(`./chunk-CiTBaPhY.cjs`);const e=require(`./PageTitle-BL50s4qY.cjs`),t=require(`./TimeZoneField-Ckn1pKAL.cjs`),n=require(`./DashboardNav-Bc619nqn.cjs`),r=require(`./schedule-BAea6q8_.cjs`),i=require(`./chevron-down-lyDK1rfL.cjs`),a=require(`./arrow-left-C39sNUA7.cjs`),o=require(`./arrow-right-CGvbxks5.cjs`),s=require(`./SupportBar-DR52UpBq.cjs`),c=require(`./PagesAdmin-1U73GM_o.cjs`),l=require(`./link-2-C7A-6PW6.cjs`),u=require(`./x-Ci8c5p6T.cjs`),d=require(`./plus-zsWFCu4F.cjs`),f=require(`./power-Bs_nchQG.cjs`),p=require(`./Said-W3KFi5uX.cjs`),m=require(`./trash-D-CpYHCs.cjs`),h=require(`./roles-BmnoAilb.cjs`),g=require(`./transactions-CIU2NcKh.cjs`),_=require(`./ConfirmModal-BUNtss4a.cjs`),v=require(`./recordsKey-B3lWGd8C.cjs`),y=require(`./Setup-DiFnnzdd.cjs`),b=require(`./serviceSwitches-mhJbQBrV.cjs`),x=require(`./serviceStatus-Cde96_OO.cjs`),S=require(`./SetupPayments-BLq0W5DU.cjs`),C=require(`./CopyLink-D6QTWSoK.cjs`),w=require(`./publishSteps-DvWlF0p_.cjs`);let T=require(`react`),E=require(`react/jsx-runtime`),D=require(`firebase/firestore`),O=require(`react-router-dom`);var k={name:`plug`,size:24,node:[[`path`,{d:`M12 22v-5`,key:`1ega77`}],[`path`,{d:`M15 8V2`,key:`18g5xt`}],[`path`,{d:`M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z`,key:`1xoxul`}],[`path`,{d:`M9 8V2`,key:`14iosj`}]]};k.node;var A=i.n(k),j={name:`tag`,size:24,node:[[`path`,{d:`M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z`,key:`vktsd0`}],[`circle`,{cx:`7.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`kqv944`}]]};j.node;var M=i.n(j),N={name:`triangle-alert`,size:24,node:[[`path`,{d:`m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3`,key:`wmoenq`}],[`path`,{d:`M12 9v4`,key:`juzpu7`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]],aliases:[`alert-triangle`]};N.node;var P=i.n(N),F={name:`workflow`,size:24,node:[[`rect`,{width:`8`,height:`8`,x:`3`,y:`3`,rx:`2`,key:`by2w9f`}],[`path`,{d:`M7 11v4a2 2 0 0 0 2 2h4`,key:`xkn7yn`}],[`rect`,{width:`8`,height:`8`,x:`13`,y:`13`,rx:`2`,key:`1cgmvn`}]]};F.node;var I=i.n(F);function L({product:e,live:n,open:r,onToggle:o,onChange:s,forPage:c,onAddToPage:l}){let u=t=>s({...e,...t});if(!t.wr(e,n))return(0,E.jsx)(`div`,{className:`rounded-2xl border border-[var(--panel-border)] opacity-50`,"aria-disabled":`true`,children:(0,E.jsxs)(`div`,{className:`w-full flex items-center justify-between gap-3 px-4 py-3`,children:[(0,E.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/60 truncate`,children:t.Er(e)}),(0,E.jsx)(t._,{state:`off`,label:`Finish it above first`})]})});let f=t.Cr(e),p=e.kind===`subscription`;return(0,E.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]`,children:[(0,E.jsxs)(`button`,{type:`button`,onClick:o,"aria-expanded":r,className:`w-full flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer`,children:[(0,E.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:t.Er(e)}),(0,E.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[(0,E.jsx)(t._,{state:f?`off`:`saved`,label:f?`Question left`:`Ready for pages`}),(0,E.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${r?`rotate-180`:``}`})]})]}),r&&(0,E.jsxs)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4`,children:[(0,E.jsx)(t.y,{label:`How will this payment work?`,hint:p?`Start to finish, in your own words — what someone does, pays, and gets. Worth saying if you care: what they tell you before paying (never their email — Stripe asks for that), what each plan unlocks, and what happens the moment they subscribe. Whatever you skip, your assistant decides.`:`Start to finish, in your own words — what someone does, pays, and gets. Worth saying if you care: what they tell you before paying (never their email — Stripe asks for that) and what happens after they pay. Whatever you skip, your assistant decides.`,value:e.how,onChange:e=>u({how:e}),placeholder:p?`People pick a plan and pay, and their member area unlocks the same minute — Basic gets the videos, Pro gets the videos and a monthly call.`:`People choose a session, tell me their phone number and what they need, and pay — then they see a thank-you, and I get in touch within a day.`}),(0,E.jsxs)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:[`The buyer’s receipt and your sale email are switched on your`,` `,(0,E.jsx)(O.Link,{to:`/email`,className:`text-accent font-semibold hover:underline`,children:`Email screen`}),`, for every payment at once.`]}),(0,E.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3 pt-1`,children:[f?(0,E.jsx)(`span`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:f}):c?(0,E.jsx)(`span`,{className:`text-[11.5px] font-semibold text-emerald-500`,children:`Ready to add to pages — add it to ${c.title} and go back.`}):(0,E.jsxs)(`span`,{className:`text-[11.5px] font-semibold text-emerald-500`,children:[`Ready to add to pages — open a page on the`,` `,(0,E.jsx)(O.Link,{to:`/pages`,className:`font-bold hover:underline`,children:`Pages screen`}),` and add it under Payments.`]}),!f&&c&&l?(0,E.jsx)(t.o,{icon:e.pageIds.includes(c.id)?a.t:d.t,onClick:()=>l(e.id),children:e.pageIds.includes(c.id)?`Back to ${c.title}`:`Add to ${c.title}`}):(0,E.jsx)(`span`,{})]})]})]})}function R({products:e,live:n,openId:r,onToggle:i,onChange:a,forPage:o,onAddToPage:s}){return e===null?(0,E.jsx)(`p`,{className:t.s,children:`Loading your payments…`}):e.length===0?(0,E.jsx)(`p`,{className:`${t.s} px-1`,children:`Nothing here yet. Describe what you sell in the card above — each payment you add appears here with one question: how it works, start to finish.`}):(0,E.jsx)(`div`,{className:`flex flex-col gap-3`,children:e.map(e=>(0,E.jsx)(L,{product:e,live:n,open:r===e.id,onToggle:()=>i(e.id),onChange:a,forPage:o,onAddToPage:s},e.id))})}var z=e=>c.pr(`pay-${t.xr(e)}`)||`pay-${e.id}`,B=e=>{let n=t.gr(e).map(e=>e.amount.trim()).filter(Boolean).join(` + `);return`${t.xr(e)}${n?` — ${n}`:``}`};function V(e,n,r){return[c.An(n,r),`This page is the page of my payment link for ${t.xr(e)} — everyone I send ${n.path} to lands here and pays here.`,...t.Tr(e,n.path)].join(`
2
2
  `)}function H({product:n,open:a,onToggle:o,onChange:s,onRemove:l,onCustomise:u}){let[d,f]=(0,T.useState)(!1),[p,h]=(0,T.useState)(!1),[g,v]=(0,T.useState)(``),[y,b]=(0,T.useState)(``),x=n.customPath.trim(),S=x?x.startsWith(`/`)?x:`/${x}`:r.jt(n.id);return(0,E.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]`,children:[(0,E.jsxs)(`div`,{className:`flex items-center gap-2 pr-3`,children:[(0,E.jsxs)(`button`,{type:`button`,onClick:o,"aria-expanded":a,className:`flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer`,children:[(0,E.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:B(n)}),(0,E.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[(0,E.jsx)(t._,{state:x?`saved`:`off`,label:x?`Your own page`:`Ready-made page`}),(0,E.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${a?`rotate-180`:``}`})]})]}),(0,E.jsx)(t.o,{icon:m.t,tone:`danger`,compact:!0,title:`Remove the link to ${t.xr(n)}`,onClick:()=>f(!0),children:`Remove`})]}),(0,E.jsx)(_.t,{isOpen:d,title:`Remove the link to ${t.xr(n)}?`,message:`Its link stops working, and it leaves What you sell.`,confirmText:`Yes, remove it`,cancelText:`Keep it`,onCancel:()=>f(!1),onConfirm:()=>{f(!1),l()}}),a&&(0,E.jsxs)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4`,children:[(0,E.jsx)(t.i,{label:`The link`,hint:`Send it to anyone. The page wears your theme and your app's name.`,children:(0,E.jsx)(C.t,{title:t.xr(n),path:S})}),(0,E.jsx)(t.b,{label:`What is it called?`,value:t.gr(n)[0]?.name||``,onChange:e=>s({...n,items:[{...t.gr(n)[0]||{amount:``},name:e},...t.gr(n).slice(1)]}),placeholder:`A one-hour session`}),(0,E.jsx)(t.y,{label:`A line or two about it`,hint:`Optional — what the buyer gets. Shown on the page.`,value:n.description,onChange:e=>s({...n,description:e}),placeholder:`One hour together on whatever you are stuck on.`}),(0,E.jsx)(t.b,{label:`The price`,value:t.gr(n)[0]?.amount||``,onChange:e=>s({...n,items:[{...t.gr(n)[0]||{name:``},amount:e},...t.gr(n).slice(1)]}),placeholder:`25`,error:t.gr(n)[0]?.amount.trim()&&t.br(t.gr(n)[0].amount)===null?`Just a number, like 25.`:void 0}),!x&&!p&&!g&&(0,E.jsx)(t.o,{icon:c.Fi,onClick:()=>h(!0),children:`Customise this page`}),(p||g)&&(0,E.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]/60 px-4 py-3.5 flex flex-col gap-4`,children:[(0,E.jsx)(t.y,{label:`What would you like on the page?`,hint:`Describe the page in your own words — what it says, what it shows, how it feels. Your assistant builds it; whatever you skip, it decides.`,value:n.customNote,onChange:e=>s({...n,customNote:e}),placeholder:`A warm page about the session: who it is for, what we cover, two testimonials, then the Pay button.`,rows:3}),y&&(0,E.jsx)(`span`,{className:`text-[11.5px] font-semibold text-red-500 leading-snug px-1`,children:y}),g?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(e.o,{title:`Ask your assistant`,description:`The page exists on the Pages screen now. Paste this into your assistant's chat; once it has built the page, tick the switch below and the link goes there.`,prompt:g}),(0,E.jsx)(t.S,{label:`The page is built — send people there`,hint:`Until this is on, the link opens the ready-made page.`,enabled:!!n.customPath.trim(),onChange:e=>s({...n,customPath:e?`/${z(n)}`:``})})]}):(0,E.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,E.jsx)(t.o,{icon:c.Fi,disabled:!n.customNote.trim(),onClick:async()=>{b(``);let e=await u();if(typeof e==`string`){b(e);return}v(e.prompt)},children:`Make the page`}),(0,E.jsx)(t.o,{onClick:()=>{h(!1),b(``)},children:`Never mind`})]})]}),x&&!g&&(0,E.jsx)(t.S,{label:`The page is built — send people there`,hint:`The link opens ${S}. Change the page from its row on the Pages screen. Turn this off to go back to the ready-made page.`,enabled:!0,onChange:e=>s({...n,customPath:e?n.customPath:``})})]})]})}function U({products:e,onChange:n,onRemove:r}){let[i,a]=(0,T.useState)(null),o=e.filter(e=>e.kind===`once`),s=()=>{let e={...t.cr(`p_${Date.now().toString(36)}`),kind:`once`,items:[{name:``,amount:``}]};n(e),a(e.id)},u=async e=>{let n=z(e),r=`Pay — ${t.xr(e)}`,i={name:r,address:n,type:`public`,about:e.customNote.trim()};try{await c._n(i)}catch(e){return console.error(`Could not make the page`,e),`The page could not be made — make sure you are signed in as an admin and try again.`}let{config:a}=c.fr(i),o={title:r,path:`/${n}`};return{path:o.path,prompt:V(e,o,a)}};return(0,E.jsx)(t.m,{icon:l.t,title:`Payment links`,description:`Every one-time payment has a page of its own you can send to anyone — a name, a line about it, a price.`,actions:({open:e})=>(0,E.jsx)(t.o,{icon:d.t,title:`Add a payment link`,onClick:()=>{e(),s()},children:`Add a payment link`}),children:(0,E.jsx)(`div`,{className:`flex flex-col gap-3`,children:o.length===0?(0,E.jsx)(`p`,{className:`${t.s} px-1`,children:`No payment link yet. Add one here — it appears under What you sell too — or describe a one-time payment there and its link shows up here.`}):o.map(e=>(0,E.jsx)(H,{product:e,open:i===e.id,onToggle:()=>a(i===e.id?null:e.id),onChange:n,onRemove:()=>r(e.id),onCustomise:()=>u(e)},e.id))})})}var W=e=>/^price_[A-Za-z0-9]+$/.test(e.trim()),G=`__new_role__`;function K({plan:e,index:n,roles:i,onChange:a,onRemove:o}){let s=t=>a({...e,...t}),l=e.name.trim(),u=l?i.find(e=>e.id===r.Ln(l)||e.name.trim().toLowerCase()===l.toLowerCase()):void 0,d=l&&!u?h.o(l,i):``,f=!!l&&!u&&!d,p=()=>{if(u){s({roleId:u.id});return}f&&(s({roleId:r.Ln(l)}),h.n(l).catch(e=>console.error(`Could not make the role`,e)))},g=[...i.map(e=>({value:e.id,label:e.name})),...e.roleId&&!i.some(t=>t.id===e.roleId)?[{value:e.roleId,label:l&&r.Ln(l)===e.roleId?l:t.qr(e.roleId,i)}]:[],...f?[{value:G,label:`New role: ${l}`}]:[]];return(0,E.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]/60 px-4 py-3.5 flex flex-col gap-4`,children:[(0,E.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,E.jsxs)(`span`,{className:`text-[11px] font-bold uppercase tracking-widest text-foreground/40`,children:[`Plan `,n+1]}),(0,E.jsx)(t.o,{icon:m.t,tone:`danger`,compact:!0,title:`Remove this plan`,onClick:o,children:`Remove plan`})]}),(0,E.jsx)(t.b,{label:`What is this plan called?`,value:e.name,onChange:e=>s({name:e}),onBlur:()=>{e.roleId||p()},placeholder:`Premium`}),(0,E.jsx)(t.g,{label:`Who they become`,hint:!e.roleId&&d?d:`Paying makes them this role; when the plan ends they are a member again.`,value:e.roleId||``,onChange:e=>e===G?p():s({roleId:e}),options:g,placeholder:l?`Choose a role`:`Name the plan first`,allowEmpty:!e.roleId}),(0,E.jsx)(t.b,{label:`One line about it`,hint:`Optional — what a buyer gets on this plan.`,value:e.description,onChange:e=>s({description:e}),placeholder:`Up to 3 projects and email support`}),[[`monthly`,`Billed monthly`,`a month`],[`yearly`,`Billed yearly`,`a year`]].map(([r,i,a])=>(0,E.jsxs)(`div`,{className:`flex flex-col gap-2.5`,children:[(0,E.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,E.jsx)(`span`,{className:`text-[13px] font-medium text-foreground/80 ml-1`,children:i}),(0,E.jsx)(t.x,{enabled:e[r].on,onChange:t=>s({[r]:{...e[r],on:t}}),label:`${i} — plan ${n+1}`})]}),e[r].on&&(0,E.jsx)(t.b,{label:`The price ${a}`,hint:`Just the number — 25 charges 25 ${a} in your Stripe account's currency.`,value:e[r].amount,onChange:t=>s({[r]:{...e[r],amount:t}}),placeholder:r===`monthly`?`25`:`250`,error:c.Pi(e[r].amount)})]},r))]})}function q({product:e,plan:n,index:r,live:i,onChange:a}){let o=i?`livePriceId`:`priceId`,s=(e,t)=>({...e,[o]:t}),c=(!n.monthly.on||W(n.monthly[o]))&&(!n.yearly.on||W(n.yearly[o])),l=e=>a({...n,...e}),u=e=>e.trim()&&!W(e)?`A price id starts with price_ — copy it from the price you just made.`:void 0;return(0,E.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]/60 px-4 py-3.5 flex flex-col gap-3`,children:[(0,E.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,E.jsx)(`span`,{className:`text-[13px] font-bold text-foreground truncate`,children:n.name.trim()||`Plan ${r+1}`}),(0,E.jsx)(t._,{state:c?`saved`:`off`,label:c?`Done`:i?`Waiting for its live ids`:`Waiting for its ids`})]}),(0,E.jsx)(`ol`,{className:`space-y-1.5 list-decimal list-inside text-[12.5px] font-medium text-foreground/60 leading-relaxed`,children:t.Ar(e,n,i).map((e,t)=>(0,E.jsx)(`li`,{children:e},t))}),n.monthly.on&&(0,E.jsx)(t.b,{label:i?`Paste the live monthly price id`:`Paste the monthly price id`,value:n.monthly[o],onChange:e=>l({monthly:s(n.monthly,e)}),placeholder:`price_…`,error:u(n.monthly[o])}),n.yearly.on&&(0,E.jsx)(t.b,{label:i?`Paste the live yearly price id`:`Paste the yearly price id`,value:n.yearly[o],onChange:e=>l({yearly:s(n.yearly,e)}),placeholder:`price_…`,error:u(n.yearly[o])}),i&&(0,E.jsx)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:`Your test ids are kept — switch back to test mode on this screen and they are exactly where you left them.`})]})}function J({product:e,open:n,live:r,roles:a,onToggle:s,onChange:l,onRemove:u,onProceed:f}){let p=t=>l({...e,...t}),h=(t,n)=>p({plans:e.plans.map((e,r)=>r===t?n:e)}),g=t.wr(e,r),v=t.Sr(e,r),[y,b]=(0,T.useState)(!1),x=t.xr(e);return(0,E.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]`,children:[(0,E.jsxs)(`div`,{className:`flex items-center gap-2 pr-3`,children:[(0,E.jsxs)(`button`,{type:`button`,onClick:s,"aria-expanded":n,className:`flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer`,children:[(0,E.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:t.Er(e)}),(0,E.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[e.kind&&(0,E.jsx)(t._,{state:g?`saved`:`off`,label:g?`Ready`:`In progress`}),(0,E.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${n?`rotate-180`:``}`})]})]}),(0,E.jsx)(t.o,{icon:m.t,tone:`danger`,compact:!0,title:`Remove ${x}`,onClick:()=>b(!0),children:`Remove`})]}),(0,E.jsx)(_.t,{isOpen:y,title:`Remove ${x}?`,message:`Its answer under How your payments work goes with it, and the pages it is on stop carrying it.`,confirmText:`Yes, remove it`,cancelText:`Keep it`,onCancel:()=>b(!1),onConfirm:()=>{b(!1),u()}}),n&&(0,E.jsxs)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4`,children:[(0,E.jsx)(t.g,{label:`How is it paid?`,value:e.kind,onChange:n=>p({kind:n===`once`||n===`subscription`?n:``,plans:n===`subscription`&&!e.plans.length?[t.sr()]:e.plans,items:n===`once`&&!e.items.length?[t.or()]:e.items}),options:[{value:`once`,label:`Once — one payment`},{value:`subscription`,label:`A subscription that renews`}],placeholder:`Choose one`}),e.kind===`once`&&(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(t.i,{label:`What are you selling?`,hint:`Each thing with its price — just the number: 25 charges 25 in your Stripe account's currency. Nothing to make in Stripe for a one-off.`,children:(0,E.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[e.items.map((t,n)=>(0,E.jsx)(c.Ni,{item:t,index:n,onChange:t=>p({items:e.items.map((e,r)=>r===n?t:e)}),onRemove:()=>p({items:e.items.filter((e,t)=>t!==n)}),removable:e.items.length>1},n)),(0,E.jsx)(t.o,{icon:d.t,className:`self-start`,onClick:()=>p({items:[...e.items,t.or()]}),children:`Add another`})]})}),e.items.length>1&&(0,E.jsx)(t.b,{label:`What do you call this group?`,hint:`Optional — one word for the lot, the way you would say it: Calls, The shop.`,value:e.name,onChange:e=>p({name:e}),placeholder:`Calls`})]}),e.kind===`subscription`&&(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(t.b,{label:`What is the subscription called?`,value:e.name,onChange:e=>p({name:e}),placeholder:`Membership`}),(0,E.jsx)(t.y,{label:`One line about it`,hint:`Optional — your assistant uses it on the page.`,value:e.description,onChange:e=>p({description:e}),placeholder:`Everything in the studio, every month.`}),(0,E.jsx)(t.i,{label:`Its plans`,hint:`Each plan can be billed monthly, yearly, or both.`,children:(0,E.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[e.plans.map((t,n)=>(0,E.jsx)(K,{plan:t,index:n,roles:a,onChange:e=>h(n,e),onRemove:()=>p({plans:e.plans.filter((e,t)=>t!==n)})},n)),(0,E.jsx)(t.o,{icon:d.t,className:`self-start`,onClick:()=>p({plans:[...e.plans,t.sr()]}),children:`Add a plan`})]})}),t.yr(e)&&(0,E.jsx)(t.i,{label:r?`Now make it in Stripe — live mode`:`Now make it in Stripe`,hint:r?`Live mode is a fresh Stripe catalogue: make each plan again with Test mode OFF, and paste the live ids it produces.`:`Five minutes in your Stripe dashboard. Each plan below says exactly what to do and takes the id it produces.`,children:(0,E.jsx)(`div`,{className:`flex flex-col gap-3`,children:e.plans.map((t,n)=>(0,E.jsx)(q,{product:e,plan:t,index:n,live:r,onChange:e=>h(n,e)},n))})})]}),(0,E.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3 pt-1`,children:[e.kind&&!g?(0,E.jsx)(`span`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:v}):e.kind?(0,E.jsx)(`span`,{className:`text-[11.5px] font-semibold text-emerald-500`,children:`Ready — press Proceed to say how it works.`}):(0,E.jsx)(`span`,{}),g?(0,E.jsx)(t.o,{icon:o.t,onClick:f,children:`Proceed`}):(0,E.jsx)(`span`,{})]})]})]})}function Y(){let[e,n]=(0,T.useState)(null),[r,i]=(0,T.useState)(!1),[a,o]=(0,T.useState)(null),[s,c]=(0,T.useState)(null),[l,u]=(0,T.useState)(``),f=(0,T.useRef)(new Map),m=(0,T.useRef)(null),g=(0,T.useRef)(null),_=v.u(),y=(0,O.useNavigate)(),[b,x]=(0,O.useSearchParams)(),[S]=(0,T.useState)(()=>b.get(`page`)||``),C=S?(_||[]).find(e=>e.id===S):void 0,w=(0,T.useRef)({done:!1,open:b.get(`open`)||``,wantsNew:b.get(`new`)===`subscription`}),k=h.l();t.Jn(`${r}:${(e||[]).reduce((e,t)=>e+(t.plans||[]).filter(e=>e.roleId).length,0)}`);let A=e=>{let n=f.current.get(e.id);n&&clearTimeout(n),f.current.set(e.id,setTimeout(async()=>{f.current.delete(e.id);try{let{id:n,...r}=e;await(0,D.setDoc)((0,D.doc)(t.ui,t.Qn,n),r)}catch(e){console.error(`Could not save the product`,e),p.n(t.ii(e,`That change to what you sell could not be saved.`))}},600))};(0,T.useEffect)(()=>{let e=(e,r)=>{let i=w.current;if(i.done||!i.open&&!i.wantsNew)return;i.done=!0;let a=i.open?e.find(e=>e.id===i.open):void 0;if(a)o(a.id);else if(i.wantsNew){let i=e.find(e=>e.kind===`subscription`&&!e.name.trim()&&!t.wr(e,r));if(i)o(i.id);else{let r={...t.cr(`p_${Date.now().toString(36)}`),kind:`subscription`,plans:[t.sr()]};n([...e,r]),o(r.id),A(r)}}setTimeout(()=>m.current?.scrollIntoView?.({behavior:`smooth`,block:`start`}),0),x(e=>{let t=new URLSearchParams(e);return t.delete(`new`),t.delete(`open`),t},{replace:!0})},r=t.Zr(t.Qn,()=>(0,D.collection)(t.ui,t.Qn),r=>{let a=!!r.docs.find(e=>e.id===t.$n)?.data()?.liveMode;if(i(a),t.kr(a),f.current.size)return;let o=[];r.forEach(e=>{e.id!==`_settings`&&o.push(t.Dr(e.id,e.data()))}),o.sort((e,t)=>(e.createdAt||0)-(t.createdAt||0)),n(o),e(o,a)},()=>n([]));return()=>r()},[]);let j=e=>{n(t=>{let n=t||[];return n.some(t=>t.id===e.id)?n.map(t=>t.id===e.id?e:t):[...n,e]}),A(e)},M=()=>{let e=t.cr(`p_${Date.now().toString(36)}`);n(t=>[...t||[],e]),o(e.id),A(e)},N=async r=>{let i=f.current.get(r);i&&(clearTimeout(i),f.current.delete(r));let l=(e||[]).find(e=>e.id===r);u(``),n(e=>(e||[]).filter(e=>e.id!==r)),a===r&&o(null),s===r&&c(null);try{await(0,D.deleteDoc)((0,D.doc)(t.ui,t.Qn,r))}catch(e){console.error(`Could not remove the product`,e),l&&n(e=>{let t=e||[];return t.some(e=>e.id===r)?t:[...t,l].sort((e,t)=>(e.createdAt||0)-(t.createdAt||0))}),u(`It could not be removed — make sure you are signed in as an admin and try again.`)}},P=e=>{o(null),c(e),g.current?.scrollIntoView({behavior:`smooth`,block:`start`})};return(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(`div`,{ref:m,children:(0,E.jsx)(t.m,{icon:p.i,title:`What you sell`,description:`Things paid for once, each with a price; or a subscription with plans and their Stripe ids.`,children:(0,E.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[S&&(0,E.jsx)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug px-1`,children:`Making a payment for ${C?.title||`your page`}. Fill it in, press Proceed, say how it works — then add it to the page.`}),e===null?(0,E.jsx)(`p`,{className:t.s,children:`Loading what you sell…`}):(0,E.jsxs)(E.Fragment,{children:[e.length===0&&(0,E.jsx)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug px-1`,children:`Nothing here yet. Describe what you sell once — things paid for once need nothing from Stripe, and a subscription walks you through Stripe step by step — then say how it works in the section below, and add it to a page from the Pages screen.`}),e.map(e=>(0,E.jsx)(J,{product:e,open:a===e.id,live:r,roles:k,onToggle:()=>o(a===e.id?null:e.id),onChange:j,onRemove:()=>N(e.id),onProceed:()=>P(e.id)},e.id)),!!l&&(0,E.jsx)(`p`,{className:`text-[12px] font-semibold text-red-500 px-1`,children:l}),(0,E.jsx)(t.o,{icon:d.t,className:`self-start`,onClick:M,children:`Add something you sell`})]})]})})}),(0,E.jsx)(`div`,{ref:g,children:(0,E.jsx)(t.m,{icon:I,title:`How your payments work`,description:`One answer per payment: what someone does, pays, and gets. Then add it to any page from its Payments section on the Pages screen.`,children:(0,E.jsx)(R,{products:e,live:r,openId:s,onToggle:e=>c(s===e?null:e),onChange:j,forPage:C?{id:C.id,title:C.title}:void 0,onAddToPage:e=>{S&&y(t.ir(S,e))}})})}),(0,E.jsx)(U,{products:e||[],onChange:j,onRemove:N})]})}function X(e,t){return!e&&t!==`live`?{state:`off`,label:`In test mode`}:t===`live`?{state:`saved`,label:`Live`}:{state:`saving`,label:`Waiting for the live key`}}function Z(e){return e?e.configured?e.enabled?e.receipts?e.senderVerified?{state:`saved`,label:`From your domain`,line:`Every buyer gets one from ${e.from||`your own domain`}, with a link to Stripe’s own receipt.`,fix:!1}:{state:`off`,label:`Waiting for your domain`,line:`Receipts wait until your domain is verified on your Email screen: until then, buyers get none.`,fix:!0}:{state:`off`,label:`Switched off`,line:`“Email buyers a receipt” is off on your Email screen.`,fix:!0}:{state:`off`,label:`Email is off`,line:`Email is switched off on your Email screen, so buyers get no receipt.`,fix:!0}:{state:`off`,label:`Not set up`,line:`Buyers get no receipt until email is connected on your Email screen.`,fix:!0}:{state:`saving`,label:`Checking`,line:`Checking whether your buyers get a receipt…`,fix:!1}}function Q({email:e}){let n=Z(e);return(0,E.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,E.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,E.jsx)(`span`,{className:`text-[12.5px] font-bold text-foreground/80`,children:`Receipts`}),(0,E.jsx)(t._,{state:n.state,label:n.label})]}),(0,E.jsxs)(`p`,{className:t.s,children:[n.line,n.fix&&(0,E.jsxs)(E.Fragment,{children:[` `,(0,E.jsx)(O.Link,{to:`/email`,className:`text-accent font-bold hover:underline`,children:`Open the Email screen`})]})]}),(0,E.jsxs)(`p`,{className:t.s,children:[`Keep Stripe’s own receipt emails off, or every buyer gets two:`,` `,(0,E.jsx)(`a`,{href:`https://dashboard.stripe.com/settings/emails`,target:`_blank`,rel:`noopener noreferrer`,className:`text-accent font-bold hover:underline`,children:`Stripe Settings → Customer emails`}),` `,`→ Successful payments, off.`]})]})}var ee=[`checkout.session.completed`,`checkout.session.async_payment_succeeded`],te=`text-[12.5px] font-medium text-foreground/70 leading-relaxed`,$=`mt-1.5 space-y-1 list-disc list-inside marker:text-foreground/30`,ne=`my-2 glass-panel border border-[var(--panel-border)] rounded-2xl overflow-hidden bg-background`;function re(){let[r,i]=(0,T.useState)(null),[a,s]=(0,T.useState)([]),{status:c}=x.i(5e3),l=c?.mode??null,u=c?.webhookConfigured??!1,{status:d}=x.n(1e4),[f]=y.a(),p=f===`local`,{record:m}=w.l(),h=t.Vn(w.s(m)),g=m.done.includes(`authorised`)&&!!h;(0,T.useEffect)(()=>t.Zr(t.Qn,()=>(0,D.collection)(t.ui,t.Qn),e=>{i(!!e.docs.find(e=>e.id===t.$n)?.data()?.liveMode);let n=[];e.forEach(e=>{e.id!==`_settings`&&n.push(t.Dr(e.id,e.data()))}),n.sort((e,t)=>(e.createdAt||0)-(t.createdAt||0)),s(n)},()=>i(!1)),[]);let _=async e=>{i(e);try{await(0,D.setDoc)((0,D.doc)(t.ui,t.Qn,t.$n),{liveMode:e},{merge:!0})}catch(e){console.error(`Could not save the go-live switch`,e)}},v=!!r,b=X(v,l),S=a.filter(e=>t.wr(e,!1)),C=S.filter(e=>!t.wr(e,!0)),k=S.length>0&&C.length===0,A=S.some(e=>e.kind===`subscription`);return(0,E.jsx)(t.v,{icon:n.w,title:`Go live`,description:v?`Real cards, real money — the steps below finish the switch.`:`Practice is free — flip this only when a test payment has gone all the way through.`,chip:b,enabled:r===null?null:v,onChange:_,children:v&&(0,E.jsxs)(E.Fragment,{children:[(0,E.jsxs)(`ol`,{className:`space-y-3.5 list-decimal list-inside ${te}`,children:[(0,E.jsxs)(`li`,{children:[(0,E.jsx)(`strong`,{children:`Your live secret key.`}),` In Stripe, click your account name in the top left corner and choose your `,(0,E.jsx)(`strong`,{children:`live`}),` account — not the sandbox.`,(0,E.jsxs)(`ul`,{className:$,children:[(0,E.jsxs)(`li`,{children:[`Open the dark strip along the bottom that says `,(0,E.jsx)(`strong`,{children:`Developers`}),`, and scroll down to the `,(0,E.jsx)(`strong`,{children:`API keys`}),` section.`]}),(0,E.jsxs)(`li`,{children:[`Click `,(0,E.jsx)(`strong`,{children:`Manage API keys`}),`. Under `,(0,E.jsx)(`strong`,{children:`Standard keys`}),`, click `,(0,E.jsx)(`strong`,{children:`+ Create secret key`}),`.`]}),(0,E.jsxs)(`li`,{children:[`Where it asks `,(0,E.jsx)(`em`,{children:`How will you be using this key?`}),`, choose`,` `,(0,E.jsx)(`strong`,{children:`Powering an integration you built`}),`, then`,` `,(0,E.jsx)(`strong`,{children:`Create secret key`}),`.`]}),(0,E.jsxs)(`li`,{children:[`Stripe asks you to confirm it is you: click `,(0,E.jsx)(`strong`,{children:`Send verification`}),` `,`and verify the request with the code it sends.`]}),(0,E.jsxs)(`li`,{children:[`Give the key a name — `,(0,E.jsx)(`span`,{className:`text-accent`,children:`my ai project app key`}),` `,`— and copy it. `,(0,E.jsx)(`strong`,{children:`Stripe will not show it to you again.`})]}),p?(0,E.jsxs)(`li`,{children:[`Open your `,(0,E.jsx)(`strong`,{children:`.env`}),` file and paste it over the sk_test_… value of `,(0,E.jsx)(`strong`,{children:`STRIPE_SECRET_KEY`}),` — replace it, do not add a second line. Start the app again, and the chip at the top of this card turns to `,(0,E.jsx)(`strong`,{children:`Live`}),` on its own.`]}):(0,E.jsxs)(`li`,{children:[`Click the `,(0,E.jsx)(t.n,{}),` icon in the top right corner of your app in Google AI Studio and find the `,(0,E.jsx)(`strong`,{children:`Secrets`}),` tab. Paste the new key over the value of `,(0,E.jsx)(`strong`,{children:`STRIPE_SECRET_KEY`}),` — replace the sk_test_… one, do not add a second. Click `,(0,E.jsx)(`strong`,{children:`Apply`}),` and refresh this page: the chip at the top of this card turns to `,(0,E.jsx)(`strong`,{children:`Live`}),` on its own.`]})]})]}),A&&(0,E.jsxs)(`li`,{children:[(0,E.jsx)(`strong`,{children:`Your live price ids.`}),` A subscription's prices are made fresh in live mode, so the ids under `,(0,E.jsx)(`strong`,{children:`What you sell`}),` change. Create each plan's price in your live Stripe account and paste its id there. Your test ids are kept and come straight back if you switch off again.`]}),(0,E.jsxs)(`li`,{children:[(0,E.jsx)(`strong`,{children:`The webhook.`}),` `,g?`What keeps receipts and your sale alerts sending when a buyer pays and never comes back to your app.`:`Stripe has to be able to reach your app from the outside, so this one waits until your app is published.`,` `,(0,E.jsx)(`span`,{className:`inline-block align-middle ml-0.5`,children:(0,E.jsx)(t._,{state:u?`saved`:`off`,label:u?`Connected`:`Not yet`})}),g?(0,E.jsxs)(`ul`,{className:$,children:[(0,E.jsxs)(`li`,{children:[`Still in your `,(0,E.jsx)(`strong`,{children:`live`}),` Stripe account, open the`,` `,(0,E.jsx)(`strong`,{children:`Developers`}),` strip at the bottom again and, in its top menu, click `,(0,E.jsx)(`strong`,{children:`Webhooks`}),`. Click `,(0,E.jsx)(`strong`,{children:`Add destination`}),`.`]}),(0,E.jsxs)(`li`,{children:[`Leave every setting as it is. Under `,(0,E.jsx)(`strong`,{children:`Events`}),`, use the`,` `,(0,E.jsx)(`em`,{children:`Find event by name or description…`}),` search bar to find these two, and click the checkmark on each:`,(0,E.jsx)(`div`,{className:`mt-1.5 flex flex-col gap-1`,children:ee.map(e=>(0,E.jsx)(y.t,{code:e,label:e,compact:!0},e))}),`The first is an ordinary card payment. The second is a bank transfer landing hours later, when nobody is watching — without it those sales send no email at all.`]}),(0,E.jsxs)(`li`,{children:[`Click `,(0,E.jsx)(`strong`,{children:`Continue`}),` and keep it as a`,` `,(0,E.jsx)(`strong`,{children:`Webhook endpoint`}),`. Give the destination a name —`,` `,(0,E.jsx)(`span`,{className:`text-accent`,children:`my ai project receipts`}),`.`]}),(0,E.jsxs)(`li`,{children:[`As the `,(0,E.jsx)(`strong`,{children:`Endpoint URL`}),`, paste exactly this — your published address with the webhook route on the end:`,(0,E.jsx)(`div`,{className:`my-2`,children:(0,E.jsx)(y.t,{code:h,label:`Copy your webhook address`,compact:!0})})]}),(0,E.jsxs)(`li`,{children:[`Create the destination. On the right, under Webhooks, you will find its`,` `,(0,E.jsx)(`strong`,{children:`signing secret`}),` — it starts with `,(0,E.jsx)(`strong`,{children:`whsec_`}),`. Copy it.`]}),(0,E.jsxs)(`li`,{children:[p?(0,E.jsxs)(E.Fragment,{children:[`Add the line below to your `,(0,E.jsx)(`strong`,{children:`.env`}),` file with the whsec_… secret as its value, and start the app again. You are all set — the chip beside this step turns green.`]}):(0,E.jsxs)(E.Fragment,{children:[`Click the `,(0,E.jsx)(t.n,{}),` icon in the top right corner of your app in Google AI Studio, scroll the menu along the top to `,(0,E.jsx)(`strong`,{children:`Secrets`}),` `,`and click `,(0,E.jsx)(`strong`,{children:`+ Add secret`}),`. Copy the name below into`,` `,(0,E.jsx)(`strong`,{children:`Secret name`}),` and paste the whsec_… secret as its value. Click `,(0,E.jsx)(`strong`,{children:`Apply`}),` and refresh this page. You are all set — the chip beside this step turns green.`]}),(0,E.jsx)(`div`,{className:ne,children:(0,E.jsx)(y.n,{name:`STRIPE_WEBHOOK_SECRET`,hint:`the whsec_… signing secret from the destination you just made`})})]})]}):(0,E.jsxs)(`div`,{className:`mt-2 flex flex-col gap-2.5`,children:[(0,E.jsxs)(t.h,{children:[`Your app has no public address yet, and the preview address in this browser is not one Stripe can reach — it changes every session.`,` `,m.done.length===0?`Publish your app first`:`Finish publishing your app first`,`: this step opens on its own once step 3 of Publish App,`,` `,(0,E.jsx)(`strong`,{children:`Add your domains and email sender`}),`, is ticked. Everything above works in the meantime.`]}),(0,E.jsxs)(O.Link,{to:`/publish`,className:`inline-flex items-center gap-1.5 w-fit h-9 px-4 rounded-[var(--btn-radius,0.75rem)] text-[12.5px] font-bold border border-accent/40 bg-accent/10 text-accent hover:bg-accent/15 transition-all active:scale-[0.98] cursor-pointer`,children:[`Take me to Publish App`,(0,E.jsx)(o.t,{className:`w-3.5 h-3.5`})]})]})]})]}),(0,E.jsx)(Q,{email:d}),(0,E.jsxs)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:[`One more switch lives in Stripe, not here: switching plans (monthly ↔ yearly, Basic ↔ Pro) appears in Stripe’s customer portal — where your buyers manage their own subscriptions — only if you allow it:`,` `,(0,E.jsx)(`a`,{href:`https://dashboard.stripe.com/settings/billing/portal`,target:`_blank`,rel:`noopener noreferrer`,className:`text-accent font-bold hover:underline`,children:`Stripe Settings → Billing → Customer portal`}),` `,`→ let customers switch plans.`]}),S.length>0&&!k&&(0,E.jsxs)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:[`Your subscriptions under What you sell now ask for `,(0,E.jsx)(`strong`,{children:`live`}),` price ids — `,C.length===S.length?`each one`:`${C.length} of ${S.length}`,` is still waiting. Your test ids are kept and come back if you switch back. Once the live ids are in, the message for your assistant appears right here.`]}),k&&(0,E.jsx)(e.o,{title:`Tell your assistant about the switch`,prompt:t.dr(S)})]})})}var ie=e=>e?{description:`Every Pay button on your pages works. Switch it off to pause all of it at once.`,chip:{state:`saved`,label:`On`}}:{description:`No Pay button shows and nothing can be bought. Your pages keep their settings.`,chip:{state:`off`,label:`Off`}};function ae(){let{user:r}=t.Ft(),{status:i,error:a,reread:o}=x.i(),[c,l]=(0,T.useState)(!1),[d,p]=(0,T.useState)(!1),[m,h]=(0,T.useState)(null),[_,v]=(0,T.useState)(``),[y,C]=(0,T.useState)(``),w=b.r(`payments`),[D,O]=(0,T.useState)(``),k=ie(w.on),j=(0,T.useCallback)(async e=>{let t=r?await r.getIdToken():``,n=await fetch(e,{headers:t?{Authorization:`Bearer ${t}`}:void 0}),i=await n.json().catch(()=>({}));if(!n.ok||i?.success===!1)throw Error(i?.error||`The server could not answer.`);return i},[r]),N=()=>{l(!1),o().then(()=>p(!0))};(0,T.useEffect)(()=>{if(!i?.configured||!r)return;let e=!1;return j(`/api/payments/products`).then(t=>{e||h(t.products||[])}).catch(t=>{e||v(t.message)}),()=>{e=!0}},[i?.configured,r,j]);let F=e=>{navigator.clipboard?.writeText(e),C(e),setTimeout(()=>C(``),2e3)},I=(m||[]).flatMap(e=>e.prices),L=i?.mode===`live`?`https://dashboard.stripe.com/products`:`https://dashboard.stripe.com/test/products`,R=!!(i&&!i.configured);return(0,E.jsxs)(`main`,{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`,children:[(0,E.jsxs)(t.nt.div,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},className:`mb-6`,children:[(0,E.jsx)(e.t,{children:`Payments`}),(0,E.jsxs)(`div`,{className:`flex items-center gap-2 text-foreground/40 font-bold uppercase tracking-[0.2em] text-[11px]`,children:[(0,E.jsx)(`span`,{className:`w-8 h-[1px] bg-foreground/10`}),`/payments`]})]}),(0,E.jsxs)(`div`,{className:`flex flex-col gap-6 flex-1 pb-16`,children:[(0,E.jsx)(n.t,{}),(0,E.jsx)(`div`,{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]`,children:!i&&!a?(0,E.jsx)(`div`,{className:`flex items-center justify-center flex-1 text-foreground/40 py-16`,children:(0,E.jsx)(u.r,{className:`w-6 h-6 animate-spin text-accent`})}):R?(0,E.jsx)(S.ConnectCard,{icon:n.j,title:`Connect Stripe`,description:`This app is not taking payments yet.`,stepsDescription:`Three steps — about five minutes, with pretend money until you say otherwise.`,button:`Set up payments`,secret:`STRIPE_SECRET_KEY`,open:c,onOpen:()=>l(!0),confirmed:d,steps:(0,E.jsx)(S.StripeSetupSteps,{onConfirm:N}),children:(0,E.jsx)(t.h,{children:`Payments run through Stripe, and connecting it is one pasted key — no code, no terminal. Once it is in, this screen fills itself: what you sell, and every payment as it happens.`})}):(0,E.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[i?.mode===`live`&&(0,E.jsxs)(`div`,{className:`flex items-center gap-3 rounded-2xl border border-red-500/25 bg-red-500/[0.06] px-4 py-3`,children:[(0,E.jsx)(P,{className:`w-4 h-4 text-red-500 shrink-0`}),(0,E.jsx)(`p`,{className:`text-[12.5px] font-semibold text-red-500 leading-snug`,children:`Live mode — real cards are being charged. Every payment on this screen is real money.`})]}),(0,E.jsx)(t.v,{icon:f.t,title:`Take payments`,description:k.description,chip:k.chip,enabled:w.loading?null:w.on,onChange:async e=>O(await w.set(e)||``),children:D?(0,E.jsx)(t.h,{tone:`error`,children:D}):null}),(0,E.jsx)(t.m,{icon:A,title:`Connection`,description:`Which Stripe account this app is running on.`,defaultOpen:!i?.configured,actions:a?(0,E.jsx)(t._,{state:`error`,label:`Unreachable`}):(0,E.jsx)(t._,{state:`saved`,label:i?.mode===`live`?`Live mode connected`:`Test mode connected`}),children:a?(0,E.jsx)(t.h,{tone:`error`,children:a}):(0,E.jsx)(t.h,{children:i?.mode===`live`?`Connected with a live key. Payments made anywhere on your site are real money.`:`Test mode connected. Your Pay buttons work end to end, but only test cards are accepted and no real money moves. When you are ready for real payments, use Go live below.`})}),(0,E.jsx)(re,{}),(0,E.jsx)(Y,{}),(0,E.jsx)(t.m,{icon:M,title:`In your Stripe account`,description:`The products and prices Stripe has right now — where price ids come from.`,defaultOpen:!1,children:_?(0,E.jsx)(t.h,{tone:`error`,children:_}):m===null?(0,E.jsx)(`div`,{className:`flex items-center justify-center py-6 text-foreground/40`,children:(0,E.jsx)(u.r,{className:`w-5 h-5 animate-spin text-accent`})}):I.length===0?(0,E.jsxs)(t.h,{children:[`Nothing needs to exist here for one-off payments — a Pay button can name its own amount. Only a subscription needs a price made in Stripe first:`,` `,(0,E.jsx)(`a`,{href:L,target:`_blank`,rel:`noreferrer`,className:`text-accent font-bold hover:underline`,children:`create one in your Stripe dashboard`}),` `,`and it appears here with its id ready to copy.`]}):(0,E.jsx)(`div`,{className:`flex flex-col gap-2.5`,children:I.map(n=>(0,E.jsxs)(`div`,{className:`flex items-center gap-3 px-3.5 py-2.5 ${t.r}`,children:[(0,E.jsx)(`span`,{className:`text-[13px] font-bold text-foreground truncate min-w-0 flex-1`,children:n.productName||`Unnamed product`}),(0,E.jsxs)(`span`,{className:`text-[12.5px] font-semibold text-foreground/60 whitespace-nowrap shrink-0`,children:[g.r(n.amount,n.currency),n.interval?` / ${n.interval}`:``]}),(0,E.jsx)(t.o,{compact:!0,icon:y===n.id?t.At:e._,title:`Copy the price id for ${n.productName||`this price`}`,onClick:()=>F(n.id),children:y===n.id?`Copied`:`Copy price id`})]},n.id))})})]})})]}),(0,E.jsx)(s.t,{video:`payments`})]})}exports.PaymentsAdmin=ae;
@@ -1 +1 @@
1
- const e=require(`./chunk-CiTBaPhY.cjs`),t=require(`./PageTitle-DQkvCB11.cjs`),n=require(`./chevron-down-lyDK1rfL.cjs`),r=require(`./shield-check-Bsd5oaif.cjs`);let i=require(`react`);i=e.a(i,1);let a=require(`react/jsx-runtime`);var o={name:`id-card`,size:24,node:[[`path`,{d:`M13 19a4 4 0 00-8 0`,key:`cugzd5`}],[`path`,{d:`M16 10h2`,key:`8sgtl7`}],[`path`,{d:`M16 14h2`,key:`epxaof`}],[`circle`,{cx:`9`,cy:`12`,r:`3`,key:`u3jwor`}],[`rect`,{x:`2`,y:`5`,width:`20`,height:`14`,rx:`2`,key:`qneu4z`}]]};o.node;var s=n.n(o),c={name:`mail-open`,size:24,node:[[`path`,{d:`M21.2 8.4c.5.38.8.97.8 1.6v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V10a2 2 0 0 1 .8-1.6l8-6a2 2 0 0 1 2.4 0l8 6Z`,key:`1jhwl8`}],[`path`,{d:`m22 10-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 10`,key:`1qfld7`}]]};c.node;var l=n.n(c),u={name:`phone`,size:24,node:[[`path`,{d:`M13.832 16.568a1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 6.392 6.384`,key:`9njp5v`}]]};u.node;var d=n.n(u),f={password:t.h,emailLink:l,google:({className:e})=>(0,a.jsxs)(`svg`,{className:e,viewBox:`0 0 24 24`,"aria-hidden":`true`,children:[(0,a.jsx)(`path`,{fill:`#4285F4`,d:`M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z`}),(0,a.jsx)(`path`,{fill:`#34A853`,d:`M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z`}),(0,a.jsx)(`path`,{fill:`#FBBC05`,d:`M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z`}),(0,a.jsx)(`path`,{fill:`#EA4335`,d:`M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z`})]}),phone:d,github:({className:e})=>(0,a.jsx)(`svg`,{className:e,viewBox:`0.6 0.6 22.8 22.8`,"aria-hidden":`true`,children:(0,a.jsx)(`path`,{fill:`currentColor`,d:`M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12`})}),twitter:({className:e})=>(0,a.jsx)(`svg`,{className:e,viewBox:`0 0 24 24`,"aria-hidden":`true`,children:(0,a.jsx)(`path`,{fill:`currentColor`,d:`M18.9 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932zm-1.29 19.49h2.039L6.486 3.24H4.298z`})}),sms2fa:r.t};Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return f}});
1
+ const e=require(`./chunk-CiTBaPhY.cjs`),t=require(`./PageTitle-BL50s4qY.cjs`),n=require(`./chevron-down-lyDK1rfL.cjs`),r=require(`./shield-check-Bsd5oaif.cjs`);let i=require(`react`);i=e.a(i,1);let a=require(`react/jsx-runtime`);var o={name:`id-card`,size:24,node:[[`path`,{d:`M13 19a4 4 0 00-8 0`,key:`cugzd5`}],[`path`,{d:`M16 10h2`,key:`8sgtl7`}],[`path`,{d:`M16 14h2`,key:`epxaof`}],[`circle`,{cx:`9`,cy:`12`,r:`3`,key:`u3jwor`}],[`rect`,{x:`2`,y:`5`,width:`20`,height:`14`,rx:`2`,key:`qneu4z`}]]};o.node;var s=n.n(o),c={name:`mail-open`,size:24,node:[[`path`,{d:`M21.2 8.4c.5.38.8.97.8 1.6v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V10a2 2 0 0 1 .8-1.6l8-6a2 2 0 0 1 2.4 0l8 6Z`,key:`1jhwl8`}],[`path`,{d:`m22 10-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 10`,key:`1qfld7`}]]};c.node;var l=n.n(c),u={name:`phone`,size:24,node:[[`path`,{d:`M13.832 16.568a1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 6.392 6.384`,key:`9njp5v`}]]};u.node;var d=n.n(u),f={password:t.h,emailLink:l,google:({className:e})=>(0,a.jsxs)(`svg`,{className:e,viewBox:`0 0 24 24`,"aria-hidden":`true`,children:[(0,a.jsx)(`path`,{fill:`#4285F4`,d:`M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z`}),(0,a.jsx)(`path`,{fill:`#34A853`,d:`M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z`}),(0,a.jsx)(`path`,{fill:`#FBBC05`,d:`M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z`}),(0,a.jsx)(`path`,{fill:`#EA4335`,d:`M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z`})]}),phone:d,github:({className:e})=>(0,a.jsx)(`svg`,{className:e,viewBox:`0.6 0.6 22.8 22.8`,"aria-hidden":`true`,children:(0,a.jsx)(`path`,{fill:`currentColor`,d:`M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12`})}),twitter:({className:e})=>(0,a.jsx)(`svg`,{className:e,viewBox:`0 0 24 24`,"aria-hidden":`true`,children:(0,a.jsx)(`path`,{fill:`currentColor`,d:`M18.9 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932zm-1.29 19.49h2.039L6.486 3.24H4.298z`})}),sms2fa:r.t};Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return f}});
@@ -1,4 +1,4 @@
1
- import { h as e } from "./PageTitle-DCoUQWw6.js";
1
+ import { h as e } from "./PageTitle-CkZriz8K.js";
2
2
  import { n as t } from "./chevron-down--LwXEv9w.js";
3
3
  import { t as n } from "./shield-check-DRQNdYcW.js";
4
4
  import "react";
@@ -1,2 +1,2 @@
1
- require(`./chunk-CiTBaPhY.cjs`);const e=require(`./PageTitle-DQkvCB11.cjs`),t=require(`./TimeZoneField-Ckn1pKAL.cjs`),n=require(`./DashboardNav-GgEUpyTa.cjs`),r=require(`./chevron-down-lyDK1rfL.cjs`),i=require(`./SupportBar-DLWruzQb.cjs`),a=require(`./Setup-R4r6_tbV.cjs`),o=require(`./serviceStatus-Cde96_OO.cjs`),s=require(`./publishSteps-DvWlF0p_.cjs`);let c=require(`react`),l=require(`react/jsx-runtime`),u=require(`react-router-dom`);var d=`text-accent underline underline-offset-2 font-semibold hover:text-accent-deep transition-colors`,f=`space-y-2 list-decimal list-inside text-foreground/75 marker:font-bold marker:text-foreground/40`;function p({href:e,children:t}){return(0,l.jsx)(`a`,{href:e,target:`_blank`,rel:`noopener noreferrer`,className:d,children:t})}function m({children:e}){return(0,l.jsx)(`h4`,{className:`text-[12px] font-extrabold uppercase tracking-[0.14em] text-foreground/40 pt-1`,children:e})}function h({number:e,title:n,done:i,open:a,onToggle:o,children:s}){let c=(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`span`,{className:`w-8 h-8 shrink-0 rounded-full flex items-center justify-center text-[13.5px] font-extrabold border ${i?`bg-emerald-500/10 border-emerald-500/20 text-emerald-500`:`bg-accent/10 border-accent/20 text-accent`}`,children:i?(0,l.jsx)(t.At,{className:`w-4 h-4`}):e}),(0,l.jsx)(`span`,{className:`flex-1 min-w-0 text-[14.5px] sm:text-[15px] font-bold text-foreground tracking-tight truncate`,children:n}),o&&(0,l.jsx)(r.t,{className:`w-4 h-4 shrink-0 text-foreground/40 transition-transform duration-200 ${a?`rotate-180`:``}`})]});return(0,l.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]/60 bg-foreground/[0.015] overflow-hidden transition-all`,children:[o?(0,l.jsx)(`button`,{type:`button`,onClick:o,"aria-expanded":a,className:`w-full px-4 sm:px-5 py-4 flex items-center gap-3 sm:gap-3.5 text-left cursor-pointer hover:bg-foreground/[0.02] transition-colors`,children:c}):(0,l.jsx)(`div`,{className:`w-full px-4 sm:px-5 py-4 flex items-center gap-3 sm:gap-3.5`,children:c}),(0,l.jsx)(t.rt,{initial:!1,children:a&&(0,l.jsx)(t.nt.div,{initial:{height:0,opacity:0},animate:{height:`auto`,opacity:1},exit:{height:0,opacity:0},transition:t.w,className:`overflow-hidden`,children:(0,l.jsx)(`div`,{className:`border-t border-[var(--panel-border)]/40 p-4 sm:p-5 flex flex-col gap-4 bg-background/30 text-[13.5px] sm:text-[14px] text-foreground/70 leading-relaxed`,children:s})})})]})}function g({label:e,onDone:n,waitingFor:r}){return(0,l.jsxs)(`div`,{className:`flex flex-col gap-2 pt-1`,children:[(0,l.jsxs)(t.nt.button,{type:`button`,whileHover:r?void 0:{scale:1.01},whileTap:r?void 0:{scale:.99},onClick:n,disabled:!!r,className:`btn-primary inline-flex items-center justify-center gap-2 h-11 px-5 rounded-[var(--btn-radius,0.75rem)] text-[13px] font-bold text-white self-start max-sm:self-stretch shadow-lg ${r?`opacity-40 cursor-not-allowed`:`cursor-pointer`}`,children:[(0,l.jsx)(t.At,{className:`w-4 h-4`}),e]}),r&&(0,l.jsx)(`span`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:r})]})}function _({label:e,hint:n,placeholder:r,invalid:i,value:a,clean:o,preview:s,onSave:u}){let[d,f]=(0,c.useState)(a),[p,m]=(0,c.useState)(!1),[h,g]=(0,c.useState)(``),_=o(d),v=d.trim().length>0,y=_!==a;return(0,l.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,l.jsx)(t.b,{label:e,hint:n,value:d,onChange:e=>{f(e),g(``)},placeholder:r,error:h,action:(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[a&&!y&&(0,l.jsx)(t._,{state:`saved`,label:`Saved`}),(0,l.jsx)(t.o,{icon:t.At,onClick:async()=>{if(!_){g(i);return}m(!0);let e=await u(_);m(!1),g(e||``),e||f(_)},busy:p,disabled:!v||!y&&!!a,children:`Save`})]})}),_&&!h&&(0,l.jsx)(`div`,{className:`px-3.5 py-2.5 rounded-xl border border-[var(--panel-border)]/60 bg-background`,children:(0,l.jsx)(`span`,{className:`text-[12.5px] font-mono text-foreground/60 truncate block`,children:s(_)})})]})}function v({label:e,url:t}){return(0,l.jsxs)(`div`,{className:`flex max-sm:flex-col sm:items-center justify-between gap-2 sm:gap-3 px-3.5 py-3 rounded-xl border border-[var(--panel-border)]/60 bg-background`,children:[(0,l.jsxs)(`div`,{className:`min-w-0 flex flex-col gap-0.5`,children:[(0,l.jsx)(`span`,{className:`text-[11px] font-bold uppercase tracking-[0.14em] text-foreground/40`,children:e}),(0,l.jsx)(`span`,{className:`text-[12.5px] font-mono text-foreground/70 truncate`,children:t})]}),(0,l.jsx)(a.t,{compact:!0,code:t,label:`Copy`})]})}var y=[`216.239.32.21`,`216.239.34.21`,`216.239.36.21`,`216.239.38.21`];function b(){let{loading:r,record:d,save:b}=s.l(),[x,S]=(0,c.useState)(null),{status:C}=o.i(),w=s.o(d.done,x),T=e=>w[s.t.indexOf(e)],E=s.n(d.appName),D=s.a(d.domain),O=d.done.length===s.t.length,k=O&&s.c(C),A=O&&!k,j=e=>{S(null),b({done:s.u(d.done,e)})},M=e=>e.open?e.done?()=>S(null):void 0:()=>S(e.done?e.id:null),N=e=>{let t=T(e);return{done:t.done,open:t.open,onToggle:M(t)}};return(0,l.jsxs)(`main`,{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`,children:[(0,l.jsxs)(t.nt.div,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},className:`mb-6`,children:[(0,l.jsx)(e.t,{children:`Publish App`}),(0,l.jsxs)(`div`,{className:`flex items-center gap-2 text-foreground/40 font-bold uppercase tracking-[0.2em] text-[11px]`,children:[(0,l.jsx)(`span`,{className:`w-8 h-[1px] bg-foreground/10`}),`/publish`]})]}),(0,l.jsxs)(`div`,{className:`flex flex-col gap-6 flex-1 pb-16`,children:[(0,l.jsx)(n.t,{}),(0,l.jsxs)(t.nt.div,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},transition:{delay:.1},className:`glass-panel border border-[var(--panel-border)] rounded-3xl p-4 sm:p-6 md:p-8 shadow-2xl relative bg-background flex flex-col fbos-tab-fill`,children:[(0,l.jsx)(`div`,{className:`mb-6 pb-4 sm:mb-8 sm:pb-6 border-b border-[var(--panel-border)]/50`,children:(0,l.jsxs)(`div`,{className:`min-w-0`,children:[(0,l.jsx)(`h2`,{className:`text-[17px] sm:text-xl font-bold text-foreground tracking-tight truncate`,children:`Putting your app in front of people`}),(0,l.jsxs)(`p`,{className:`text-[13px] font-medium text-foreground/50 mt-1 sm:mt-1.5 leading-snug truncate`,children:[(0,l.jsx)(`span`,{className:`sm:hidden`,children:`One step at a time. Stuck? Ask me below.`}),(0,l.jsx)(`span`,{className:`max-sm:hidden`,children:`One step at a time — the next one appears as you tick each off. Stuck anywhere? Ask me below.`})]})]})}),!r&&(0,l.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,l.jsxs)(h,{number:1,title:`Publish in AI Studio`,...N(`published`),children:[(0,l.jsxs)(`ol`,{className:f,children:[(0,l.jsxs)(`li`,{children:[`In `,(0,l.jsx)(p,{href:`https://aistudio.google.com`,children:`Google AI Studio`}),`, click`,` `,(0,l.jsx)(`strong`,{children:`Publish`}),` in the top left corner, then `,(0,l.jsx)(`strong`,{children:`Get started`}),`.`]}),(0,l.jsxs)(`li`,{children:[`It asks for an app URL. Type a name for your app —`,` `,(0,l.jsx)(`span`,{className:`text-accent`,children:`my-ai-project`}),` — and copy it, you need it again at the bottom of this step.`]}),(0,l.jsxs)(`li`,{children:[`Follow the rest of AI Studio's instructions, then click `,(0,l.jsx)(`strong`,{children:`Publish your app`}),`.`]})]}),(0,l.jsxs)(`p`,{children:[`If it says `,(0,l.jsx)(`strong`,{children:`Failed to publish app`}),`, reload the page, unpublish, and publish again. It usually goes through the second time.`]}),(0,l.jsx)(_,{label:`Your app name`,hint:`The name you just typed into AI Studio. Saving only keeps it for step 3 — nothing changes in AI Studio, it just says Saved. Pasting the whole address is fine; only the name is kept.`,placeholder:`my-ai-project`,invalid:`That does not look like an app name — letters, numbers and dashes.`,value:d.appName,clean:s.r,preview:s.n,onSave:e=>b({appName:e})}),(0,l.jsx)(g,{label:`My app is published`,onDone:()=>j(`published`),waitingFor:d.appName?void 0:`Save your app name first — step 3 asks for this address.`})]}),T(`connected`).visible&&(0,l.jsxs)(h,{number:2,title:`Connect your website domain`,...N(`connected`),children:[(0,l.jsxs)(`p`,{children:[`Your app is live at `,(0,l.jsx)(`span`,{className:`font-mono text-foreground/80`,children:E||`your AI Studio address`}),` `,`already. This step puts it on a domain of your own.`]}),(0,l.jsx)(m,{children:`Start the mapping`}),(0,l.jsxs)(`ol`,{className:f,children:[(0,l.jsxs)(`li`,{children:[`Back where you published, click `,(0,l.jsx)(`strong`,{children:`Advanced settings`}),`. It takes you to Google Cloud Run.`]}),(0,l.jsxs)(`li`,{children:[`In the menu on the left, open `,(0,l.jsx)(`strong`,{children:`Domain mappings`}),`, then`,` `,(0,l.jsx)(`strong`,{children:`Add mapping`}),` at the top.`]}),(0,l.jsxs)(`li`,{children:[`Choose your service, then under `,(0,l.jsx)(`strong`,{children:`Select a verified domain`}),` click`,` `,(0,l.jsx)(`strong`,{children:`Verify new domain`}),`.`]}),(0,l.jsxs)(`li`,{children:[`Type your domain — `,(0,l.jsx)(`span`,{className:`text-accent`,children:`myaiproject.com`}),` — and click`,` `,(0,l.jsx)(`strong`,{children:`Continue`}),`, then `,(0,l.jsx)(`strong`,{children:`Verify in Search Console`}),`.`]})]}),(0,l.jsx)(m,{children:`Prove the domain is yours`}),(0,l.jsxs)(`ol`,{className:f,children:[(0,l.jsxs)(`li`,{children:[`Google Search Console opens. Click `,(0,l.jsx)(`strong`,{children:`Add a website`}),`, type the same domain, and click `,(0,l.jsx)(`strong`,{children:`Continue`}),`.`]}),(0,l.jsxs)(`li`,{children:[`On the next screen, under `,(0,l.jsxs)(`em`,{children:[`Copy the TXT record below into the DNS configuration for `,s.i(d.domain)||`myaiproject.com`]}),`, copy the`,` `,(0,l.jsx)(`strong`,{children:`TXT record`}),` — a long line starting`,` `,(0,l.jsx)(`span`,{className:`font-mono text-foreground/80`,children:`google-site-verification=`})]}),(0,l.jsxs)(`li`,{children:[`Open your domain registrar in another tab — GoDaddy, Namecheap, whoever you bought the domain from — go to its `,(0,l.jsx)(`strong`,{children:`DNS settings`}),`, and click`,` `,(0,l.jsx)(`strong`,{children:`Add record`}),`. Choose `,(0,l.jsx)(`strong`,{children:`TXT`}),`, paste the line into`,` `,(0,l.jsx)(`strong`,{children:`Value`}),`, and put `,(0,l.jsx)(`span`,{className:`font-mono text-foreground/80`,children:`@`}),` `,`in `,(0,l.jsx)(`strong`,{children:`Host`}),` or `,(0,l.jsx)(`strong`,{children:`Name`}),`. Save it.`]}),(0,l.jsxs)(`li`,{children:[`Back in Search Console, click `,(0,l.jsx)(`strong`,{children:`Verify`}),`.`]}),(0,l.jsxs)(`li`,{children:[`Once it is verified you are done with Search Console — close that tab. Go back to the Google Cloud Run tab (`,(0,l.jsx)(`span`,{className:`font-mono text-foreground/80`,children:`console.cloud.google.com`}),`) where you clicked to verify, and press its `,(0,l.jsx)(`strong`,{children:`refresh`}),` button. It should say `,(0,l.jsxs)(`em`,{children:[`Your ownership of `,s.i(d.domain)||`myaiproject.com`,` has been successfully verified. You can now map this domain to your Cloud Run services.`]})]})]}),(0,l.jsx)(m,{children:`Point the domain at your app`}),(0,l.jsxs)(`ol`,{className:f,children:[(0,l.jsxs)(`li`,{children:[`Add a subdomain if you want one, then click `,(0,l.jsx)(`strong`,{children:`Continue`}),`. Cloud Run now shows you the records to add.`]}),(0,l.jsxs)(`li`,{children:[`Back at your registrar, add each one as an `,(0,l.jsx)(`strong`,{children:`A record`}),`, the same way you added the TXT. It is normally these four:`]})]}),(0,l.jsxs)(`div`,{className:`rounded-xl border border-[var(--panel-border)]/60 bg-background overflow-hidden`,children:[(0,l.jsxs)(`div`,{className:`flex items-center justify-between gap-3 px-3.5 py-2.5 border-b border-[var(--panel-border)]/40`,children:[(0,l.jsx)(`span`,{className:`text-[11px] font-bold uppercase tracking-[0.14em] text-foreground/40`,children:`A records`}),(0,l.jsx)(a.t,{compact:!0,code:y.join(`
1
+ require(`./chunk-CiTBaPhY.cjs`);const e=require(`./PageTitle-BL50s4qY.cjs`),t=require(`./TimeZoneField-Ckn1pKAL.cjs`),n=require(`./DashboardNav-Bc619nqn.cjs`),r=require(`./chevron-down-lyDK1rfL.cjs`),i=require(`./SupportBar-DR52UpBq.cjs`),a=require(`./Setup-DiFnnzdd.cjs`),o=require(`./serviceStatus-Cde96_OO.cjs`),s=require(`./publishSteps-DvWlF0p_.cjs`);let c=require(`react`),l=require(`react/jsx-runtime`),u=require(`react-router-dom`);var d=`text-accent underline underline-offset-2 font-semibold hover:text-accent-deep transition-colors`,f=`space-y-2 list-decimal list-inside text-foreground/75 marker:font-bold marker:text-foreground/40`;function p({href:e,children:t}){return(0,l.jsx)(`a`,{href:e,target:`_blank`,rel:`noopener noreferrer`,className:d,children:t})}function m({children:e}){return(0,l.jsx)(`h4`,{className:`text-[12px] font-extrabold uppercase tracking-[0.14em] text-foreground/40 pt-1`,children:e})}function h({number:e,title:n,done:i,open:a,onToggle:o,children:s}){let c=(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`span`,{className:`w-8 h-8 shrink-0 rounded-full flex items-center justify-center text-[13.5px] font-extrabold border ${i?`bg-emerald-500/10 border-emerald-500/20 text-emerald-500`:`bg-accent/10 border-accent/20 text-accent`}`,children:i?(0,l.jsx)(t.At,{className:`w-4 h-4`}):e}),(0,l.jsx)(`span`,{className:`flex-1 min-w-0 text-[14.5px] sm:text-[15px] font-bold text-foreground tracking-tight truncate`,children:n}),o&&(0,l.jsx)(r.t,{className:`w-4 h-4 shrink-0 text-foreground/40 transition-transform duration-200 ${a?`rotate-180`:``}`})]});return(0,l.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]/60 bg-foreground/[0.015] overflow-hidden transition-all`,children:[o?(0,l.jsx)(`button`,{type:`button`,onClick:o,"aria-expanded":a,className:`w-full px-4 sm:px-5 py-4 flex items-center gap-3 sm:gap-3.5 text-left cursor-pointer hover:bg-foreground/[0.02] transition-colors`,children:c}):(0,l.jsx)(`div`,{className:`w-full px-4 sm:px-5 py-4 flex items-center gap-3 sm:gap-3.5`,children:c}),(0,l.jsx)(t.rt,{initial:!1,children:a&&(0,l.jsx)(t.nt.div,{initial:{height:0,opacity:0},animate:{height:`auto`,opacity:1},exit:{height:0,opacity:0},transition:t.w,className:`overflow-hidden`,children:(0,l.jsx)(`div`,{className:`border-t border-[var(--panel-border)]/40 p-4 sm:p-5 flex flex-col gap-4 bg-background/30 text-[13.5px] sm:text-[14px] text-foreground/70 leading-relaxed`,children:s})})})]})}function g({label:e,onDone:n,waitingFor:r}){return(0,l.jsxs)(`div`,{className:`flex flex-col gap-2 pt-1`,children:[(0,l.jsxs)(t.nt.button,{type:`button`,whileHover:r?void 0:{scale:1.01},whileTap:r?void 0:{scale:.99},onClick:n,disabled:!!r,className:`btn-primary inline-flex items-center justify-center gap-2 h-11 px-5 rounded-[var(--btn-radius,0.75rem)] text-[13px] font-bold text-white self-start max-sm:self-stretch shadow-lg ${r?`opacity-40 cursor-not-allowed`:`cursor-pointer`}`,children:[(0,l.jsx)(t.At,{className:`w-4 h-4`}),e]}),r&&(0,l.jsx)(`span`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:r})]})}function _({label:e,hint:n,placeholder:r,invalid:i,value:a,clean:o,preview:s,onSave:u}){let[d,f]=(0,c.useState)(a),[p,m]=(0,c.useState)(!1),[h,g]=(0,c.useState)(``),_=o(d),v=d.trim().length>0,y=_!==a;return(0,l.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,l.jsx)(t.b,{label:e,hint:n,value:d,onChange:e=>{f(e),g(``)},placeholder:r,error:h,action:(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[a&&!y&&(0,l.jsx)(t._,{state:`saved`,label:`Saved`}),(0,l.jsx)(t.o,{icon:t.At,onClick:async()=>{if(!_){g(i);return}m(!0);let e=await u(_);m(!1),g(e||``),e||f(_)},busy:p,disabled:!v||!y&&!!a,children:`Save`})]})}),_&&!h&&(0,l.jsx)(`div`,{className:`px-3.5 py-2.5 rounded-xl border border-[var(--panel-border)]/60 bg-background`,children:(0,l.jsx)(`span`,{className:`text-[12.5px] font-mono text-foreground/60 truncate block`,children:s(_)})})]})}function v({label:e,url:t}){return(0,l.jsxs)(`div`,{className:`flex max-sm:flex-col sm:items-center justify-between gap-2 sm:gap-3 px-3.5 py-3 rounded-xl border border-[var(--panel-border)]/60 bg-background`,children:[(0,l.jsxs)(`div`,{className:`min-w-0 flex flex-col gap-0.5`,children:[(0,l.jsx)(`span`,{className:`text-[11px] font-bold uppercase tracking-[0.14em] text-foreground/40`,children:e}),(0,l.jsx)(`span`,{className:`text-[12.5px] font-mono text-foreground/70 truncate`,children:t})]}),(0,l.jsx)(a.t,{compact:!0,code:t,label:`Copy`})]})}var y=[`216.239.32.21`,`216.239.34.21`,`216.239.36.21`,`216.239.38.21`];function b(){let{loading:r,record:d,save:b}=s.l(),[x,S]=(0,c.useState)(null),{status:C}=o.i(),w=s.o(d.done,x),T=e=>w[s.t.indexOf(e)],E=s.n(d.appName),D=s.a(d.domain),O=d.done.length===s.t.length,k=O&&s.c(C),A=O&&!k,j=e=>{S(null),b({done:s.u(d.done,e)})},M=e=>e.open?e.done?()=>S(null):void 0:()=>S(e.done?e.id:null),N=e=>{let t=T(e);return{done:t.done,open:t.open,onToggle:M(t)}};return(0,l.jsxs)(`main`,{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`,children:[(0,l.jsxs)(t.nt.div,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},className:`mb-6`,children:[(0,l.jsx)(e.t,{children:`Publish App`}),(0,l.jsxs)(`div`,{className:`flex items-center gap-2 text-foreground/40 font-bold uppercase tracking-[0.2em] text-[11px]`,children:[(0,l.jsx)(`span`,{className:`w-8 h-[1px] bg-foreground/10`}),`/publish`]})]}),(0,l.jsxs)(`div`,{className:`flex flex-col gap-6 flex-1 pb-16`,children:[(0,l.jsx)(n.t,{}),(0,l.jsxs)(t.nt.div,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},transition:{delay:.1},className:`glass-panel border border-[var(--panel-border)] rounded-3xl p-4 sm:p-6 md:p-8 shadow-2xl relative bg-background flex flex-col fbos-tab-fill`,children:[(0,l.jsx)(`div`,{className:`mb-6 pb-4 sm:mb-8 sm:pb-6 border-b border-[var(--panel-border)]/50`,children:(0,l.jsxs)(`div`,{className:`min-w-0`,children:[(0,l.jsx)(`h2`,{className:`text-[17px] sm:text-xl font-bold text-foreground tracking-tight truncate`,children:`Putting your app in front of people`}),(0,l.jsxs)(`p`,{className:`text-[13px] font-medium text-foreground/50 mt-1 sm:mt-1.5 leading-snug truncate`,children:[(0,l.jsx)(`span`,{className:`sm:hidden`,children:`One step at a time. Stuck? Ask me below.`}),(0,l.jsx)(`span`,{className:`max-sm:hidden`,children:`One step at a time — the next one appears as you tick each off. Stuck anywhere? Ask me below.`})]})]})}),!r&&(0,l.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,l.jsxs)(h,{number:1,title:`Publish in AI Studio`,...N(`published`),children:[(0,l.jsxs)(`ol`,{className:f,children:[(0,l.jsxs)(`li`,{children:[`In `,(0,l.jsx)(p,{href:`https://aistudio.google.com`,children:`Google AI Studio`}),`, click`,` `,(0,l.jsx)(`strong`,{children:`Publish`}),` in the top left corner, then `,(0,l.jsx)(`strong`,{children:`Get started`}),`.`]}),(0,l.jsxs)(`li`,{children:[`It asks for an app URL. Type a name for your app —`,` `,(0,l.jsx)(`span`,{className:`text-accent`,children:`my-ai-project`}),` — and copy it, you need it again at the bottom of this step.`]}),(0,l.jsxs)(`li`,{children:[`Follow the rest of AI Studio's instructions, then click `,(0,l.jsx)(`strong`,{children:`Publish your app`}),`.`]})]}),(0,l.jsxs)(`p`,{children:[`If it says `,(0,l.jsx)(`strong`,{children:`Failed to publish app`}),`, reload the page, unpublish, and publish again. It usually goes through the second time.`]}),(0,l.jsx)(_,{label:`Your app name`,hint:`The name you just typed into AI Studio. Saving only keeps it for step 3 — nothing changes in AI Studio, it just says Saved. Pasting the whole address is fine; only the name is kept.`,placeholder:`my-ai-project`,invalid:`That does not look like an app name — letters, numbers and dashes.`,value:d.appName,clean:s.r,preview:s.n,onSave:e=>b({appName:e})}),(0,l.jsx)(g,{label:`My app is published`,onDone:()=>j(`published`),waitingFor:d.appName?void 0:`Save your app name first — step 3 asks for this address.`})]}),T(`connected`).visible&&(0,l.jsxs)(h,{number:2,title:`Connect your website domain`,...N(`connected`),children:[(0,l.jsxs)(`p`,{children:[`Your app is live at `,(0,l.jsx)(`span`,{className:`font-mono text-foreground/80`,children:E||`your AI Studio address`}),` `,`already. This step puts it on a domain of your own.`]}),(0,l.jsx)(m,{children:`Start the mapping`}),(0,l.jsxs)(`ol`,{className:f,children:[(0,l.jsxs)(`li`,{children:[`Back where you published, click `,(0,l.jsx)(`strong`,{children:`Advanced settings`}),`. It takes you to Google Cloud Run.`]}),(0,l.jsxs)(`li`,{children:[`In the menu on the left, open `,(0,l.jsx)(`strong`,{children:`Domain mappings`}),`, then`,` `,(0,l.jsx)(`strong`,{children:`Add mapping`}),` at the top.`]}),(0,l.jsxs)(`li`,{children:[`Choose your service, then under `,(0,l.jsx)(`strong`,{children:`Select a verified domain`}),` click`,` `,(0,l.jsx)(`strong`,{children:`Verify new domain`}),`.`]}),(0,l.jsxs)(`li`,{children:[`Type your domain — `,(0,l.jsx)(`span`,{className:`text-accent`,children:`myaiproject.com`}),` — and click`,` `,(0,l.jsx)(`strong`,{children:`Continue`}),`, then `,(0,l.jsx)(`strong`,{children:`Verify in Search Console`}),`.`]})]}),(0,l.jsx)(m,{children:`Prove the domain is yours`}),(0,l.jsxs)(`ol`,{className:f,children:[(0,l.jsxs)(`li`,{children:[`Google Search Console opens. Click `,(0,l.jsx)(`strong`,{children:`Add a website`}),`, type the same domain, and click `,(0,l.jsx)(`strong`,{children:`Continue`}),`.`]}),(0,l.jsxs)(`li`,{children:[`On the next screen, under `,(0,l.jsxs)(`em`,{children:[`Copy the TXT record below into the DNS configuration for `,s.i(d.domain)||`myaiproject.com`]}),`, copy the`,` `,(0,l.jsx)(`strong`,{children:`TXT record`}),` — a long line starting`,` `,(0,l.jsx)(`span`,{className:`font-mono text-foreground/80`,children:`google-site-verification=`})]}),(0,l.jsxs)(`li`,{children:[`Open your domain registrar in another tab — GoDaddy, Namecheap, whoever you bought the domain from — go to its `,(0,l.jsx)(`strong`,{children:`DNS settings`}),`, and click`,` `,(0,l.jsx)(`strong`,{children:`Add record`}),`. Choose `,(0,l.jsx)(`strong`,{children:`TXT`}),`, paste the line into`,` `,(0,l.jsx)(`strong`,{children:`Value`}),`, and put `,(0,l.jsx)(`span`,{className:`font-mono text-foreground/80`,children:`@`}),` `,`in `,(0,l.jsx)(`strong`,{children:`Host`}),` or `,(0,l.jsx)(`strong`,{children:`Name`}),`. Save it.`]}),(0,l.jsxs)(`li`,{children:[`Back in Search Console, click `,(0,l.jsx)(`strong`,{children:`Verify`}),`.`]}),(0,l.jsxs)(`li`,{children:[`Once it is verified you are done with Search Console — close that tab. Go back to the Google Cloud Run tab (`,(0,l.jsx)(`span`,{className:`font-mono text-foreground/80`,children:`console.cloud.google.com`}),`) where you clicked to verify, and press its `,(0,l.jsx)(`strong`,{children:`refresh`}),` button. It should say `,(0,l.jsxs)(`em`,{children:[`Your ownership of `,s.i(d.domain)||`myaiproject.com`,` has been successfully verified. You can now map this domain to your Cloud Run services.`]})]})]}),(0,l.jsx)(m,{children:`Point the domain at your app`}),(0,l.jsxs)(`ol`,{className:f,children:[(0,l.jsxs)(`li`,{children:[`Add a subdomain if you want one, then click `,(0,l.jsx)(`strong`,{children:`Continue`}),`. Cloud Run now shows you the records to add.`]}),(0,l.jsxs)(`li`,{children:[`Back at your registrar, add each one as an `,(0,l.jsx)(`strong`,{children:`A record`}),`, the same way you added the TXT. It is normally these four:`]})]}),(0,l.jsxs)(`div`,{className:`rounded-xl border border-[var(--panel-border)]/60 bg-background overflow-hidden`,children:[(0,l.jsxs)(`div`,{className:`flex items-center justify-between gap-3 px-3.5 py-2.5 border-b border-[var(--panel-border)]/40`,children:[(0,l.jsx)(`span`,{className:`text-[11px] font-bold uppercase tracking-[0.14em] text-foreground/40`,children:`A records`}),(0,l.jsx)(a.t,{compact:!0,code:y.join(`
2
2
  `),label:`Copy all four`})]}),(0,l.jsx)(`div`,{className:`px-3.5 py-2.5 flex flex-col gap-1`,children:y.map(e=>(0,l.jsx)(`span`,{className:`text-[12.5px] font-mono text-foreground/70`,children:e},e))})]}),(0,l.jsx)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:`Use whatever your own Cloud Run screen shows if it differs from these — that screen is always right.`}),(0,l.jsxs)(`p`,{children:[`Once they are all in, press `,(0,l.jsx)(`strong`,{children:`Done`}),` in Cloud Run and wait — this can take an hour or more. Check every few minutes by typing your domain into any browser, like `,(0,l.jsx)(`span`,{className:`text-accent`,children:`myaiproject.com`}),`: when your published app comes up, it is connected.`]}),(0,l.jsx)(_,{label:`Your domain`,hint:`However you have it — with or without https:// and www. Only the domain itself is kept, for step 3.`,placeholder:`myaiproject.com`,invalid:`That does not look like a domain — something like myaiproject.com.`,value:d.domain,clean:s.i,preview:s.a,onSave:e=>b({domain:e})}),(0,l.jsx)(g,{label:`My domain is verified and my app is connected`,onDone:()=>j(`connected`),waitingFor:d.domain?void 0:`Save your domain first — step 3 asks for this address.`})]}),T(`authorised`).visible&&(0,l.jsxs)(h,{number:3,title:`Add your domains and email sender`,...N(`authorised`),children:[(0,l.jsxs)(`p`,{children:[`Once your domain answers, head back to the`,` `,(0,l.jsx)(p,{href:`https://console.firebase.google.com`,children:`Firebase console`}),`. Two jobs, both under `,(0,l.jsx)(`strong`,{children:`Security → Authentication`}),`.`]}),(0,l.jsx)(m,{children:`Authorise both addresses`}),(0,l.jsxs)(`p`,{children:[`Nobody can sign in from an address Firebase does not know. Open`,` `,(0,l.jsx)(`strong`,{children:`Security → Authentication → Settings → Authorised domains`}),`, click`,` `,(0,l.jsx)(`strong`,{children:`Add domain`}),`, and paste these in one at a time — both need to be there.`]}),(0,l.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,l.jsx)(v,{label:`Your AI Studio address`,url:E?`${s.r(d.appName)}.ai.studio`:`—`}),(0,l.jsx)(v,{label:`Your own domain`,url:s.i(d.domain)||`—`})]}),(0,l.jsx)(m,{children:`Send email from your own domain`}),(0,l.jsxs)(`ol`,{className:f,children:[(0,l.jsxs)(`li`,{children:[`On the same Authentication page, open the `,(0,l.jsx)(`strong`,{children:`Templates`}),` tab. Every email Firebase sends for you lives here — password changes, email verification. You can reword them, but the one thing worth doing is the sender.`]}),(0,l.jsxs)(`li`,{children:[`Click the pencil beside `,(0,l.jsx)(`strong`,{children:`From`}),`. It will be something like`,` `,(0,l.jsx)(`span`,{className:`font-mono text-foreground/80`,children:`noreply@your-project.firebaseapp.com`})]}),(0,l.jsxs)(`li`,{children:[`On the right, click `,(0,l.jsx)(`strong`,{children:`Customise domain`}),`, enter your own domain, and follow the steps it gives you — more records at your registrar, same as before.`]})]}),(0,l.jsx)(`p`,{children:`This is what keeps your emails out of people's spam folders, and it is why they arrive looking like they came from you.`}),(0,l.jsx)(g,{label:`I've added my domains and verified my email domain`,onDone:()=>j(`authorised`)})]}),k&&(0,l.jsxs)(h,{number:4,title:`Finalise your Stripe live setup`,done:!1,open:!0,children:[(0,l.jsx)(`p`,{children:`Your payments are not live yet — still on practice cards, or live without the webhook that sends receipts. Finish Go live on the Payments screen and your setup is complete.`}),(0,l.jsxs)(`p`,{children:[`Switch `,(0,l.jsx)(`strong`,{children:`Go live`}),` on and follow its steps. Its webhook step was waiting for your published address, and it is open now that step 3 is ticked.`]}),(0,l.jsxs)(u.Link,{to:`/payments`,className:`btn-primary inline-flex items-center justify-center gap-2 h-11 px-5 rounded-[var(--btn-radius,0.75rem)] text-[13px] font-bold text-white self-start max-sm:self-stretch shadow-lg cursor-pointer`,children:[(0,l.jsx)(n.j,{className:`w-4 h-4`}),`Take me to Go live`]})]}),A&&(0,l.jsxs)(`div`,{className:`mt-3 flex max-sm:flex-col sm:items-center gap-4 sm:gap-6 p-5 sm:p-6 rounded-2xl border border-emerald-500/20 bg-emerald-500/[0.06]`,children:[(0,l.jsx)(`div`,{className:`w-10 h-10 shrink-0 rounded-2xl flex items-center justify-center border border-emerald-500/20 bg-emerald-500/10 text-emerald-500`,children:(0,l.jsx)(n.w,{className:`w-5 h-5`})}),(0,l.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,l.jsx)(`h3`,{className:`text-[15px] font-bold text-foreground tracking-tight`,children:`Your app is live`}),(0,l.jsxs)(`p`,{className:`text-[13px] text-foreground/60 font-medium leading-relaxed mt-1`,children:[D?(0,l.jsxs)(l.Fragment,{children:[`Anyone can open `,(0,l.jsx)(p,{href:D,children:s.i(d.domain)}),` and sign up.`]}):(0,l.jsx)(l.Fragment,{children:`Anyone can open your app and sign up.`}),` `,`Any step above opens again if you need to check what you typed.`]})]})]})]})]}),(0,l.jsx)(i.t,{video:`publish`})]})]})}exports.PublishApp=b;
@@ -1,9 +1,9 @@
1
- import { t as e } from "./PageTitle-DCoUQWw6.js";
1
+ import { t as e } from "./PageTitle-CkZriz8K.js";
2
2
  import { At as t, _ as n, b as r, nt as i, o as a, rt as o, w as s } from "./TimeZoneField-oIMwb5_X.js";
3
- import { j as c, t as l, w as u } from "./DashboardNav-CEd8gGPm.js";
3
+ import { j as c, t as l, w as u } from "./DashboardNav-CxS3Qnl-.js";
4
4
  import { t as d } from "./chevron-down--LwXEv9w.js";
5
- import { t as f } from "./SupportBar-DI_XbEsG.js";
6
- import { t as p } from "./Setup-_G-s5y5Q.js";
5
+ import { t as f } from "./SupportBar-0nIiQp-_.js";
6
+ import { t as p } from "./Setup-DOGI-_8f.js";
7
7
  import { i as m } from "./serviceStatus-C9izcuQz.js";
8
8
  import { a as h, c as g, i as _, l as v, n as y, o as b, r as x, t as S, u as C } from "./publishSteps-Cf5pSB_H.js";
9
9
  import { useState as w } from "react";
@@ -1,11 +1,11 @@
1
- import { a as e, t } from "./PageTitle-DCoUQWw6.js";
1
+ import { a as e, t } from "./PageTitle-CkZriz8K.js";
2
2
  import { Dr as n, Ft as r, Jn as i, Mt as a, Qn as o, S as s, Z as c, Zr as l, _ as u, b as d, br as f, c as p, cr as m, g as h, gr as g, i as _, jt as v, m as y, nt as b, o as x, s as S, t as C, ui as w, x as T, xr as E, y as D } from "./TimeZoneField-oIMwb5_X.js";
3
- import { C as O, S as k, t as A } from "./DashboardNav-CEd8gGPm.js";
3
+ import { C as O, S as k, t as A } from "./DashboardNav-CxS3Qnl-.js";
4
4
  import { B as j, Bt as M, D as N, G as P, K as F, M as ee, O as I, Sn as L, U as te, W as ne, Zt as re, _ as ie, b as ae, d as oe, dt as se, et as ce, ft as le, h as ue, ht as de, j as fe, l as pe, m as me, mt as he, nn as R, o as ge, ot as _e, pt as ve, qt as ye, rn as be, s as xe, t as Se, u as z, ut as Ce } from "./schedule-C13m_kiO.js";
5
5
  import { t as B } from "./chevron-down--LwXEv9w.js";
6
6
  import { B as we, C as Te, F as Ee, H as De, I as Oe, L as ke, M as Ae, N as je, P as Me, R as Ne, S as Pe, T as Fe, U as Ie, V, a as Le, c as Re, d as ze, f as Be, g as H, h as Ve, m as He, n as Ue, p as We, r as Ge, t as Ke, u as qe, v as Je, w as Ye, y as Xe, z as Ze } from "./scheduleData-DR6A-Q7Z.js";
7
7
  import { d as Qe } from "./BookingCalendar-Bej__mIs.js";
8
- import { n as $e, t as et } from "./paidSessions-B8e5RHi4.js";
8
+ import { n as $e, t as et } from "./paidSessions-C9392hZH.js";
9
9
  import { t as tt } from "./link-2-CtDUJiNU.js";
10
10
  import { t as U } from "./x-hax8aKt8.js";
11
11
  import { t as W } from "./plus-BKrt0Qx5.js";
@@ -19,7 +19,7 @@ import { i as vt } from "./AccessNotice-DGsp8Xfl.js";
19
19
  import { n as yt } from "./SystemTabContent-CMyT7mDN.js";
20
20
  import { r as bt } from "./serviceStatus-C9izcuQz.js";
21
21
  import { n as xt, t as St } from "./NeedsService-SxEZO5Fa.js";
22
- import { t as Ct } from "./CopyLink-CNjDLzOl.js";
22
+ import { t as Ct } from "./CopyLink-kROJG9Qf.js";
23
23
  import { useEffect as K, useMemo as q, useRef as J, useState as Y } from "react";
24
24
  import { Fragment as X, jsx as Z, jsxs as Q } from "react/jsx-runtime";
25
25
  import { collection as wt, doc as Tt, setDoc as Et } from "firebase/firestore";
@@ -1 +1 @@
1
- require(`./chunk-CiTBaPhY.cjs`);const e=require(`./PageTitle-DQkvCB11.cjs`),t=require(`./TimeZoneField-Ckn1pKAL.cjs`),n=require(`./DashboardNav-GgEUpyTa.cjs`),r=require(`./schedule-BAea6q8_.cjs`),i=require(`./chevron-down-lyDK1rfL.cjs`),a=require(`./scheduleData-BXjNXVHY.cjs`),o=require(`./BookingCalendar-BcvJiyaq.cjs`),s=require(`./paidSessions-D-zHC4oG.cjs`),c=require(`./link-2-C7A-6PW6.cjs`),l=require(`./x-Ci8c5p6T.cjs`),u=require(`./plus-zsWFCu4F.cjs`),d=require(`./trash-D-CpYHCs.cjs`),f=require(`./Loader-QHqQsXLr.cjs`),p=require(`./email-Sya6gl4F.cjs`),m=require(`./notices-CKm9-Pqt.cjs`),h=require(`./ConfirmModal-BUNtss4a.cjs`),g=require(`./bookingPages-Dx1ViiwW.cjs`),_=require(`./AccessNotice-BClqr7A9.cjs`),v=require(`./SystemTabContent-BWhRHoXx.cjs`),y=require(`./serviceStatus-Cde96_OO.cjs`),b=require(`./NeedsService-DIF7mEHq.cjs`),x=require(`./CopyLink-C5lKLyOU.cjs`);let S=require(`react`),C=require(`react/jsx-runtime`),w=require(`firebase/firestore`),T=require(`react-router-dom`);var E=`w-[6.5rem] shrink-0`,D=`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`,O=`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`,k={from:`09:00`,to:`13:00`};function A(e,t){return{upcoming:e.filter(e=>e.date>=t),past:e.filter(e=>e.date<t)}}function j({row:e,onChange:n,onRemove:i}){let a=e.windows.length===0,o=(t,r)=>n({...e,windows:e.windows.map((e,n)=>n===t?{...e,...r}:e)});return(0,C.jsxs)(`div`,{className:`flex flex-col gap-2 py-2.5`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,C.jsx)(`input`,{type:`date`,value:e.date,"aria-label":`The date`,onChange:t=>n({...e,date:t.target.value}),className:O,style:{borderRadius:`var(--input-radius, 0.75rem)`}}),(0,C.jsx)(`div`,{className:`w-[11rem] shrink-0`,children:(0,C.jsx)(t.Z,{ariaLabel:`${e.date} — how much of it`,value:a?`all`:`some`,options:[{value:`all`,label:`All day`},{value:`some`,label:`Only some hours`}],onChange:t=>n({...e,windows:t===`all`?[]:[k]}),className:`console-select`,compact:!0,dense:!0,portal:!0,direction:`auto`})}),(0,C.jsx)(`button`,{type:`button`,title:`Remove ${e.date||`this date`}`,"aria-label":`Remove ${e.date||`this date`}`,onClick:i,className:`${D} ml-auto`,children:(0,C.jsx)(l.t,{className:`w-3.5 h-3.5`})})]}),!a&&(0,C.jsxs)(`div`,{className:`flex flex-col gap-2 sm:pl-[0.125rem]`,children:[e.windows.map((i,a)=>(0,C.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,C.jsx)(`div`,{className:E,children:(0,C.jsx)(t.Z,{ariaLabel:`${e.date} from${a?` (${a+1})`:``}`,value:i.from,options:r.m,onChange:e=>o(a,{from:e}),className:`console-select`,compact:!0,portal:!0,direction:`auto`})}),(0,C.jsx)(`span`,{className:`w-3 text-center text-foreground/40 text-[13px] shrink-0 select-none`,children:`–`}),(0,C.jsx)(`div`,{className:E,children:(0,C.jsx)(t.Z,{ariaLabel:`${e.date} to${a?` (${a+1})`:``}`,value:i.to,options:r.d,onChange:e=>o(a,{to:e}),className:`console-select`,compact:!0,portal:!0,direction:`auto`})}),e.windows.length>1&&(0,C.jsx)(`button`,{type:`button`,title:`Remove these hours on ${e.date}`,"aria-label":`Remove ${e.date} hours ${a+1}`,onClick:()=>n({...e,windows:e.windows.filter((e,t)=>t!==a)}),className:D,children:(0,C.jsx)(l.t,{className:`w-3.5 h-3.5`})})]},a)),e.windows.length<2&&(0,C.jsx)(`button`,{type:`button`,onClick:()=>n({...e,windows:[...e.windows,{from:`14:00`,to:`18:00`}]}),className:`self-start h-6 px-1 text-[11.5px] font-semibold text-foreground/45 hover:text-accent transition-colors cursor-pointer`,children:`+ Add a second stretch`})]})]})}function M({blocked:e,onChange:n,now:i}){let a=r.rn(i?i():new Date),[o,s]=(0,S.useState)(!1),{upcoming:c,past:l}=A(e,a),d=o?[...l,...c]:c,f=(t,r)=>n(e.map(e=>e===t?r:e));return(0,C.jsx)(t.i,{label:`Days away`,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.`,children:(0,C.jsxs)(`div`,{className:`flex flex-col divide-y divide-[var(--panel-border)]/60 rounded-2xl border border-[var(--panel-border)]/60 px-4 py-1`,children:[d.length===0?(0,C.jsx)(`p`,{className:`${t.s} py-3`,children:`No days blocked out. Add one for a holiday or a day off.`}):d.map((t,r)=>(0,C.jsx)(j,{row:t,onChange:e=>f(t,e),onRemove:()=>n(e.filter(e=>e!==t))},`${t.date}-${r}`)),(0,C.jsxs)(`div`,{className:`flex items-center justify-between gap-3 py-2.5`,children:[(0,C.jsx)(t.o,{icon:u.t,compact:!0,title:`Add a day away`,onClick:()=>n([...e,{date:a,windows:[]}]),children:`Add a date`}),l.length>0&&(0,C.jsx)(`button`,{type:`button`,onClick:()=>s(e=>!e),className:`h-6 px-1 text-[11.5px] font-semibold text-foreground/45 hover:text-accent transition-colors cursor-pointer`,children:o?`Hide past dates`:`Show ${l.length} past date${l.length===1?``:`s`}`})]})]})})}var N=e=>r.s.find(t=>t.value===e)?.label||`Short text`;function P({options:e,onChange:n}){return(0,C.jsx)(t.i,{label:`Choices`,hint:`What people pick from.`,children:(0,C.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[e.length===0&&(0,C.jsx)(`span`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug px-1`,children:`No choices yet — add the first one.`}),e.map((r,i)=>(0,C.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,C.jsx)(`input`,{type:`text`,value:r,"aria-label":`Choice ${i+1}`,placeholder:`e.g. At my place`,onChange:t=>n(e.map((e,n)=>n===i?t.target.value:e)),className:t.c}),(0,C.jsx)(t.o,{icon:l.t,tone:`danger`,compact:!0,title:`Remove choice ${i+1}`,onClick:()=>n(e.filter((e,t)=>t!==i)),children:`Remove`})]},i)),(0,C.jsx)(`div`,{children:(0,C.jsx)(t.o,{icon:u.t,onClick:()=>n([...e,``]),children:`Add choice`})})]})})}function F({question:e,index:n,count:a,siblings:o,fixed:s,onChange:c,onMove:l,onRemove:u}){let[f,p]=(0,S.useState)(!e.label.trim()),m=e.label.trim()||`A new question`;return(0,C.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-1.5 sm:gap-2.5 pr-2.5 sm:pr-3.5`,children:[(0,C.jsxs)(`button`,{type:`button`,onClick:()=>p(e=>!e),"aria-expanded":f,className:`flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3.5 text-left cursor-pointer`,children:[(0,C.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:m}),(0,C.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[(0,C.jsx)(`span`,{className:`${t.s} max-sm:hidden`,children:s?`Always asked`:`${N(e.type)}${e.required?` · must be answered`:``}`}),(0,C.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${f?`rotate-180`:``}`})]})]}),!s&&(0,C.jsxs)(`div`,{className:`flex items-center gap-1 sm:gap-1.5 shrink-0`,children:[(0,C.jsx)(t.o,{icon:t.jt,compact:!0,disabled:n===0,title:`Move ${m} up`,onClick:()=>l(-1),children:`Up`}),(0,C.jsx)(t.o,{icon:t.Mt,compact:!0,disabled:n===a-1,title:`Move ${m} down`,onClick:()=>l(1),children:`Down`}),(0,C.jsx)(`span`,{className:`max-sm:hidden w-px h-5 bg-[var(--panel-border)] mx-0.5`}),(0,C.jsx)(t.o,{icon:d.t,tone:`danger`,compact:!0,title:`Remove ${m}`,onClick:u,children:`Remove`})]})]}),f&&(0,C.jsxs)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4`,children:[(0,C.jsx)(t.b,{label:`What are you asking?`,hint:s?`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.`,value:e.label,placeholder:s?`e.g. Who is coming?`:`e.g. What is your phone number?`,onChange:t=>c({...e,label:t,name:s?e.name:r.K(e,t,o)})}),!s&&(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(t.g,{label:`Kind of answer`,hint:`Sets the box they type into. The example below follows what you pick.`,value:e.type,options:r.s,allowEmpty:!1,onChange:t=>c({...e,type:t,options:t===`select`?e.options:[],placeholder:r.W(e,t)})}),(0,C.jsx)(t.S,{label:`Must be answered`,hint:`On means they cannot book until it is filled in.`,hintWideOnly:!0,enabled:e.required,onChange:t=>c({...e,required:t})})]}),e.type===`select`&&(0,C.jsx)(P,{options:e.options,onChange:t=>c({...e,options:t})}),r.G(e.type)&&(0,C.jsx)(t.b,{label:`Example answer`,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.`,value:e.placeholder,placeholder:r.o[e.type]||`e.g. +1 555 0123`,onChange:t=>c({...e,placeholder:t})})]})]})}function I({questions:e,onChange:n}){let i=e.filter(e=>r.ht(e.name)),a=e.filter(e=>!r.ht(e.name)),o=e=>n([...i,...e]);return(0,C.jsx)(t.i,{label:`What does a booking ask for?`,children:(0,C.jsxs)(`div`,{className:`flex flex-col gap-3.5`,children:[i.map(t=>(0,C.jsx)(F,{question:t,index:0,count:1,siblings:e,fixed:!0,onChange:r=>n(e.map(e=>e.name===t.name?r:e)),onMove:()=>{},onRemove:()=>{}},t.name)),a.map((t,n)=>(0,C.jsx)(F,{question:t,index:n,count:a.length,siblings:e,onChange:e=>o(a.map((t,r)=>r===n?e:t)),onMove:e=>{let t=n+e;if(t<0||t>=a.length)return;let r=[...a];[r[n],r[t]]=[r[t],r[n]],o(r)},onRemove:()=>o(a.filter((e,t)=>t!==n))},n)),(0,C.jsxs)(`div`,{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`,children:[(0,C.jsx)(t.o,{icon:u.t,title:`Add a question`,onClick:()=>o([...a,r.j()]),children:`Add a question`}),a.length===0&&(0,C.jsx)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:`Nothing else is asked — just a name and an email.`})]})]})})}var L=(e,t,n=72)=>e>=n&&e<=Math.max(n,t*.45);function R(e,t=340){if(!e)return null;let n=()=>{let t=e.getBoundingClientRect?.(),n=typeof window<`u`&&window.innerHeight||0;t&&n&&L(t.top,n)||e.scrollIntoView?.({behavior:`smooth`,block:`start`})};return typeof setTimeout==`function`?setTimeout(n,t):(n(),null)}function z(e,t,n){let r=(0,S.useRef)(new Set);(0,S.useEffect)(()=>{let i=new Set(e),a=[...r.current].filter(e=>!i.has(e)&&!n.current.has(e));e.forEach(e=>r.current.add(e)),a.length&&(a.forEach(e=>r.current.delete(e)),t(e=>{if(!a.some(t=>t in e))return e;let t={...e};for(let e of a)delete t[e];return t}))},[e.join(`\0`)])}var B=`__new_payment__`;function V(){let[e,n]=(0,S.useState)([]);return(0,S.useEffect)(()=>{let e=t.Zr(t.Qn,()=>(0,w.collection)(t.ui,t.Qn),e=>{let r=[];e.forEach(e=>{e.id!==`_settings`&&r.push(t.Dr(e.id,e.data()))}),n(r.filter(e=>e.kind===`once`).sort((e,t)=>(e.createdAt||0)-(t.createdAt||0)))},()=>n([]));return()=>e()},[]),e}function H({value:e,products:n,meetingName:r,canCreate:i,onChange:a,onCreate:o}){let[s,c]=(0,S.useState)(!1),[l,d]=(0,S.useState)(``),[f,p]=(0,S.useState)(``),[m,h]=(0,S.useState)(!1),g=[...n.map(e=>({value:e.id,label:`${t.xr(e)} — ${t.gr(e).map(e=>e.amount).filter(Boolean).join(` + `)||`no price yet`}`})),...i?[{value:B,label:`+ A new one-time payment`}]:[]],_=n.find(t=>t.id===e),v=l.trim()&&t.br(l)===null?`Just a number, like 25.`:void 0;return(0,C.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,C.jsx)(t.g,{label:`Payment for this meeting`,hint:_?`Taken on the booking page before the time is confirmed. Its price and its link are on the Payments screen.`:i?`Optional. A one-time payment taken on the booking page before the time is confirmed.`:n.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.`,value:s?B:e,placeholder:`No payment`,options:g,onChange:e=>{if(e===`__new_payment__`){c(!0);return}c(!1),a(e)}}),s&&(0,C.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]/60 px-4 py-3.5 flex flex-col gap-3`,children:[(0,C.jsx)(t.b,{label:`The price`,hint:`Just the number — 25 charges 25 in your Stripe account's currency. The payment is called ${r} and appears on the Payments screen too.`,value:l,onChange:e=>{d(e),f&&p(``)},placeholder:`25`,error:f||v}),(0,C.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,C.jsx)(t.o,{icon:u.t,busy:m,onClick:async()=>{if(t.br(l)===null){p(`Just a number for the price, like 25.`);return}p(``),h(!0);let e=await o(r,l.trim());if(h(!1),e){p(e);return}c(!1),d(``)},children:`Create it`}),(0,C.jsx)(t.o,{onClick:()=>{c(!1),p(``),d(``)},children:`Never mind`})]})]})]})}function U({link:e,onChange:n}){return(0,C.jsx)(t.i,{label:`Emails about bookings`,hint:`Sent the moment a time is taken. Every booking is in your Inbox and on the calendar regardless.`,children:(0,C.jsxs)(`div`,{className:`flex flex-col gap-3 rounded-2xl border border-[var(--panel-border)]/60 px-4 py-3.5`,children:[(0,C.jsx)(t.S,{label:`Email me when someone books`,hint:`A note at your address — the sale alert, when they paid.`,hintWideOnly:!0,enabled:e.notifyOwner,onChange:e=>n({notifyOwner:e})}),(0,C.jsx)(t.S,{label:`Email them a confirmation`,hint:`Their receipt when they pay. For a free booking, a note that the time is theirs — to people who book signed in.`,hintWideOnly:!0,enabled:e.confirmBooker,onChange:e=>n({confirmBooker:e})})]})})}var ee=e=>{let t={...a.I(a.H(),e),createdAt:Date.now()};return{...t,name:r.O(t),description:r.D(t)}};function te({link:e,schedules:n,products:i,services:o,isAdmin:s=!0,onChange:c,onCreatePayment:l}){let u=n.find(t=>t.id===e.scheduleId),d=t=>c({...e,...t}),f=a.z(e,u),p=u?a.L(e,u):null,m=t=>{let n={...e,...t};return{...t,...e.name.trim()===r.O(e)?{name:r.O(n)}:{},...e.description.trim()===r.D(e)?{description:r.D(n)}:{}}};return(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(t.g,{label:`Which hours is it booked in?`,hint:`Change the hours and every meeting booked in them changes with it — one holiday, entered once, closes them all.`,value:e.scheduleId,options:n.map(e=>({value:e.id,label:r.ut(e)})),allowEmpty:!1,onChange:t=>{let r=n.find(e=>e.id===t);if(!r)return;let i=!u||e.memberName.trim()===u.memberName.trim();d(m({scheduleId:r.id,memberId:r.memberId,...i?{memberName:r.memberName}:{}}))}}),(0,C.jsx)(t.b,{label:`What is it called?`,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 ${r.O(e)}.`,value:e.name,onChange:e=>d({name:e}),placeholder:r.O(e)}),(0,C.jsx)(t.y,{label:`A line or two about it`,hint:`Visitors read it under the name — what it is for, what to bring, what happens after. Emptied, the booking page simply shows none.`,value:e.description,onChange:e=>d({description:e}),placeholder:`A first conversation about what you need and how I can help.`}),(0,C.jsx)(t.b,{label:`The name visitors see`,value:e.memberName,onChange:e=>d(m({memberName:e})),placeholder:`Anna`}),(0,C.jsx)(t.g,{label:`How long is one booking?`,value:String(e.slotMinutes),options:r.b,allowEmpty:!1,onChange:e=>d(m({slotMinutes:Number(e)}))}),(0,C.jsx)(t.g,{label:`How far ahead can people book?`,value:String(e.horizonDays),options:r.h,allowEmpty:!1,onChange:e=>d({horizonDays:Number(e)})}),(0,C.jsx)(t.g,{label:`How much notice do you need?`,value:String(e.noticeHours),options:r._,allowEmpty:!1,onChange:e=>d({noticeHours:Number(e)})}),(0,C.jsx)(I,{questions:e.questions,onChange:e=>d({questions:e})}),(0,C.jsx)(b.t,{service:`payments`,readiness:b.n(o.payments),children:(0,C.jsx)(H,{value:e.paymentId,products:i,meetingName:a.V(e),canCreate:s,onChange:e=>d({paymentId:e}),onCreate:async(e,t)=>{let n=await l(e,t);return n&&n.startsWith(`p_`)?(d({paymentId:n}),null):n||`The payment could not be made — make sure you are signed in as an admin and try again.`}})}),(0,C.jsx)(b.t,{service:`email`,readiness:b.n(o.email),children:(0,C.jsx)(U,{link:e,onChange:d})}),(0,C.jsx)(t.i,{label:`Booking link`,hint:p&&!f&&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.`,children:(0,C.jsx)(x.t,{title:a.V(e),path:r.U(e.id)})}),(0,C.jsx)(`div`,{className:`pt-1`,children:f?e.enabled?(0,C.jsxs)(`span`,{className:`text-[11.5px] font-semibold text-amber-500`,children:[`Turned on, but not bookable yet — `,f]}):(0,C.jsx)(`span`,{className:t.s,children:f}):e.enabled?(0,C.jsx)(`span`,{className:`text-[11.5px] font-semibold text-emerald-500`,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.`}):(0,C.jsx)(`span`,{className:t.s,children:`Complete — flip the switch at the top of the row to offer it.`})})]})}function W({link:e,schedules:n,products:r,services:o,isAdmin:s=!0,open:c,fresh:l,error:u,onToggle:f,onChange:p,onRemove:m,onCreatePayment:g}){let _=n.find(t=>t.id===e.scheduleId),v=a.R(e,_),[y,b]=(0,S.useState)(!1),x=a.V(e),w=(0,S.useRef)(null);return(0,S.useEffect)(()=>{if(!l)return;let e=R(w.current);return()=>{e&&clearTimeout(e)}},[l]),(0,C.jsxs)(`div`,{ref:w,className:`scroll-mt-4 rounded-2xl border border-[var(--panel-border)]`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-2 sm:gap-2.5 pr-3`,children:[(0,C.jsxs)(`button`,{type:`button`,onClick:f,"aria-expanded":c,className:`flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer`,children:[(0,C.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:a.B(e,_)}),(0,C.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[(0,C.jsx)(`span`,{className:`max-sm:hidden`,children:(0,C.jsx)(t._,{state:v.state,label:v.label})}),(0,C.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${c?`rotate-180`:``}`})]})]}),(0,C.jsx)(t.x,{enabled:e.enabled,onChange:t=>p({...e,enabled:t}),label:`${x} — can be booked`}),(0,C.jsx)(t.o,{icon:d.t,tone:`danger`,compact:!0,title:`Remove ${x}`,onClick:()=>b(!0),children:`Remove`})]}),(0,C.jsx)(h.t,{isOpen:y,title:`Remove ${x}?`,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.`,confirmText:`Yes, remove`,cancelText:`Keep it`,onCancel:()=>b(!1),onConfirm:()=>{b(!1),m()}}),c&&(0,C.jsx)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4`,children:(0,C.jsx)(te,{link:e,schedules:n,products:r,services:o,isAdmin:s,onChange:p,onCreatePayment:g})}),u&&(0,C.jsx)(`p`,{className:`text-[12px] font-semibold text-red-500 px-4 pb-3`,children:u})]})}function G({isAdmin:e=!0}={}){let{user:n}=t.Ft(),{loading:i,docs:o}=a.S(),s=V(),l={payments:y.r(`payments`),email:y.r(`email`)},[d,f]=(0,S.useState)({}),[p,m]=(0,S.useState)([]),[h,g]=(0,S.useState)(null),[_,v]=(0,S.useState)(null),[b,x]=(0,S.useState)({}),T=(0,S.useRef)(new Map);z(o.links.map(e=>e.id),f,T);let E=n?.uid||``,D=(0,S.useMemo)(()=>[...e?o.schedules:o.schedules.filter(e=>e.memberId===E)].sort((e,t)=>Number(t.memberId===E)-Number(e.memberId===E)),[o.schedules,e,E]),O=(0,S.useMemo)(()=>{let t=new Map(o.links.map(e=>[e.id,e]));for(let e of Object.values(d))t.set(e.id,e);for(let e of p)t.delete(e);return[...t.values()].filter(t=>e||t.memberId===E).sort((e,t)=>Number(t.memberId===E)-Number(e.memberId===E)||(e.createdAt||0)-(t.createdAt||0)||e.id.localeCompare(t.id))},[o.links,d,p,e,E]),k=e=>{let t=T.current.get(e.id);t&&clearTimeout(t),T.current.set(e.id,setTimeout(async()=>{T.current.delete(e.id);let t=await a.f(e);x(n=>{let r={...n};return t?r[e.id]=t:delete r[e.id],r})},600))},A=e=>{f(t=>({...t,[e.id]:e})),k(e)},j=()=>{let e=D.find(e=>e.memberId===E)||D[0];if(!e)return;let t=ee(e);f(e=>({...e,[t.id]:t})),g(t.id),v(t.id),k(t)},M=async e=>{let t=T.current.get(e);t&&(clearTimeout(t),T.current.delete(e)),f(t=>{let n={...t};return delete n[e],n}),m(t=>[...t,e]),h===e&&g(null);let n=await a.u(e);n&&(m(t=>t.filter(t=>t!==e)),x(t=>({...t,[e]:n})))},N=async(e,n)=>{let r={...t.cr(`p_${Date.now().toString(36)}`),kind:`once`,items:[{name:e,amount:n}]};try{let{id:e,...n}=r;return await(0,w.setDoc)((0,w.doc)(t.ui,t.Qn,e),n),e}catch(e){return console.error(`Could not make the payment`,e),null}};return(0,C.jsx)(t.m,{icon:c.t,title:`Booking links`,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.`,actions:!i&&D.length>0?({open:e})=>(0,C.jsx)(t.o,{icon:u.t,compact:!0,title:`Add a booking link`,onClick:()=>{e(),j()},children:`Add a booking link`}):void 0,children:(0,C.jsx)(`div`,{className:`flex flex-col gap-3`,children:i?(0,C.jsx)(`p`,{className:t.s,children:`Loading your booking links…`}):D.length===0?(0,C.jsx)(`p`,{className:`${t.s} px-1`,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.`}):O.length===0?(0,C.jsxs)(`p`,{className:`${t.s} px-1`,children:[`No booking link yet — press Add a booking link. It is what turns `,r.dt(D[0]),` into something people can book.`]}):O.map(t=>(0,C.jsx)(W,{link:t,schedules:D,products:s,services:l,isAdmin:e,open:h===t.id,fresh:_===t.id,error:b[t.id],onToggle:()=>g(h===t.id?null:t.id),onChange:A,onRemove:()=>M(t.id),onCreatePayment:N},t.id))})})}var K=`team`,ne=e=>`m:${e}`,re=`__nobody__`;function ie(e,t,n){return[{value:`me`,label:`My calendar`},{value:K,label:`My team's calendar`},...e.filter(e=>e.id!==n).map(e=>({value:ne(e.id),label:a.g(e)||e.email,disabled:!t.has(e.id)}))]}var q=e=>e.startsWith(`m:`)?e.slice(2):``;function J(e,t,n,i=``){if(!e.email)return Promise.resolve();let a=r.Zt(e,e.timeZone||n);return p.i(t,r.t,e.id,{when:`${a.day}, ${a.time}`,memberName:e.memberName,scheduleName:e.scheduleName,reason:i.trim()}).then(()=>{}).catch(()=>{})}function ae(e,t,n){let r=e=>[...new Set(e.map(e=>String(e||``).trim()))].filter(e=>e&&e!==n),i=r([e.memberId,...t.map(e=>e.memberId),...e.copyIds.map(e=>e.split(`__`)[0])]);return{members:i,bookers:r([e.uid,...t.map(e=>e.uid)]).filter(e=>e!==`guest`).filter(e=>!i.includes(e))}}async function oe(e,t,n,i){if(e.own||e.heldOnly)return;let a={title:`Meeting removed`,body:`${r.B(e)} · ${r.ot(new Date(e.start),i)}`};await J(e,`booking_cancelled`,i,`The meeting was removed from the calendar.`);let{members:o,bookers:s}=ae(e,t,n);await m.r(o,{...a,link:`/schedule`}),await m.r(s,{...a,link:`/my-bookings`})}var Y=e=>{try{return localStorage.getItem(`fbos_calendar_had_${e}`)===`1`}catch{return!1}};function se(){let{user:e}=t.Ft();return Y(e?.uid||``)?(0,C.jsx)(f.n,{className:`h-[420px] w-full`}):null}function X({isAdmin:e}){let{user:n}=t.Ft(),i=n?.uid||``,c=r.et(),[l,u]=(0,T.useSearchParams)(),d=l.get(`open`)||l.get(`booking`)||``,{schedules:p}=a.w(),{members:m}=a.T(),h=(0,S.useMemo)(()=>new Set(p.map(e=>e.memberId)),[p]),g=(0,S.useMemo)(()=>ie(m,h,i),[m,h,i]),[_,v]=(0,S.useState)(null);(0,S.useEffect)(()=>{d&&e&&v(e=>e??`team`)},[d,e]);let y=_??`me`,b=new Set(g.filter(e=>!e.disabled).map(e=>e.value)).has(y)?y:`me`,x=q(b),{loading:w,bookings:E,error:D}=a.v({members:b===`team`?void 0:[x||i||re],includePast:!0}),O=(0,S.useMemo)(()=>a.P(E),[E]),k=(0,S.useMemo)(()=>E.map(e=>{let t=O.get(e.id);return t?{...e,...t}:e}),[E,O]),{paid:A,checkouts:j}=s.t(k),M=a.C((0,S.useMemo)(()=>(b===`team`?m.map(e=>e.id):[x||i]).filter(Boolean),[b,m,x,i]),(0,S.useMemo)(()=>{let e=new Date;return new Date(Date.UTC(e.getUTCFullYear(),e.getUTCMonth()-1,1))},[]),{keepOpen:!0}),[N,P]=(0,S.useState)(()=>Date.now());(0,S.useEffect)(()=>{let e=setInterval(()=>P(Date.now()),6e4);return()=>clearInterval(e)},[]);let F=(0,S.useMemo)(()=>{let e=new Set(M.filter(e=>!e.open).map(e=>r.qt(e.memberId,e.start))),t=k.map(t=>a.M(t,j[t.id],e,N)),n=e=>{let t=m.find(t=>t.id===e);return p.find(t=>t.memberId===e)?.memberName||(t?a.g(t):``)},i=a.F(M,E,N).map(e=>a.N(e,n(e.memberId)));return i.length?[...t,...i]:t},[E,k,M,N,m,p,j]);(0,S.useEffect)(()=>{if(!(w||!i))try{localStorage.setItem(`fbos_calendar_had_${i}`,F.length?`1`:`0`)}catch{}},[w,i,F.length]);let I=x||i,L=m.find(e=>e.id===I),R=p.find(e=>e.memberId===I)?.memberName||(L?a.g(L):``)||(I===i?String(n?.displayName||``):``);return w&&F.length===0?Y(i)?(0,C.jsx)(f.n,{className:`h-[420px] w-full`}):null:F.length===0?null:(0,C.jsx)(t.m,{icon:o.d,title:`Calendar`,description:b===`team`?`Every booking made with your team, and the events they put on their own days — in your time, ${r.nn(c)}.`:x?`${R||`Their`} calendar, read as they read it — in your time, ${r.nn(c)}.`:`Every booking made with you, under every schedule of yours — in your time, ${r.nn(c)}.`,actions:e&&g.length>2?(0,C.jsx)(t.Z,{ariaLabel:`Whose calendar`,value:b,options:g,onChange:v,className:`console-select`,compact:!0,dense:!0,portal:!0,direction:`auto`}):void 0,children:w?(0,C.jsx)(`p`,{className:t.s,children:`Loading the calendar…`}):D?(0,C.jsx)(`p`,{className:`text-[12px] font-semibold text-red-500 px-1`,children:D}):(0,C.jsx)(s.n,{bookings:F,zone:c,paid:A,openBookingId:d||void 0,onOpened:d?()=>u(e=>(e.delete(`open`),e.delete(`booking`),e),{replace:!0}):void 0,withMember:b===K,me:i,onAccept:async e=>{let t=await a.t(e.id);return t||J(e,`booking_confirmed`,c),t},onCancel:async(e,t)=>{let r=await a.r(e.id,{ids:e.copyIds,reason:t,side:`host`,by:e.memberId===i?R||String(n?.displayName||``):e.memberName,byUid:i});return r||J(e,`booking_cancelled`,c,t),r},onDelete:async e=>(await oe(e,E,i,c),a.a(e.id,e.copyIds)),canDelete:t=>e||t.own&&t.memberId===i,onRelease:e=>a.c(e.memberId,e.start),onColor:a.m,onAdd:b===`team`?void 0:e=>a.n({...e,memberId:I,memberName:R,timeZone:c})})})}function ce(e,t){if(!e.enabled)return{state:`off`,label:`Off`};if(g.c(e,t))return{state:`error`,label:`Unfinished`};let n=e.schedules.length;return{state:`saved`,label:n===1?`1 meeting`:`${n} meetings`}}var le=e=>{let t=e.schedules.length;return`${g.s(e)} — ${t===0?`nothing on it yet`:t===1?`1 meeting`:`${t} meetings`}`};function Z({page:e,schedules:n,onChange:i}){return n.length?(0,C.jsx)(t.i,{label:`Meetings on this page`,hint:`They appear in the order you tick them. A meeting switched off above is kept off the page too.`,children:(0,C.jsx)(`div`,{className:`flex flex-col gap-1.5`,children:n.map(t=>{let n=e.schedules.includes(t.id);return(0,C.jsxs)(`button`,{type:`button`,role:`checkbox`,"aria-checked":n,onClick:()=>i(g.p(e,t.id)),className:`flex items-center gap-3 px-3 py-2.5 rounded-xl border text-left transition-all cursor-pointer active:scale-[0.995] ${n?`border-accent/45 bg-accent/[0.07]`:`border-[var(--panel-border)]/70 hover:border-accent/30 hover:bg-foreground/[0.03]`}`,children:[(0,C.jsx)(`span`,{"aria-hidden":!0,className:`w-[18px] h-[18px] rounded-[5px] border flex items-center justify-center shrink-0 transition-all ${n?`border-accent bg-accent`:`border-foreground/25`}`,children:n&&(0,C.jsx)(`span`,{className:`w-[7px] h-[7px] rounded-[2px] bg-[var(--button-fg,#fff)]`})}),(0,C.jsx)(`span`,{className:`flex-1 min-w-0 text-[13px] font-semibold text-foreground/80 truncate`,children:r.Bt(t)})]},t.id)})})}):(0,C.jsx)(t.i,{label:`Meetings on this page`,children:(0,C.jsx)(`p`,{className:`${t.s} px-1`,children:`Make a schedule above first — a page offers the meetings you have set up.`})})}function ue({page:e,taken:n,onRename:r}){let[i,a]=(0,S.useState)(e.id),o=g.f(i),s=!!o&&o!==e.id&&n.includes(o);return(0,C.jsx)(t.b,{label:`Its address`,prefix:`/meet/`,value:i,onChange:a,onBlur:()=>{if(!o||s||o===e.id){a(e.id);return}r(o)},placeholder:`anna-bell`,error:s?`Another page already has that address.`:void 0,hint:`Change it and the old link stops working, so change it before you send it out.`})}function de({page:n,schedules:r,taken:a,open:o,fresh:s,error:c,onToggle:l,onChange:u,onRename:f,onRemove:p}){let[m,_]=(0,S.useState)(!1),v=ce(n,r),y=g.s(n),b=g.c(n,r),w=(0,S.useRef)(null);return(0,S.useEffect)(()=>{if(!s)return;let e=R(w.current);return()=>{e&&clearTimeout(e)}},[s]),(0,C.jsxs)(`div`,{ref:w,className:`scroll-mt-4 rounded-2xl border border-[var(--panel-border)]`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-2 sm:gap-2.5 pr-3`,children:[(0,C.jsxs)(`button`,{type:`button`,onClick:l,"aria-expanded":o,className:`flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer`,children:[(0,C.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:le(n)}),(0,C.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[(0,C.jsx)(`span`,{className:`max-sm:hidden`,children:(0,C.jsx)(t._,{state:v.state,label:v.label})}),(0,C.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${o?`rotate-180`:``}`})]})]}),(0,C.jsx)(t.x,{enabled:n.enabled,onChange:e=>u({...n,enabled:e}),label:`${y} — page is live`}),(0,C.jsx)(t.o,{icon:d.t,tone:`danger`,compact:!0,title:`Remove ${y}`,onClick:()=>_(!0),children:`Remove`})]}),(0,C.jsx)(h.t,{isOpen:m,title:`Remove ${y}?`,message:`Its link stops working. The meetings on it are untouched and keep their own links, and bookings already taken are kept.`,confirmText:`Yes, remove`,cancelText:`Keep it`,onCancel:()=>_(!1),onConfirm:()=>{_(!1),p()}}),o&&(0,C.jsxs)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4`,children:[(0,C.jsx)(t.b,{label:`Name on the page`,value:n.title,onChange:e=>u({...n,title:e}),placeholder:`Anna Bell`,hint:`Usually the name of whoever the page is for.`}),(0,C.jsx)(e.a,{label:`Photo`,hint:`Shown at the top of the page. A square picture of the person works best.`,value:n.photo,onChange:e=>u({...n,photo:e})}),(0,C.jsx)(t.y,{label:`About this page`,value:n.intro,onChange:e=>u({...n,intro:e}),rows:3,placeholder:`I help small studios get their bookkeeping straight. Pick a time below and tell me what you need.`}),(0,C.jsx)(Z,{page:n,schedules:r,onChange:u}),(0,C.jsx)(ue,{page:n,taken:a,onRename:f}),b?(0,C.jsx)(`p`,{className:`text-[12px] font-semibold text-amber-500 px-1`,children:b}):(0,C.jsx)(x.t,{title:y,path:g.l(n.id)})]}),c&&(0,C.jsx)(`p`,{className:`text-[12px] font-semibold text-red-500 px-4 pb-3`,children:c})]})}function fe({schedules:e,myName:n,isAdmin:r=!0,meId:i=``}){let{loading:a,pages:o}=g.i(),[s,l]=(0,S.useState)({}),[d,f]=(0,S.useState)([]),[p,m]=(0,S.useState)(null),[h,_]=(0,S.useState)(null),[v,y]=(0,S.useState)({}),b=(0,S.useRef)(new Map);z(o.map(e=>e.id),l,b);let x=new Map(o.map(e=>[e.id,e]));for(let e of Object.values(s))x.set(e.id,e);for(let e of d)x.delete(e);let w=[...x.values()].sort((e,t)=>(e.createdAt||0)-(t.createdAt||0)||e.id.localeCompare(t.id)),T=w.map(e=>e.id),E=g.u(w,i,r),D=r?e:e.filter(e=>e.memberId===i),O=e=>{let t=b.current.get(e.id);t&&clearTimeout(t),b.current.set(e.id,setTimeout(async()=>{b.current.delete(e.id);let t=await g.r(e);y(n=>{let r={...n};return t?r[e.id]=t:delete r[e.id],r})},600))},k=e=>{l(t=>({...t,[e.id]:e})),O(e)},A=()=>{let e=g.a(g.m(n||`my page`,T),n,i);l(t=>({...t,[e.id]:e})),f(t=>t.filter(t=>t!==e.id)),m(e.id),_(e.id),O(e)},j=async(e,t)=>{let n=b.current.get(e.id);n&&(clearTimeout(n),b.current.delete(e.id));let r={...e,id:t};l(n=>{let i={...n};return delete i[e.id],i[t]=r,i}),f(n=>[...n.filter(e=>e!==t),e.id]),p===e.id&&m(t);let i=await g.n(e.id,r);i&&y(e=>({...e,[t]:i}))},M=async e=>{let t=b.current.get(e);t&&(clearTimeout(t),b.current.delete(e)),l(t=>{let n={...t};return delete n[e],n}),f(t=>[...t,e]),p===e&&m(null);let n=await g.t(e);n&&(f(t=>t.filter(t=>t!==e)),y(t=>({...t,[e]:n})))};return(0,C.jsx)(t.m,{icon:c.t,title:`Your booking pages`,description:`One link with a photo, a line about you and every meeting you offer.`,actions:({open:e})=>(0,C.jsx)(t.o,{icon:u.t,compact:!0,title:`Create a page`,onClick:()=>{e(),A()},children:`Create a page`}),children:(0,C.jsx)(`div`,{className:`flex flex-col gap-3`,children:a?(0,C.jsx)(`p`,{className:`${t.s} px-1`,children:`Loading pages…`}):E.length===0?(0,C.jsx)(`p`,{className:`${t.s} px-1`,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.`}):E.map(e=>(0,C.jsx)(de,{page:e,schedules:D,taken:T,open:p===e.id,fresh:h===e.id,error:v[e.id],onToggle:()=>m(t=>t===e.id?null:e.id),onChange:k,onRename:t=>j(e,t),onRemove:()=>M(e.id)},e.id))})})}var pe={from:`09:00`,to:`17:00`},me=e=>r.pt(e)?{state:`saved`,label:`Ready`}:{state:`off`,label:`In progress`},he=e=>({...r.M(a.U(),e.id,a.g(e),r.et()),name:`Working hours`,enabled:!0,createdAt:Date.now()}),Q=`w-[6.5rem] shrink-0`,ge=`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`;function _e({day:e,windows:n,onChange:i}){let a=n.length>0,o=(e,t)=>i(n.map((n,r)=>r===e?{...n,...t}:n));return(0,C.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-[8.5rem_minmax(0,1fr)] items-start gap-x-4 gap-y-2 py-2.5`,children:[(0,C.jsxs)(`div`,{className:`flex items-center justify-between gap-3 h-9`,children:[(0,C.jsx)(`span`,{className:`text-[13px] font-medium ${a?`text-foreground/80`:`text-foreground/40`}`,children:r.u[e]}),(0,C.jsx)(t.x,{enabled:a,onChange:e=>i(e?[pe]:[]),label:`${r.u[e]} — bookable`})]}),a&&(0,C.jsxs)(`div`,{className:`flex flex-col gap-2 min-w-0`,children:[n.map((a,s)=>(0,C.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,C.jsx)(`div`,{className:Q,children:(0,C.jsx)(t.Z,{ariaLabel:`${r.u[e]} from${s?` (${s+1})`:``}`,value:a.from,options:r.m,onChange:e=>o(s,{from:e}),className:`console-select`,compact:!0,portal:!0,direction:`auto`})}),(0,C.jsx)(`span`,{className:`w-3 text-center text-foreground/40 text-[13px] shrink-0 select-none`,children:`–`}),(0,C.jsx)(`div`,{className:Q,children:(0,C.jsx)(t.Z,{ariaLabel:`${r.u[e]} to${s?` (${s+1})`:``}`,value:a.to,options:r.d,onChange:e=>o(s,{to:e}),className:`console-select`,compact:!0,portal:!0,direction:`auto`})}),n.length>1&&(0,C.jsx)(`button`,{type:`button`,title:`Remove these hours on ${r.u[e]}`,"aria-label":`Remove ${r.u[e]} hours ${s+1}`,onClick:()=>i(n.filter((e,t)=>t!==s)),className:ge,children:(0,C.jsx)(l.t,{className:`w-3.5 h-3.5`})})]},s)),n.length<2&&(0,C.jsx)(`button`,{type:`button`,onClick:()=>i([...n,{from:`18:00`,to:`20:00`}]),className:`self-start h-6 px-1 text-[11.5px] font-semibold text-foreground/45 hover:text-accent transition-colors cursor-pointer`,children:`+ Add a second stretch`})]})]})}function ve({schedule:e,onChange:n}){let i=t=>n({...e,...t}),a=r.ft(e);return(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(t.b,{label:`What are these hours called?`,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.`,value:e.name,onChange:e=>i({name:e}),placeholder:`Working hours`}),(0,C.jsx)(t.t,{value:e.timeZone,onChange:e=>i({timeZone:e})}),(0,C.jsx)(t.i,{label:`When`,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.`,children:(0,C.jsx)(`div`,{className:`flex flex-col divide-y divide-[var(--panel-border)]/60 rounded-2xl border border-[var(--panel-border)]/60 px-4 py-1`,children:r.l.map(t=>(0,C.jsx)(_e,{day:t,windows:e.days[t]||[],onChange:n=>i({days:{...e.days,[t]:n}})},t))})}),(0,C.jsx)(M,{blocked:e.blocked,onChange:e=>i({blocked:e})}),(0,C.jsx)(`div`,{className:`pt-1`,children:a?(0,C.jsxs)(`span`,{className:`text-[11.5px] font-semibold text-amber-500`,children:[`Not usable yet — `,a]}):(0,C.jsx)(`span`,{className:`text-[11.5px] font-semibold text-emerald-500`,children:`Ready — add a booking link below to let people book these hours, or ask for a page built on them.`})})]})}function $({schedule:e,open:n,stale:a,fresh:o,error:s,onToggle:c,onChange:l,onRemove:u}){let f=me(e),[p,m]=(0,S.useState)(!1),g=r.dt(e),_=(0,S.useRef)(null);return(0,S.useEffect)(()=>{if(!o)return;let e=R(_.current);return()=>{e&&clearTimeout(e)}},[o]),(0,C.jsxs)(`div`,{ref:_,className:`scroll-mt-4 rounded-2xl border border-[var(--panel-border)] ${a?`opacity-60`:``}`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-2 sm:gap-2.5 pr-3`,children:[(0,C.jsxs)(`button`,{type:`button`,onClick:c,"aria-expanded":n,className:`flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer`,children:[(0,C.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:r.mt(e)}),(0,C.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[a?(0,C.jsx)(`span`,{className:`${t.s} max-sm:hidden`,children:`No longer on the team`}):(0,C.jsx)(`span`,{className:`max-sm:hidden`,children:(0,C.jsx)(t._,{state:f.state,label:f.label})}),(0,C.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${n?`rotate-180`:``}`})]})]}),(0,C.jsx)(t.o,{icon:d.t,tone:`danger`,compact:!0,title:`Remove ${g}`,onClick:()=>m(!0),children:`Remove`})]}),(0,C.jsx)(h.t,{isOpen:p,title:`Remove ${g}?`,message:a?`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.`,confirmText:`Yes, remove`,cancelText:`Keep it`,onCancel:()=>m(!1),onConfirm:()=>{m(!1),u()}}),n&&(0,C.jsx)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4`,children:(0,C.jsx)(ve,{schedule:e,onChange:l})}),s&&(0,C.jsx)(`p`,{className:`text-[12px] font-semibold text-red-500 px-4 pb-3`,children:s})]})}function ye({name:e,schedules:n,stale:r,open:a,onToggle:o,onAdd:s,openScheduleId:c,freshId:l,errors:d,onToggleSchedule:f,onChange:p,onRemove:m}){let h=r?`No longer on the team`:n.length===0?`No schedules yet`:`${n.length} schedule${n.length===1?``:`s`}`,g=(0,S.useRef)(null);return(0,S.useEffect)(()=>{if(!a)return;let e=R(g.current);return()=>{e&&clearTimeout(e)}},[a]),(0,C.jsxs)(`div`,{ref:g,className:`scroll-mt-4 rounded-2xl border border-[var(--panel-border)]`,children:[(0,C.jsxs)(`button`,{type:`button`,onClick:o,"aria-expanded":a,className:`w-full flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer`,children:[(0,C.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:e}),(0,C.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[(0,C.jsx)(`span`,{className:`${t.s} max-sm:hidden`,children:h}),(0,C.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${a?`rotate-180`:``}`})]})]}),a&&(0,C.jsxs)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-3`,children:[n.map(e=>(0,C.jsx)($,{schedule:e,stale:r,fresh:l===e.id,open:c===e.id,error:d[e.id],onToggle:()=>f(e.id),onChange:p,onRemove:()=>m(e.id)},e.id)),r?n.length===0&&(0,C.jsxs)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:[`No schedule yet for `,e,`.`]}):(0,C.jsxs)(`div`,{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`,children:[(0,C.jsx)(t.o,{icon:u.t,title:`Add a schedule for ${e}`,onClick:s,children:`Add a schedule`}),n.length===0&&(0,C.jsxs)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:[`No schedule yet for `,e,`.`]})]})]})]})}var be=e=>({id:e.uid,name:String(e.displayName||``),email:String(e.email||``),role:`admin`});function xe({isAdmin:e=!0}={}){let{user:r}=t.Ft(),{loading:i,members:o}=a.T(),{loading:s,docs:c}=a.S(),l=c.schedules,[d,f]=(0,S.useState)({}),[p,m]=(0,S.useState)([]),[h,g]=(0,S.useState)(null),[_,v]=(0,S.useState)(null),[y,b]=(0,S.useState)(null),[x,w]=(0,S.useState)({}),E=(0,S.useRef)(new Map);z(l.map(e=>e.id),f,E);let D=(0,S.useMemo)(()=>{let e=new Map(l.map(e=>[e.id,e]));for(let t of Object.values(d))e.set(t.id,t);for(let t of p)e.delete(t);return[...e.values()].sort((e,t)=>(e.createdAt||0)-(t.createdAt||0)||e.id.localeCompare(t.id))},[l,d,p]),O=e=>{let t=E.current.get(e.id);t&&clearTimeout(t),E.current.set(e.id,setTimeout(async()=>{E.current.delete(e.id);let t=await a.p(e);w(n=>{let r={...n};return t?r[e.id]=t:delete r[e.id],r})},600))},k=e=>{f(t=>({...t,[e.id]:e})),O(e)},A=(0,S.useMemo)(()=>r?o.find(e=>e.id===r.uid)||be(r):null,[r,o]),j=(0,S.useMemo)(()=>A&&!o.some(e=>e.id===A.id)?[A,...o]:o,[A,o]),M=(0,S.useRef)(!1),[N,P]=(0,S.useState)(``),F=(0,S.useMemo)(()=>c.schedules.filter(t=>c.legacyIds.includes(t.id)&&(e||t.memberId===A?.id)),[c.schedules,c.legacyIds,e,A]);(0,S.useEffect)(()=>{M.current||F.length===0||(M.current=!0,a.h(F).then(e=>{e&&P(e)}))},[F]);let I=e=>{let t=he(e);f(e=>({...e,[t.id]:t})),g(t.id),v(t.id),A&&e.id!==A.id&&b(e.id),O(t)},L=()=>{A&&I(A)},R=async e=>{let t=E.current.get(e);t&&(clearTimeout(t),E.current.delete(e)),f(t=>{let n={...t};return delete n[e],n}),m(t=>[...t,e]),h===e&&g(null);let n=await a.d(e);n&&(m(t=>t.filter(t=>t!==e)),w(t=>({...t,[e]:n})))},B=i||s,V=new Set(j.map(e=>e.id)),H=A?D.filter(e=>e.memberId===A.id):[],U=(0,S.useMemo)(()=>{if(!A)return[];let e=new Map;for(let t of D){if(t.memberId===A.id)continue;let n=e.get(t.memberId);n?n.push(t):e.set(t.memberId,[t])}let t=[];for(let n of j)n.id!==A.id&&(t.push({id:n.id,name:a.g(n)||n.email,stale:!1,schedules:e.get(n.id)||[]}),e.delete(n.id));for(let[n,r]of e)t.push({id:n,name:r[0].memberName.trim()||`Someone no longer on the team`,stale:!0,schedules:r});return t},[D,j,A]);return(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(t.m,{icon:n.C,title:`Your schedules`,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.`,actions:B?void 0:({open:e})=>(0,C.jsx)(t.o,{icon:u.t,compact:!0,title:`Add a schedule`,onClick:()=>{e(),L()},children:`Add a schedule`}),children:(0,C.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[B?(0,C.jsx)(`p`,{className:t.s,children:`Loading your schedules…`}):H.length===0?(0,C.jsx)(`p`,{className:`${t.s} px-1`,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.`}):H.map(e=>(0,C.jsx)($,{schedule:e,stale:!V.has(e.memberId),fresh:_===e.id,open:h===e.id,error:x[e.id],onToggle:()=>g(h===e.id?null:e.id),onChange:k,onRemove:()=>R(e.id)},e.id)),!!N&&(0,C.jsx)(`p`,{className:`text-[12px] font-semibold text-red-500 px-1`,children:N})]})}),e&&(0,C.jsx)(t.m,{icon:n.S,title:`Your team's schedules`,description:`When everyone else is free — one folded row per person; open a name to add their hours or see what they keep.`,children:(0,C.jsx)(`div`,{className:`flex flex-col gap-3`,children:B?(0,C.jsx)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:`Loading your team's schedules…`}):U.length===0?(0,C.jsxs)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug px-1`,children:[`Nobody else is marked Internal or Admin yet. Add them on the`,` `,(0,C.jsx)(T.Link,{to:`/users`,className:`text-accent font-bold hover:underline`,children:`Users screen`}),` and a folded row for them appears here.`]}):U.map(e=>(0,C.jsx)(ye,{name:e.name,schedules:e.schedules,stale:e.stale,open:y===e.id,onToggle:()=>{let t=y!==e.id;b(t?e.id:null),t&&e.schedules.length&&g(e.schedules[0].id)},onAdd:()=>{let t=j.find(t=>t.id===e.id);t&&I(t)},openScheduleId:h,freshId:_,errors:x,onToggleSchedule:e=>g(h===e?null:e),onChange:k,onRemove:R},e.id))})})]})}function Se(){let{ready:e}=t.Jn(`schedule`);return e?(0,C.jsx)(X,{isAdmin:!0}):(0,C.jsx)(se,{})}function Ce(){let{user:i,userRole:o}=t.Ft(),s=o===`admin`,{schedules:c}=a.y(),l=i&&(i.displayName||i.email?.split(`@`)[0])||``;return r.Sn(o)?(0,C.jsxs)(`main`,{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`,children:[(0,C.jsxs)(t.nt.div,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},className:`mb-6`,children:[(0,C.jsx)(e.t,{children:`Schedule`}),(0,C.jsxs)(`div`,{className:`flex items-center gap-2 text-foreground/40 font-bold uppercase tracking-[0.2em] text-[11px]`,children:[(0,C.jsx)(`span`,{className:`w-8 h-[1px] bg-foreground/10`}),`/schedule`]})]}),(0,C.jsxs)(`div`,{className:`flex flex-col gap-6 flex-1 pb-16`,children:[(0,C.jsx)(n.t,{}),(0,C.jsx)(v.n,{tab:`schedule`}),(0,C.jsx)(`div`,{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]`,children:(0,C.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,C.jsx)(`div`,{className:`flex flex-col gap-1.5 px-1`,children:(0,C.jsx)(`p`,{className:`text-[13px] font-medium text-foreground/60 leading-relaxed`,children:s?`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.`})}),s?(0,C.jsx)(Se,{}):(0,C.jsx)(X,{isAdmin:!1}),(0,C.jsx)(xe,{isAdmin:s}),(0,C.jsx)(G,{isAdmin:s}),(0,C.jsx)(fe,{schedules:c,myName:l,isAdmin:s,meId:i?.uid||``})]})})]})]}):(0,C.jsx)(`main`,{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`,children:(0,C.jsx)(_.i,{})})}exports.ScheduleAdmin=Ce;
1
+ require(`./chunk-CiTBaPhY.cjs`);const e=require(`./PageTitle-BL50s4qY.cjs`),t=require(`./TimeZoneField-Ckn1pKAL.cjs`),n=require(`./DashboardNav-Bc619nqn.cjs`),r=require(`./schedule-BAea6q8_.cjs`),i=require(`./chevron-down-lyDK1rfL.cjs`),a=require(`./scheduleData-BXjNXVHY.cjs`),o=require(`./BookingCalendar-BcvJiyaq.cjs`),s=require(`./paidSessions-BK9qlIyL.cjs`),c=require(`./link-2-C7A-6PW6.cjs`),l=require(`./x-Ci8c5p6T.cjs`),u=require(`./plus-zsWFCu4F.cjs`),d=require(`./trash-D-CpYHCs.cjs`),f=require(`./Loader-QHqQsXLr.cjs`),p=require(`./email-Sya6gl4F.cjs`),m=require(`./notices-CKm9-Pqt.cjs`),h=require(`./ConfirmModal-BUNtss4a.cjs`),g=require(`./bookingPages-Dx1ViiwW.cjs`),_=require(`./AccessNotice-BClqr7A9.cjs`),v=require(`./SystemTabContent-BWhRHoXx.cjs`),y=require(`./serviceStatus-Cde96_OO.cjs`),b=require(`./NeedsService-DIF7mEHq.cjs`),x=require(`./CopyLink-D6QTWSoK.cjs`);let S=require(`react`),C=require(`react/jsx-runtime`),w=require(`firebase/firestore`),T=require(`react-router-dom`);var E=`w-[6.5rem] shrink-0`,D=`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`,O=`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`,k={from:`09:00`,to:`13:00`};function A(e,t){return{upcoming:e.filter(e=>e.date>=t),past:e.filter(e=>e.date<t)}}function j({row:e,onChange:n,onRemove:i}){let a=e.windows.length===0,o=(t,r)=>n({...e,windows:e.windows.map((e,n)=>n===t?{...e,...r}:e)});return(0,C.jsxs)(`div`,{className:`flex flex-col gap-2 py-2.5`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,C.jsx)(`input`,{type:`date`,value:e.date,"aria-label":`The date`,onChange:t=>n({...e,date:t.target.value}),className:O,style:{borderRadius:`var(--input-radius, 0.75rem)`}}),(0,C.jsx)(`div`,{className:`w-[11rem] shrink-0`,children:(0,C.jsx)(t.Z,{ariaLabel:`${e.date} — how much of it`,value:a?`all`:`some`,options:[{value:`all`,label:`All day`},{value:`some`,label:`Only some hours`}],onChange:t=>n({...e,windows:t===`all`?[]:[k]}),className:`console-select`,compact:!0,dense:!0,portal:!0,direction:`auto`})}),(0,C.jsx)(`button`,{type:`button`,title:`Remove ${e.date||`this date`}`,"aria-label":`Remove ${e.date||`this date`}`,onClick:i,className:`${D} ml-auto`,children:(0,C.jsx)(l.t,{className:`w-3.5 h-3.5`})})]}),!a&&(0,C.jsxs)(`div`,{className:`flex flex-col gap-2 sm:pl-[0.125rem]`,children:[e.windows.map((i,a)=>(0,C.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,C.jsx)(`div`,{className:E,children:(0,C.jsx)(t.Z,{ariaLabel:`${e.date} from${a?` (${a+1})`:``}`,value:i.from,options:r.m,onChange:e=>o(a,{from:e}),className:`console-select`,compact:!0,portal:!0,direction:`auto`})}),(0,C.jsx)(`span`,{className:`w-3 text-center text-foreground/40 text-[13px] shrink-0 select-none`,children:`–`}),(0,C.jsx)(`div`,{className:E,children:(0,C.jsx)(t.Z,{ariaLabel:`${e.date} to${a?` (${a+1})`:``}`,value:i.to,options:r.d,onChange:e=>o(a,{to:e}),className:`console-select`,compact:!0,portal:!0,direction:`auto`})}),e.windows.length>1&&(0,C.jsx)(`button`,{type:`button`,title:`Remove these hours on ${e.date}`,"aria-label":`Remove ${e.date} hours ${a+1}`,onClick:()=>n({...e,windows:e.windows.filter((e,t)=>t!==a)}),className:D,children:(0,C.jsx)(l.t,{className:`w-3.5 h-3.5`})})]},a)),e.windows.length<2&&(0,C.jsx)(`button`,{type:`button`,onClick:()=>n({...e,windows:[...e.windows,{from:`14:00`,to:`18:00`}]}),className:`self-start h-6 px-1 text-[11.5px] font-semibold text-foreground/45 hover:text-accent transition-colors cursor-pointer`,children:`+ Add a second stretch`})]})]})}function M({blocked:e,onChange:n,now:i}){let a=r.rn(i?i():new Date),[o,s]=(0,S.useState)(!1),{upcoming:c,past:l}=A(e,a),d=o?[...l,...c]:c,f=(t,r)=>n(e.map(e=>e===t?r:e));return(0,C.jsx)(t.i,{label:`Days away`,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.`,children:(0,C.jsxs)(`div`,{className:`flex flex-col divide-y divide-[var(--panel-border)]/60 rounded-2xl border border-[var(--panel-border)]/60 px-4 py-1`,children:[d.length===0?(0,C.jsx)(`p`,{className:`${t.s} py-3`,children:`No days blocked out. Add one for a holiday or a day off.`}):d.map((t,r)=>(0,C.jsx)(j,{row:t,onChange:e=>f(t,e),onRemove:()=>n(e.filter(e=>e!==t))},`${t.date}-${r}`)),(0,C.jsxs)(`div`,{className:`flex items-center justify-between gap-3 py-2.5`,children:[(0,C.jsx)(t.o,{icon:u.t,compact:!0,title:`Add a day away`,onClick:()=>n([...e,{date:a,windows:[]}]),children:`Add a date`}),l.length>0&&(0,C.jsx)(`button`,{type:`button`,onClick:()=>s(e=>!e),className:`h-6 px-1 text-[11.5px] font-semibold text-foreground/45 hover:text-accent transition-colors cursor-pointer`,children:o?`Hide past dates`:`Show ${l.length} past date${l.length===1?``:`s`}`})]})]})})}var N=e=>r.s.find(t=>t.value===e)?.label||`Short text`;function P({options:e,onChange:n}){return(0,C.jsx)(t.i,{label:`Choices`,hint:`What people pick from.`,children:(0,C.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[e.length===0&&(0,C.jsx)(`span`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug px-1`,children:`No choices yet — add the first one.`}),e.map((r,i)=>(0,C.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,C.jsx)(`input`,{type:`text`,value:r,"aria-label":`Choice ${i+1}`,placeholder:`e.g. At my place`,onChange:t=>n(e.map((e,n)=>n===i?t.target.value:e)),className:t.c}),(0,C.jsx)(t.o,{icon:l.t,tone:`danger`,compact:!0,title:`Remove choice ${i+1}`,onClick:()=>n(e.filter((e,t)=>t!==i)),children:`Remove`})]},i)),(0,C.jsx)(`div`,{children:(0,C.jsx)(t.o,{icon:u.t,onClick:()=>n([...e,``]),children:`Add choice`})})]})})}function F({question:e,index:n,count:a,siblings:o,fixed:s,onChange:c,onMove:l,onRemove:u}){let[f,p]=(0,S.useState)(!e.label.trim()),m=e.label.trim()||`A new question`;return(0,C.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-1.5 sm:gap-2.5 pr-2.5 sm:pr-3.5`,children:[(0,C.jsxs)(`button`,{type:`button`,onClick:()=>p(e=>!e),"aria-expanded":f,className:`flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3.5 text-left cursor-pointer`,children:[(0,C.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:m}),(0,C.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[(0,C.jsx)(`span`,{className:`${t.s} max-sm:hidden`,children:s?`Always asked`:`${N(e.type)}${e.required?` · must be answered`:``}`}),(0,C.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${f?`rotate-180`:``}`})]})]}),!s&&(0,C.jsxs)(`div`,{className:`flex items-center gap-1 sm:gap-1.5 shrink-0`,children:[(0,C.jsx)(t.o,{icon:t.jt,compact:!0,disabled:n===0,title:`Move ${m} up`,onClick:()=>l(-1),children:`Up`}),(0,C.jsx)(t.o,{icon:t.Mt,compact:!0,disabled:n===a-1,title:`Move ${m} down`,onClick:()=>l(1),children:`Down`}),(0,C.jsx)(`span`,{className:`max-sm:hidden w-px h-5 bg-[var(--panel-border)] mx-0.5`}),(0,C.jsx)(t.o,{icon:d.t,tone:`danger`,compact:!0,title:`Remove ${m}`,onClick:u,children:`Remove`})]})]}),f&&(0,C.jsxs)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4`,children:[(0,C.jsx)(t.b,{label:`What are you asking?`,hint:s?`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.`,value:e.label,placeholder:s?`e.g. Who is coming?`:`e.g. What is your phone number?`,onChange:t=>c({...e,label:t,name:s?e.name:r.K(e,t,o)})}),!s&&(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(t.g,{label:`Kind of answer`,hint:`Sets the box they type into. The example below follows what you pick.`,value:e.type,options:r.s,allowEmpty:!1,onChange:t=>c({...e,type:t,options:t===`select`?e.options:[],placeholder:r.W(e,t)})}),(0,C.jsx)(t.S,{label:`Must be answered`,hint:`On means they cannot book until it is filled in.`,hintWideOnly:!0,enabled:e.required,onChange:t=>c({...e,required:t})})]}),e.type===`select`&&(0,C.jsx)(P,{options:e.options,onChange:t=>c({...e,options:t})}),r.G(e.type)&&(0,C.jsx)(t.b,{label:`Example answer`,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.`,value:e.placeholder,placeholder:r.o[e.type]||`e.g. +1 555 0123`,onChange:t=>c({...e,placeholder:t})})]})]})}function I({questions:e,onChange:n}){let i=e.filter(e=>r.ht(e.name)),a=e.filter(e=>!r.ht(e.name)),o=e=>n([...i,...e]);return(0,C.jsx)(t.i,{label:`What does a booking ask for?`,children:(0,C.jsxs)(`div`,{className:`flex flex-col gap-3.5`,children:[i.map(t=>(0,C.jsx)(F,{question:t,index:0,count:1,siblings:e,fixed:!0,onChange:r=>n(e.map(e=>e.name===t.name?r:e)),onMove:()=>{},onRemove:()=>{}},t.name)),a.map((t,n)=>(0,C.jsx)(F,{question:t,index:n,count:a.length,siblings:e,onChange:e=>o(a.map((t,r)=>r===n?e:t)),onMove:e=>{let t=n+e;if(t<0||t>=a.length)return;let r=[...a];[r[n],r[t]]=[r[t],r[n]],o(r)},onRemove:()=>o(a.filter((e,t)=>t!==n))},n)),(0,C.jsxs)(`div`,{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`,children:[(0,C.jsx)(t.o,{icon:u.t,title:`Add a question`,onClick:()=>o([...a,r.j()]),children:`Add a question`}),a.length===0&&(0,C.jsx)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:`Nothing else is asked — just a name and an email.`})]})]})})}var L=(e,t,n=72)=>e>=n&&e<=Math.max(n,t*.45);function R(e,t=340){if(!e)return null;let n=()=>{let t=e.getBoundingClientRect?.(),n=typeof window<`u`&&window.innerHeight||0;t&&n&&L(t.top,n)||e.scrollIntoView?.({behavior:`smooth`,block:`start`})};return typeof setTimeout==`function`?setTimeout(n,t):(n(),null)}function z(e,t,n){let r=(0,S.useRef)(new Set);(0,S.useEffect)(()=>{let i=new Set(e),a=[...r.current].filter(e=>!i.has(e)&&!n.current.has(e));e.forEach(e=>r.current.add(e)),a.length&&(a.forEach(e=>r.current.delete(e)),t(e=>{if(!a.some(t=>t in e))return e;let t={...e};for(let e of a)delete t[e];return t}))},[e.join(`\0`)])}var B=`__new_payment__`;function V(){let[e,n]=(0,S.useState)([]);return(0,S.useEffect)(()=>{let e=t.Zr(t.Qn,()=>(0,w.collection)(t.ui,t.Qn),e=>{let r=[];e.forEach(e=>{e.id!==`_settings`&&r.push(t.Dr(e.id,e.data()))}),n(r.filter(e=>e.kind===`once`).sort((e,t)=>(e.createdAt||0)-(t.createdAt||0)))},()=>n([]));return()=>e()},[]),e}function H({value:e,products:n,meetingName:r,canCreate:i,onChange:a,onCreate:o}){let[s,c]=(0,S.useState)(!1),[l,d]=(0,S.useState)(``),[f,p]=(0,S.useState)(``),[m,h]=(0,S.useState)(!1),g=[...n.map(e=>({value:e.id,label:`${t.xr(e)} — ${t.gr(e).map(e=>e.amount).filter(Boolean).join(` + `)||`no price yet`}`})),...i?[{value:B,label:`+ A new one-time payment`}]:[]],_=n.find(t=>t.id===e),v=l.trim()&&t.br(l)===null?`Just a number, like 25.`:void 0;return(0,C.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,C.jsx)(t.g,{label:`Payment for this meeting`,hint:_?`Taken on the booking page before the time is confirmed. Its price and its link are on the Payments screen.`:i?`Optional. A one-time payment taken on the booking page before the time is confirmed.`:n.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.`,value:s?B:e,placeholder:`No payment`,options:g,onChange:e=>{if(e===`__new_payment__`){c(!0);return}c(!1),a(e)}}),s&&(0,C.jsxs)(`div`,{className:`rounded-2xl border border-[var(--panel-border)]/60 px-4 py-3.5 flex flex-col gap-3`,children:[(0,C.jsx)(t.b,{label:`The price`,hint:`Just the number — 25 charges 25 in your Stripe account's currency. The payment is called ${r} and appears on the Payments screen too.`,value:l,onChange:e=>{d(e),f&&p(``)},placeholder:`25`,error:f||v}),(0,C.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,C.jsx)(t.o,{icon:u.t,busy:m,onClick:async()=>{if(t.br(l)===null){p(`Just a number for the price, like 25.`);return}p(``),h(!0);let e=await o(r,l.trim());if(h(!1),e){p(e);return}c(!1),d(``)},children:`Create it`}),(0,C.jsx)(t.o,{onClick:()=>{c(!1),p(``),d(``)},children:`Never mind`})]})]})]})}function U({link:e,onChange:n}){return(0,C.jsx)(t.i,{label:`Emails about bookings`,hint:`Sent the moment a time is taken. Every booking is in your Inbox and on the calendar regardless.`,children:(0,C.jsxs)(`div`,{className:`flex flex-col gap-3 rounded-2xl border border-[var(--panel-border)]/60 px-4 py-3.5`,children:[(0,C.jsx)(t.S,{label:`Email me when someone books`,hint:`A note at your address — the sale alert, when they paid.`,hintWideOnly:!0,enabled:e.notifyOwner,onChange:e=>n({notifyOwner:e})}),(0,C.jsx)(t.S,{label:`Email them a confirmation`,hint:`Their receipt when they pay. For a free booking, a note that the time is theirs — to people who book signed in.`,hintWideOnly:!0,enabled:e.confirmBooker,onChange:e=>n({confirmBooker:e})})]})})}var ee=e=>{let t={...a.I(a.H(),e),createdAt:Date.now()};return{...t,name:r.O(t),description:r.D(t)}};function te({link:e,schedules:n,products:i,services:o,isAdmin:s=!0,onChange:c,onCreatePayment:l}){let u=n.find(t=>t.id===e.scheduleId),d=t=>c({...e,...t}),f=a.z(e,u),p=u?a.L(e,u):null,m=t=>{let n={...e,...t};return{...t,...e.name.trim()===r.O(e)?{name:r.O(n)}:{},...e.description.trim()===r.D(e)?{description:r.D(n)}:{}}};return(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(t.g,{label:`Which hours is it booked in?`,hint:`Change the hours and every meeting booked in them changes with it — one holiday, entered once, closes them all.`,value:e.scheduleId,options:n.map(e=>({value:e.id,label:r.ut(e)})),allowEmpty:!1,onChange:t=>{let r=n.find(e=>e.id===t);if(!r)return;let i=!u||e.memberName.trim()===u.memberName.trim();d(m({scheduleId:r.id,memberId:r.memberId,...i?{memberName:r.memberName}:{}}))}}),(0,C.jsx)(t.b,{label:`What is it called?`,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 ${r.O(e)}.`,value:e.name,onChange:e=>d({name:e}),placeholder:r.O(e)}),(0,C.jsx)(t.y,{label:`A line or two about it`,hint:`Visitors read it under the name — what it is for, what to bring, what happens after. Emptied, the booking page simply shows none.`,value:e.description,onChange:e=>d({description:e}),placeholder:`A first conversation about what you need and how I can help.`}),(0,C.jsx)(t.b,{label:`The name visitors see`,value:e.memberName,onChange:e=>d(m({memberName:e})),placeholder:`Anna`}),(0,C.jsx)(t.g,{label:`How long is one booking?`,value:String(e.slotMinutes),options:r.b,allowEmpty:!1,onChange:e=>d(m({slotMinutes:Number(e)}))}),(0,C.jsx)(t.g,{label:`How far ahead can people book?`,value:String(e.horizonDays),options:r.h,allowEmpty:!1,onChange:e=>d({horizonDays:Number(e)})}),(0,C.jsx)(t.g,{label:`How much notice do you need?`,value:String(e.noticeHours),options:r._,allowEmpty:!1,onChange:e=>d({noticeHours:Number(e)})}),(0,C.jsx)(I,{questions:e.questions,onChange:e=>d({questions:e})}),(0,C.jsx)(b.t,{service:`payments`,readiness:b.n(o.payments),children:(0,C.jsx)(H,{value:e.paymentId,products:i,meetingName:a.V(e),canCreate:s,onChange:e=>d({paymentId:e}),onCreate:async(e,t)=>{let n=await l(e,t);return n&&n.startsWith(`p_`)?(d({paymentId:n}),null):n||`The payment could not be made — make sure you are signed in as an admin and try again.`}})}),(0,C.jsx)(b.t,{service:`email`,readiness:b.n(o.email),children:(0,C.jsx)(U,{link:e,onChange:d})}),(0,C.jsx)(t.i,{label:`Booking link`,hint:p&&!f&&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.`,children:(0,C.jsx)(x.t,{title:a.V(e),path:r.U(e.id)})}),(0,C.jsx)(`div`,{className:`pt-1`,children:f?e.enabled?(0,C.jsxs)(`span`,{className:`text-[11.5px] font-semibold text-amber-500`,children:[`Turned on, but not bookable yet — `,f]}):(0,C.jsx)(`span`,{className:t.s,children:f}):e.enabled?(0,C.jsx)(`span`,{className:`text-[11.5px] font-semibold text-emerald-500`,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.`}):(0,C.jsx)(`span`,{className:t.s,children:`Complete — flip the switch at the top of the row to offer it.`})})]})}function W({link:e,schedules:n,products:r,services:o,isAdmin:s=!0,open:c,fresh:l,error:u,onToggle:f,onChange:p,onRemove:m,onCreatePayment:g}){let _=n.find(t=>t.id===e.scheduleId),v=a.R(e,_),[y,b]=(0,S.useState)(!1),x=a.V(e),w=(0,S.useRef)(null);return(0,S.useEffect)(()=>{if(!l)return;let e=R(w.current);return()=>{e&&clearTimeout(e)}},[l]),(0,C.jsxs)(`div`,{ref:w,className:`scroll-mt-4 rounded-2xl border border-[var(--panel-border)]`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-2 sm:gap-2.5 pr-3`,children:[(0,C.jsxs)(`button`,{type:`button`,onClick:f,"aria-expanded":c,className:`flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer`,children:[(0,C.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:a.B(e,_)}),(0,C.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[(0,C.jsx)(`span`,{className:`max-sm:hidden`,children:(0,C.jsx)(t._,{state:v.state,label:v.label})}),(0,C.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${c?`rotate-180`:``}`})]})]}),(0,C.jsx)(t.x,{enabled:e.enabled,onChange:t=>p({...e,enabled:t}),label:`${x} — can be booked`}),(0,C.jsx)(t.o,{icon:d.t,tone:`danger`,compact:!0,title:`Remove ${x}`,onClick:()=>b(!0),children:`Remove`})]}),(0,C.jsx)(h.t,{isOpen:y,title:`Remove ${x}?`,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.`,confirmText:`Yes, remove`,cancelText:`Keep it`,onCancel:()=>b(!1),onConfirm:()=>{b(!1),m()}}),c&&(0,C.jsx)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4`,children:(0,C.jsx)(te,{link:e,schedules:n,products:r,services:o,isAdmin:s,onChange:p,onCreatePayment:g})}),u&&(0,C.jsx)(`p`,{className:`text-[12px] font-semibold text-red-500 px-4 pb-3`,children:u})]})}function G({isAdmin:e=!0}={}){let{user:n}=t.Ft(),{loading:i,docs:o}=a.S(),s=V(),l={payments:y.r(`payments`),email:y.r(`email`)},[d,f]=(0,S.useState)({}),[p,m]=(0,S.useState)([]),[h,g]=(0,S.useState)(null),[_,v]=(0,S.useState)(null),[b,x]=(0,S.useState)({}),T=(0,S.useRef)(new Map);z(o.links.map(e=>e.id),f,T);let E=n?.uid||``,D=(0,S.useMemo)(()=>[...e?o.schedules:o.schedules.filter(e=>e.memberId===E)].sort((e,t)=>Number(t.memberId===E)-Number(e.memberId===E)),[o.schedules,e,E]),O=(0,S.useMemo)(()=>{let t=new Map(o.links.map(e=>[e.id,e]));for(let e of Object.values(d))t.set(e.id,e);for(let e of p)t.delete(e);return[...t.values()].filter(t=>e||t.memberId===E).sort((e,t)=>Number(t.memberId===E)-Number(e.memberId===E)||(e.createdAt||0)-(t.createdAt||0)||e.id.localeCompare(t.id))},[o.links,d,p,e,E]),k=e=>{let t=T.current.get(e.id);t&&clearTimeout(t),T.current.set(e.id,setTimeout(async()=>{T.current.delete(e.id);let t=await a.f(e);x(n=>{let r={...n};return t?r[e.id]=t:delete r[e.id],r})},600))},A=e=>{f(t=>({...t,[e.id]:e})),k(e)},j=()=>{let e=D.find(e=>e.memberId===E)||D[0];if(!e)return;let t=ee(e);f(e=>({...e,[t.id]:t})),g(t.id),v(t.id),k(t)},M=async e=>{let t=T.current.get(e);t&&(clearTimeout(t),T.current.delete(e)),f(t=>{let n={...t};return delete n[e],n}),m(t=>[...t,e]),h===e&&g(null);let n=await a.u(e);n&&(m(t=>t.filter(t=>t!==e)),x(t=>({...t,[e]:n})))},N=async(e,n)=>{let r={...t.cr(`p_${Date.now().toString(36)}`),kind:`once`,items:[{name:e,amount:n}]};try{let{id:e,...n}=r;return await(0,w.setDoc)((0,w.doc)(t.ui,t.Qn,e),n),e}catch(e){return console.error(`Could not make the payment`,e),null}};return(0,C.jsx)(t.m,{icon:c.t,title:`Booking links`,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.`,actions:!i&&D.length>0?({open:e})=>(0,C.jsx)(t.o,{icon:u.t,compact:!0,title:`Add a booking link`,onClick:()=>{e(),j()},children:`Add a booking link`}):void 0,children:(0,C.jsx)(`div`,{className:`flex flex-col gap-3`,children:i?(0,C.jsx)(`p`,{className:t.s,children:`Loading your booking links…`}):D.length===0?(0,C.jsx)(`p`,{className:`${t.s} px-1`,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.`}):O.length===0?(0,C.jsxs)(`p`,{className:`${t.s} px-1`,children:[`No booking link yet — press Add a booking link. It is what turns `,r.dt(D[0]),` into something people can book.`]}):O.map(t=>(0,C.jsx)(W,{link:t,schedules:D,products:s,services:l,isAdmin:e,open:h===t.id,fresh:_===t.id,error:b[t.id],onToggle:()=>g(h===t.id?null:t.id),onChange:A,onRemove:()=>M(t.id),onCreatePayment:N},t.id))})})}var K=`team`,ne=e=>`m:${e}`,re=`__nobody__`;function ie(e,t,n){return[{value:`me`,label:`My calendar`},{value:K,label:`My team's calendar`},...e.filter(e=>e.id!==n).map(e=>({value:ne(e.id),label:a.g(e)||e.email,disabled:!t.has(e.id)}))]}var q=e=>e.startsWith(`m:`)?e.slice(2):``;function J(e,t,n,i=``){if(!e.email)return Promise.resolve();let a=r.Zt(e,e.timeZone||n);return p.i(t,r.t,e.id,{when:`${a.day}, ${a.time}`,memberName:e.memberName,scheduleName:e.scheduleName,reason:i.trim()}).then(()=>{}).catch(()=>{})}function ae(e,t,n){let r=e=>[...new Set(e.map(e=>String(e||``).trim()))].filter(e=>e&&e!==n),i=r([e.memberId,...t.map(e=>e.memberId),...e.copyIds.map(e=>e.split(`__`)[0])]);return{members:i,bookers:r([e.uid,...t.map(e=>e.uid)]).filter(e=>e!==`guest`).filter(e=>!i.includes(e))}}async function oe(e,t,n,i){if(e.own||e.heldOnly)return;let a={title:`Meeting removed`,body:`${r.B(e)} · ${r.ot(new Date(e.start),i)}`};await J(e,`booking_cancelled`,i,`The meeting was removed from the calendar.`);let{members:o,bookers:s}=ae(e,t,n);await m.r(o,{...a,link:`/schedule`}),await m.r(s,{...a,link:`/my-bookings`})}var Y=e=>{try{return localStorage.getItem(`fbos_calendar_had_${e}`)===`1`}catch{return!1}};function se(){let{user:e}=t.Ft();return Y(e?.uid||``)?(0,C.jsx)(f.n,{className:`h-[420px] w-full`}):null}function X({isAdmin:e}){let{user:n}=t.Ft(),i=n?.uid||``,c=r.et(),[l,u]=(0,T.useSearchParams)(),d=l.get(`open`)||l.get(`booking`)||``,{schedules:p}=a.w(),{members:m}=a.T(),h=(0,S.useMemo)(()=>new Set(p.map(e=>e.memberId)),[p]),g=(0,S.useMemo)(()=>ie(m,h,i),[m,h,i]),[_,v]=(0,S.useState)(null);(0,S.useEffect)(()=>{d&&e&&v(e=>e??`team`)},[d,e]);let y=_??`me`,b=new Set(g.filter(e=>!e.disabled).map(e=>e.value)).has(y)?y:`me`,x=q(b),{loading:w,bookings:E,error:D}=a.v({members:b===`team`?void 0:[x||i||re],includePast:!0}),O=(0,S.useMemo)(()=>a.P(E),[E]),k=(0,S.useMemo)(()=>E.map(e=>{let t=O.get(e.id);return t?{...e,...t}:e}),[E,O]),{paid:A,checkouts:j}=s.t(k),M=a.C((0,S.useMemo)(()=>(b===`team`?m.map(e=>e.id):[x||i]).filter(Boolean),[b,m,x,i]),(0,S.useMemo)(()=>{let e=new Date;return new Date(Date.UTC(e.getUTCFullYear(),e.getUTCMonth()-1,1))},[]),{keepOpen:!0}),[N,P]=(0,S.useState)(()=>Date.now());(0,S.useEffect)(()=>{let e=setInterval(()=>P(Date.now()),6e4);return()=>clearInterval(e)},[]);let F=(0,S.useMemo)(()=>{let e=new Set(M.filter(e=>!e.open).map(e=>r.qt(e.memberId,e.start))),t=k.map(t=>a.M(t,j[t.id],e,N)),n=e=>{let t=m.find(t=>t.id===e);return p.find(t=>t.memberId===e)?.memberName||(t?a.g(t):``)},i=a.F(M,E,N).map(e=>a.N(e,n(e.memberId)));return i.length?[...t,...i]:t},[E,k,M,N,m,p,j]);(0,S.useEffect)(()=>{if(!(w||!i))try{localStorage.setItem(`fbos_calendar_had_${i}`,F.length?`1`:`0`)}catch{}},[w,i,F.length]);let I=x||i,L=m.find(e=>e.id===I),R=p.find(e=>e.memberId===I)?.memberName||(L?a.g(L):``)||(I===i?String(n?.displayName||``):``);return w&&F.length===0?Y(i)?(0,C.jsx)(f.n,{className:`h-[420px] w-full`}):null:F.length===0?null:(0,C.jsx)(t.m,{icon:o.d,title:`Calendar`,description:b===`team`?`Every booking made with your team, and the events they put on their own days — in your time, ${r.nn(c)}.`:x?`${R||`Their`} calendar, read as they read it — in your time, ${r.nn(c)}.`:`Every booking made with you, under every schedule of yours — in your time, ${r.nn(c)}.`,actions:e&&g.length>2?(0,C.jsx)(t.Z,{ariaLabel:`Whose calendar`,value:b,options:g,onChange:v,className:`console-select`,compact:!0,dense:!0,portal:!0,direction:`auto`}):void 0,children:w?(0,C.jsx)(`p`,{className:t.s,children:`Loading the calendar…`}):D?(0,C.jsx)(`p`,{className:`text-[12px] font-semibold text-red-500 px-1`,children:D}):(0,C.jsx)(s.n,{bookings:F,zone:c,paid:A,openBookingId:d||void 0,onOpened:d?()=>u(e=>(e.delete(`open`),e.delete(`booking`),e),{replace:!0}):void 0,withMember:b===K,me:i,onAccept:async e=>{let t=await a.t(e.id);return t||J(e,`booking_confirmed`,c),t},onCancel:async(e,t)=>{let r=await a.r(e.id,{ids:e.copyIds,reason:t,side:`host`,by:e.memberId===i?R||String(n?.displayName||``):e.memberName,byUid:i});return r||J(e,`booking_cancelled`,c,t),r},onDelete:async e=>(await oe(e,E,i,c),a.a(e.id,e.copyIds)),canDelete:t=>e||t.own&&t.memberId===i,onRelease:e=>a.c(e.memberId,e.start),onColor:a.m,onAdd:b===`team`?void 0:e=>a.n({...e,memberId:I,memberName:R,timeZone:c})})})}function ce(e,t){if(!e.enabled)return{state:`off`,label:`Off`};if(g.c(e,t))return{state:`error`,label:`Unfinished`};let n=e.schedules.length;return{state:`saved`,label:n===1?`1 meeting`:`${n} meetings`}}var le=e=>{let t=e.schedules.length;return`${g.s(e)} — ${t===0?`nothing on it yet`:t===1?`1 meeting`:`${t} meetings`}`};function Z({page:e,schedules:n,onChange:i}){return n.length?(0,C.jsx)(t.i,{label:`Meetings on this page`,hint:`They appear in the order you tick them. A meeting switched off above is kept off the page too.`,children:(0,C.jsx)(`div`,{className:`flex flex-col gap-1.5`,children:n.map(t=>{let n=e.schedules.includes(t.id);return(0,C.jsxs)(`button`,{type:`button`,role:`checkbox`,"aria-checked":n,onClick:()=>i(g.p(e,t.id)),className:`flex items-center gap-3 px-3 py-2.5 rounded-xl border text-left transition-all cursor-pointer active:scale-[0.995] ${n?`border-accent/45 bg-accent/[0.07]`:`border-[var(--panel-border)]/70 hover:border-accent/30 hover:bg-foreground/[0.03]`}`,children:[(0,C.jsx)(`span`,{"aria-hidden":!0,className:`w-[18px] h-[18px] rounded-[5px] border flex items-center justify-center shrink-0 transition-all ${n?`border-accent bg-accent`:`border-foreground/25`}`,children:n&&(0,C.jsx)(`span`,{className:`w-[7px] h-[7px] rounded-[2px] bg-[var(--button-fg,#fff)]`})}),(0,C.jsx)(`span`,{className:`flex-1 min-w-0 text-[13px] font-semibold text-foreground/80 truncate`,children:r.Bt(t)})]},t.id)})})}):(0,C.jsx)(t.i,{label:`Meetings on this page`,children:(0,C.jsx)(`p`,{className:`${t.s} px-1`,children:`Make a schedule above first — a page offers the meetings you have set up.`})})}function ue({page:e,taken:n,onRename:r}){let[i,a]=(0,S.useState)(e.id),o=g.f(i),s=!!o&&o!==e.id&&n.includes(o);return(0,C.jsx)(t.b,{label:`Its address`,prefix:`/meet/`,value:i,onChange:a,onBlur:()=>{if(!o||s||o===e.id){a(e.id);return}r(o)},placeholder:`anna-bell`,error:s?`Another page already has that address.`:void 0,hint:`Change it and the old link stops working, so change it before you send it out.`})}function de({page:n,schedules:r,taken:a,open:o,fresh:s,error:c,onToggle:l,onChange:u,onRename:f,onRemove:p}){let[m,_]=(0,S.useState)(!1),v=ce(n,r),y=g.s(n),b=g.c(n,r),w=(0,S.useRef)(null);return(0,S.useEffect)(()=>{if(!s)return;let e=R(w.current);return()=>{e&&clearTimeout(e)}},[s]),(0,C.jsxs)(`div`,{ref:w,className:`scroll-mt-4 rounded-2xl border border-[var(--panel-border)]`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-2 sm:gap-2.5 pr-3`,children:[(0,C.jsxs)(`button`,{type:`button`,onClick:l,"aria-expanded":o,className:`flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer`,children:[(0,C.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:le(n)}),(0,C.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[(0,C.jsx)(`span`,{className:`max-sm:hidden`,children:(0,C.jsx)(t._,{state:v.state,label:v.label})}),(0,C.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${o?`rotate-180`:``}`})]})]}),(0,C.jsx)(t.x,{enabled:n.enabled,onChange:e=>u({...n,enabled:e}),label:`${y} — page is live`}),(0,C.jsx)(t.o,{icon:d.t,tone:`danger`,compact:!0,title:`Remove ${y}`,onClick:()=>_(!0),children:`Remove`})]}),(0,C.jsx)(h.t,{isOpen:m,title:`Remove ${y}?`,message:`Its link stops working. The meetings on it are untouched and keep their own links, and bookings already taken are kept.`,confirmText:`Yes, remove`,cancelText:`Keep it`,onCancel:()=>_(!1),onConfirm:()=>{_(!1),p()}}),o&&(0,C.jsxs)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4`,children:[(0,C.jsx)(t.b,{label:`Name on the page`,value:n.title,onChange:e=>u({...n,title:e}),placeholder:`Anna Bell`,hint:`Usually the name of whoever the page is for.`}),(0,C.jsx)(e.a,{label:`Photo`,hint:`Shown at the top of the page. A square picture of the person works best.`,value:n.photo,onChange:e=>u({...n,photo:e})}),(0,C.jsx)(t.y,{label:`About this page`,value:n.intro,onChange:e=>u({...n,intro:e}),rows:3,placeholder:`I help small studios get their bookkeeping straight. Pick a time below and tell me what you need.`}),(0,C.jsx)(Z,{page:n,schedules:r,onChange:u}),(0,C.jsx)(ue,{page:n,taken:a,onRename:f}),b?(0,C.jsx)(`p`,{className:`text-[12px] font-semibold text-amber-500 px-1`,children:b}):(0,C.jsx)(x.t,{title:y,path:g.l(n.id)})]}),c&&(0,C.jsx)(`p`,{className:`text-[12px] font-semibold text-red-500 px-4 pb-3`,children:c})]})}function fe({schedules:e,myName:n,isAdmin:r=!0,meId:i=``}){let{loading:a,pages:o}=g.i(),[s,l]=(0,S.useState)({}),[d,f]=(0,S.useState)([]),[p,m]=(0,S.useState)(null),[h,_]=(0,S.useState)(null),[v,y]=(0,S.useState)({}),b=(0,S.useRef)(new Map);z(o.map(e=>e.id),l,b);let x=new Map(o.map(e=>[e.id,e]));for(let e of Object.values(s))x.set(e.id,e);for(let e of d)x.delete(e);let w=[...x.values()].sort((e,t)=>(e.createdAt||0)-(t.createdAt||0)||e.id.localeCompare(t.id)),T=w.map(e=>e.id),E=g.u(w,i,r),D=r?e:e.filter(e=>e.memberId===i),O=e=>{let t=b.current.get(e.id);t&&clearTimeout(t),b.current.set(e.id,setTimeout(async()=>{b.current.delete(e.id);let t=await g.r(e);y(n=>{let r={...n};return t?r[e.id]=t:delete r[e.id],r})},600))},k=e=>{l(t=>({...t,[e.id]:e})),O(e)},A=()=>{let e=g.a(g.m(n||`my page`,T),n,i);l(t=>({...t,[e.id]:e})),f(t=>t.filter(t=>t!==e.id)),m(e.id),_(e.id),O(e)},j=async(e,t)=>{let n=b.current.get(e.id);n&&(clearTimeout(n),b.current.delete(e.id));let r={...e,id:t};l(n=>{let i={...n};return delete i[e.id],i[t]=r,i}),f(n=>[...n.filter(e=>e!==t),e.id]),p===e.id&&m(t);let i=await g.n(e.id,r);i&&y(e=>({...e,[t]:i}))},M=async e=>{let t=b.current.get(e);t&&(clearTimeout(t),b.current.delete(e)),l(t=>{let n={...t};return delete n[e],n}),f(t=>[...t,e]),p===e&&m(null);let n=await g.t(e);n&&(f(t=>t.filter(t=>t!==e)),y(t=>({...t,[e]:n})))};return(0,C.jsx)(t.m,{icon:c.t,title:`Your booking pages`,description:`One link with a photo, a line about you and every meeting you offer.`,actions:({open:e})=>(0,C.jsx)(t.o,{icon:u.t,compact:!0,title:`Create a page`,onClick:()=>{e(),A()},children:`Create a page`}),children:(0,C.jsx)(`div`,{className:`flex flex-col gap-3`,children:a?(0,C.jsx)(`p`,{className:`${t.s} px-1`,children:`Loading pages…`}):E.length===0?(0,C.jsx)(`p`,{className:`${t.s} px-1`,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.`}):E.map(e=>(0,C.jsx)(de,{page:e,schedules:D,taken:T,open:p===e.id,fresh:h===e.id,error:v[e.id],onToggle:()=>m(t=>t===e.id?null:e.id),onChange:k,onRename:t=>j(e,t),onRemove:()=>M(e.id)},e.id))})})}var pe={from:`09:00`,to:`17:00`},me=e=>r.pt(e)?{state:`saved`,label:`Ready`}:{state:`off`,label:`In progress`},he=e=>({...r.M(a.U(),e.id,a.g(e),r.et()),name:`Working hours`,enabled:!0,createdAt:Date.now()}),Q=`w-[6.5rem] shrink-0`,ge=`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`;function _e({day:e,windows:n,onChange:i}){let a=n.length>0,o=(e,t)=>i(n.map((n,r)=>r===e?{...n,...t}:n));return(0,C.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-[8.5rem_minmax(0,1fr)] items-start gap-x-4 gap-y-2 py-2.5`,children:[(0,C.jsxs)(`div`,{className:`flex items-center justify-between gap-3 h-9`,children:[(0,C.jsx)(`span`,{className:`text-[13px] font-medium ${a?`text-foreground/80`:`text-foreground/40`}`,children:r.u[e]}),(0,C.jsx)(t.x,{enabled:a,onChange:e=>i(e?[pe]:[]),label:`${r.u[e]} — bookable`})]}),a&&(0,C.jsxs)(`div`,{className:`flex flex-col gap-2 min-w-0`,children:[n.map((a,s)=>(0,C.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,C.jsx)(`div`,{className:Q,children:(0,C.jsx)(t.Z,{ariaLabel:`${r.u[e]} from${s?` (${s+1})`:``}`,value:a.from,options:r.m,onChange:e=>o(s,{from:e}),className:`console-select`,compact:!0,portal:!0,direction:`auto`})}),(0,C.jsx)(`span`,{className:`w-3 text-center text-foreground/40 text-[13px] shrink-0 select-none`,children:`–`}),(0,C.jsx)(`div`,{className:Q,children:(0,C.jsx)(t.Z,{ariaLabel:`${r.u[e]} to${s?` (${s+1})`:``}`,value:a.to,options:r.d,onChange:e=>o(s,{to:e}),className:`console-select`,compact:!0,portal:!0,direction:`auto`})}),n.length>1&&(0,C.jsx)(`button`,{type:`button`,title:`Remove these hours on ${r.u[e]}`,"aria-label":`Remove ${r.u[e]} hours ${s+1}`,onClick:()=>i(n.filter((e,t)=>t!==s)),className:ge,children:(0,C.jsx)(l.t,{className:`w-3.5 h-3.5`})})]},s)),n.length<2&&(0,C.jsx)(`button`,{type:`button`,onClick:()=>i([...n,{from:`18:00`,to:`20:00`}]),className:`self-start h-6 px-1 text-[11.5px] font-semibold text-foreground/45 hover:text-accent transition-colors cursor-pointer`,children:`+ Add a second stretch`})]})]})}function ve({schedule:e,onChange:n}){let i=t=>n({...e,...t}),a=r.ft(e);return(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(t.b,{label:`What are these hours called?`,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.`,value:e.name,onChange:e=>i({name:e}),placeholder:`Working hours`}),(0,C.jsx)(t.t,{value:e.timeZone,onChange:e=>i({timeZone:e})}),(0,C.jsx)(t.i,{label:`When`,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.`,children:(0,C.jsx)(`div`,{className:`flex flex-col divide-y divide-[var(--panel-border)]/60 rounded-2xl border border-[var(--panel-border)]/60 px-4 py-1`,children:r.l.map(t=>(0,C.jsx)(_e,{day:t,windows:e.days[t]||[],onChange:n=>i({days:{...e.days,[t]:n}})},t))})}),(0,C.jsx)(M,{blocked:e.blocked,onChange:e=>i({blocked:e})}),(0,C.jsx)(`div`,{className:`pt-1`,children:a?(0,C.jsxs)(`span`,{className:`text-[11.5px] font-semibold text-amber-500`,children:[`Not usable yet — `,a]}):(0,C.jsx)(`span`,{className:`text-[11.5px] font-semibold text-emerald-500`,children:`Ready — add a booking link below to let people book these hours, or ask for a page built on them.`})})]})}function $({schedule:e,open:n,stale:a,fresh:o,error:s,onToggle:c,onChange:l,onRemove:u}){let f=me(e),[p,m]=(0,S.useState)(!1),g=r.dt(e),_=(0,S.useRef)(null);return(0,S.useEffect)(()=>{if(!o)return;let e=R(_.current);return()=>{e&&clearTimeout(e)}},[o]),(0,C.jsxs)(`div`,{ref:_,className:`scroll-mt-4 rounded-2xl border border-[var(--panel-border)] ${a?`opacity-60`:``}`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-2 sm:gap-2.5 pr-3`,children:[(0,C.jsxs)(`button`,{type:`button`,onClick:c,"aria-expanded":n,className:`flex-1 min-w-0 flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer`,children:[(0,C.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:r.mt(e)}),(0,C.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[a?(0,C.jsx)(`span`,{className:`${t.s} max-sm:hidden`,children:`No longer on the team`}):(0,C.jsx)(`span`,{className:`max-sm:hidden`,children:(0,C.jsx)(t._,{state:f.state,label:f.label})}),(0,C.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${n?`rotate-180`:``}`})]})]}),(0,C.jsx)(t.o,{icon:d.t,tone:`danger`,compact:!0,title:`Remove ${g}`,onClick:()=>m(!0),children:`Remove`})]}),(0,C.jsx)(h.t,{isOpen:p,title:`Remove ${g}?`,message:a?`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.`,confirmText:`Yes, remove`,cancelText:`Keep it`,onCancel:()=>m(!1),onConfirm:()=>{m(!1),u()}}),n&&(0,C.jsx)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-4`,children:(0,C.jsx)(ve,{schedule:e,onChange:l})}),s&&(0,C.jsx)(`p`,{className:`text-[12px] font-semibold text-red-500 px-4 pb-3`,children:s})]})}function ye({name:e,schedules:n,stale:r,open:a,onToggle:o,onAdd:s,openScheduleId:c,freshId:l,errors:d,onToggleSchedule:f,onChange:p,onRemove:m}){let h=r?`No longer on the team`:n.length===0?`No schedules yet`:`${n.length} schedule${n.length===1?``:`s`}`,g=(0,S.useRef)(null);return(0,S.useEffect)(()=>{if(!a)return;let e=R(g.current);return()=>{e&&clearTimeout(e)}},[a]),(0,C.jsxs)(`div`,{ref:g,className:`scroll-mt-4 rounded-2xl border border-[var(--panel-border)]`,children:[(0,C.jsxs)(`button`,{type:`button`,onClick:o,"aria-expanded":a,className:`w-full flex items-center justify-between gap-3 px-4 py-3 text-left cursor-pointer`,children:[(0,C.jsx)(`span`,{className:`text-[13px] font-semibold text-foreground/75 truncate`,children:e}),(0,C.jsxs)(`span`,{className:`flex items-center gap-2.5 shrink-0`,children:[(0,C.jsx)(`span`,{className:`${t.s} max-sm:hidden`,children:h}),(0,C.jsx)(i.t,{className:`w-3.5 h-3.5 text-foreground/40 shrink-0 transition-transform ${a?`rotate-180`:``}`})]})]}),a&&(0,C.jsxs)(`div`,{className:`px-4 pb-4 pt-4 border-t border-[var(--panel-border)]/60 flex flex-col gap-3`,children:[n.map(e=>(0,C.jsx)($,{schedule:e,stale:r,fresh:l===e.id,open:c===e.id,error:d[e.id],onToggle:()=>f(e.id),onChange:p,onRemove:()=>m(e.id)},e.id)),r?n.length===0&&(0,C.jsxs)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:[`No schedule yet for `,e,`.`]}):(0,C.jsxs)(`div`,{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`,children:[(0,C.jsx)(t.o,{icon:u.t,title:`Add a schedule for ${e}`,onClick:s,children:`Add a schedule`}),n.length===0&&(0,C.jsxs)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:[`No schedule yet for `,e,`.`]})]})]})]})}var be=e=>({id:e.uid,name:String(e.displayName||``),email:String(e.email||``),role:`admin`});function xe({isAdmin:e=!0}={}){let{user:r}=t.Ft(),{loading:i,members:o}=a.T(),{loading:s,docs:c}=a.S(),l=c.schedules,[d,f]=(0,S.useState)({}),[p,m]=(0,S.useState)([]),[h,g]=(0,S.useState)(null),[_,v]=(0,S.useState)(null),[y,b]=(0,S.useState)(null),[x,w]=(0,S.useState)({}),E=(0,S.useRef)(new Map);z(l.map(e=>e.id),f,E);let D=(0,S.useMemo)(()=>{let e=new Map(l.map(e=>[e.id,e]));for(let t of Object.values(d))e.set(t.id,t);for(let t of p)e.delete(t);return[...e.values()].sort((e,t)=>(e.createdAt||0)-(t.createdAt||0)||e.id.localeCompare(t.id))},[l,d,p]),O=e=>{let t=E.current.get(e.id);t&&clearTimeout(t),E.current.set(e.id,setTimeout(async()=>{E.current.delete(e.id);let t=await a.p(e);w(n=>{let r={...n};return t?r[e.id]=t:delete r[e.id],r})},600))},k=e=>{f(t=>({...t,[e.id]:e})),O(e)},A=(0,S.useMemo)(()=>r?o.find(e=>e.id===r.uid)||be(r):null,[r,o]),j=(0,S.useMemo)(()=>A&&!o.some(e=>e.id===A.id)?[A,...o]:o,[A,o]),M=(0,S.useRef)(!1),[N,P]=(0,S.useState)(``),F=(0,S.useMemo)(()=>c.schedules.filter(t=>c.legacyIds.includes(t.id)&&(e||t.memberId===A?.id)),[c.schedules,c.legacyIds,e,A]);(0,S.useEffect)(()=>{M.current||F.length===0||(M.current=!0,a.h(F).then(e=>{e&&P(e)}))},[F]);let I=e=>{let t=he(e);f(e=>({...e,[t.id]:t})),g(t.id),v(t.id),A&&e.id!==A.id&&b(e.id),O(t)},L=()=>{A&&I(A)},R=async e=>{let t=E.current.get(e);t&&(clearTimeout(t),E.current.delete(e)),f(t=>{let n={...t};return delete n[e],n}),m(t=>[...t,e]),h===e&&g(null);let n=await a.d(e);n&&(m(t=>t.filter(t=>t!==e)),w(t=>({...t,[e]:n})))},B=i||s,V=new Set(j.map(e=>e.id)),H=A?D.filter(e=>e.memberId===A.id):[],U=(0,S.useMemo)(()=>{if(!A)return[];let e=new Map;for(let t of D){if(t.memberId===A.id)continue;let n=e.get(t.memberId);n?n.push(t):e.set(t.memberId,[t])}let t=[];for(let n of j)n.id!==A.id&&(t.push({id:n.id,name:a.g(n)||n.email,stale:!1,schedules:e.get(n.id)||[]}),e.delete(n.id));for(let[n,r]of e)t.push({id:n,name:r[0].memberName.trim()||`Someone no longer on the team`,stale:!0,schedules:r});return t},[D,j,A]);return(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(t.m,{icon:n.C,title:`Your schedules`,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.`,actions:B?void 0:({open:e})=>(0,C.jsx)(t.o,{icon:u.t,compact:!0,title:`Add a schedule`,onClick:()=>{e(),L()},children:`Add a schedule`}),children:(0,C.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[B?(0,C.jsx)(`p`,{className:t.s,children:`Loading your schedules…`}):H.length===0?(0,C.jsx)(`p`,{className:`${t.s} px-1`,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.`}):H.map(e=>(0,C.jsx)($,{schedule:e,stale:!V.has(e.memberId),fresh:_===e.id,open:h===e.id,error:x[e.id],onToggle:()=>g(h===e.id?null:e.id),onChange:k,onRemove:()=>R(e.id)},e.id)),!!N&&(0,C.jsx)(`p`,{className:`text-[12px] font-semibold text-red-500 px-1`,children:N})]})}),e&&(0,C.jsx)(t.m,{icon:n.S,title:`Your team's schedules`,description:`When everyone else is free — one folded row per person; open a name to add their hours or see what they keep.`,children:(0,C.jsx)(`div`,{className:`flex flex-col gap-3`,children:B?(0,C.jsx)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug`,children:`Loading your team's schedules…`}):U.length===0?(0,C.jsxs)(`p`,{className:`text-[11px] sm:text-[11.5px] text-foreground/40 font-medium leading-snug px-1`,children:[`Nobody else is marked Internal or Admin yet. Add them on the`,` `,(0,C.jsx)(T.Link,{to:`/users`,className:`text-accent font-bold hover:underline`,children:`Users screen`}),` and a folded row for them appears here.`]}):U.map(e=>(0,C.jsx)(ye,{name:e.name,schedules:e.schedules,stale:e.stale,open:y===e.id,onToggle:()=>{let t=y!==e.id;b(t?e.id:null),t&&e.schedules.length&&g(e.schedules[0].id)},onAdd:()=>{let t=j.find(t=>t.id===e.id);t&&I(t)},openScheduleId:h,freshId:_,errors:x,onToggleSchedule:e=>g(h===e?null:e),onChange:k,onRemove:R},e.id))})})]})}function Se(){let{ready:e}=t.Jn(`schedule`);return e?(0,C.jsx)(X,{isAdmin:!0}):(0,C.jsx)(se,{})}function Ce(){let{user:i,userRole:o}=t.Ft(),s=o===`admin`,{schedules:c}=a.y(),l=i&&(i.displayName||i.email?.split(`@`)[0])||``;return r.Sn(o)?(0,C.jsxs)(`main`,{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`,children:[(0,C.jsxs)(t.nt.div,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},className:`mb-6`,children:[(0,C.jsx)(e.t,{children:`Schedule`}),(0,C.jsxs)(`div`,{className:`flex items-center gap-2 text-foreground/40 font-bold uppercase tracking-[0.2em] text-[11px]`,children:[(0,C.jsx)(`span`,{className:`w-8 h-[1px] bg-foreground/10`}),`/schedule`]})]}),(0,C.jsxs)(`div`,{className:`flex flex-col gap-6 flex-1 pb-16`,children:[(0,C.jsx)(n.t,{}),(0,C.jsx)(v.n,{tab:`schedule`}),(0,C.jsx)(`div`,{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]`,children:(0,C.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,C.jsx)(`div`,{className:`flex flex-col gap-1.5 px-1`,children:(0,C.jsx)(`p`,{className:`text-[13px] font-medium text-foreground/60 leading-relaxed`,children:s?`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.`})}),s?(0,C.jsx)(Se,{}):(0,C.jsx)(X,{isAdmin:!1}),(0,C.jsx)(xe,{isAdmin:s}),(0,C.jsx)(G,{isAdmin:s}),(0,C.jsx)(fe,{schedules:c,myName:l,isAdmin:s,meId:i?.uid||``})]})})]})]}):(0,C.jsx)(`main`,{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`,children:(0,C.jsx)(_.i,{})})}exports.ScheduleAdmin=Ce;
@@ -1 +1 @@
1
- require(`./chunk-CiTBaPhY.cjs`),require(`./PageTitle-DQkvCB11.cjs`);const e=require(`./TimeZoneField-Ckn1pKAL.cjs`),t=require(`./schedule-BAea6q8_.cjs`),n=require(`./chevron-down-lyDK1rfL.cjs`),r=require(`./x-Ci8c5p6T.cjs`);let i=require(`react`),a=require(`react/jsx-runtime`),o=require(`react-router-dom`);var s=()=>{if(typeof window>`u`||!window.getSelection)return!1;try{let e=window.getSelection();return!!e&&!e.isCollapsed&&e.toString().trim().length>0}catch{return!1}},c=(e,t)=>t&&(Math.abs(e.clientX-t.x)>4||Math.abs(e.clientY-t.y)>4)?!1:!s(),l=e=>`${t.Vt(e)} · ${t.Yt(e.slotMinutes)}`,u=e=>{let n=t.X(e);return n?`${t.ut(e)} · ${n}`:t.ut(e)};function d({schedules:s,selected:c,onPick:d,placeholder:f=`Pick a schedule`,mode:p=`meetings`}){let[m,h]=(0,i.useState)(!1),g=p===`hours`,_=e=>g?t.ut(e):t.Vt(e),v=e=>g?u(e):l(e),y=e=>g?t.pt(e):t.P(e),b=e=>g?t.ft(e)?`Unfinished on the Schedule screen`:``:e.enabled?t.Rt(e)?`Unfinished on the Schedule screen`:``:`Turned off on the Schedule screen`;if(s.length===0)return(0,a.jsxs)(`p`,{className:e.s,children:[g?`No hours yet`:`No schedule yet`,` — add `,g?`a week`:`one`,` on the`,` `,(0,a.jsx)(o.Link,{to:`/schedule`,className:`text-accent font-bold hover:underline`,children:`Schedule screen`}),` first.`]});let x=c.map(e=>s.find(t=>t.id===e)).filter(e=>!!e);return(0,a.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,a.jsxs)(`div`,{className:`w-full min-h-11 flex items-center gap-2 px-3 py-1.5 rounded-[var(--input-radius,0.75rem)] border bg-[var(--panel-bg)] transition-all duration-300 console-field ${m?`border-accent`:`border-[var(--panel-border)] hover:border-accent/40`}`,children:[(0,a.jsxs)(`div`,{className:`flex-1 min-w-0 flex flex-wrap items-center gap-1.5`,children:[x.length===0&&(0,a.jsx)(`button`,{type:`button`,onClick:()=>h(e=>!e),className:`text-[14px] text-foreground/35 text-left cursor-pointer`,children:f}),x.map(e=>(0,a.jsxs)(`span`,{className:`inline-flex items-center gap-1.5 h-7 pl-2.5 pr-1.5 rounded-lg bg-accent/10 border border-accent/20 text-[12.5px] font-semibold text-foreground max-w-full`,children:[(0,a.jsx)(`span`,{className:`truncate`,children:_(e)}),(0,a.jsx)(`button`,{type:`button`,"aria-label":`Remove ${_(e)}`,onClick:()=>d(e.id),className:`w-4 h-4 rounded-md flex items-center justify-center text-foreground/50 hover:text-red-500 hover:bg-red-500/10 transition-colors cursor-pointer`,children:(0,a.jsx)(r.t,{className:`w-3 h-3`})})]},e.id))]}),(0,a.jsx)(`button`,{type:`button`,"aria-label":m?`Close the list of schedules`:`Open the list of schedules`,"aria-expanded":m,onClick:()=>h(e=>!e),className:`w-8 h-8 shrink-0 rounded-lg flex items-center justify-center text-foreground/40 hover:text-foreground hover:bg-foreground/[0.05] transition-colors cursor-pointer`,children:(0,a.jsx)(n.t,{className:`w-4 h-4 transition-transform ${m?`rotate-180`:``}`})})]}),m&&(0,a.jsx)(`div`,{className:`flex flex-col rounded-2xl border border-[var(--panel-border)]/60 px-2 py-1.5`,role:`listbox`,"aria-label":`Schedules`,"aria-multiselectable":!0,children:s.map(t=>{let n=c.includes(t.id),r=b(t);return(0,a.jsxs)(`button`,{type:`button`,role:`option`,"aria-selected":n,"aria-label":_(t),onClick:()=>d(t.id),className:`w-full flex items-center gap-2.5 px-2 py-2 text-left cursor-pointer rounded-xl hover:bg-foreground/[0.04] transition-colors ${y(t)?``:`opacity-70`}`,children:[(0,a.jsx)(`span`,{"aria-hidden":!0,className:`w-[18px] h-[18px] rounded-md border flex items-center justify-center shrink-0 transition-colors ${n?`bg-accent border-accent`:`border-[var(--panel-border)]`}`,children:n&&(0,a.jsx)(e.At,{className:`w-3 h-3 text-[var(--button-fg,#fff)]`})}),(0,a.jsx)(`span`,{className:`text-[13px] font-medium text-foreground/80 truncate min-w-0`,children:v(t)}),r&&(0,a.jsx)(`span`,{className:`text-[11px] font-semibold text-foreground/40 whitespace-nowrap shrink-0 max-sm:hidden`,children:r})]},t.id)})}),(0,a.jsx)(`span`,{className:e.s,children:g?`One person’s hours each — picking a second week of theirs replaces the first.`:`One schedule per person — picking a second one of theirs replaces the first.`})]})}Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return d}});
1
+ require(`./chunk-CiTBaPhY.cjs`),require(`./PageTitle-BL50s4qY.cjs`);const e=require(`./TimeZoneField-Ckn1pKAL.cjs`),t=require(`./schedule-BAea6q8_.cjs`),n=require(`./chevron-down-lyDK1rfL.cjs`),r=require(`./x-Ci8c5p6T.cjs`);let i=require(`react`),a=require(`react/jsx-runtime`),o=require(`react-router-dom`);var s=()=>{if(typeof window>`u`||!window.getSelection)return!1;try{let e=window.getSelection();return!!e&&!e.isCollapsed&&e.toString().trim().length>0}catch{return!1}},c=(e,t)=>t&&(Math.abs(e.clientX-t.x)>4||Math.abs(e.clientY-t.y)>4)?!1:!s(),l=e=>`${t.Vt(e)} · ${t.Yt(e.slotMinutes)}`,u=e=>{let n=t.X(e);return n?`${t.ut(e)} · ${n}`:t.ut(e)};function d({schedules:s,selected:c,onPick:d,placeholder:f=`Pick a schedule`,mode:p=`meetings`}){let[m,h]=(0,i.useState)(!1),g=p===`hours`,_=e=>g?t.ut(e):t.Vt(e),v=e=>g?u(e):l(e),y=e=>g?t.pt(e):t.P(e),b=e=>g?t.ft(e)?`Unfinished on the Schedule screen`:``:e.enabled?t.Rt(e)?`Unfinished on the Schedule screen`:``:`Turned off on the Schedule screen`;if(s.length===0)return(0,a.jsxs)(`p`,{className:e.s,children:[g?`No hours yet`:`No schedule yet`,` — add `,g?`a week`:`one`,` on the`,` `,(0,a.jsx)(o.Link,{to:`/schedule`,className:`text-accent font-bold hover:underline`,children:`Schedule screen`}),` first.`]});let x=c.map(e=>s.find(t=>t.id===e)).filter(e=>!!e);return(0,a.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,a.jsxs)(`div`,{className:`w-full min-h-11 flex items-center gap-2 px-3 py-1.5 rounded-[var(--input-radius,0.75rem)] border bg-[var(--panel-bg)] transition-all duration-300 console-field ${m?`border-accent`:`border-[var(--panel-border)] hover:border-accent/40`}`,children:[(0,a.jsxs)(`div`,{className:`flex-1 min-w-0 flex flex-wrap items-center gap-1.5`,children:[x.length===0&&(0,a.jsx)(`button`,{type:`button`,onClick:()=>h(e=>!e),className:`text-[14px] text-foreground/35 text-left cursor-pointer`,children:f}),x.map(e=>(0,a.jsxs)(`span`,{className:`inline-flex items-center gap-1.5 h-7 pl-2.5 pr-1.5 rounded-lg bg-accent/10 border border-accent/20 text-[12.5px] font-semibold text-foreground max-w-full`,children:[(0,a.jsx)(`span`,{className:`truncate`,children:_(e)}),(0,a.jsx)(`button`,{type:`button`,"aria-label":`Remove ${_(e)}`,onClick:()=>d(e.id),className:`w-4 h-4 rounded-md flex items-center justify-center text-foreground/50 hover:text-red-500 hover:bg-red-500/10 transition-colors cursor-pointer`,children:(0,a.jsx)(r.t,{className:`w-3 h-3`})})]},e.id))]}),(0,a.jsx)(`button`,{type:`button`,"aria-label":m?`Close the list of schedules`:`Open the list of schedules`,"aria-expanded":m,onClick:()=>h(e=>!e),className:`w-8 h-8 shrink-0 rounded-lg flex items-center justify-center text-foreground/40 hover:text-foreground hover:bg-foreground/[0.05] transition-colors cursor-pointer`,children:(0,a.jsx)(n.t,{className:`w-4 h-4 transition-transform ${m?`rotate-180`:``}`})})]}),m&&(0,a.jsx)(`div`,{className:`flex flex-col rounded-2xl border border-[var(--panel-border)]/60 px-2 py-1.5`,role:`listbox`,"aria-label":`Schedules`,"aria-multiselectable":!0,children:s.map(t=>{let n=c.includes(t.id),r=b(t);return(0,a.jsxs)(`button`,{type:`button`,role:`option`,"aria-selected":n,"aria-label":_(t),onClick:()=>d(t.id),className:`w-full flex items-center gap-2.5 px-2 py-2 text-left cursor-pointer rounded-xl hover:bg-foreground/[0.04] transition-colors ${y(t)?``:`opacity-70`}`,children:[(0,a.jsx)(`span`,{"aria-hidden":!0,className:`w-[18px] h-[18px] rounded-md border flex items-center justify-center shrink-0 transition-colors ${n?`bg-accent border-accent`:`border-[var(--panel-border)]`}`,children:n&&(0,a.jsx)(e.At,{className:`w-3 h-3 text-[var(--button-fg,#fff)]`})}),(0,a.jsx)(`span`,{className:`text-[13px] font-medium text-foreground/80 truncate min-w-0`,children:v(t)}),r&&(0,a.jsx)(`span`,{className:`text-[11px] font-semibold text-foreground/40 whitespace-nowrap shrink-0 max-sm:hidden`,children:r})]},t.id)})}),(0,a.jsx)(`span`,{className:e.s,children:g?`One person’s hours each — picking a second week of theirs replaces the first.`:`One schedule per person — picking a second one of theirs replaces the first.`})]})}Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return d}});
@@ -1,4 +1,4 @@
1
- import "./PageTitle-DCoUQWw6.js";
1
+ import "./PageTitle-CkZriz8K.js";
2
2
  import { At as e, s as t } from "./TimeZoneField-oIMwb5_X.js";
3
3
  import { P as n, Rt as r, Vt as i, X as a, Yt as o, ft as s, pt as c, ut as l } from "./schedule-C13m_kiO.js";
4
4
  import { t as u } from "./chevron-down--LwXEv9w.js";
@@ -1,7 +1,7 @@
1
- import { _ as e, b as t, t as n } from "./PageTitle-DCoUQWw6.js";
1
+ import { _ as e, b as t, t as n } from "./PageTitle-CkZriz8K.js";
2
2
  import { At as r, It as i, Lt as a, Rt as o, mi as s, nt as c } from "./TimeZoneField-oIMwb5_X.js";
3
3
  import { t as l } from "./arrow-right-C6OLl8Zh.js";
4
- import { t as u } from "./SupportBar-DI_XbEsG.js";
4
+ import { t as u } from "./SupportBar-0nIiQp-_.js";
5
5
  import { t as d } from "./eye-off-CgKkn1b3.js";
6
6
  import { r as f } from "./x-hax8aKt8.js";
7
7
  import { t as p } from "./shield-check-DRQNdYcW.js";
@@ -1,4 +1,4 @@
1
- const e=require(`./chunk-CiTBaPhY.cjs`),t=require(`./PageTitle-DQkvCB11.cjs`),n=require(`./TimeZoneField-Ckn1pKAL.cjs`),r=require(`./arrow-right-CGvbxks5.cjs`),i=require(`./SupportBar-DLWruzQb.cjs`),a=require(`./eye-off-zYG7T389.cjs`),o=require(`./x-Ci8c5p6T.cjs`),s=require(`./shield-check-Bsd5oaif.cjs`);let c=require(`react`);c=e.a(c,1);let l=require(`react/jsx-runtime`);require(`firebase/firestore`);var u=`aistudio`;function d(){return u}function f(){let[e,t]=(0,c.useState)(d);return[e,(0,c.useCallback)(e=>{t(e)},[])]}var p=`Set this project up for Your AI Firebase, and do only what is listed here.
1
+ const e=require(`./chunk-CiTBaPhY.cjs`),t=require(`./PageTitle-BL50s4qY.cjs`),n=require(`./TimeZoneField-Ckn1pKAL.cjs`),r=require(`./arrow-right-CGvbxks5.cjs`),i=require(`./SupportBar-DR52UpBq.cjs`),a=require(`./eye-off-zYG7T389.cjs`),o=require(`./x-Ci8c5p6T.cjs`),s=require(`./shield-check-Bsd5oaif.cjs`);let c=require(`react`);c=e.a(c,1);let l=require(`react/jsx-runtime`);require(`firebase/firestore`);var u=`aistudio`;function d(){return u}function f(){let[e,t]=(0,c.useState)(d);return[e,(0,c.useCallback)(e=>{t(e)},[])]}var p=`Set this project up for Your AI Firebase, and do only what is listed here.
2
2
 
3
3
  1. If there is no app in this folder yet, create a Vite + React + TypeScript app in it.
4
4
  2. Delete the starter demo — the counter, the logos, App.css, the sample markup. None of the template's own content stays.