PageSourceSearch

https://resoflow-prod.web.app/assets/GiftCardsPage-DpLiCjww.js

js resoflow-prod.web.app collected 2026-10-03 12:35:59 UTC 153,138 bytes, 8 lines download raw bytes

1!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};e.SENTRY_RELEASE={id:"1.0.0"};var t=(new e.Error).stack;t&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[t]="ebd15d89-0616-4b1c-b1ef-86b2a72c0b1f",e._sentryDebugIdIdentifier="sentry-dbid-ebd15d89-0616-4b1c-b1ef-86b2a72c0b1f")}catch(a){}}();import{G as e,j as t,E as a,dZ as s,J as r,A as n,T as l,bd as i,as as o,bx as d,a4 as c,I as m}from"./index-CJ0eVksD.js";import{u}from"./useRecordNavigation-DjjepiyG.js";import{a as h,B as p}from"./BackToOrigin-RuW2dzKN.js";import{O as x}from"./OverflowRow-BuyPqomT.js";import{R as g,r as b,c as f,b as y,L as j}from"./vendor-react-Cg5IBgwO.js";import{u as v}from"./useSettingsSearchTarget-eeaQVCow.js";import{i as k}from"./giftCardsSearchIndex-CcVl7Qu9.js";import{g as w,d as N,b as C,q as S,c as P,l as A,f as $,k as F,w as D}from"./vendor-firebase-db-BWYKWqg8.js";import{db as B}from"./firebase-DvHzvjpo.js";import{E as M}from"./EmptyState-CfE3HFLj.js";import{G as I}from"./GiftLinkSharePanel-CkH8mQD4.js";import{GiftCardSummarySection as E}from"./AnalyticsReportsPage-VYkcF6qU.js";import{u as L}from"./DashboardContext-CecwK-yo.js";import{u as T}from"./useEffectivePermissions-DeR9iY_g.js";import{c as R}from"./planService-RCjdxSEx.js";import{c as O}from"./apiClient--m1UJa-S.js";import{n as V}from"./notify-DLhs2xBD.js";import{friendlyErrorMessage as z}from"./errorMessages-DM6_MVJz.js";import{F as G}from"./FeatureLockedCard-2Y2aIVAt.js";import{l as U,m as _}from"./lockedFeatureUpsell-C7aSIBGh.js";import{T as q}from"./ToggleSwitch-B1alh_UU.js";import{u as H}from"./useSettingsForm-BeuidS82.js";import{S as W}from"./SettingsPageHeader-Br1PjBgk.js";import{I as Y}from"./IntroCard-BbVLhQ7_.js";import{D as K}from"./DashboardPageHeader-DaImy8ER.js";import{D as X,a as Q,b as J,c as Z,d as ee}from"./dialog-BCSGQg7_.js";import"./useEscapeLayer-BYkrVTo8.js";import"./layoutOverlayHost--rgM4dhW.js";import{b as te,a as ae}from"./PreviewIframe-B_TDQB3C.js";import{I as se}from"./ImageLibraryPicker-C54s0AeP.js";import{P as re,G as ne,M as le,C as ie}from"./ColourRow-lfsVvGjp.js";import{r as oe,b as de,A as ce,c as me}from"./passDesignShared-YmXh3dza.js";import{P as ue,A as he}from"./passFaces-CrGqGVrS.js";import{S as pe}from"./smartphone-RM1CIE-K.js";import{W as xe}from"./wallet-BxO8dl5I.js";import{j as ge}from"./core-6ZUfEAoE.js";import{a as be,F as fe,b as ye,N as je}from"./flowModel-D1Xmk-8w.js";import{u as ve}from"./useCreateFlow-DTQcOpmf.js";import{c as ke}from"./appFlowDraft-Bcn3Oz2d.js";import{X as we}from"./x-C3OBs_Zs.js";import{I as Ne}from"./image-plus-BWoqLJyD.js";import{C as Ce}from"./chevron-right-Gtu9w0j0.js";import{c as Se,C as Pe}from"./csvExport-BD005uXO.js";import{B as Ae}from"./button-Duwog9Kr.js";import{L as $e}from"./LockChip-B9bn6ZQx.js";import{S as Fe}from"./SuperAdminGateBadge-kTo0SbdR.js";import{F as De}from"./FirstThirtyDaysCard-DtgSE7S9.js";import{F as Be}from"./FeatureSettingsGear-Dbajixlo.js";import{D as Me}from"./DefaultChip-jDW45DA1.js";import{C as Ie}from"./CollapsibleBody-lwrwOhFp.js";import{u as Ee,D as Le}from"./DetailOverlay-sxQQoznb.js";import{s as Te}from"./scopedLocalStorage-C63pQoBG.js";import{u as Re}from"./useEntityLinks-vchY6mwM.js";import{S as Oe}from"./StatusBadge-BI14dKeu.js";import{S as Ve}from"./SegmentedControl-4bRNcesj.js";import{T as ze}from"./TabStrip-CArP_qo3.js";import{F as Ge}from"./FilterPill-CslfQf7S.js";import{A as Ue}from"./ActionButton-CE1Zg744.js";import{S as _e}from"./StatTile-D4twhVcu.js";import{C as qe}from"./ConfirmWarning-BIvPgVml.js";import{L as He}from"./LoadMoreList-CkOY2mAS.js";import{c as We}from"./collapsibleHeaderA11y-CIeQkCy-.js";import{u as Ye,S as Ke}from"./useSudoConfirmedAction-EdUPmc7B.js";import{P as Xe}from"./PinAuthoriseModal-ruf00N_e.js";import{d as Qe,a as Je,G as Ze,f as et,g as tt,h as at,i as st,j as rt,e as nt,k as lt,l as it,m as ot,n as dt,o as ct,p as mt,q as ut,b as ht,c as pt,r as xt,s as gt,D as bt,t as ft,u as yt,v as jt,w as vt,x as kt,y as wt,z as Nt,A as Ct,B as St,C as Pt,E as At,F as $t,H as Ft}from"./giftCardsPageModel-DI6mTVGk.js";import{R as Dt}from"./depositPolicy-C36EmljD.js";import{e as Bt,f as Mt}from"./formatMediumDate-DrTRR0Rb.js";import{D as It,d as Et,a as Lt,b as Tt,c as Rt}from"./DocumentSheet-BSfArzvk.js";import{r as Ot}from"./analyticsDataService-DV3bdrcr.js";import{u as Vt,C as zt}from"./analyticsGiftCardsService-BbOaUH8X.js";import{u as Gt}from"./usePrintSheet-DLT0QDTZ.js";import{f as Ut}from"./format-Cqu3RLcn.js";import{D as _t}from"./download-BuJGlMly.js";import{P as qt}from"./printer-Ktz_tnCx.js";import{f as Ht,i as Wt}from"./giftCardCode-CDVE1dQs.js";import{R as Yt}from"./RecordHistoryPanel-DUOFNwG0.js";import{a as Kt,C as Xt}from"./CopyableLink-cZsFs-kq.js";import{F as Qt}from"./file-text-u_eZxk1v.js";import{S as Jt}from"./scan-line-NLd5QWU6.js";import{L as Zt}from"./lock-DOPcn-g5.js";import{P as ea}from"./palette-BBeglEgF.js";import{S as ta}from"./sliders-horizontal-CPIbHz5P.js";import{S as aa}from"./search-D6ZOdNce.js";import{H as sa}from"./hand-coins-CjcbM6c2.js";import{M as ra}from"./mail-84xnCgqV.js";import{C as na}from"./calendar-plus-BefAFM5h.js";import{B as la}from"./banknote-_OVrR--s.js";import{E as ia}from"./external-link-V1YUMAgj.js";import{C as oa}from"./chevron-down-BXn20CPd.js";import{P as da}from"./plus-BHmXlL-_.js";import{S as ca}from"./sparkles-CgUeOSxs.js";import{B as ma}from"./badge-percent-BRDMSgAe.js";import{P as ua}from"./package-DLmUjuxN.js";import"./quickViewModel-CxCC59T1.js";import"./recordOrigin-mFCiAWUy.js";import"./chevron-left-Bp7EXqvH.js";import"./vendor-firebase-auth-Dw-tYyLh.js";import"./turnstileScript-Nso5-LFr.js";import"./UpdatedRefresh-BxqvDo89.js";import"./bookingCardRepaymentReport-B0mZ7Qq9.js";import"./eventRefundSummary-ByWVbDC6.js";import"./noShowFeeHistory-CaSTrGdy.js";import"./orderAndPayModel-Bflirgh7.js";import"./paymentLinksModel-BOfA3MTR.js";import"./tableLabel-CTusWA06.js";import"./orderFulfilment-B3VHUeT3.js";import"./StatStrip-nzG12xbl.js";import"./venueDayBounds-VJSOk1_p.js";import"./send-D0Sf24lu.js";import"./ModalShell-Ch-10s0s.js";import"./useBodyScrollLock-DyGE1b4L.js";import"./useFocusTrap-CalndOMK.js";import"./receipt-Ra8FArt2.js";import"./file-spreadsheet-B42zXlXH.js";import"./RecordLink-wVN0oHeM.js";import"./undo-2-B14zI8XL.js";import"./depositRefunds-B6RqvsGv.js";import"./coins-Cy3053b1.js";import"./piggy-bank-Cz_Wmkfz.js";import"./reportsBookingsCore-KNmCeMWB.js";import"./isWalkInSource-GMcf3upj.js";import"./reportFeeTotals-C9HCIblz.js";import"./calendar-check-E8FKLf7A.js";import"./user-x-BqG3PD0f.js";import"./RightSideOverlayPanel-0Jqbjv39.js";import"./detailSheet-Bnsb-Tek.js";import"./eye-CfKknz7o.js";import"./arrow-right-DcL7LUW3.js";import"./chart-column-Ce60bk00.js";import"./check-BWVn7Uwa.js";import"./concierge-bell-DKe79pEg.js";import"./helpers-DlcxdMGb.js";import"./cycleWindow-BHn3tM_i.js";import"./subDays-DeC4Dhpo.js";import"./en-US-DSTBSzO8.js";import"./postSignOutError-BXWQuBO0.js";import"./reportListenerDeath-Dlr7Syko.js";import"./publicBookingSource-CE6_PvFq.js";import"./eventService-Cq61G-nh.js";import"./useListenerRedial-Dy6lpSEx.js";
1import"./waitlist-BBTyHysC.js";import"./specialDateRules-BSvcUCYt.js";import"./staffTableJoining-D_MbVaX2.js";import"./userDocNameCache-7DB8l2eC.js";import"./bookingTypesModel-Dj3kT6QP.js";import"./noShowTableHold-Bu7QzwNJ.js";import"./waitlistRules-Bs9wu54o.js";import"./settingsService-DWNbfFyj.js";import"./timelineColourDefaults-DmyWhyHT.js";import"./staffService-Dn6Yer-g.js";import"./themeWriteRegister-CY0ImIDj.js";import"./offlineActionPolicy-Djb7n2Z2.js";import"./menuDealsModel-3su4us9K.js";import"./menuDietary-zYYOBkf9.js";import"./sha256Sync-21y9jCIc.js";import"./themeSync-BN6IDfTv.js";import"./defaults-sFNQu5fI.js";import"./SaveBarPresenceFlag-AnShycis.js";import"./productGoLive-DCloO1M9.js";import"./navVisibility-DeWB5MK3.js";import"./screenModes-DOVe14Vw.js";import"./useSetupWizardState-DMAylw7u.js";import"./visitTrackingMode-Ctuo0xO9.js";import"./HelpBubble-BANzJ5lJ.js";import"./LazyMountBoundary-BrLkzM1_.js";import"./circle-question-mark-B2AzTWoo.js";import"./wifi-off-Q64yAg_D.js";import"./popover-CCJTvFZr.js";import"./utils-DruVD-uI.js";import"./composite-DSWmIJ4G.js";import"./useButton-Dv-sk77p.js";import"./useBaseUiId-D49M12hI.js";import"./useRole-BY-HprSY.js";import"./ToolbarRootContext-BSjCopqj.js";import"./useViewportQuery-vHNKbmrR.js";import"./topbarTitleStore-nyK4uHxE.js";import"./ellipsis-UW_yNHBe.js";import"./Spinner-DieiqsRN.js";import"./index-C30fg99R.js";import"./monitor-CEuKXWea.js";import"./sun-AoCdfPtH.js";import"./moon-CR2FisSJ.js";import"./ImageCropModal-zG5aYrQa.js";import"./zoom-in-BW-uHuwR.js";import"./imagePipeline-BsWxDmXr.js";import"./images-CWpjfLF2.js";import"./upload-Vf4uzVPv.js";import"./camera-DZbvM-44.js";import"./circle-alert-D3WishKZ.js";import"./index-Cs92S-Ed.js";import"./label-BoaP9-o7.js";import"./rotate-ccw-C_2hB___.js";import"./venueAccent-DMW231X_.js";import"./settings-C3buqRAy.js";import"./NotificationBadge-DGdNA51i.js";import"./input-BNbbDe0f.js";import"./PinPad-DYB3_sFd.js";import"./key-round-qaK-xVfM.js";import"./giftCardBuyModel-C0cCjMqW.js";import"./partialRefundPolicy-mnu0SBYM.js";import"./auditLogRenderer-DX0JKk3U.js";import"./featureLabels-CQ70cw_j.js";import"./pluralise-CEAZ9OZE.js";import"./noNamePlaceholder-DJ5OS4JE.js";import"./constructNow-BTc9E087.js";import"./isSameDay-Coo3eWBk.js";import"./formatDistanceToNow-hAFKidyx.js";import"./getRoundingMethod-zHPTmWDF.js";import"./endOfMonth-CRwyNRy1.js";import"./history-DJ32pGjz.js";import"./circle-check-big-T2wfvjnq.js";import"./copy-CTf-EqRx.js";
2/**
3 * @license lucide-react v0.546.0 - ISC
4 *
5 * This source code is licensed under the ISC license.
6 * See the LICENSE file in the root directory of this source tree.
7 */const ha=e("pencil-line",[["path",{d:"M13 21h8",key:"1jsn5i"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}],["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}]]);const pa="GFTC-ARDP-REVW-SMPL",xa="£50.00",ga="16 Jul 2028";function ba({design:e,restaurantName:a,logoUrl:s,balanceLabel:r}){const{accentColor:n,textColor:l,labelColor:i}=e,o=`${e.emoji} ${e.greeting}`.trim(),d=function(e,t){if(!Number.isFinite(t)||t<=0)return 14;const a=function(e){let t=0;for(const a of e){const e=a.codePointAt(0)??0;65039!==e&&8205!==e&&(t+=e>8592?1.05:" "===a?.28:.52)}return t}(e);if(a<=0)return 34;const s=Math.floor(t/a);return Math.max(14,Math.min(34,s))}(xa,268),c=(r||"").trim()||"Balance";return t.jsxs("div",{className:"w-full max-w-[300px] rounded-2xl shadow-lg overflow-hidden",style:{backgroundColor:n,color:l},children:[t.jsxs("div",{className:"px-4 pt-3 flex items-start justify-between gap-2",children:[t.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[s&&t.jsx(ue,{src:oe(s,{lightBackgroun
7d:de(n)})||"",alt:"Venue logo",className:"h-7 w-auto max-w-[72px] object-contain shrink-0"}),t.jsx("span",{className:"text-sm font-semibold truncate",style:{color:l},children:a})]}),e.imageUrl&&t.jsx("div",{className:"shrink-0","data-wallet-slot":"header",children:t.jsx(he,{label:c,value:xa,fg:l,labelColor:i,align:"right"})})]}),e.imageUrl?t.jsx(ue,{src:e.imageUrl,alt:"Design image",className:"w-full object-cover mt-2.5",style:{aspectRatio:ce}}):t.jsxs("div",{className:"mt-2.5 px-4 flex flex-col justify-center",style:{aspectRatio:ce},children:[t.jsx("p",{className:"text-[9px] font-semibold uppercase tracking-wider leading-none",style:{color:i},children:c}),t.jsx("p",{"data-wallet-slot":"primary",className:"w-full font-light leading-none tracking-tight truncate mt-1",style:{color:l,fontSize:`${d}px`},children:xa})]}),t.jsxs("div",{className:"px-4 pt-3 flex items-end justify-between gap-4",children:[t.jsx("p",{"data-wallet-slot":"greeting",className:"min-w-0 text-[13px] leading-tight truncate",style:{color:l},title:o,children:o}),t.jsx("div",{className:"shrink-0",children:t.jsx(he,{label:"Expires",value:ga,fg:l,labelColor:i,align:"right"})})]}),t.jsx("div",{className:"px-4 py-3 flex justify-center",style:{color:l},children:t.jsx(le,{code:pa,variant:"wallet"})})]})}function fa({design:e,restaurantName:a,logoUrl:s}){const{accentColor:r,textColor:n,labelColor:l}=e;return t.jsxs("div",{className:"w-full max-w-[300px] rounded-2xl shadow-lg overflow-hidden",style:{backgroundColor:r,color:n},children:[t.jsxs("div",{className:"px-4 pt-3 flex items-center gap-2.5",children:[t.jsx("div",{className:"w-8 h-8 rounded-full bg-white overflow-hidden flex items-center justify-center shrink-0",children:s?t.jsx(ue,{src:s,alt:"Venue logo",className:"w-full h-full object-contain"}):t.jsx("span",{className:"text-base leading-none","aria-hidden":"true",children:e.emoji})}),t.jsx("span",{className:"text-xs font-medium truncate",style:{color:l},children:a})]}),t.jsxs("div",{className:"px-4 pt-2.5",children:[t.jsx("p",{className:"text-base font-semibold leading-tight truncate",style:{color:n},children:a}),t.jsx("p",{className:"text-[10px] mt-2",style:{color:l},children:"Balance"}),t.jsx("p",{className:"text-lg font-semibold leading-tight",style:{color:n},children:xa}),t.jsx("p",{className:"text-[10px] mt-2",style:{color:l},children:"Card number"}),t.jsx("p",{className:"text-[11px] font-medium leading-tight",style:{color:n},children:pa})]}),t.jsx("div",{className:"px-4 py-3 flex justify-center",style:{color:n},children:t.jsx(le,{code:pa,variant:"wallet"})}),e.imageUrl&&t.jsx(ue,{src:e.imageUrl,alt:"Design image",className:"w-full object-cover",style:{aspectRatio:ce}})]})}function ya(e){return t.jsx(re,{ariaLabel:"Gift card wallet preview by platform",panels:[{value:"apple",label:"Apple Wallet",icon:pe,content:t.jsx(ba,{...e}),caption:"A guide — Wallet decides the final type size, and shortens any line that does not fit. The balance is the pass’s large main line and your greeting sits on a normal line under it; with a picture, the picture fills that space and the balance moves up beside your name. The balance updates on the customer’s phone after every redemption. "+((e.backNote||"").trim()?"On the back: the code, a link to check the balance, your note, and your venue’s name.":"On the back: the code, a link to check the balance, and your venue’s name.")},{value:"google",label:"Google Wallet",icon:xe,content:t.jsxs(t.Fragment,{children:[t.jsx(fa,{...e}),t.jsx(ne,{rows:[{label:"Greeting",value:`${e.design.emoji} ${e.design.greeting}`.trim()},{label:"Expires",value:ga},...(e.backNote||"").trim()?[{label:"About",value:(e.backNote||"").trim()}]:[]]})]}),caption:"Google lays the card out itself — your accent colour and image apply; text colours and the word “Balance” are Google’s. The balance is already Google’s main line."}]})}const ja=[{id:"classic",label:"Classic",emoji:"🎁",accentColor:"#334155",greeting:"A gift for you",intro:"You've been given a gift card for {{restaurantName}} — a treat to look forward to."},{id:"birthday",label:"Birthday",emoji:"🎂",accentColor:"#DB2777",greeting:"Happy birthday!",intro:"Someone thinks your birthday deserves a proper celebration at {{restaurantName}}."},{id:"christmas",label:"Christmas",emoji:"🎄",accentColor:"#166534",greeting:"Merry Christmas!",intro:"A festive treat for you — a {{restaurantName}} gift card to enjoy whenever you fancy."}
7,{id:"thank_you",label:"Thank you",emoji:"🌻",accentColor:"#B45309",greeting:"Thank you!",intro:"A small way of saying a big thank you — enjoy a visit to {{restaurantName}}."},{id:"congratulations",label:"Congratulations",emoji:"🎉",accentColor:"#7C3AED",greeting:"Congratulations!",intro:"Someone's celebrating you — enjoy it in style at {{restaurantName}}."},{id:"anniversary",label:"Anniversary",emoji:"💞",accentColor:"#BE123C",greeting:"Happy anniversary!",intro:"Here's to the two of you — a {{restaurantName}} gift card to celebrate together."},{id:"wedding",label:"Wedding",emoji:"🥂",accentColor:"#A16207",greeting:"Congratulations on your wedding!",intro:"Wishing you a lifetime of happiness — starting with a lovely meal at {{restaurantName}}."},{id:"with_love",label:"With love",emoji:"❤️",accentColor:"#B91C1C",greeting:"With love",intro:"A treat from someone who loves you — enjoy {{restaurantName}} together."},{id:"mothers_day",label:"Mother's Day",emoji:"🌷",accentColor:"#C026D3",greeting:"Happy Mother's Day!",intro:"For a wonderful mum — a well-earned treat at {{restaurantName}}."},{id:"fathers_day",label:"Father's Day",emoji:"🍻",accentColor:"#92400E",greeting:"Happy Father's Day!",intro:"For a brilliant dad — good food and good company at {{restaurantName}}."}],va=ja.map(e=>e.id),ka=/^#[0-9a-fA-F]{6}$/;function wa(e){if(!ka.test(e))return 0;return.2126*(parseInt(e.slice(1,3),16)/255)+.7152*(parseInt(e.slice(3,5),16)/255)+.0722*(parseInt(e.slice(5,7),16)/255)}function Na(e){return wa(e)>.6?"rgba(15,23,42,.72)":"rgba(255,255,255,.82)"}function Ca(e,t){const a=ja.find(t=>t.id===e)||ja[0],s=t&&t[a.id]||{},r="string"==typeof s.accentColor&&ka.test(s.accentColor)?s.accentColor:a.accentColor;return{id:a.id,label:a.label,emoji:a.emoji,accentColor:r,textColor:(n=r,wa(n)>.6?"#0F172A":"#FFFFFF"),labelColor:Na(r),greeting:"string"==typeof s.greeting&&s.greeting.trim()||a.greeting,intro:"string"==typeof s.intro&&s.intro.trim()||a.intro,imageUrl:"string"==typeof s.imageUrl&&s.imageUrl?s.imageUrl:null,enabled:!1!==s.enabled};var n}const Sa=e=>"string"==typeof e?e:"";function Pa(e,t){const a=[],s=Sa(e.greeting);s&&a.push(`“${s}”`);const r=[];return Sa(e.greeting)!==Sa(t.greeting)&&r.push("your greeting"),Sa(e.intro)!==Sa(t.intro)&&r.push("your intro"),Sa(e.accentColor)!==Sa(t.accentColor)&&r.push("your colour"),Sa(e.imageUrl)&&r.push("your photo"),a.push(r.length>0?`with ${ge(r)}`:"the standard design"),!1===e.enabled&&a.push("switched off"),a.join(" · ")}function Aa(e){return{...""!==e.greeting.trim()&&{greeting:e.greeting.trim()},...""!==e.intro.trim()&&{intro:e.intro.trim()},...""!==e.accentColor&&{accentColor:e.accentColor},...""!==e.imageUrl&&{imageUrl:e.imageUrl}}}function $a({tenantId:e,designId:s,entry:r,readOnly:n,restaurantName:l,logoUrl:i,balanceLabel:o,backNote:d,onClose:c,onApply:m}){var u;const h=ja.find(e=>e.id===s)||ja[0],p=g.useMemo(()=>ke(`resoflow.flowDraft.giftCardDesign.${h.id}`,1),[]),x=g.useMemo(()=>({greeting:r.greeting??"",intro:r.intro??"",accentColor:r.accentColor??"",imageUrl:"string"==typeof r.imageUrl?r.imageUrl:""}),[]),b=g.useMemo(()=>[{id:"greeting",label:"Greeting",answerSummary:e=>e.greeting.trim()?`“${e.greeting.trim()}”`:"the design’s own"},{id:"intro",label:"Intro line",answerSummary:e=>e.intro.trim()?`“${e.intro.trim()}”`:"the design’s own"},{id:"colour",label:"Accent colour",answerSummary:e=>e.accentColor?e.accentColor:"the design’s own"},{id:"photo",label:"Photo",optional:!0,answerSummary:e=>e.imageUrl?"your own photo":`the ${h.emoji} emoji`},{id:"review",label:"Check & apply"}],[h.emoji]),f=ve({steps:b,initialAnswers:x,draft:p}),{answers:y,setAnswers:j}=f,v=(null==(u=f.step)?void 0:u.id)??"greeting",[k,w]=g.useState(!1),[N,C]=g.useState(""),[S,P]=g.useState(!1),[A,$]=g.useState(!1),F=g.useRef(0),D=(e,t)=>j(a=>({...a,[e]:t})),B=g.useMemo(()=>Ca(h.id,{[h.id]:{...Aa(y),enabled:r.enabled}}),[h.id,y,r.enabled]),M=g.useMemo(()=>function(e,t){const a=[],s=Sa(e.label)||"This",r=Sa(e.greeting),n=Sa(e.intro),l=Sa(e.imageUrl),i=Sa(e.emoji);return r&&a.push(`Buyers picking the ${s} design send a gift that opens with “${r}” — on the gift email and the wallet pass.`),n&&a.push(`The intro line reads “${function(e){return e.replace(/\{\{restaurantName\}\}/g,"your venue name")}(n)}”.`),a.push(l?"The email band and the pass show your own photo.":`The email band and the pass show the ${i||"design's"} emoji.`),a.push(Sa(e.accentColor)!==Sa(t.accentColor)?`The accent colour is your own (${Sa(e.accentColor)}
7) — it colours the email band and the pass background.`:"The accent colour is the design's own — it colours the email band and the pass background."),!1===e.enabled&&a.push("Currently switched off — buyers can't pick this design, but gift cards already sent with it still show it."),a}(B,h),[B,h]),I=Pa(B,h);g.useEffect(()=>{if("review"!==v)return;const t=++F.current;P(!0);const a=window.setTimeout(async()=>{try{const a=await O("previewGiftCardEmail")({tenantId:e,designId:h.id,draftOverride:{...Aa(y)}});if(t!==F.current)return;C(a.data.renderedHtml)}catch(a){if(t!==F.current)return;console.warn("[GiftCardDesignFlow] preview failed:",a)}finally{t===F.current&&P(!1)}},300);return()=>window.clearTimeout(a)},[e,h.id,y,v]);const E=t.jsxs("div",{className:"mt-6",children:[t.jsx("p",{className:"text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-2",children:"Live wallet pass"}),t.jsx(ya,{design:B,restaurantName:l,logoUrl:i,balanceLabel:o,backNote:d})]}),L="mt-1.5 w-full px-3 py-2 rounded-dash-md border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 text-sm text-slate-900 dark:text-white placeholder:text-slate-500 disabled:opacity-60";return t.jsxs(be,{open:!0,title:`${h.label} design`,stepIndex:f.stepIndex,stepCount:f.stepCount,onExit:()=>{f.saveDraftNow(),c()},exitLabel:"Exit — saved as draft",inShell:!0,stepLabels:b.map(e=>e.label),onStepSelect:f.goTo,rail:t.jsx(je,{narration:t.jsxs(t.Fragment,{children:[t.jsx("span",{className:"font-bold",children:I})," — ",M.join(" ")]}),pendingHint:"review"===v?void 0:"… every answer is optional — blank keeps the design’s own.",steps:f.rail,eyebrow:"You're customising",onStepSelect:f.goTo,allowJumpAll:!0}),children:["greeting"===v&&t.jsxs(t.Fragment,{children:[t.jsx(fe,{eyebrow:"Greeting",question:`How should the ${h.label} design greet the person receiving it?`,help:`Shown big on the gift email and the wallet pass. Leave it blank to keep the design’s own greeting — “${h.greeting}”.`,children:t.jsx("input",{type:"text","aria-label":"Greeting",value:y.greeting,placeholder:h.greeting,maxLength:60,disabled:n,onChange:e=>D("greeting",e.target.value),className:L})}),E,t.jsx(ye,{onBack:f.back,canBack:f.canBack,onNext:f.next})]}),"intro"===v&&t.jsxs(t.Fragment,{children:[t.jsx(fe,{eyebrow:"Intro line",question:"What should the intro line say?",help:"The line under the greeting on the gift email. Leave it blank to keep the design’s own.",children:t.jsxs("div",{children:[t.jsx("textarea",{"aria-label":"Intro line",value:y.intro,placeholder:h.intro,maxLength:240,rows:3,disabled:n,onChange:e=>D("intro",e.target.value),className:L}),t.jsxs("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:["{{restaurantName}}"," becomes your venue name."]})]})}),E,t.jsx(ye,{onBack:f.back,canBack:f.canBack,onNext:f.next})]}),"colour"===v&&t.jsxs(t.Fragment,{children:[t.jsx(fe,{eyebrow:"Accent colour",question:"Which accent colour should it use?",help:"It colours the email band and the wallet pass background — the preview updates as you pick.",children:t.jsx(ie,{label:"Accent colour",hint:"The email band and the wallet pass background.",value:y.accentColor,defaultHex:h.accentColor,defaultLabel:"Use the design's colour",disabled:n,onChange:e=>D("accentColor",e||"")})}),E,t.jsx(ye,{onBack:f.back,canBack:f.canBack,onNext:f.next})]}),"photo"===v&&t.jsxs(t.Fragment,{children:[t.jsx(fe,{eyebrow:"Photo",question:"Add your own photo?",help:`Optional — it replaces the ${h.emoji} emoji on the email band and the pass.`,children:t.jsx("div",{className:"flex items-center gap-3",children:y.imageUrl?t.jsxs(t.Fragment,{children:[t.jsx("img",{src:y.imageUrl,alt:"Design",className:"w-24 h-14 roun
7ded-dash-md object-cover border border-slate-200 dark:border-slate-700"}),t.jsxs("button",{type:"button",disabled:n,onClick:()=>D("imageUrl",""),className:"inline-flex items-center gap-1 px-2.5 py-2 text-xs font-semibold rounded-dash-md border border-slate-200 dark:border-slate-700 text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 disabled:opacity-50",children:[t.jsx(we,{size:12})," Remove"]})]}):t.jsxs("button",{type:"button",disabled:n,onClick:()=>w(!0),className:"inline-flex items-center gap-1.5 px-3.5 py-2.5 text-sm font-semibold rounded-dash-lg border border-slate-200 dark:border-slate-700 text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 disabled:opacity-50",children:[t.jsx(Ne,{size:15})," Choose image…"]})})}),E,t.jsx(ye,{onBack:f.back,canBack:f.canBack,onNext:f.next,skip:""===y.imageUrl?{label:`Skip the photo — keep the ${h.emoji} emoji`,onSkip:f.next}:void 0})]}),"review"===v&&t.jsxs(t.Fragment,{children:[t.jsxs(fe,{eyebrow:"Check & apply",question:"Does this look right?",help:n?"You can look around, but applying design changes needs the “Manage gift cards” permission.":"The previews are exactly what buyers get. Applying returns you to the designs page — save your changes from the top bar there.",children:[t.jsxs("div",{className:"rounded-dash-xl border border-primary/20 bg-primary/5 dark:bg-primary/10 px-4 py-4",children:[t.jsx("p",{className:"text-[11px] font-bold uppercase tracking-wider text-primary/80 mb-1.5",children:"What this does"}),t.jsx("ul",{className:"space-y-1",children:M.map((e,a)=>t.jsx("li",{className:"text-xs text-slate-700 dark:text-slate-300 leading-relaxed",children:e},a))})]}),t.jsxs("section",{children:[t.jsxs("div",{className:"flex items-center justify-between mb-2",children:[t.jsx("p",{className:"text-sm font-bold text-slate-900 dark:text-white",children:"The gift email"}),t.jsx(te,{dark:A,onDarkChange:$})]}),t.jsx(ae,{srcDoc:N,width:"desktop",loading:S,dark:A})]}),t.jsxs("section",{children:[t.jsx("p",{className:"text-sm font-bold text-slate-900 dark:text-white mb-2",children:"The wallet pass"}),t.jsx(ya,{design:B,restaurantName:l,logoUrl:i,balanceLabel:o,backNote:d}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400 mt-2",children:"Google Wallet applies design changes to gift cards saved after the change — already-saved Google cards keep their look. Apple Wallet passes pick up the new design the next time they refresh."})]})]}),t.jsxs("div",{className:"flex flex-wrap items-center gap-3 mt-7",children:[t.jsx("button",{type:"button",onClick:f.back,"data-slot":"button",className:"inline-flex items-center gap-1.5 h-11 px-4 rounded-dash-lg border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 text-sm font-bold text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors",children:"Back"}),t.jsx("span",{className:"flex-1"}),!n&&t.jsx("button",{type:"button",onClick:()=>{f.clearDraft(),m(Aa(y)),c()},"data-slot":"button",className:a("inline-flex items-center gap-2 h-11 px-5 rounded-dash-lg bg-primary text-primary-foreground text-[15px] font-bold hover:bg-primary/90 transition-colors"),children:"Apply design"})]})]}),t.jsx(se,{open:k,tenantId:e,spot:{sourceSurface:"library",cropSpec:"giftCardBanner",stockKind:"cover",title:`${h.label} design image`,autoFolderId:"giftcards"},onClose:()=>w(!1),onSelect:e=>{w(!1),D("imageUrl",e.url)}})]})}function Fa(e){const t={};for(const[a,s]of Object.entries(e))t[a]={enabled:!0,...s};return t}function Da({isActiveTab:e}){const{tenantId:a,settings:n,emailSettings:l,planState:i}=L(),o=T(),d=o.has("vouchers.manage"),c=(null==i?void 0:i.planConfig)||(null==i?void 0:i.plan)||"taster",m=R(c,"giftVouchers"),[u,h]=g.useState({}),[p,x]=g.useState({passBalanceLabel:"",passBackNote:""}),[b,f]=g.useState(!1),[y,j]=g.useState(null);g.useEffect(()=>{if(!a||!m)return;let e=!1;return(async()=>{var t;try{const s=await w(N(B,"tenants",a,"settings","giftCardConfig"));if(e)return;const r=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return null;const t={};for(const[a,s]of Object.entries(e)){if(!va.includes(a))continue;if(!s||"object"!=typeof s||Array.isArray(s))continue;const e=s,r={};"boolean"==typeof e.enabled&&(r.enabled=e.enabled),"string"==typeof e.greeting&&e.greeting.trim()&&(r.greeting=e.greeting.trim().slice(0,60)),"string"==typeof e.intro&&e.intro.trim()&&(r.intro=e.intro.trim().slice(0,240)),"string"==typeof e.accentColor&&ka.test(e.accentColor.trim())&&(r.accentColor=e.accentColor.trim().toUpperCase()),null===e.imageUrl?r.imageUrl=null:"string"==typeof e.imageUrl&&e.imageUrl.length<=1024&&/^https:\/\//.test(e.imageUrl)&&(r.imageUrl=e.imageUrl),Object.keys(r).length>0&&(t[a]=r)}
7return Object.keys(t).length>0?t:null}(null==(t=s.data())?void 0:t.occasionDesigns)||{};h(Fa(r));const n=s.data()||{};x({passBalanceLabel:"string"==typeof n.passBalanceLabel?n.passBalanceLabel:"",passBackNote:"string"==typeof n.passBackNote?n.passBackNote:""})}catch(s){console.warn("[GiftCardDesignsSection] config load failed:",s)}finally{e||f(!0)}})(),()=>{e=!0}},[a,m]);const v=g.useMemo(()=>({overrides:u,...p}),[u,p]),k=H({savedValues:v,onSave:async e=>{if(!a)return;const t={passBalanceLabel:e.passBalanceLabel.trim(),passBackNote:e.passBackNote.trim()};try{await O("updateGiftCardConfig")({tenantId:a,config:{occasionDesigns:Object.keys(e.overrides).length>0?e.overrides:null,...t}})}catch(s){throw V.error(z(s)),new Error("save failed")}h(Fa(e.overrides)),x(t)}}),C=k.values.overrides,[S,P]=g.useState(!1);g.useEffect(()=>{!S&&b&&requestAnimationFrame(()=>{requestAnimationFrame(()=>P(!0))})},[b,S]);const A=g.useMemo(()=>me(l||{},n||{}),[l,n]),$=(null==n?void 0:n.restaurantName)||"Your venue";if(null==i?void 0:i.loading)return t.jsx(s,{});if(!m){const e=U("giftVouchers",_("giftVouchers"));return t.jsx(G,{headline:"Gift cards are available on Pro and Complete",description:"Sell beautiful digital gift cards from your own page — with occasion designs, scheduled delivery for birthdays and Christmas, wallet passes and full balance tracking."+(e?` ${e}`:""),icon:t.jsx(r,{size:28,className:"text-white"})})}const F=!d||!o.loaded,D=y&&ja.find(e=>e.id===y)||null;return t.jsxs("div",{className:"space-y-6",children:[e&&t.jsx(W,{icon:null,title:"Gift card designs",description:null,dirty:k.dirty,saving:k.saving,savedFlash:k.savedFlash,onSave:k.save,onDiscard:k.discard}),t.jsx(Y,{lead:"Choose which occasion designs buyers can pick, and give each one your venue's touch — the greeting, the intro line, the accent colour and an optional photo. Open a design to customise it with live previews of the gift email and the wallet pass."}),F&&o.loaded&&t.jsx("div",{className:"rounded-dash-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 px-4 py-3 text-sm text-amber-800 dark:text-amber-200",children:"You can look around, but editing designs needs the “Manage gift cards” permission."}),t.jsx("div",{className:"rounded-dash-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm divide-y divide-slate-100 dark:divide-slate-800",children:ja.map(e=>{const a=Ca(e.id,C),s=Pa(a,e);return t.jsxs("div",{className:"flex items-center gap-3 px-3 py-2.5",children:[t.jsxs("button",{type:"button",onClick:()=>j(e.id),"data-slot":"button",className:"flex items-center gap-3 flex-1 min-w-0 text-left rounded-dash-md hover:bg-slate-50 dark:hover:bg-slate-800/40 transition-colors py-1 -my-1 px-1 -mx-1",children:[t.jsx("span",{className:"w-8 h-8 rounded-dash-md flex items-center justify-center text-base shrink-0",style:{backgroundColor:a.accentColor},"aria-hidden":"true",children:a.emoji}),t.jsxs("span",{className:"flex-1 min-w-0",children:[t.jsx("span",{className:"block text-sm font-semibold truncate "+(a.enabled?"text-slate-900 dark:text-white":"text-slate-500 dark:text-slate-400"),children:e.label}),t.jsx("span",{className:"block text-[11px] text-slate-500 dark:text-slate-400 truncate",children:s})]}),t.jsx(Ce,{size:16,className:"text-slate-500 dark:text-slate-400 shrink-0","aria-hidden":"true"})]}),t.jsx(q,{value:a.enabled,disabled:F,ariaLabel:`Offer the ${e.label} design`,initialLoadComplete:S,onChange:()=>{k.setValue("overrides",{...C,[e.id]:{...C[e.id]||{},enabled:!a.enabled}})}})]},e.id)})}),t.jsxs("div",{className:"rounded-dash-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm p-4 space-y-4",children:[t.jsxs("div",{children:[t.jsx("p",{className:"text-sm font-bold text-slate-900 dark:text-white",children:"Words on the wallet pass"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400 mt-0.5",children:"These apply to every design. A wallet decides its own type size and typeface — no pass can change those."})]}),t.jsxs("div",{className:"space-y-1",children:[t.jsx("label",{className:"text-xs font-semibold text-slate-700 dark:text-slate-200",htmlFor:"gift-pass-balance-label",children:"Your word for the balance"}),t.jsx("input",{id:"gift-pass-balance-label",type:"text",value:k.values.passBalanceLabel,maxLength:20,disabled:F,placeholder:"Balance",onChange:e=>k.setValue("passBalanceLabel",e.target.value),className:"w-full max-w-xs rounded-dash-md border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-900 text-slate-900 dark:text-white px-3 py-2 text-sm disabled:opacity-60"}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400",children:"Shown above the amount on the Apple Wallet pass — for example “Credit” or “To spend”. Up to 20 characters. Google Wallet always says “Balance”."})]}),t.jsxs("div",{className:"space-y-1",children:[t.jsx("label",{className:"text-xs font-semibold text-slate-700 dark:text-slate-200",htmlFor:"gift-pass-back-note",children:"A note on the back of the pass"}),t.jsx("textarea",{id:"gift-pass-back-note",value:k.values.passBackNote,maxLength:200,rows:3,disabled:F,placeholder:"e.g. Book a table at any time — just show this card when you pay.",onChange:e=>k.setValue("passBackNote",e.target.value),className:"w-full rounded-dash-md border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-900 text-slate-900 dark:text-white px-3 py-2 text-sm disabled:opacity-60"}),t.jsxs("p",{className:"text-[11px] text-slate-500 dark:text-slate-400",children:[k.values.passBackNote.trim().length,"/200 · On the back of the Apple pass, and listed when a Google card is opened. Passes already saved to a phone pick it up the next time they update."]})]})]}),a&&D&&t.jsx($a,{tenantId:a,designId:D.id,entry:C[D.id]||{},readOnly:F,restaurantName:$,logoUrl:A.logoUrl||null,balanceLabel:k.values.passBalanceLabel,backNote:k.values.passBackNote,onClose:()=>j(null),onApply:e=>((e,t)=>{const a=C[e]||{},s={...t,...void 0!==a.enabled&&{enabled:a.enabled}},r={...C};0===Object.keys(s).length?delete r[e]:r[e]=s,k.setValue("overrides",r)})(D.id,e)},D.id),k.blockerModal]})}function Ba(e,t){const a=!0===(null==e?void 0:e.acceptForTableOrders);if("table"===t)return a;const s="collection"===t?null==e?void 0:e.acceptForCollectionOrders:null==e?void 0:e.acceptForDeliveryOrders;return"boolean"==typeof s?s:a}const Ma="The recorded movements don't quite add up to this card's current balance. The balance shown is what the card actually holds — if anything looks wrong, contact ResoFlow support.",Ia=e=>e.paymentTakenBy?` (${Qe[e.paymentTakenBy]})`:"";function Ea(e,t,a){switch(e){case"issue":return"at_venue"===a.saleChannel?`Sold at the venue${Ia(a)}`:"Bought online";case"activate":return`Activated at the venue${Ia(a)}`;case"redeem":return"Spent at the venue";case"adjust":return t<0?"Balance correction (removed)":"Balance correction (added)";case"refund":return"Refunded to the buyer";case"expiry":return"Expired — remaining balance removed";case"void":return"Voided";case"replace_out":return"Balance moved to a replacement card";case"replace_in":return"Balance moved from the card this one replaced";case"replacement":return"Returned gift value re-issued on this card";default:return"Movement"}}const La=[{key:"date",label:"Date"},{key:"movement",label:"Movement"},{key:"amount",label:"Amount (£)"},{key:"balanceAfter",label:"Balance after (£)"},{key:"recordedBy",label:"Recorded by"},{key:"note",label:"Note"}],Ta=e=>(e/100).toFixed(2),Ra=e=>{if(null===e)return"";const t=new Date(e),a=String(t.getMonth()+1).padStart(2,"0"),s=String(t.getDate()).padStart(2,"0");return`${t.getFullYear()}-${a}-${s}`};function Oa(e,t){return null!==e&&e>t&&e<=t+2592e6}const Va=[{key:"item",label:"Item"},{key:"value",label:"Value"}];const za=e=>null===e?"—":Mt(new Date(e));function Ga({card:e,statement:a,venueName:s,logoSrc:r}){const{effectiveUse24Hour:n}=L(),l=Bt(new Date,n),i=Je(e,Date.now()).label,o=[{label:"Status",value:i},{label:"Sold",value:[za(e.issuedAtMs),e.replacementOrderId?"Linked order replacement (no new payment)":Ze[e.saleChannel]+(e.paymentTakenBy?` (${Qe[e.paymentTakenBy]})`:""),e.soldByName?`by ${e.soldByName}
7`:""].filter(Boolean).join(" · ")},{label:"Buyer",value:e.buyerName||"—"},{label:"Recipient",value:e.recipientName||(e.recipientEmail?"Sent by email":"Sent to the buyer")},{label:"Original value",value:et(e.initialAmountPence)+(e.bonusAmountPence?` (includes ${et(e.bonusAmountPence)} bonus)`:"")},{label:"Expires",value:za(e.expiresAtMs)}];return t.jsxs(It,{title:"Gift card statement",sub:`Code ending ${e.codeLast4} · printed ${l}`,venueName:s,periodLabel:`Printed ${l}`,logoSrc:r,children:[t.jsx(Et,{tiles:[{label:"Current balance",value:et(a.currentBalancePence)},{label:"Original value",value:et(e.initialAmountPence),hint:e.bonusAmountPence?`includes ${et(e.bonusAmountPence)} bonus`:void 0},{label:"Status",value:i},{label:"Expires",value:za(e.expiresAtMs)}]}),t.jsx(Lt,{title:"The card"}),t.jsx(Tt,{columns:[{label:"Fact",cls:"strong nw"},{label:"Detail"}],rows:o.filter(e=>"Status"!==e.label&&"Expires"!==e.label).map(e=>({key:e.label,cells:[e.label,e.value]}))}),t.jsx(Lt,{title:"Movements",aside:`— ${a.lines.length}`}),0===a.lines.length?t.jsx(Rt,{children:"No movements recorded for this card."}):t.jsx(Tt,{columns:[{label:"Date",cls:"nw"},{label:"Movement",cls:"strong"},{label:"Amount",align:"r",cls:"nw"},{label:"Balance after",align:"r",cls:"nw"},{label:"Details",cls:"muted"}],rows:[...a.lines.map(e=>({key:e.id,cells:[za(e.dateMs),e.label,`${e.amountPence<0?"−":"+"}${et(Math.abs(e.amountPence))}`,et(e.balanceAfterPence),[e.actorName,e.note].filter(Boolean).join(" · ")||"—"]})),{key:"current",cells:["","Current balance","",et(a.currentBalancePence),""],rowClass:"total"}]}),a.discrepancy&&t.jsxs(Rt,{strong:!0,children:["Please note: ",Ma]}),t.jsx(Rt,{children:"Balances are the venue's records at the time of printing. The card's full code is never shown on a statement."})]})}function Ua(){const{printing:e,setPrinting:t}=Gt();return{printing:e,startPrint:()=>t(!0),stopPrint:()=>t(!1)}}const _a=[{value:"today",label:"Today"},{value:"this-week",label:"This week"},{value:"this-month",label:"This month"},{value:"last-30d",label:"Last 30 days"},{value:"this-year",label:"This year"},{value:"custom",label:"Custom"}],qa=e=>Mt(e);function Ha({open:e,onClose:a,tenantId:s,venueName:r,ensureAllRows:l}){const i=Ut(new Date,"yyyy-MM-dd"),[o,d]=b.useState("this-month"),[c,m]=b.useState(i),[u,h]=b.useState(i),[p,x]=b.useState(!0),{printing:g,startPrint:y}=Ua(),j=b.useMemo(()=>"custom"===o?function(e,t){const a=e=>{if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,a,s]=e.split("-").map(Number),r=new Date(t,a-1,s);return Number.isFinite(r.getTime())?r:null},s=new Date;s.setHours(0,0,0,0);let r=a(e)||s,n=a(t)||s;return r.getTime()>n.getTime()&&([r,n]=[n,r]),{start:r,end:n,preset:"custom",label:`${qa(r)} – ${qa(n)}`}}(c,u):Ot(o),[o,c,u]),{summed:v,loading:k,error:w}=Vt(s,j),N=b.useRef(l);N.current=l;const[C,S]=b.useState(null);b.useEffect(()=>{let e=!1;return N.current().then(t=>{e||S(t)}
7).catch(t=>{console.warn("[GiftCardSummaryDialog] card load failed:",t),e||(V.error(z(t)),a())}),()=>{e=!0}},[]);const P=b.useMemo(()=>function(e,t){const a={totalCards:e.length,activeCount:0,inactiveCount:0,redeemedCount:0,expiredCount:0,voidCount:0,outstandingLiabilityPence:0,expiringSoonCount:0,expiringSoonValuePence:0,activeCards:[]};for(const s of e)switch(s.status){case"active":{a.activeCount++;const e=Math.max(0,s.remainingBalancePence||0);a.outstandingLiabilityPence+=e,a.activeCards.push(s),Oa(s.expiresAtMs,t)&&(a.expiringSoonCount++,a.expiringSoonValuePence+=e);break}case"inactive":a.inactiveCount++;break;case"redeemed":a.redeemedCount++;break;case"expired":a.expiredCount++;break;case"void":a.voidCount++}return a.activeCards.sort((e,t)=>(null===e.expiresAtMs?Number.POSITIVE_INFINITY:e.expiresAtMs)-(null===t.expiresAtMs?Number.POSITIVE_INFINITY:t.expiresAtMs)),a}(C||[],Date.now()),[C]),A=k||null===C;return t.jsxs(t.Fragment,{children:[t.jsx(X,{open:e,onOpenChange:e=>!e&&a(),children:t.jsxs(Q,{className:"sm:max-w-lg print:hidden",children:[t.jsxs(J,{children:[t.jsx(Z,{children:"Gift cards summary"}),t.jsx(ee,{children:"Your gift card figures for a period — print them or download a CSV."})]}),t.jsxs("div",{children:[t.jsx("div",{className:"t-caption uppercase text-muted-foreground mb-1.5",children:"Period"}),t.jsx("div",{className:"grid grid-cols-3 gap-1.5",role:"group","aria-label":"Summary period",children:_a.map(e=>t.jsx(Ge,{active:o===e.value,onClick:()=>d(e.value),activeClassName:"bg-primary text-white border-primary",inactiveClassName:"bg-white dark:bg-slate-900 text-slate-600 dark:text-slate-400 border-slate-200 dark:border-slate-700 hover:bg-slate-50 dark:hover:bg-slate-800",className:"h-8 w-full justify-center px-2 font-semibold",children:e.label},e.value))}),"custom"===o&&t.jsxs("div",{className:"flex items-center gap-2 mt-2",children:[t.jsx("input",{type:"date",value:c,onChange:e=>m(e.target.value),"aria-label":"From date",className:"h-8 flex-1 rounded-dash-md border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 px-2 text-xs font-semibold text-slate-700 dark:text-slate-300 dark:[color-scheme:dark]"}),t.jsx("span",{className:"text-xs text-muted-foreground shrink-0",children:"to"}),t.jsx("input",{type:"date",value:u,onChange:e=>h(e.target.value),"aria-label":"To date",className:"h-8 flex-1 rounded-dash-md border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 px-2 text-xs font-semibold text-slate-700 dark:text-slate-300 dark:[color-scheme:dark]"})]})]}),t.jsxs("label",{className:"flex items-center gap-2 cursor-pointer py-0.5 min-w-0",children:[t.jsx("input",{type:"checkbox",checked:p,onChange:()=>x(e=>!e),className:"rounded border-primary/30 w-3.5 h-3.5 accent-primary shrink-0"}),t.jsx("span",{className:"text-xs font-semibold text-slate-700 dark:text-slate-300",children:"Print the list of active cards and their balances"})]}),t.jsx("div",{className:"rounded-dash-lg bg-slate-50 dark:bg-slate-800/60 border border-slate-200 dark:border-slate-700 px-3 py-2 text-xs font-semibold text-slate-700 dark:text-slate-300",children:A?t.jsxs("span",{className:"flex items-center gap-2",children:[t.jsx(n,{size:13,className:"animate-spin text-primary shrink-0"}),"Adding up your gift cards…"]}):w?t.jsx("span",{className:"text-red-600 dark:text-red-400",children:w}):t.jsxs(t.Fragment,{children:[j.label,": sold ",et(v.soldValuePence)," (",v.soldCount," card",1===v.soldCount?"":"s",") · spent ",et(v.redeemedValuePence),t.jsx("br",{}),"Right now: ",et(P.outstandingLiabilityPence)," outstanding on ",P.activeCount," ","active card",1===P.activeCount?"":"s"]})}),t.jsxs("div",{className:"flex justify-end gap-2",children:[t.jsx(Ae,{variant:"outline",onClick:a,className:"h-9 rounded-dash-lg px-4 text-xs font-bold",children:"Cancel"}),t.jsxs(Ae,{variant:"outline",onClick:()=>{A||Se(function(e,t,a){return[{item:"Period",value:e},{item:"Cards sold in period",value:String(t.soldCount)},{item:"Value loaded onto cards in period (£)",value:Ta(t.soldValuePence)},{item:"Redemptions in period",value:String(t.redeemedCount)},{item:"Value spent at the venue in period (£)",value:Ta(t.redeemedValuePence)},{item:"Refunded value in period (£)",value:Ta(t.refundedValuePence)},{item:"Voided value in period (£)",value:Ta(t.voidedValuePence)},{item:"Value lost to expiry in period (£)",value:Ta(t.expiredForfeitPence)},{item:"Cards on the books (all time)",value:String(a.totalCards)},{item:"Active cards",value:String(a.activeCount)}
7,{item:"Outstanding balance on active cards (£)",value:Ta(a.outstandingLiabilityPence)},{item:"Not activated (physical stock)",value:String(a.inactiveCount)},{item:"Fully used",value:String(a.redeemedCount)},{item:"Expired",value:String(a.expiredCount)},{item:"Voided",value:String(a.voidCount)},{item:"Active cards expiring in the next 30 days",value:String(a.expiringSoonCount)},{item:"Balance on those expiring cards (£)",value:Ta(a.expiringSoonValuePence)}]}(j.label,v,P),`gift-cards-summary-${Ut(new Date,"yyyy-MM-dd")}.csv`,Va)},disabled:A||!!w,className:"h-9 rounded-dash-lg px-4 text-xs font-bold gap-1.5",children:[t.jsx(_t,{size:14}),"Download CSV"]}),t.jsxs(Ae,{onClick:y,disabled:A||!!w||g,className:"h-9 rounded-dash-lg px-4 text-xs font-bold gap-1.5 bg-primary hover:bg-primary/90 text-primary-foreground",children:[t.jsx(qt,{size:14}),"Print"]})]})]})}),g&&"undefined"!=typeof document&&f.createPortal(t.jsx(Ya,{venueName:r,periodLabel:j.label,summed:v,holding:P,includeActiveList:p}),document.body)]})}const Wa=e=>null===e?"—":Mt(new Date(e));function Ya({venueName:e,periodLabel:a,summed:s,holding:r,includeActiveList:n,logoSrc:l}){const{effectiveUse24Hour:i}=L(),o=Bt(new Date,i),d=[{label:"Cards sold",value:`${s.soldCount} · ${et(s.soldValuePence)} loaded onto cards`},{label:"Spent at the venue",value:`${s.redeemedCount} redemption${1===s.redeemedCount?"":"s"} · ${et(s.redeemedValuePence)}`},{label:"Refunded",value:et(s.refundedValuePence)},{label:"Voided",value:et(s.voidedValuePence)},{label:"Lost to expiry",value:et(s.expiredForfeitPence)}],c=[{label:"Outstanding on active cards",value:`${et(r.outstandingLiabilityPence)} across ${r.activeCount} card${1===r.activeCount?"":"s"}`},{label:"Expiring in the next 30 days",value:`${r.expiringSoonCount} card${1===r.expiringSoonCount?"":"s"} · ${et(r.expiringSoonValuePence)} still on them`},{label:"Not activated (physical stock)",value:String(r.inactiveCount)},{label:"Fully used",value:String(r.redeemedCount)},{label:"Expired",value:String(r.expiredCount)},{label:"Voided",value:String(r.voidCount)},{label:"Cards on the books (all time)",value:String(r.totalCards)}],m=e=>t.jsx(Tt,{columns:[{label:"Figure",cls:"strong"},{label:"Value"}],rows:e.map(e=>({key:e.label,cells:[e.label,e.value]}))});return t.jsxs(It,{title:"Gift cards summary",sub:`${a} · printed ${o}`,venueName:e,periodLabel:a,logoSrc:l,children:[t.jsx(Et,{tiles:[{label:"Loaded onto cards",value:et(s.soldValuePence),hint:`${s.soldCount} sold`},{label:"Spent at the venue",value:et(s.redeemedValuePence),hint:`${s.redeemedCount} redemption${1===s.redeemedCount?"":"s"}`},{label:"Outstanding now",value:et(r.outstandingLiabilityPence),hint:`${r.activeCount} active card${1===r.activeCount?"":"s"}`}]}),t.jsx(Lt,{title:a}),m(d),t.jsx(Lt,{title:"Right now"}),m(c),n&&r.activeCards.length>0&&t.jsxs(t.Fragment,{children:[t.jsx(Lt,{title:"Active cards",aside:"— soonest expiry first"}),t.jsx(Tt,{columns:[{label:"Code ending",cls:"mono strong nw"},{label:"Buyer"},{label:"Recipient"},{label:"Issued",cls:"nw"},{label:"Expires",cls:"nw"},{label:"Balance",align:"r",cls:"strong nw"}],rows:r.activeCards.map(e=>({key:e.id,cells:[`…${e.codeLast4}`,e.buyerName||"—",e.recipientName||"—",Wa(e.issuedAtMs),Wa(e.expiresAtMs),et(e.remainingBalancePence)]}))})]}),t.jsx(Rt,{children:'Outstanding balances are money your customers can still spend with you — your gift-card liability. Period figures come from the card movement records: "sold" is the value loaded onto cards (any bonus promotion value included); "spent" is what customers redeemed at the venue.'})]})}const Ka=400,Xa="w-full px-3 py-2 rounded-dash-md border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 text-sm text-slate-900 dark:text-white placeholder:text-slate-500 disabled:opacity-60 dark:[color-scheme:dark]",Qa="text-xs font-semibold text-slate-600 dark:text-slate-300",Ja=[{value:"all",label:"All statuses"},{value:"active",label:"Active"},{value:"redeemed",label:"Fully used"},{value:"expired",label:"Expired"},{value:"void",label:"Voided"},{value:"inactive",label:"Not activated"}],Za=[{value:"all",label:"All channels"},{value:"online",label:"Online"},{value:"at_venue",label:"At the venue"}],es=e=>null===e?"—":Mt(new Date(e)),ts=e=>{const[t,a,s]=e.split("-").map(Number);return Mt(new Date(t,a-1,s))},as=e=>{const t=Number.parseFloat(e.replace(/[£,\s]/g,""));return Number.isFinite(t)?Math.round(100*t):null},ss=()=>("undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID().replace(/-/g,""):`${Date.now()}${Math.random().toString(36).slice(2)}`).slice(0,32);function rs(){const{tenantId:e,planState:a,settings:m}=L(),b=Re(e||""),j=y(),q=j.pathname.startsWith("/portal")?"/portal":"/dashboard",H=Boolean((null==m?void 0:m.stripeConnectAccountId)&&!1!==(null==m?void 0:m.stripeConnectChargesEnabled)),W=T(),J=W.has("vouchers.redeem"),ee=W.has("vouchers.refund"),te=W.has("vouchers.manage"),ae=W.has("vouchers.issue"),se="owner"===W.role||"admin"===W.role||"superadmin"===W.role,re=(null==a?void 0:a.planConfig)||(null==a?void 0:a.plan)||"taster",ne=R(re,"giftVouchers"),{trigger:le,modalProps:ie,pinModalProps:oe}=Ye(),[de,ce]=g.useState("cards"),[me,ue]=g.useState(!1);v(),g.useEffect(()=>{const e=j.hash.replace(/^#/,"");e&&k(e)&&(pe(!0),ce("settings"))},[j.hash]);const[he,pe]=g.useState(!1);g.useEffect(()=>{if(!he)return;const e=j.hash.replace(/^#/,"");e&&k(e)&&window.dispatchEvent(new Event("hashchange"))},[he]),g.useEffect(()=>{const e=()=>{const e=window.location.hash.replace(/^#/,"");"settings"!==e&&"physical"!==e||(pe(!0),ce("settings")),"designs"===e&&(ue(!0),ce("designs"))};return e(),window.addEventListener("hashchange",e),()=>window.removeEventListener("hashchange",e)},[j.hash]);const[xe,ge]=g.useState(null);g.useEffect(()=>{if(!e)return;if(ne)return void ge(!0);let t=!1;return(async()=>{try{const a=await C(S(P(B,"tenants",e,"vouchers"),A(1)));t||ge(!a.empty)}catch(a){console.warn("[GiftCardsPage] locked-plan probe failed:",a),t||ge(!1)}})(),()=>{t=!0}},[e,ne]);const[be,fe]=g.useState(null);g.useEffect(()=>{if(!e||"cards"!==de)return;let t=!1;return w(N(B,"tenants",e,"settings","giftCardConfig")).then(e=>{t||fe(!0===(e.exists()?e.data():{}).onlineSaleEnabled)}).catch(()=>{}),()=>{t=!0}},[e,de]);const[ye,je]=g.useState([]),[ve,ke]=g.useState(!0),[Ne,Ce]=g.useState(!1),[Pe,$e]=g.useState(!1),Fe=g.useRef(null),Me=ne||!0===xe,Ie=g.useCallback(async t=>{if(!e)return;const a=P(B,"tenants",e,"vouchers"),s=t||!Fe.current?S(a,$("issuedAt","desc"),A(100)):S(a,$("issuedAt","desc"),F(Fe.current),A(100)),r=await C(s);Fe.current=r.docs.length>0?r.docs[r.docs.length-1]:Fe.current;const n=r.docs.map(e=>tt(e.id,e.data()));je(e=>t?n:[...e,...n]),$e(100===r.docs.length)},[e]),[Te,We]=g.useState(!1),[xt,gt]=g.useState(0);g.useEffect(()=>{if(!e||!Me)return;let t=!1;return ke(!0),We(!1),Fe.current=null,(async()=>{try{await Ie(!0)}catch(e){console.warn("[GiftCardsPage] list load failed:",e),t||We(!0)}finally{t||ke(!1)}})(),()=>{t=!0}},[e,Me,Ie,xt]);const[bt,ft]=g.useState(null),[yt,jt]=g.useState(!0),vt=g.useCallback(async()=>
7{if(e)try{const t=await O("getGiftCardStats")({tenantId:e});ft(t.data)}catch(t){console.warn("[GiftCardsPage] stats load failed:",t)}finally{jt(!1)}},[e]);g.useEffect(()=>{Me&&vt()},[Me,vt]);const[kt,wt]=g.useState(""),[Nt,Ct]=g.useState("all"),[St,Pt]=g.useState("all"),At=""!==kt.trim()||"all"!==Nt||"all"!==St,[$t,Ft]=g.useState(!1);g.useEffect(()=>{if(!At||!Pe||$t||ve)return;let t=!1;return Ft(!0),(async()=>{try{for(let a=0;a<30&&!t;a++){const t=await C(S(P(B,"tenants",e,"vouchers"),$("issuedAt","desc"),F(Fe.current),A(Ka)));t.docs.length>0&&(Fe.current=t.docs[t.docs.length-1]);const a=t.docs.map(e=>tt(e.id,e.data()));if(a.length>0&&je(e=>[...e,...a]),t.docs.length<Ka){$e(!1);break}}}catch(a){console.warn("[GiftCardsPage] load-all failed:",a)}finally{t||Ft(!1)}})(),()=>{t=!0}},[At,Pe,$t,ve,e]);const Dt=Date.now(),Bt=g.useMemo(()=>ye.filter(e=>at(e,Nt,St,Dt)&&st(e,kt)),[ye,Nt,St,kt,Dt]),[Mt,It,Et]=Ee("id"),Lt=u(),Tt=h(),[Rt,Ot]=g.useState(null),Vt=g.useMemo(()=>ye.find(e=>e.id===Mt)||(Rt&&Rt.id===Mt?Rt:null),[ye,Mt,Rt]),Gt=g.useRef(null);g.useEffect(()=>{const t=Mt;t&&e&&Me&&!ve&&(ye.some(e=>e.id===t)?Gt.current=null:Rt&&Rt.id===t||Gt.current!==t&&(Gt.current=t,(async()=>{try{const a=await w(N(B,"tenants",e,"vouchers",t));if(Gt.current!==t)return;a.exists()?Ot(tt(a.id,a.data())):(V.info("That gift card is no longer available"),Et())}catch{V.error("Couldn't open that gift card. Please try again."),Et()}})()))},[Mt,ye,ve,e,Me,Rt,Et]);const[Ut,Xt]=g.useState([]),[ia,oa]=g.useState(!1),[da,ca]=g.useState(!1),ma=g.useCallback(async t=>{if(e){oa(!0),ca(!1);try{const a=(await C(S(P(B,"tenants",e,"voucherLedger"),D("voucherId","==",t)))).docs.map(e=>rt(e.id,e.data())).sort((e,t)=>(t.createdAtMs||0)-(e.createdAtMs||0));Xt(a)}catch(a){console.warn("[GiftCardsPage] ledger load failed:",a),Xt([]),ca(!0)}finally{oa(!1)}}},[e]);g.useEffect(()=>{Mt?ma(Mt):Xt([])},[Mt,ma]);const ua=g.useCallback(async t=>{if(e){try{const a=await w(N(B,"tenants",e,"vouchers",t));if(a.exists()){const e=tt(a.id,a.data());je(a=>a.map(a=>a.id===t?e:a)),Ot(a=>a&&a.id===t?e:a)}}catch(a){console.warn("[GiftCardsPage] row refresh failed:",a)}ma(t),vt()}},[e,ma,vt]),pa=Ua(),[xa,ga]=g.useState(!1),ba=g.useMemo(()=>Vt?function(e,t){const a=function(e){const t=[...e].sort((e,t)=>(null===e.createdAtMs?-1:e.createdAtMs)-(null===t.createdAtMs?-1:t.createdAtMs)),a=[];let s=0,r=0;for(;r<t.length;){let e=r+1;for(;e<t.length&&t[e].createdAtMs===t[r].createdAtMs;)e++;const n=t.slice(r,e);if(1===n.length)a.push(n[0]),s=n[0].balanceAfterPence;else{const e=[...n];for(;e.length>0;){const t=e.findIndex(e=>e.balanceAfterPence-e.amountPence===s),r=e.splice(t>=0?t:0,1)[0];a.push(r),s=r.balanceAfterPence}}r=e}return a}(t),s="number"==typeof e.remainingBalancePence?e.remainingBalancePence:0;let r=0,n=!0,l=0;return{lines:a.map(t=>{const a=Number.isFinite(t.amountPence)?t.amountPence:0;return r+=a,l+=a,t.balanceAfterPence!==l&&(n=!1),{id:t.id,dateMs:t.createdAtMs,label:Ea(t.type,a,e),amountPence:a,balanceAfterPence:t.balanceAfterPence,...t.actorName?{actorName:t.actorName}:{},...t.note?{note:t.note}:{}}}),currentBalancePence:s,ledgerSumPence:r,discrepancy:r!==s||!n}}(Vt,Ut):null,[Vt,Ut]),fa=!ia&&!da&&Ut.length>0,[ya,ja]=g.useState(!1),[ka,wa]=g.useState(""),Na=g.useRef(""),[Sa,Pa]=g.useState(!1),[Aa,$a]=g.useState(""),[Fa,Ba]=g.useState("add"),[Ia,Va]=g.useState(""),za=g.useRef(""),[_a,qa]=g.useState(!1),[Wa,Ya]=g.useState(!1),rs=g.useRef(""),[ns,is]=g.useState(null),[cs,ms]=g.useState(!1),[us,hs]=g.useState(""),[ps,xs]=g.useState(null);g.useEffect(()=>{if(!cs||!Vt||!e)return void xs(null);if(!Vt.replacesVoucherId)return void xs({forId:Vt.id,status:"ready",row:Vt});let t=!1;const a=Vt.id;return xs({forId:a,status:"loading"}),(async()=>{try{let s=Vt;const r=new Set([Vt.id]);for(let t=0;t<16&&s.replacesVoucherId&&!r.has(s.replacesVoucherId);t+=1){const t=s.replacesVoucherId;r.add(t);const a=await w(N(B,"tenants",e,"vouchers",t));if(!a.exists())throw new Error("replaced card not found");s=tt(a.id,a.data())}t||xs({forId:a,status:"ready",row:s})}catch(s){console.warn("[GiftCardsPage] refund payment source read failed:",s),t||xs({forId:a,status:"error"})}})(),()=>{t=!0}},[cs,Vt,e]);const[gs,bs]=g.useState(!1),[fs,ys]=g.useState(""),[js,vs]=g.useState(""),[ks,ws]=g.useState(!1),Ns=g.useRef(""),[Cs,Ss]=g.useState(!1),[Ps,As]=g.useState(""),[$s,Fs]=g.useState(!1),[Ds,Bs]=g.useState(null),[Ms,Is]=g.useState(!1),[Es,Ls]=g.useState(""),[Ts,Rs
7]=g.useState("cash"),[Os,Vs]=g.useState(""),[zs,Gs]=g.useState(""),[Us,_s]=g.useState(""),[qs,Hs]=g.useState(""),[Ws,Ys]=g.useState(""),[Ks,Xs]=g.useState("classic"),Qs=g.useRef(""),[Js,Zs]=g.useState(null),[er,tr]=g.useState(null),[ar,sr]=g.useState(!1),[rr,nr]=g.useState(""),[lr,ir]=g.useState(""),[or,dr]=g.useState("cash"),[cr,mr]=g.useState(""),[ur,hr]=g.useState(""),pr=g.useRef(""),[xr,gr]=g.useState(null),[br,fr]=g.useState(null),[yr,jr]=g.useState(void 0),vr=g.useMemo(()=>va.map(e=>Ca(e,yr??null)).filter(e=>e.enabled),[yr]),kr=g.useCallback(async()=>{Fe.current=null;try{await Ie(!0)}catch(e){console.warn("[GiftCardsPage] list refresh failed:",e)}vt()},[Ie,vt]),wr=()=>{Na.current=ss(),wa(""),ja(!0)},Nr=async()=>{if(!e||Ds)return;if("payment_link"===Ts)return void(await(async()=>{if(!e||Ds)return;const t=as(Es);if(null===t||t<=0)V.error("Please enter a valid amount.");else if(!zs.trim()||/^\S+@\S+\.\S+$/.test(zs.trim()))if(!qs.trim()||/^\S+@\S+\.\S+$/.test(qs.trim()))if(zs.trim()||qs.trim()){Bs("sell");try{const a=await O("createGiftCardPaymentRequest")({tenantId:e,amountPence:t,...Os.trim()?{buyerName:Os.trim()}:{},...zs.trim()?{buyerEmail:zs.trim()}:{},...Us.trim()?{recipientName:Us.trim()}:{},...qs.trim()?{recipientEmail:qs.trim()}:{},...Ws.trim()?{personalMessage:Ws.trim()}:{},...Ks?{occasionDesignId:Ks}:{}});tr({url:a.data.url}),V.success("Payment link created — the gift card is made the moment it's paid")}catch(a){V.error(z(a))}finally{Bs(null)}}else V.error("Add the buyer's or the recipient's email address — the gift card is emailed once the link is paid.");else V.error("Please check the recipient's email address.");else V.error("Please check the buyer's email address.")})());const t=as(Es);if(null===t||t<=0)V.error("Please enter a valid amount.");else if(!zs.trim()||/^\S+@\S+\.\S+$/.test(zs.trim()))if(!qs.trim()||/^\S+@\S+\.\S+$/.test(qs.trim())){Bs("sell");try{const a=await O("sellVoucherAtVenue")({tenantId:e,amountPence:t,paymentTakenBy:Ts,idempotencyKey:Qs.current,...Os.trim()?{buyerName:Os.trim()}:{},...zs.trim()?{buyerEmail:zs.trim()}:{},...Us.trim()?{recipientName:Us.trim()}:{},...qs.trim()?{recipientEmail:qs.trim()}:{},...Ws.trim()?{personalMessage:Ws.trim()}:{},...Ks?{occasionDesignId:Ks}:{}});Zs(a.data),await kr()}catch(a){V.error(z(a))}finally{Bs(null)}}else V.error("Please check the recipient's email address.");else V.error("Please check the buyer's email address.")},Cr=async()=>{if(!e||Ds)return;if("payment_link"===or)return void(await(async()=>{if(!e||Ds)return;if(!Wt(rr))return void V.error("That doesn't look like a gift card code — it has 16 letters and numbers.");const t=as(lr);if(null===t||t<=0)V.error("Please enter a valid amount.");else if(!ur.trim()||/^\S+@\S+\.\S+$/.test(ur.trim())){Bs("activate");try{const a=await O("createGiftCardActivationRequest")({tenantId:e,code:rr,amountPence:t,...cr.trim()?{buyerName:cr.trim()}:{},...ur.trim()?{buyerEmail:ur.trim()}:{}});fr({url:a.data.url}),V.success("Payment link created — the card goes live the moment it's paid")}catch(a){V.error(z(a))}finally{Bs(null)}}else V.error("Please check the email address.")})());if(!Wt(rr))return void V.error("That doesn't look like a gift card code — it has 16 letters and numbers.");const t=as(lr);if(null===t||t<=0)V.error("Please enter a valid amount.");else if(!ur.trim()||/^\S+@\S+\.\S+$/.test(ur.trim())){Bs("activate");try{const a=await O("activateGiftCard")({tenantId:e,code:rr,amountPence:t,paymentTakenBy:or,idempotencyKey:pr.current,...cr.trim()?{buyerName:cr.trim()}:{},...ur.trim()?{buyerEmail:ur.trim()}:{}});gr(a.data),await kr()}catch(a){V.error(z(a))}finally{Bs(null)}}else V.error("Please check the email address.")},Sr=async t=>{if(e&&Vt&&!Ds){Bs("redeem");try{const a=(await O("redeemGiftCard")({tenantId:e,idempotencyKey:Na.current,amountPence:t,voucherId:Vt.id,codeLast4:Vt.codeLast4})).data;a.shortfallPence>0?V.success(`${et(a.amountRedeemedPence)} redeemed — the card is now empty. ${et(a.shortfallPence)} of the bill still to take another way.`):V.success(`${et(a.amountRedeemedPence)} redeemed — ${et(a.remainingBalancePence)} left on the card`),ja(!1),await ua(Vt.id)}catch(a){V.error(z(a))}finally{Bs(null)}}},Pr=g.useCallback(async()=>
7{if(!e||!Pe)return ye;let t=ye,a=Fe.current;for(let s=0;s<30;s++){const s=await C(S(P(B,"tenants",e,"vouchers"),$("issuedAt","desc"),...a?[F(a)]:[],A(Ka))),r=s.docs.map(e=>tt(e.id,e.data()));if(t=[...t,...r],s.docs.length<Ka)break;a=s.docs[s.docs.length-1]}return je(t),$e(!1),t},[e,Pe,ye]),[Ar,$r]=g.useState(!1);if((null==a?void 0:a.loading)||!e||!ne&&null===xe)return t.jsx(s,{});if(!ne&&!1===xe){const e=U("giftVouchers",_("giftVouchers"));return t.jsx("div",{className:"p-4 md:p-8 max-w-7xl mx-auto",children:t.jsx(G,{headline:"Gift cards are available on Pro and Complete",description:"Sell beautiful digital gift cards from your own page — with occasion designs, scheduled delivery for birthdays and Christmas, balance tracking and simple at-the-venue redemption."+(e?` ${e}`:""),icon:t.jsx(r,{size:28,className:"text-white"})})})}const Fr=Vt?nt(Vt,Dt):null,Dr="scheduled"===(null==Vt?void 0:Vt.giftEmailState);return t.jsxs("div",{className:"p-4 md:p-8 max-w-7xl mx-auto space-y-6",children:[t.jsx(p,{}),t.jsx(K,{icon:r,title:"Gift cards",subtitle:yt||!bt?"Sell, track and redeem gift cards":`${bt.activeCount} active card${1===bt.activeCount?"":"s"} · ${et(bt.outstandingLiabilityPence)} outstanding`,right:t.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[t.jsxs(Ae,{variant:"outline",className:"rounded-dash-lg font-bold",onClick:()=>ga(!0),disabled:ve,children:[t.jsx(Qt,{size:14,className:"mr-1.5"})," Summary"]}),t.jsxs(Ae,{variant:"outline",className:"rounded-dash-lg font-bold",onClick:async()=>{if(e&&!Ar){$r(!0);try{const e=await Pr(),t=Date.now(),a=e.filter(e=>at(e,Nt,St,t)&&st(e,kt));Se(ht(a,t),`gift-cards-${(new Date).toISOString().slice(0,10)}.csv`,pt)}catch(t){V.error(z(t))}finally{$r(!1)}}},disabled:Ar||ve,children:[Ar?t.jsx(n,{size:14,className:"mr-1.5 animate-spin"}):t.jsx(_t,{size:14,className:"mr-1.5"})," Export CSV"]}),ne&&ae&&t.jsxs(t.Fragment,{children:[t.jsxs(Ae,{variant:"outline",className:"rounded-dash-lg font-bold",onClick:()=>{pr.current=ss(),nr(""),ir(""),dr("cash"),mr(""),hr(""),gr(null),fr(null),sr(!0)},children:[t.jsx(Jt,{size:14,className:"mr-1.5"})," Activate a card"]}),t.jsxs(Ae,{id:"sell",onClick:()=>{Qs.current=ss(),Ls(""),Rs("cash"),Vs(""),Gs(""),_s(""),Hs(""),Ys(""),Xs("classic"),Zs(null),tr(null),Is(!0),void 0===yr&&e&&w(N(B,"tenants",e,"settings","giftCardConfig")).then(e=>jr((e.exists()?e.data():{}).occasionDesigns??null)).catch(()=>jr(null))},className:"rounded-dash-lg bg-primary hover:bg-primary/90 text-primary-foreground font-bold",children:[t.jsx(r,{size:14,className:"mr-1.5"})," Sell a gift card"]})]}),t.jsx(Be,{to:`${q}/gift-cards#settings`,label:"Gift card settings",backLabel:"Gift cards"})]})}),t.jsx(Y,{lead:"Sell gift cards online or at the venue, then look them up and redeem them here when customers spend them. Every card keeps its own balance and a full money trail, and the money lands in your own Stripe account.",sub:"Design how the cards look on the Designs tab; choose amounts, expiry and online selling under Selling & settings."}),ne&&t.jsx(De,{storageKey:"giftCards",title:"Getting gift cards earning",intro:"Five things, in this order. The first sale is usually the slow one — most venues get there by putting the link somewhere customers already look.",steps:[{label:"Pick how the cards look",detail:"The Designs tab — one for everyday, and an occasion design or two for Christmas and birthdays."},{label:"Set your amounts and expiry",detail:"Under Selling & settings: the amounts customers can choose, and how long a card lasts.",done:null!==be||void 0},{label:"Switch on selling online",detail:"Also under Selling & settings. Until this is on, cards can only be sold at the venue.",done:null===be?void 0:be},{label:"Put the link where customers look",detail:"Your gift page link, on your website, your Instagram bio and a QR poster for the bar. This is the step that decides whether anyone buys one."},{label:"Show your staff how to redeem one",detail:"The Scanner takes a gift card code like any other — worth two minutes at a handover so nobody is stuck with a customer waiting."},{label:"Your first sale",detail:"It will appear in the table below, with its balance and full money trail.",done:ve?void 0:ye.length>0}]}),!ne&&t.jsxs("div",{className:"rounded-dash-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 px-4 py-3 text-sm text-amber-800 dark:text-amber-200 flex items-start gap-2",children:[t.jsx(Zt,{size:15,className:"mt-0.5 shrink-0"}),t.jsx("span",{children:"Your current plan doesn't include gift card selling, but every card you've already sold keeps working — you can still look cards up, redeem them, resend their emails, extend expiry dates and put things right here. Upgrade to Pro to sell again."})]}),m&&!H&&ye.some(e=>"online"===e.saleChannel&&("active"===nt(e,Date.now())||e.refundPending))&&t.jsxs("div",{className:"rounded-dash-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 px-4 py-3 text-sm text-amber-800 dark:text-amber-200 flex items-start gap-2",children:[t.jsx(l,{size:15,className:"mt-0.5 shrink-0"}),t.jsx("span",{children:"Stripe isn't connected, so gift card refunds are paused until you reconnect it in Settings → Payouts and Stripe. Redeeming cards at the venue keeps working as normal."})]}),t.jsxs("div",{className:"grid grid-cols-2 lg:grid-cols-4 gap-3",children:[t.jsx(_e,{label:"Outstanding on cards",value:bt?et(bt.outstandingLiabilityPence):"—",sub:bt?`${bt.activeCount} active card${1===bt.activeCount?"":"s"}`:void 0,loading:yt}),t.jsx(_e,{label:"Sold this month",value:bt?et(bt.month.soldValuePence):"—",sub:bt?`${bt.month.soldCount} card${1===bt.month.soldCount?"":"s"}${"number"==typeof bt.month.soldLoadedPence&&bt.month.soldLoadedPence!==bt.month.soldValuePence?` · ${et(bt.month.soldLoadedPence)} loaded onto cards`:""}${bt.month.channels?` · ${bt.month.channels.online.count} online · ${bt.month.channels.at_venue.count} at the venue`:""}`:void 0,loading:yt}),t.jsx(_e,{label:"Redeemed this month",value:bt?et(bt.month.redeemedValuePence):"—",sub:bt?`${bt.month.redeemedCount} redemption${1===bt.month.redeemedCount?"":"s"}`:void 0,loading:yt}
7),t.jsx(_e,{label:"Expiring in 30 days",value:bt?String(bt.expiringSoonCount):"—",sub:bt&&bt.expiringSoonCount>0&&"number"==typeof bt.expiringSoonValuePence?`${et(bt.expiringSoonValuePence)} still on those cards`:void 0,loading:yt})]}),ne&&e&&t.jsx(os,{tenantId:e,shellPrefix:q,onlineSaleOn:be,onOpenSettings:()=>{pe(!0),ce("settings")},qrHubAllowed:b.settingsAllowed("qrcodes")}),(()=>{const e=[{value:"cards",label:"Sold cards",icon:i},{value:"designs",label:"Designs",icon:ea},{value:"settings",label:"Selling & settings",icon:ta}];return t.jsx(ze,{tabs:e,activeValue:de,onChange:e=>{"settings"===e&&pe(!0),"designs"===e&&ue(!0),ce(e)},ariaLabel:"Gift cards sections"})})(),me&&t.jsx("div",{className:"designs"===de?"":"hidden",children:t.jsx(Da,{isActiveTab:"designs"===de})}),he&&t.jsxs("div",{className:"settings"===de?"space-y-6":"hidden",children:[t.jsx("div",{id:"settings",children:t.jsx(ds,{tenantId:e,unlocked:ne,canManage:te,isActiveTab:"settings"===de})}),ne&&ae&&se&&t.jsx("div",{id:"physical",children:t.jsx(ls,{tenantId:e,triggerSudo:le,onMinted:kr})}),!R(re,"analytics")&&t.jsx("div",{id:"gift-card-summary",children:t.jsx(E,{tenantId:e,unlocked:ne})})]}),"cards"===de&&t.jsxs("div",{children:[t.jsxs("div",{className:"space-y-3 min-w-0",children:[t.jsxs("div",{className:"space-y-2",children:[t.jsxs("div",{className:"relative",children:[t.jsx(aa,{size:14,className:"absolute left-3 top-1/2 -translate-y-1/2 text-slate-500 dark:text-slate-400 pointer-events-none"}),t.jsx("input",{type:"text",value:kt,onChange:e=>wt(e.target.value),placeholder:"Search by code ending, buyer or recipient…","aria-label":"Search gift cards",className:`${Xa} pl-9`})]}),t.jsxs(x,{wrapperClassName:"min-w-0",className:"flex items-center gap-1.5",role:"group","aria-label":"Filter gift cards",children:[Ja.map(e=>t.jsx(Ge,{active:Nt===e.value,tone:"all"===e.value?"primary":lt[e.value].tone,onClick:()=>Ct(e.value),children:e.label},e.value)),t.jsx("div",{className:"w-px h-4 bg-slate-200 dark:bg-slate-700 shrink-0","aria-hidden":"true"}),Za.map(e=>t.jsx(Ge,{active:St===e.value,onClick:()=>Pt(e.value),children:e.label},e.value))]})]}),ve?t.jsx("div",{className:"space-y-2",children:[0,1,2,3].map(e=>t.jsx("div",{className:"h-16 rounded-dash-xl bg-slate-100 dark:bg-slate-800 animate-pulse"},e))}):Te?t.jsxs("div",{className:"rounded-dash-xl border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 px-6 py-12 flex flex-col items-center text-center gap-3",children:[t.jsx("div",{className:"w-14 h-14 rounded-dash-xl bg-amber-100 dark:bg-amber-900/40 flex items-center justify-center text-amber-600 dark:text-amber-400",children:t.jsx(l,{size:26})}),t.jsxs("div",{className:"max-w-sm space-y-1",children:[t.jsx("p",{className:"text-sm font-semibold text-slate-700 dark:text-slate-300",children:"We couldn't load your gift cards."}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:"Check your connection and try again — nothing has been lost."})]}),t.jsx(Ue,{size:"sm",icon:t.jsx(o,{size:13}),onClick:()=>gt(e=>e+1),children:"Try again"})]}):0===Bt.length?t.jsx("div",{className:"rounded-dash-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm",children:0===ye.length?t.jsx(M,{icon:r,iconTone:"primary",title:"No gift cards sold yet",description:!1===be?'Your public gift card page is switched off, so customers can’t buy cards online yet — switch on "Sell gift cards online" in Selling & settings.':"Cards bought on your public gift card page will appear here the moment they’re paid for.",actionLabel:!1===be?"Open Selling & settings":void 0,onAction:!1===be?()=>{pe(!0),ce("settings")}:void 0}):t.jsx(M,{icon:aa,title:"Nothing matches those filters",description:"Try clearing the search or filters."})}):t.jsx("div",{className:"rounded-dash-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm divide-y divide-slate-100 dark:divide-slate-800 overflow-hidden",children:Bt.map(e=>{const a=nt(e,Dt),s=Je(e,Dt),r=J&&"active"===a,n=te&&"active"===a&&"scheduled"!==e.giftEmailState&&!(!e.recipientEmail&&!e.buyerEmail);return t.jsxs("div",{className:"px-4 py-3 flex flex-wrap items-center gap-x-3 gap-y-1 transition-colors hover:bg-slate-50/60 dark:hover:bg-slate-800/40",children:[t.jsxs("button",{type:"button",onClick:()=>It(e.id),className:"flex-1 basis-60 min-w-0 text-left flex items-center gap-3",children:[t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[t.jsxs("span",{className:"font-mono text-sm font-bold text-slate-900 dark:text-white",children:["…",e.codeLast4]}),t.jsx(Oe,{tone:s.tone,size:"sm",children:s.label}),"active"===a&&Oa(e.expiresAtMs,Dt)&&t.jsx(Oe,{tone:"amber",size:"sm",children:"Expiring soon"}
7),"scheduled"===e.giftEmailState&&e.scheduledDeliveryDate&&t.jsxs(Oe,{tone:"purple",size:"sm",children:["Sends ",ts(e.scheduledDeliveryDate)]})]}),t.jsxs("p",{className:"text-xs text-slate-500 dark:text-slate-400 truncate mt-0.5",children:[e.buyerName||"Unknown buyer",e.recipientName?` → ${e.recipientName}`:""," · ",it(e)," · ",es(e.issuedAtMs)]})]}),t.jsxs("div",{className:"text-right shrink-0",children:[t.jsx("p",{className:"text-sm font-bold text-slate-900 dark:text-white",children:et(e.remainingBalancePence)}),t.jsxs("p",{className:"text-[11px] text-slate-500 dark:text-slate-400",children:["of ",et(e.initialAmountPence)]})]})]}),(r||n)&&t.jsxs("div",{className:"flex items-center gap-x-4 shrink-0 ml-auto",children:[r&&t.jsxs("button",{type:"button",onClick:()=>{It(e.id),wr()},className:"touch-hitslop text-xs text-slate-500 dark:text-slate-400 hover:text-primary font-medium flex items-center gap-1 transition-colors rounded-dash-sm focus-visible:ring-2 focus-visible:ring-primary focus-visible:outline-none","aria-label":`Redeem the gift card ending ${e.codeLast4}`,children:[t.jsx(sa,{size:12}),"Redeem"]}),n&&t.jsxs("button",{type:"button",onClick:()=>{It(e.id),Ns.current=`rsnd_${ss()}`,ws(!0)},className:"touch-hitslop text-xs text-slate-500 dark:text-slate-400 hover:text-primary font-medium flex items-center gap-1 transition-colors rounded-dash-sm focus-visible:ring-2 focus-visible:ring-primary focus-visible:outline-none","aria-label":`Resend the gift card email for the card ending ${e.codeLast4}`,children:[t.jsx(ra,{size:12}),"Resend email"]})]})]},e.id)})}),Pe&&!At&&!ve&&t.jsx(He,{onClick:async()=>{if(!Ne&&Pe){Ce(!0);try{await Ie(!1)}catch(e){V.error(z(e))}finally{Ce(!1)}}},loading:Ne}),$t&&t.jsxs("p",{className:"text-xs text-slate-500 dark:text-slate-400 flex items-center gap-1.5",children:[t.jsx(n,{size:12,className:"animate-spin"})," Loading every card so the filters are complete…"]})]}),Vt&&t.jsx(Le,{open:!0,onClose:Et,origin:Tt,title:`Code ending ${Vt.codeLast4}`,subtitle:`${Vt.replacementOrderId?"Order gift return":Vt.buyerName||"Unknown buyer"}${Vt.recipientName?` → ${Vt.recipientName}`:""} · ${it(Vt)} · issued ${es(Vt.issuedAtMs)}`,icon:i,chips:t.jsxs(t.Fragment,{children:[Fr&&t.jsx(Oe,{tone:Je(Vt,Dt).tone,size:"md",uppercase:!0,children:Je(Vt,Dt).label}),"active"===Fr&&Oa(Vt.expiresAtMs,Dt)&&t.jsx(Oe,{tone:"amber",size:"md",uppercase:!0,children:"Expiring soon"}),"scheduled"===Vt.giftEmailState&&Vt.scheduledDeliveryDate&&t.jsxs(Oe,{tone:"purple",size:"md",uppercase:!0,children:["Sends ",ts(Vt.scheduledDeliveryDate)]})]}),children:t.jsxs("div",{children:[t.jsxs("div",{className:"px-5 py-4 space-y-3",children:[t.jsxs("div",{children:[t.jsx("p",{className:"text-3xl font-bold text-slate-900 dark:text-white",children:et(Vt.remainingBalancePence)}),t.jsxs("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:["of ",et(Vt.initialAmountPence)," originally",Vt.bonusAmountPence?` (includes ${et(Vt.bonusAmountPence)} bonus)`:"","expired"===Fr&&Vt.forfeitedBalancePence?` · ${et(Vt.forfeitedBalancePence)} forfeited at expiry`:""]})]}),t.jsxs("dl",{className:"grid grid-cols-2 gap-x-3 gap-y-1.5 text-xs",children:[t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Buyer"}),t.jsxs("dd",{className:"text-slate-700 dark:text-slate-200 truncate",children:[Vt.buyerEmail&&b.allowed("customers")?t.jsx("button",{type:"button",className:"text-xs text-primary font-semibold hover:underline text-left",onClick:()=>Lt(Et,{kind:"customer",by:"email",value:Vt.buyerEmail}),children:Vt.buyerName||Vt.buyerEmail}):Vt.buyerName||Vt.buyerEmail||"—",Vt.buyerName&&Vt.buyerEmail?` · ${Vt.buyerEmail}`:""]}),t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Recipient"}),t.jsx("dd",{className:"text-slate-700 dark:text-slate-200 truncate",children:Vt.recipientName||Vt.recipientEmail?Vt.recipientEmail&&b.allowed("customers")?t.jsx("button",{type:"button",className:"text-xs text-primary font-semibold hover:underline text-left",onClick:()=>Lt(Et,{kind:"customer",by:"email",value:Vt.recipientEmail}
7),children:Vt.recipientName||Vt.recipientEmail}):Vt.recipientName||Vt.recipientEmail:"Sent to the buyer"}),t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Sold"}),t.jsxs("dd",{className:"text-slate-700 dark:text-slate-200",children:[es(Vt.issuedAtMs)," · ",Vt.replacementOrderId?"Linked replacement · no new payment":Vt.replacesVoucherId?"Replacement card · no new payment":Ze[Vt.saleChannel],Vt.replacementOrderId||Vt.replacesVoucherId||!Vt.paymentTakenBy?"":` (${Qe[Vt.paymentTakenBy]})`,Vt.soldByName?` by ${Vt.soldByName}`:"",b.allowed("payments")&&t.jsxs(t.Fragment,{children:[" · ",t.jsx("button",{type:"button",className:"text-primary font-semibold hover:underline",onClick:()=>Lt(Et,{kind:"payment",subject:"gift",id:Vt.id}),children:"View the payment record"})]})]}),Vt.replacedByVoucherId&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Replaced"}),t.jsxs("dd",{className:"text-slate-700 dark:text-slate-200",children:[Vt.replacedAtMs?`${es(Vt.replacedAtMs)} · `:"",t.jsxs("button",{type:"button",className:"text-primary font-semibold hover:underline",onClick:()=>It(Vt.replacedByVoucherId),children:["Replaced by …",Vt.replacedByCodeLast4||"the new card"]})," ","— the balance moved across; this code no longer works"]})]}),Vt.replacesVoucherId&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Replaces"}),t.jsxs("dd",{className:"text-slate-700 dark:text-slate-200",children:[t.jsxs("button",{type:"button",className:"text-primary font-semibold hover:underline",onClick:()=>It(Vt.replacesVoucherId),children:["Replaces …",Vt.replacesCodeLast4||"the old card"]})," ","— same money, new code"]})]}),t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Expires"}),t.jsx("dd",{className:"text-slate-700 dark:text-slate-200",children:es(Vt.expiresAtMs)}),"scheduled"===Vt.giftEmailState&&Vt.scheduledDeliveryDate&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Email delivery"}),t.jsxs("dd",{className:"text-slate-700 dark:text-slate-200",children:["Scheduled for ",ts(Vt.scheduledDeliveryDate)," (~8am)"]})]}),"cancelled"===Vt.giftEmailState&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Email delivery"}),t.jsx("dd",{className:"text-amber-600 dark:text-amber-400",children:"Cancelled — use Resend email if it should go out"})]}),Vt.voidReason&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Void reason"}),t.jsx("dd",{className:"text-slate-700 dark:text-slate-200",children:Vt.voidReason})]}),Vt.refundId&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Refunded"}),t.jsxs("dd",{className:"text-slate-700 dark:text-slate-200",children:["number"==typeof Vt.refundStripeAmountPence?`${et(Vt.refundStripeAmountPence)} to the buyer`:"To the buyer",Vt.refundedAtMs?` on ${es(Vt.refundedAtMs)}`:"",Vt.refundBonusVoidedPence?` (${et(Vt.refundBonusVoidedPence)} promotional value withdrawn)`:"",Vt.purchaseRefundedViaVoucherId&&t.jsxs(t.Fragment,{children:[", through ",t.jsxs("button",{type:"button",className:"text-primary font-semibold hover:underline",onClick:()=>It(Vt.purchaseRefundedViaVoucherId),children:["the card ending ",Vt.purchaseRefundedViaCodeLast4||"…"]})]})]})]}),Vt.refundPending&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Refund"}),t.jsx("dd",{className:"text-amber-600 dark:text-amber-400",children:ot(Vt)?"In progress — the card is closed but the money hasn't gone back yet. Use Retry refund.":t.jsxs(t.Fragment,{children:["In progress through"," ",t.jsxs("button",{type:"button",className:"font-semibold underline",onClick:()=>It(Vt.purchaseRefundedViaVoucherId),children:["the card ending ",Vt.purchaseRefundedViaCodeLast4||"…"]})," ","— the money hasn't gone back yet. Open that card and use Retry refund."]})})]}),Vt.refundReason&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Refund reason"}),t.jsx("dd",{className:"text-slate-700 dark:text-slate-200",children:Vt.refundReason})]})]}),t.jsxs("div",{className:"flex flex-wrap gap-2 pt-1",children:[J&&"active"===Fr&&t.jsx(Ue,{size:"sm",icon:t.jsx(sa,{size:14}),onClick:wr,children:"Redeem"}),te&&"active"===Fr&&!Dr&&(Vt.recipientEmail||Vt.buyerEmail)&&t.jsx(Ue,{size:"sm",variant:"outline",tone
7:"slate",icon:t.jsx(ra,{size:14}),onClick:()=>{Ns.current=`rsnd_${ss()}`,ws(!0)},children:"Resend email"}),te&&Dr&&t.jsxs(t.Fragment,{children:[t.jsx(Ue,{size:"sm",variant:"outline",tone:"slate",icon:t.jsx(d,{size:14}),onClick:()=>{As(Vt.scheduledDeliveryDate||""),Ss(!0)},children:"Re-date delivery"}),t.jsx(Ue,{size:"sm",variant:"outline",tone:"slate",icon:t.jsx(we,{size:14}),onClick:()=>Fs(!0),children:"Cancel delivery"})]}),te&&("active"===Fr||"expired"===Fr)&&t.jsx(Ue,{size:"sm",variant:"outline",tone:"slate",icon:t.jsx(na,{size:14}),onClick:()=>{ys(""),vs(""),bs(!0)},children:"Extend expiry"}),ee&&("active"===Fr||"redeemed"===Fr)&&t.jsx(Ue,{size:"sm",variant:"outline",tone:"slate",icon:t.jsx(ha,{size:14}),onClick:()=>{za.current=ss(),$a(""),Ba("add"),Va(""),Pa(!0)},children:"Adjust balance"}),ee&&("online"===Vt.saleChannel||Vt.replacesVoucherId)&&("active"===Fr||ot(Vt))&&t.jsx("span",{title:H?void 0:"Refunds are paused until Stripe is reconnected.",children:t.jsx(Ue,{size:"sm",variant:"outline",tone:"amber",icon:t.jsx(la,{size:14}),disabled:!H,onClick:()=>{hs(Vt.refundReason||""),ms(!0)},children:Vt.refundPending?"Retry refund":"Refund purchase"})}),ee&&dt(Vt,Dt)&&t.jsx(Ue,{size:"sm",variant:"outline",tone:"slate",icon:t.jsx(o,{size:14}),onClick:()=>{rs.current=`rpl_${ss()}`,Ya(!0)},children:"Replace card"}),ee&&("active"===Fr||"inactive"===Fr)&&t.jsx(Ue,{size:"sm",variant:"outline",tone:"red",icon:t.jsx(zt,{size:14}),onClick:()=>qa(!0),children:"Void card"})]})]}),t.jsxs("div",{className:"px-5 pb-4",children:[t.jsxs("div",{className:"flex items-center justify-between gap-2 mb-2",children:[t.jsx("p",{className:"text-[11px] font-semibold uppercase tracking-wide text-slate-500 dark:text-slate-400",children:"History"}),fa&&t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx(Ue,{size:"sm",variant:"outline",tone:"slate",icon:t.jsx(qt,{size:13}),ariaLabel:"Print this card's statement",onClick:()=>pa.startPrint(),children:"Print"}),t.jsx(Ue,{size:"sm",variant:"outline",tone:"slate",icon:t.jsx(_t,{size:13}),ariaLabel:"Download this card's statement as a CSV",onClick:()=>{Vt&&ba&&Se(function(e,t){const a=t.lines.map(e=>({date:Ra(e.dateMs),movement:e.label,amount:Ta(e.amountPence),balanceAfter:Ta(e.balanceAfterPence),recordedBy:e.actorName||"",note:e.note||""}));return a.push({date:"",movement:"Current balance",amount:"",balanceAfter:Ta(t.currentBalancePence),recordedBy:"",note:""}),t.discrepancy&&a.push({date:"",movement:"Please note",amount:"",balanceAfter:"",recordedBy:"",note:Ma}),a}(0,ba),`gift-card-statement-${Vt.codeLast4}-${(new Date).toISOString().slice(0,10)}.csv`,La)},children:"CSV"})]})]}
7),!ia&&!da&&(null==ba?void 0:ba.discrepancy)&&t.jsx("div",{className:"mb-2 rounded-dash-md border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 px-3 py-2 text-[11px] leading-snug text-amber-800 dark:text-amber-200",children:Ma}),da&&!ia&&t.jsx("div",{className:"mb-2 rounded-dash-md border border-slate-200 dark:border-slate-700 bg-slate-50 dark:bg-slate-800/60 px-3 py-2 text-[11px] leading-snug text-slate-500 dark:text-slate-400",children:"Couldn't load this card's history just now — close and reopen the card to try again."}),ia?t.jsx("div",{className:"h-16 rounded-dash-md bg-slate-100 dark:bg-slate-800 animate-pulse"}):0===Ut.length?da?null:t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:"No movements recorded yet."}):t.jsx("ul",{className:"space-y-1.5",children:Ut.map(e=>t.jsxs("li",{className:"flex items-start justify-between gap-2 text-xs",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsx("span",{className:"font-semibold text-slate-700 dark:text-slate-200",children:ct[e.type]}),t.jsxs("span",{className:"text-slate-500 dark:text-slate-400",children:[" · ",e.createdAtMs?es(e.createdAtMs):"—",e.actorName?` · ${e.actorName}`:""]}),e.note&&t.jsx("p",{className:"text-slate-500 dark:text-slate-400 truncate",children:e.note}),(()=>{const a=mt(e);if(!a)return null;return("order"===a.kind?b.allowed("orders"):b.allowed("bookings"))?t.jsx("p",{children:t.jsx("button",{type:"button",className:"text-primary font-semibold hover:underline",onClick:()=>Lt(Et,"order"===a.kind?{kind:"order",id:a.id}:{kind:"booking",id:a.id}),children:"order"===a.kind?"View the order":"View the booking"})}):null})(),e.pairedVoucherId&&t.jsx("p",{children:t.jsx("button",{type:"button",className:"text-primary font-semibold hover:underline",onClick:()=>It(e.pairedVoucherId),children:"replace_out"===e.type?"View the new card":"View the old card"})})]}),t.jsxs("div",{className:"text-right shrink-0",children:[t.jsxs("span",{className:"font-semibold "+(e.amountPence<0?"text-slate-700 dark:text-slate-200":"text-emerald-600 dark:text-emerald-400"),children:[e.amountPence<0?"−":"+",et(Math.abs(e.amountPence))]}),t.jsxs("p",{className:"text-[10px] text-slate-500 dark:text-slate-400",children:[et(e.balanceAfterPence)," left"]})]})]},e.id))}),(null==Vt?void 0:Vt.id)&&t.jsx(Yt,{tenantId:e||"",targetId:Vt.id,subjectType:"giftCard",label:"Audit history",className:"mt-3"})]})]})})]}),t.jsx(X,{open:Ms,onOpenChange:e=>{e||Is(!1)},children:t.jsxs(Q,{className:"sm:max-w-md",children:[t.jsx(Z,{children:Js?"Gift card sold":er?"Share the payment link":"Sell a gift card"}),er?t.jsx(I,{url:er.url,onDone:()=>Is(!1)}):Js?Js.code?t.jsxs("div",{className:"space-y-3",children:[t.jsxs("p",{className:"text-sm text-slate-600 dark:text-slate-300",children:[et(Js.initialAmountPence)," gift card sold. This is the code the customer spends:"]}),t.jsx(Kt,{code:Js.code,label:"gift card code",successMessage:"Code copied",wrap:!0,className:"w-full justify-center text-lg tracking-wider text-slate-900 dark:text-white py-3"}),t.jsxs("div",{className:"rounded-dash-md bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 px-3 py-2 text-xs text-amber-800 dark:text-amber-200 flex items-start gap-2",children:[t.jsx(l,{size:13,className:"mt-0.5 shrink-0"}),t.jsx("span",{children:"This is the ONLY time the full code is shown — it's stored securely and can't be looked up again. Print it or copy it before closing."})]}),t.jsxs("div",{className:"flex flex-wrap gap-2",children:[Js.printPath&&t.jsxs(Ae,{variant:"outline",className:"rounded-dash-lg font-bold",nativeButton:!1,render:t.jsx("a",{href:Js.printPath,target:"_blank",rel:"noreferrer"}),children:[t.jsx(qt,{size:14,className:"mr-1.5"})," Print gift card"]}),t.jsx(Ue,{className:"ml-auto",onClick:()=>Is(!1),children:"Done"})]}),(zs.trim()||qs.trim())&&t.jsxs("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:["The gift card email ",qs.trim()?"is on its way to the recipient":"is on its way to the buyer",zs.trim()?" (the buyer gets a receipt too)":"","."]})]}):t.jsxs("div",{className:"space-y-3",children:[t.jsx("p",{className:"text-sm text-slate-600 dar
7k:text-slate-300",children:"This sale had already gone through — each sale shows its code exactly once, so it can't be shown again. If nobody noted the code, void that card from the sold list and sell a fresh one."}),t.jsx(Ue,{className:"w-full",onClick:()=>Is(!1),children:"Close"})]}):t.jsxs("div",{className:"space-y-3",children:[t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-sell-amount",children:"Amount (£)"}),t.jsx("input",{id:"gc-sell-amount",type:"number",min:"5",step:"0.01",inputMode:"decimal",value:Es,onChange:e=>Ls(e.target.value),placeholder:"e.g. 50.00",className:`${Xa} mt-1`})]}),t.jsxs("div",{children:[t.jsxs("p",{className:Qa,children:["How was payment taken? ",t.jsx("span",{className:"text-red-500",children:"*"})]}),t.jsx("div",{className:"mt-1",children:t.jsx(Ve,{ariaLabel:"How payment was taken",options:[{value:"cash",label:"Cash"},{value:"card_at_venue",label:"Card at venue"},{value:"complimentary",label:"Complimentary"},{value:"payment_link",label:"Payment link"}],value:Ts,onChange:Rs})}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"payment_link"===Ts?"The customer pays on their own phone — the gift card is only created once they’ve paid. The link lasts 72 hours.":"You take the money yourself — ResoFlow just records the sale."})]}),t.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-sell-buyer-name",children:"Buyer name (optional)"}),t.jsx("input",{id:"gc-sell-buyer-name",type:"text",value:Os,onChange:e=>Vs(e.target.value),className:`${Xa} mt-1`})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-sell-buyer-email",children:"Buyer email (optional)"}),t.jsx("input",{id:"gc-sell-buyer-email",type:"email",value:zs,onChange:e=>Gs(e.target.value),placeholder:"Gets a receipt",className:`${Xa} mt-1`})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-sell-recipient-name",children:"Recipient name (optional)"}),t.jsx("input",{id:"gc-sell-recipient-name",type:"text",value:Us,onChange:e=>_s(e.target.value),className:`${Xa} mt-1`})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-sell-recipient-email",children:"Recipient email (optional)"}),t.jsx("input",{id:"gc-sell-recipient-email",type:"email",value:qs,onChange:e=>Hs(e.target.value),placeholder:"Gets the gift email",className:`${Xa} mt-1`})]})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-sell-message",children:"Gift message (optional)"}),t.jsx("textarea",{id:"gc-sell-message",rows:2,maxLength:450,value:Ws,onChange:e=>Ys(e.target.value),placeholder:"Shown in the gift email and on the printed card",className:`${Xa} mt-1`})]}),t.jsxs("div",{children:[t.jsx("p",{className:Qa,children:"Occasion design"}),t.jsx("div",{className:"mt-1.5 flex flex-wrap gap-1.5",role:"group","aria-label":"Occasion design",children:vr.map(e=>t.jsx(Ge,{active:Ks===e.id,onClick:()=>Xs(e.id),icon:t.jsx("span",{"aria-hidden":"true",children:e.emoji}),children:e.label},e.id))})]}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400",children:"payment_link"===Ts?"A payment-link sale needs the buyer’s or recipient’s email — the gift card is emailed once it’s paid.":"No email? No problem — the customer gets a printable gift card with the code and QR on it instead."}),t.jsx(Ue,{className:"w-full",loading:"sell"===Ds,icon:"payment_link"===Ts?t.jsx(c,{size:14}):t.jsx(r,{size:14}),onClick:()=>{Nr()},children:"payment_link"===Ts?"Create payment link":"Complete sale"})]})]})}),t.jsx(X,{open:ar,onOpenChange:e=>{e||sr(!1)},children:t.jsxs(Q,{className:"sm:max-w-md",children:[t.jsx(Z,{children:xr?"Gift card activated":br?"Share the payment link":"Activate a physical card"}),br?t.jsx(I,{url:br.url,onDone:()=>sr(!1)}):xr?t.jsxs("div",{className:"space-y-3",children:[t.jsxs("p",{className:"text-sm text-slate-600 dark:text-slate-300",children:["The card ending ",t.jsx("span",{className:"font-mono font-semibold",children:xr.codeLast4})," is now live with ",et(xr.initialAmountPence)," on it",xr.expiresAtMs?`, valid until ${es(xr.expiresAtMs)}`:"",". Hand the card to the customer — it's ready to spend."]}),t.jsxs("div",{className:"flex flex-wrap gap-2",children:[t.jsxs(Ae,{variant:"outline",className:"rounded-dash-lg font-bold",nativeButton:!1,render:t.jsx("a",{href:xr.printPath,target:"_blank",rel:"noreferrer"}),children:[t.jsx(qt,{size:14,className:"mr-1.5"})," Print a gift certificate"]}),t.jsx(Ue,{className:"ml-auto",onClick:()=>sr(!1),children:"Done"})]})]}):t.jsxs("div",{className:"space-y-3",children:[t.jsx("p",{className:"text-sm text-slate-600 dar
7k:text-slate-300",children:"For pre-printed physical cards: type the code from the card (or scan it in the Scanner), choose the amount the customer paid, and the card goes live."}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-activate-code",children:"Card code"}),t.jsx("input",{id:"gc-activate-code",type:"text",autoComplete:"off",autoCapitalize:"characters",spellCheck:!1,value:rr,onChange:e=>nr(Ht(e.target.value)),placeholder:"XXXX-XXXX-XXXX-XXXX",className:`${Xa} mt-1 font-mono tracking-wider`})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-activate-amount",children:"Amount (£)"}),t.jsx("input",{id:"gc-activate-amount",type:"number",min:"5",step:"0.01",inputMode:"decimal",value:lr,onChange:e=>ir(e.target.value),placeholder:"e.g. 50.00",className:`${Xa} mt-1`})]}),t.jsxs("div",{children:[t.jsxs("p",{className:Qa,children:["How was payment taken? ",t.jsx("span",{className:"text-red-500",children:"*"})]}),t.jsx("div",{className:"mt-1",children:t.jsx(Ve,{ariaLabel:"How payment was taken",options:[{value:"cash",label:"Cash"},{value:"card_at_venue",label:"Card at venue"},{value:"complimentary",label:"Complimentary"},{value:"payment_link",label:"Payment link"}],value:or,onChange:dr})}),"payment_link"===or&&t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"The customer pays on their own phone — the card only goes live once they’ve paid. The link lasts 72 hours."})]}),t.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-activate-buyer-name",children:"Buyer name (optional)"}),t.jsx("input",{id:"gc-activate-buyer-name",type:"text",value:cr,onChange:e=>mr(e.target.value),className:`${Xa} mt-1`})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-activate-buyer-email",children:"Buyer email (optional)"}),t.jsx("input",{id:"gc-activate-buyer-email",type:"email",value:ur,onChange:e=>hr(e.target.value),placeholder:"Gets a receipt + the card details",className:`${Xa} mt-1`})]})]}),t.jsx(Ue,{className:"w-full",loading:"activate"===Ds,icon:"payment_link"===or?t.jsx(c,{size:14}):t.jsx(Jt,{size:14}),onClick:()=>{Cr()},children:"payment_link"===or?"Create payment link":"Activate card"})]})]})}),t.jsx(X,{open:ya&&!!Vt,onOpenChange:e=>{e||ja(!1)},children:t.jsxs(Q,{className:"sm:max-w-md",children:[t.jsx(Z,{children:"Redeem gift card"}),Vt&&t.jsxs("div",{className:"space-y-3",children:[t.jsxs("p",{className:"text-sm text-slate-600 dark:text-slate-300",children:[et(Vt.remainingBalancePence)," left on the card ending ",t.jsx("span",{className:"font-mono font-semibold",children:Vt.codeLast4}),". If the bill is bigger than the balance, the card covers what it can and the rest is taken however you normally take payment."]}),t.jsxs(Ue,{className:"w-full",loading:"redeem"===Ds,icon:t.jsx(la,{size:14}),onClick:()=>{Sr(Vt.remainingBalancePence)},children:["Use the full balance (",et(Vt.remainingBalancePence),")"]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("div",{className:"h-px flex-1 bg-slate-200 dark:bg-slate-700"}),t.jsx("span",{className:"text-[11px] text-slate-500 dark:text-slate-400",children:"or enter the bill amount"}),t.jsx("div",{className:"h-px flex-1 bg-slate-200 dark:bg-slate-700"})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-redeem-amount",children:"Amount (£)"}),t.jsx("input",{id:"gc-redeem-amount",type:"number",min:"0.01",step:"0.01",inputMode:"decimal",value:ka,onChange:e=>wa(e.target.value),placeholder:"e.g. 25.00",className:`${Xa} mt-1`})]}),t.jsx(Ue,{className:"w-full",loading:"redeem"===Ds,disabled:null===as(ka)||(as(ka)||0)<=0,icon:t.jsx(sa,{size:14}),onClick:()=>{const e=as(ka);null!==e&&e>0&&Sr(e)},children:"Redeem this amount"})]})]})}),t.jsx(X,{open:Sa&&!!Vt,onOpenChange:e=>{e||Pa(!1)},children:t.jsxs(Q,{className:"sm:max-w-md",children:[t.jsx(Z,{children:"Adjust balance"}),Vt&&t.jsxs("div",{className:"space-y-3",children:[t.jsxs("p",{className:"text-sm text-slate-600 dark:text-slate-300",children:["For putting a mis-keyed redemption right. The balance is ",et(Vt.remainingBalancePence)," of ",et(Vt.initialAmountPence)," — an adjustment can never take it below £0.00 or above the original value."]}),t.jsx(Ve,{ariaLabel:"Adjustment direction",options:[{value:"add",label:"Give money back"},{value:"remove",label:"Take money off"}],value:Fa,onChange:Ba}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-adjust-amount",children:"Amount (£)"}),t.jsx("input",{id:"gc-adjust-amount",type:"number",min:"0.01",step:"0.01",inputMode:"decimal",value:Aa,onChange:e=>$a(e.target.value),placeholder:"e.g. 45.00",className:`${Xa} mt-1`})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-adjust-reason",children:"Reason (required)"}),t.jsx("textarea",{id:"gc-adjust-reason",rows:2,value:Ia,onChange:e=>Va(e.target.value),placeholder:"e.g. Keyed £50.00 instead of £5.00 at the venue",className:`${Xa} mt-1`})]}),t.jsx(Ue,{className:"w-full",loading:"adjust"===Ds,icon:t.jsx(ha,{size:14}),onClick:()=>{(async()=>
7{if(!e||!Vt||Ds)return;const t=as(Aa);if(null===t||t<=0)return void V.error("Please enter a valid amount.");if(Ia.trim().length<3)return void V.error("Please give a short reason.");const a="add"===Fa?t:-t,s=Vt.id;Bs("adjust");try{await le("Adjust gift card balance",async t=>{const r=await O("adjustGiftCardBalance")({tenantId:e,voucherId:s,deltaPence:a,reason:Ia.trim(),idempotencyKey:za.current,...(null==t?void 0:t.pinAuthNonce)?{pinAuthNonce:t.pinAuthNonce}:{}});V.success(`Balance adjusted — now ${et(r.data.remainingBalancePence)}`),Pa(!1),await ua(s)},void 0,void 0,{opName:"adjustGiftCardBalance",tenantId:e})}catch(r){V.error(z(r))}finally{Bs(null)}})()},children:"Apply adjustment"})]})]})}),t.jsx(X,{open:gs&&!!Vt,onOpenChange:e=>{e||bs(!1)},children:t.jsxs(Q,{className:"sm:max-w-md",children:[t.jsx(Z,{children:"Extend expiry"}),Vt&&t.jsxs("div",{className:"space-y-3",children:[t.jsxs("p",{className:"text-sm text-slate-600 dark:text-slate-300",children:["Currently expires ",es(Vt.expiresAtMs),".","expired"===Fr&&" This card has expired — extending it brings it back to life and restores any forfeited balance."," ","The new date must be later than the current one."]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-extend-date",children:"New expiry date"}),t.jsx("input",{id:"gc-extend-date",type:"date",value:fs,onChange:e=>ys(e.target.value),className:`${Xa} mt-1`})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-extend-reason",children:"Reason (required)"}),t.jsx("textarea",{id:"gc-extend-reason",rows:2,value:js,onChange:e=>vs(e.target.value),placeholder:"e.g. Goodwill — customer was unwell over Christmas",className:`${Xa} mt-1`})]}),t.jsx(Ue,{className:"w-full",loading:"extend"===Ds,icon:t.jsx(na,{size:14}),onClick:()=>{(async()=>{if(!e||!Vt||Ds)return;if(!/^\d{4}-\d{2}-\d{2}$/.test(fs))return void V.error("Please choose the new expiry date.");if(js.trim().length<3)return void V.error("Please give a short reason.");const t=Vt.id;Bs("extend");try{const a=await O("extendGiftCardExpiry")({tenantId:e,voucherId:t,newExpiryDate:fs,reason:js.trim()});V.success(a.data.restoredBalancePence>0?`Expiry extended to ${es(a.data.expiresAtMs)} — ${et(a.data.restoredBalancePence)} restored to the card.`:`Expiry extended to ${es(a.data.expiresAtMs)}.`),bs(!1),await ua(t)}catch(a){V.error(z(a))}finally{Bs(null)}})()},children:"Extend expiry"})]})]})}),t.jsx(X,{open:Cs&&!!Vt,onOpenChange:e=>{e||Ss(!1)},children:t.jsxs(Q,{className:"sm:max-w-md",children:[t.jsx(Z,{children:"Re-date the gift email"}),Vt&&t.jsxs("div",{className:"space-y-3",children:[t.jsxs("p",{className:"text-sm text-slate-600 dark:text-slate-300",children:["The gift email is scheduled for ",Vt.scheduledDeliveryDate?ts(Vt.scheduledDeliveryDate):"—",". It sends around 8am on the day you pick."]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-reschedule-date",children:"New delivery date"}),t.jsx("input",{id:"gc-reschedule-date",type:"date",value:Ps,onChange:e=>As(e.target.value),className:`${Xa} mt-1`})]}),t.jsx(Ue,{className:"w-full",loading:"reschedule"===Ds,icon:t.jsx(d,{size:14}),onClick:()=>{(async()=>{if(e&&Vt&&!Ds)if(/^\d{4}-\d{2}-\d{2}$/.test(Ps)){Bs("reschedule");try{await O("rescheduleGiftCardDelivery")({tenantId:e,voucherId:Vt.id,newDate:Ps}),V.success(`Delivery moved to ${ts(Ps)} (around 8am)`),Ss(!1),await ua(Vt.id)}catch(t){V.error(z(t))}finally{Bs(null)}}else V.error("Please choose the new delivery date.")})()},children:"Move the delivery"})]})]})}),t.jsx(qe,{open:_a&&!!Vt,onClose:()=>qa(!1),onConfirm:t=>{t&&t.trim().length>=3?(async t=>{if(!e||!Vt||Ds)return;const a=Vt.id;Bs("void");try{await le("Void gift card",async s=>{await O("voidGiftCard")({tenantId:e,voucherId:a,reason:t,...(null==s?void 0:s.pinAuthNonce)?{pinAuthNonce:s.pinAuthNonce}:{}}),V.success("Gift card voided"),qa(!1),await ua(a)},void 0,void 0,{opName:"voidGiftCard",tenantId:e})}catch(s){V.error(z(s))}finally{Bs(null)}})(t.trim()):V.error("Please give a short reason.")},title:"Void this gift card?",message:`The card ending ${(null==Vt?void 0:Vt.codeLast4)||""} will stop working immediately and its ${Vt?et(Vt.remainingBalancePence):""} balance is written off. Voiding never moves money — if the customer paid at the venue, return their money yourself; online purchases get their money back through the refunds flow.`,confirmLabel:"Void card",busy:"void"===Ds,inputLabel:"Reason (required)",inputPlaceholder:"e.g. Customer refunded in cash at the bar",inputRequired:!0}),t.jsx(qe,{open:Wa&&!!Vt,onClose:()=>Ya(!1),onConfirm:t=>{t&&t.trim().length>=3?(async t=>{if(!e||!Vt||Ds)return;const a=Vt.id;Bs("replace");try{await le("Replace gift card",async s=>
7{const r=await O("replaceGiftCard")({tenantId:e,voucherId:a,reason:t,attemptId:rs.current,...(null==s?void 0:s.pinAuthNonce)?{pinAuthNonce:s.pinAuthNonce}:{}});Ya(!1),is(r.data),await ua(a)},void 0,void 0,{opName:"replaceGiftCard",tenantId:e})}catch(s){V.error(z(s))}finally{Bs(null)}})(t.trim()):V.error("Please give a short reason.")},title:"Replace this gift card?",message:Vt?`The card ending ${Vt.codeLast4} stops working straight away. Its whole ${et(Vt.remainingBalancePence)} balance moves to a new card with a new code and the same expiry date — no money is taken and nothing is counted as a new sale. ${"cancelled"!==Vt.giftEmailState&&Vt.recipientEmail?`The new card is emailed to the recipient (${Vt.recipientEmail}).`:Vt.buyerEmail?`The new card is emailed to the buyer (${Vt.buyerEmail}).`:"There is no email address on this card, so you will be shown the new code to print or read out."} If the old card is saved in a phone's wallet it greys out and says it was replaced. A purchase refund can still be made from the new card — it follows the link back to the original payment.`:"",confirmLabel:"Replace card",busy:"replace"===Ds,inputLabel:"Reason (required)",inputPlaceholder:"e.g. Customer lost the email with the code",inputRequired:!0}),t.jsx(X,{open:!!ns,onOpenChange:e=>{e||is(null)},children:t.jsxs(Q,{className:"sm:max-w-md",children:[t.jsx(Z,{children:(null==ns?void 0:ns.alreadyProcessed)?"This card was already replaced":"Gift card replaced"}),ns&&t.jsxs("div",{className:"space-y-3 text-sm text-slate-600 dark:text-slate-300",children:[t.jsxs("p",{children:[et(ns.movedBalancePence)," moved from the card ending ",ns.previousCodeLast4," to a new card ending ",t.jsx("strong",{className:"text-slate-900 dark:text-white",children:ns.codeLast4}),". The old code no longer works."]}),"nobody"!==ns.sentTo&&!ns.emailPending&&!ns.alreadyProcessed&&t.jsxs("p",{children:["The new card has been emailed to the ","buyer"===ns.sentTo?"buyer":"recipient",", with its own Add to Wallet buttons."]}),ns.emailPending&&t.jsx("p",{className:"text-amber-600 dark:text-amber-400",children:"The email with the new card could not be sent. Open the new card and use Resend email — it sends a fresh code."}),ns.code&&("nobody"===ns.sentTo||ns.emailPending)&&t.jsxs("div",{className:"rounded-dash-md border border-slate-200 dark:border-slate-700 px-3 py-2",children:[t.jsx("p",{className:"text-[11px] font-semibold uppercase tracking-wide text-slate-500 dark:text-slate-400",children:"New code — shown once"}),t.jsx("p",{className:"font-mono text-base text-slate-900 dark:text-white select-all",children:ns.code})]}),t.jsxs("div",{className:"flex flex-wrap justify-end gap-2 pt-1",children:[ns.printPath&&t.jsx(Ue,{size:"sm",variant:"outline",tone:"slate",icon:t.jsx(qt,{size:14}),onClick:()=>window.open(ns.printPath,"_blank","noopener"),children:"Print the new card"}),t.jsx(Ue,{size:"sm",tone:"primary",onClick:()=>{const e=ns.newVoucherId;is(null),It(e)},children:"Open the new card"})]})]})]})}),t.jsx(X,{open:cs&&!!Vt,onOpenChange:e=>{e||ms(!1)},children:t.jsxs(Q,{className:"sm:max-w-md",children:[t.jsx(Z,{children:(null==Vt?void 0:Vt.refundPending)?"Retry the refund":"Refund this purchase"}),Vt&&(()=>{const a=ps&&ps.forId===Vt.id&&"ready"===ps.status?ps.row:null,s=a?ut(Vt,a):null,r=!!ps&&ps.forId===Vt.id&&"error"===ps.status,n=!0===Vt.refundPending,l="number"==typeof Vt.refundStripeAmountPence?Vt.refundStripeAmountPence:(null==s?void 0:s.refundToBuyerPence)??null;return t.jsxs("div",{className:"space-y-3",children:[n?t.jsxs("p",{className:"text-sm text-slate-600 dark:text-slate-300",children:["This card is already closed for a refund, but the money hasn't gone back yet. Retrying sends the same ",null!==l?et(l):"amount"," to the buyer — it can never be paid twice."]}):s?t.jsxs(t.Fragment,{children:[t.jsxs("p",{className:"text-sm text-slate-600 dark:text-slate-300",children:["The buyer gets ",t.jsx("strong",{className:"text-slate-900 dark:text-white",children:et(s.refundToBuyerPence)})," back to the card they paid with, and this gift card (ending ",Vt.codeLast4,") stops working immediately."]}),t.jsxs("dl",{className:"rounded-dash-md border border-slate-200 dark:border-slate-700 divide-y divide-slate-100 dar
7k:divide-slate-800 text-xs",children:[t.jsxs("div",{className:"flex items-center justify-between px-3 py-2",children:[t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Left on the card"}),t.jsx("dd",{className:"font-semibold text-slate-900 dark:text-white",children:et(Vt.remainingBalancePence)})]}),t.jsxs("div",{className:"flex items-center justify-between px-3 py-2",children:[t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Refunded to the buyer"}),t.jsx("dd",{className:"font-semibold text-slate-900 dark:text-white",children:et(s.refundToBuyerPence)})]}),s.bonusVoidedPence>0&&t.jsxs("div",{className:"flex items-center justify-between px-3 py-2",children:[t.jsx("dt",{className:"text-slate-500 dark:text-slate-400",children:"Promotional value withdrawn (not refunded)"}),t.jsx("dd",{className:"font-semibold text-slate-900 dark:text-white",children:et(s.bonusVoidedPence)})]})]}),s.bonusVoidedPence>0&&t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400",children:"Promotional value — a free bonus, or the discount the buyer never paid — is withdrawn with the refund rather than refunded (only money the buyer actually paid goes back)."})]}):t.jsx("p",{className:"text-sm text-slate-600 dark:text-slate-300",children:r?"We couldn't read the original card's purchase, so we can't show the refund yet. Close this and try again.":"Working out what the buyer paid for the original card…"}),t.jsxs("div",{className:"space-y-1",children:[t.jsx("label",{className:Qa,htmlFor:"gift-refund-reason",children:"Reason (required)"}),t.jsx("input",{id:"gift-refund-reason",type:"text",value:us,onChange:e=>hs(e.target.value),placeholder:"e.g. Buyer changed their mind within cooling-off",className:Xa})]}),t.jsxs("div",{className:"flex justify-end gap-2",children:[t.jsx(Ue,{variant:"outline",tone:"slate",onClick:()=>ms(!1),children:"Cancel"}),t.jsx(Ue,{loading:"refund"===Ds,disabled:us.trim().length<3||!n&&!s,icon:t.jsx(la,{size:14}),onClick:()=>{(async()=>{if(!e||!Vt||Ds)return;if(us.trim().length<3)return void V.error("Please give a short reason.");const t=Vt.id;Bs("refund");try{await le("Refund gift card purchase",async a=>{const s=await O("refundGiftCardPurchase")({tenantId:e,voucherId:t,reason:us.trim(),...(null==a?void 0:a.pinAuthNonce)?{pinAuthNonce:a.pinAuthNonce}:{}});V.success(s.data.alreadyProcessed?"This gift card had already been refunded.":`${et(s.data.refundToBuyerPence)} refunded to the buyer — the card is now closed.`),ms(!1),await ua(t)},void 0,void 0,{opName:"refundGiftCardPurchase",tenantId:e})}catch(a){V.error(z(a)),await ua(t)}finally{Bs(null)}})()},children:n?"Retry refund":s?`Refund ${et(s.refundToBuyerPence)}`:"Refund"})]})]})})()]})}),t.jsx(qe,{open:ks&&!!Vt,onClose:()=>ws(!1),onConfirm:()=>{(async()=>{if(!e||!Vt||Ds)return;const t=Vt.id;Bs("resend");try{await le("Resend gift card email",async a=>{const s=await O("resendGiftCardEmail")({tenantId:e,voucherId:t,attemptId:Ns.current||`rsnd_${ss()}`,...(null==a?void 0:a.pinAuthNonce)?{pinAuthNonce:a.pinAuthNonce}:{}});if(s.data.emailPending?V.error(`The balance moved to a new card (ending ${s.data.codeLast4}) but the email could not be sent — open the new card and use Resend email again.`):V.success(`Gift card email resent to the ${"buyer"===s.data.sentTo?"buyer":"recipient"} — a new card with a fresh code (ending ${s.data.codeLast4}) and the same balance. The old card no longer works.`),ws(!1),await ua(t),s.data.newVoucherId)try{const t=await w(N(B,"tenants",e,"vouchers",s.data.newVoucherId));if(t.exists()){const e=tt(t.id,t.data());je(t=>t.some(t=>t.id===e.id)?t.map(t=>t.id===e.id?e:t):[e,...t]),It(e.id)}}catch(r){console.warn("[GiftCardsPage] new card fetch after resend failed:",r)}},void 0,void 0,{opName:"resendGiftCardEmail",tenantId:e})}catch(a){V.error(z(a))}finally{Bs(null)}})()},title:"Resend the gift card email?",message:`Resending issues a NEW card with a fresh code and emails it to the ${"cancelled"!==(null==Vt?void 0:Vt.giftEmailState)&&(null==Vt?void 0:Vt.recipientEmail)?"recipient":"buyer"}. The old card (ending ${(null==Vt?void 0:Vt.codeLast4)||""}) stops working the moment you confirm — and if it is saved in a phone's wallet it greys out and says it was replaced. The whole balance and the expiry date move to the new card; no money is taken and nothing is counted as a new sale.`,confirmLabel:"Resend with a fresh code",variant:"neutral",busy:"resend"===Ds}),t.jsx(qe,{open:$s&&!!Vt,onClose:()=>Fs(!1),onConfirm:()=>{(async()=>
7{if(e&&Vt&&!Ds){Bs("cancelScheduled");try{await O("cancelGiftCardScheduledDelivery")({tenantId:e,voucherId:Vt.id}),V.success("Scheduled delivery cancelled — the card itself stays live. Use “Resend email” if it should go out after all."),Fs(!1),await ua(Vt.id)}catch(t){V.error(z(t))}finally{Bs(null)}}})()},title:"Cancel the scheduled gift email?",message:"The email won't be sent, but the card itself stays live and spendable. If it should go out after all, use “Resend email” afterwards — that issues a fresh code.",confirmLabel:"Cancel the delivery",busy:"cancelScheduled"===Ds}),xa&&t.jsx(Ha,{open:!0,onClose:()=>ga(!1),tenantId:e,venueName:(null==m?void 0:m.restaurantName)||"",ensureAllRows:Pr}),pa.printing&&Vt&&ba&&"undefined"!=typeof document&&f.createPortal(t.jsx(Ga,{card:Vt,statement:ba,venueName:(null==m?void 0:m.restaurantName)||""}),document.body),t.jsx(Ke,{...ie}),t.jsx(Xe,{...oe})]})}function ns(e,t){const a=URL.createObjectURL(e),s=document.createElement("a");s.href=a,s.download=t,document.body.appendChild(s),s.click(),document.body.removeChild(s),URL.revokeObjectURL(a)}function ls({tenantId:e,triggerSudo:a,onMinted:s}){const[r,n]=g.useState([]),[i,o]=g.useState(!0),[d,c]=g.useState(!1),[m,u]=g.useState("50"),[h,p]=g.useState(""),x=g.useRef(""),[b,f]=g.useState(!1),[y,j]=g.useState(null),v=g.useCallback(async()=>{try{const t=await C(S(P(B,"tenants",e,"voucherBatches"),$("createdAt","desc"),A(25)));n(t.docs.map(e=>{const t=e.data(),a=t.createdAt;return{id:e.id,quantity:"number"==typeof t.quantity?t.quantity:0,..."string"==typeof t.label&&t.label?{label:t.label}:{},..."string"==typeof t.mintedByName&&t.mintedByName?{mintedByName:t.mintedByName}:{},createdAtMs:a&&"function"==typeof a.toMillis?a.toMillis():null}}))}catch(t){console.warn("[PhysicalCardBatchesSection] batches load failed:",t)}finally{o(!1)}},[e]);g.useEffect(()=>{v()},[v]);return t.jsxs("section",{className:"rounded-dash-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm overflow-hidden",children:[t.jsx("div",{className:"px-6 py-4 border-b border-slate-100 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50",children:t.jsxs("div",{className:"flex items-center justify-between gap-4",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("div",{className:"w-9 h-9 rounded-dash-lg bg-primary/10 flex items-center justify-center shrink-0",children:t.jsx(ua,{size:18,className:"text-primary"})}),t.jsxs("div",{children:[t.jsx("h3",{className:"text-sm font-bold text-slate-900 dark:text-white",children:"Physical gift cards"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:"Mint a batch of codes, print the QR sticker sheet onto blank cards, then use “Activate a card” front-of-house when a customer buys one. Cards hold no value until they're activated."})]})]}),t.jsxs(Ae,{onClick:()=>{x.current=ss(),u("50"),p(""),j(null),c(!0)},className:"rounded-dash-lg bg-primary hover:bg-primary/90 text-primary-foreground font-bold shrink-0",children:[t.jsx(da,{size:14,className:"mr-1.5"})," Mint a batch"]})]})}),t.jsx("div",{className:"p-6 pt-4",children:i?t.jsx("div",{className:"h-10 rounded-dash-md bg-slate-100 dark:bg-slate-800 animate-pulse"}):0===r.length?t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:"No batches minted yet."}):t.jsx("ul",{className:"divide-y divide-slate-100 dark:divide-slate-800 border border-slate-100 dark:border-slate-800 rounded-dash-lg overflow-hidden",children:r.map(e=>t.jsxs("li",{className:"px-3 py-2 flex items-center justify-between gap-3 text-xs",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsxs("p",{className:"font-semibold text-slate-700 dark:text-slate-200 truncate",children:[e.quantity," card",1===e.quantity?"":"s",e.label?` · ${e.label}`:""]}),t.jsxs("p",{className:"text-slate-500 dark:text-slate-400",children:[e.createdAtMs?es(e.createdAtMs):"—",e.mintedByName?` · by ${e.mintedByName}`:""]})]}),t.jsx("span",{className:"font-mono text-[10px] text-slate-500 dark:text-slate-400 shrink-0",children:e.id})]},e.id))})}),t.jsx(X,{open:d,onOpenChange:e=>{e||c(!1)},children:t.jsxs(Q,{className:"sm:max-w-md",children:[t.jsx(Z,{children:y?"Batch minted":"Mint physical gift cards"}),y?y.csv||y.pdfBase64?t.jsxs("div",{className:"space-y-3",children:[t.jsxs("p",{className:"text-sm text-slate-600 dar
7k:text-slate-300",children:[y.quantity," card",1===y.quantity?"":"s"," minted (",y.batchId,")."]}),t.jsxs("div",{className:"rounded-dash-md bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 px-3 py-2 text-xs text-amber-800 dark:text-amber-200 flex items-start gap-2",children:[t.jsx(l,{size:13,className:"mt-0.5 shrink-0"}),t.jsx("span",{children:"Download BOTH files now — this is your ONLY copy of the codes. From this moment they're stored securely and can never be exported again. Treat the sheet like cash."})]}),t.jsxs("div",{className:"flex flex-wrap gap-2",children:[t.jsx(Ue,{icon:t.jsx(qt,{size:14}),disabled:!y.pdfBase64,onClick:()=>{if(!(null==y?void 0:y.pdfBase64))return;const e=Uint8Array.from(atob(y.pdfBase64),e=>e.charCodeAt(0));ns(new Blob([e],{type:"application/pdf"}),`gift-card-stickers-${y.batchId}.pdf`)},children:"QR sticker sheet (PDF)"}),t.jsx(Ue,{variant:"outline",tone:"slate",icon:t.jsx(_t,{size:14}),disabled:!y.csv,onClick:()=>{(null==y?void 0:y.csv)&&ns(new Blob([Pe,y.csv],{type:"text/csv;charset=utf-8;"}),`gift-cards-${y.batchId}.csv`)},children:"Codes (CSV)"})]}),t.jsx(Ue,{variant:"outline",tone:"slate",className:"w-full",onClick:()=>c(!1),children:"I've downloaded them — close"})]}):t.jsxs("div",{className:"space-y-3",children:[t.jsx("p",{className:"text-sm text-slate-600 dark:text-slate-300",children:"This batch had already been minted — its one-time code export was returned at the time and can't be regenerated (codes are stored securely). If the sheet is lost, void the unused cards and mint a new batch."}),t.jsx(Ue,{className:"w-full",onClick:()=>c(!1),children:"Close"})]}):t.jsxs("div",{className:"space-y-3",children:[t.jsx("p",{className:"text-sm text-slate-600 dark:text-slate-300",children:"Each card is minted at £0 and only becomes spendable when it's activated at a sale. You'll get a QR sticker sheet (PDF) and a CSV of the codes — shown exactly once."}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-mint-quantity",children:"How many cards? (1–100)"}),t.jsx("input",{id:"gc-mint-quantity",type:"number",min:"1",max:"100",step:"1",value:m,onChange:e=>u(e.target.value),className:`${Xa} mt-1`})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-mint-label",children:"Label (optional)"}),t.jsx("input",{id:"gc-mint-label",type:"text",maxLength:80,value:h,onChange:e=>p(e.target.value),placeholder:"e.g. Christmas front-of-house stock",className:`${Xa} mt-1`})]}),t.jsx(Ue,{className:"w-full",loading:b,icon:t.jsx(ua,{size:14}),onClick:()=>{(async()=>{if(b)return;const t=Number.parseInt(m,10);if(!Number.isInteger(t)||t<1||t>100)V.error("Please choose between 1 and 100 cards per batch.");else{f(!0);try{await a("Mint physical gift cards",async()=>{const a=await O("batchMintGiftCards")({tenantId:e,quantity:t,idempotencyKey:x.current,...h.trim()?{label:h.trim()}:{}});j(a.data),v(),s()})}catch(r){V.error(z(r))}finally{f(!1)}}})()},children:"Mint batch"})]})]})})]})}const is={onlineSaleEnabled:!1,acceptAtOnlineCheckout:!1,acceptForTableOrders:!1,acceptForCollectionOrders:!1,acceptForDeliveryOrders:!1,passFeeToBuyer:!1,quickPicks:[2500,5e3,7500,1e4],minPounds:"5.00",maxPounds:"500.00",expiryMonths:"24",settleHoldHours:"0",scheduleMaxDays:"90",...ft,...bt};function os({tenantId:e,shellPrefix:a,onlineSaleOn:s,onOpenSettings:r,qrHubAllowed:n}){const l=`${"undefined"!=typeof window?`${window.location.protocol}//${window.location.host}`:"https://resoflow.co.uk"}/gift/${e}`,i=!1===s;return t.jsxs("div",{className:"rounded-dash-xl border border-v4-line bg-v4-surface px-4 sm:px-5 py-4 space-y-3",children:[t.jsxs("div",{className:"flex items-start justify-between gap-3 flex-wrap",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsx("h2",{className:"text-sm font-bold text-v4-ink",children:"Your gift page"}),t.jsx("p",{className:"text-xs text-v4-ink-3 mt-0.5",children:i?"This is where your gift page will live. It’s closed to customers until you switch online selling on.":"Share this anywhere customers look — your social bios, email footers, your own website."})]}),i&&t.jsx("button",{type:"button",onClick:r,className:"touch-hitslop shrink-0 inline-flex items-center gap-1.5 h-9 pointer-coarse:min-h-11 px-3 rounded-dash-lg bg-primary text-white text-xs font-bold hover:bg-primary/90 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",children:"Open Selling & settings"})]}),t.jsxs("div",{className:"flex items-stretch gap-2",children:[t.jsx(Xt,{url:l,display:l.replace(/^https?:\/\//,""),label:"gift card page link",successMessage:"Link copied",className:"rounded-dash-lg text-sm font-medium py-2.5"}),t.jsxs("a",{href:l,target:"_blank",rel:"noopener noreferrer",className:"touch-hitslop shrink-0 inline-flex items-center gap-1.5 rounded-dash-lg border border-v4-line bg-v4-surface px-3.5 text-sm font-bold text-v4-ink-2 hover:bg-v4-surface-2 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",children:[t.jsx(ia,{size:15}),"Open"]})]}),t.jsxs("p",{className:"text-xs text-v4-ink-3 leading-relaxed",children:[t.jsx(c,{size:13,className:"inline-block mr-1 -mt-0.5"}),"Want it on the wall? The"," ",n?t.jsx(j,{to:`${a}/settings/qrcodes`,className:"text-primary font-semibold hover:underline",children:"QR codes page"}):t.jsx("span",{className:"font-semibold text-v4-ink-2",children:"QR codes page"})," ","turns this same link into a printable code, and the poster studio there prints a full gift-card poster with your logo and colours."]})]})}function ds({tenantId:e,unlocked:a,canManage:s,isActiveTab:n}){const l=y().pathname.startsWith("/portal")?"/portal":"/dashboard",[i,o]=g.useState(null),[d,c]=g.useState(""),[u,h]=g.useState(()=>"undefined"==typeof window||"false"!==Te.getItem("resoflow_giftcards_selling_expanded")),[p,x]=g.useState(()=>"undefined"!=typeof window&&"true"===Te.getItem("resoflow_giftcards_amounts_expanded")),[b,f]=g.useState(()=>"undefined"!=typeof window&&"true"===Te.getItem("resoflow_giftcards_promo_expanded")),[v,k]=g.useState(()=>"undefined"!=typeof window&&"true"===Te.getItem("resoflow_giftcards_discount_expanded"));g.useEffect(()=>{Te.setItem("resoflow_giftcards_selling_expanded",JSON.stringify(u))},[u]),g.useEffect(()=>{Te.setItem("resoflow_giftcards_amounts_expanded",JSON.stringify(p))}
7,[p]),g.useEffect(()=>{Te.setItem("resoflow_giftcards_promo_expanded",JSON.stringify(b))},[b]),g.useEffect(()=>{Te.setItem("resoflow_giftcards_discount_expanded",JSON.stringify(v))},[v]);const{settings:C,planState:S}=L(),P=(null==S?void 0:S.planConfig)||(null==S?void 0:S.plan)||"taster",A=Dt(null==C?void 0:C.timezone);g.useEffect(()=>{let t=!1;return(async()=>{try{const a=await w(N(B,"tenants",e,"settings","giftCardConfig")),s=a.exists()?a.data():{};if(t)return;o({onlineSaleEnabled:!0===s.onlineSaleEnabled,acceptAtOnlineCheckout:!0===s.acceptAtOnlineCheckout,acceptForTableOrders:!0===s.acceptForTableOrders,acceptForCollectionOrders:Ba(s,"collection"),acceptForDeliveryOrders:Ba(s,"delivery"),passFeeToBuyer:!0===s.passFeeToBuyer,quickPicks:Array.isArray(s.quickPickAmountsPence)?s.quickPickAmountsPence.filter(e=>Number.isInteger(e)):[2500,5e3,7500,1e4],minPounds:((s.minCustomAmountPence||500)/100).toFixed(2),maxPounds:((s.maxCustomAmountPence||5e4)/100).toFixed(2),expiryMonths:String(s.expiryMonths||24),settleHoldHours:String("number"==typeof s.settleHoldHours?s.settleHoldHours:0),scheduleMaxDays:String("number"==typeof s.scheduleMaxDaysAhead?s.scheduleMaxDaysAhead:90),...gt(s.bonusPromo),...xt(s.priceDiscount)})}catch(a){console.warn("[GiftCardSettingsSection] config load failed:",a),t||V.error(z(a))}})(),()=>{t=!0}},[e]);const $=H({savedValues:i??is,onSave:async t=>{var a,s;const r=as(t.minPounds),n=as(t.maxPounds),l=Number.parseInt(t.expiryMonths,10),i=Number.parseInt(t.settleHoldHours||"0",10),d=Number.parseInt(t.scheduleMaxDays||"90",10);if(null===r||null===n||!Number.isFinite(l)||!Number.isFinite(i)||i<0||!Number.isFinite(d)||d<1)throw V.error("Please check the amounts, expiry months, settle-hold hours and the schedule-ahead limit."),new Error("validation failed");const c=yt(t);if(!c.ok)throw V.error(c.error),new Error("validation failed");const m=jt(t);if(!m.ok)throw V.error(m.error),new Error("validation failed");if(!0===(null==(a=c.bonusPromo)?void 0:a.enabled)&&!0===(null==(s=m.priceDiscount)?void 0:s.enabled)&&vt(c.bonusPromo,m.priceDiscount))throw V.error("Only one gift card offer can run at a time. Give the bonus promotion and the price discount dates that don't overlap, or switch one of them off."),new Error("validation failed");try{const a=(await O("updateGiftCardConfig")({tenantId:e,config:{onlineSaleEnabled:t.onlineSaleEnabled,acceptAtOnlineCheckout:t.acceptAtOnlineCheckout,acceptForTableOrders:t.acceptForTableOrders,acceptForCollectionOrders:t.acceptForCollectionOrders,acceptForDeliveryOrders:t.acceptForDeliveryOrders,passFeeToBuyer:t.passFeeToBuyer,quickPickAmountsPence:t.quickPicks,minCustomAmountPence:r,maxCustomAmountPence:n,expiryMonths:l,settleHoldHours:i,scheduleMaxDaysAhead:d,bonusPromo:c.bonusPromo,priceDiscount:m.priceDiscount}})).data.config;o({onlineSaleEnabled:a.onlineSaleEnabled,acceptAtOnlineCheckout:!0===a.acceptAtOnlineCheckout,acceptForTableOrders:!0===a.acceptForTableOrders,acceptForCollectionOrders:Ba(a,"collection"),acceptForDeliveryOrders:Ba(a,"delivery"),passFeeToBuyer:!0===a.passFeeToBuyer,quickPicks:a.quickPickAmountsPence,minPounds:(a.minCustomAmountPence/100).toFixed(2),maxPounds:(a.maxCustomAmountPence/100).toFixed(2),expiryMonths:String(a.expiryMonths),settleHoldHours:String("number"==typeof a.settleHoldHours?a.settleHoldHours:0),scheduleMaxDays:String("number"==typeof a.scheduleMaxDaysAhead?a.scheduleMaxDaysAhead:90),...gt(a.bonusPromo),...xt(a.priceDiscount)})}catch(u){throw V.error(z(u)),new Error("save failed")}}}),[F,D]=g.useState(!1);if(g.useEffect(()=>{!F&&i&&requestAnimationFrame(()=>{requestAnimationFrame(()=>D(!0))})},[i,F]),!a){const e=_("giftVouchers"),a=U("giftVouchers",e);return t.jsxs("div",{className:"rounded-dash-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm px-5 py-6 flex items-start gap-3",children:[t.jsx(Zt,{size:16,className:"mt-0.5 text-slate-400 shrink-0"}),t.jsxs("div",{children:[t.jsx("p",{className:"text-sm font-semibold text-slate-700 dark:text-slate-200",children:e?`Selling settings need ${e}`:"Selling settings need a plan upgrade"}),t.jsxs("p",{className:"text-xs text-slate-500 dark:text-slate-400 mt-1 max-w-lg",children:["Your plan doesn't include gift card selling, so the online page, quick-
7pick amounts and selling settings are paused. Everything already sold stays redeemable from the Sold cards tab.",a?` ${a}`:""]})]})]})}if(!i)return t.jsx("div",{className:"h-64 rounded-dash-xl bg-slate-100 dark:bg-slate-800 animate-pulse"});const M=!s,I=$.values,E=e=>$.setValues(e),T=()=>{const e=as(d);null===e||e<=0?V.error("Please enter a valid amount."):I.quickPicks.includes(e)?c(""):I.quickPicks.length>=6?V.error("Up to 6 quick-pick amounts."):(E({quickPicks:[...I.quickPicks,e].sort((e,t)=>e-t)}),c(""))};return t.jsxs("div",{className:"space-y-6",children:[n&&t.jsx(W,{icon:null,title:"Selling & settings",description:null,dirty:$.dirty,saving:$.saving,savedFlash:$.savedFlash,onSave:$.save,onDiscard:$.discard}),M&&t.jsx("div",{className:"rounded-dash-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 px-4 py-3 text-sm text-amber-800 dark:text-amber-200",children:"You can look around, but changing these settings needs the “Manage gift cards” permission."}),t.jsxs("section",{className:"rounded-dash-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm overflow-hidden",children:[t.jsx("div",{className:"px-6 py-4 border-b border-slate-100 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50 cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors",...We(()=>h(!u),u),children:t.jsxs("div",{className:"flex items-center justify-between gap-4",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("div",{className:"w-9 h-9 rounded-dash-lg bg-primary/10 flex items-center justify-center shrink-0",children:t.jsx(r,{size:18,className:"text-primary"})}),t.jsxs("div",{children:[t.jsx("h3",{className:"text-sm font-bold text-slate-900 dark:text-white",children:"Online selling"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:kt(I)})]})]}),t.jsx("div",{className:"shrink-0",children:t.jsx(oa,{size:20,className:"text-slate-500 dark:text-slate-400 transition-transform duration-200 "+(u?"rotate-180":"")})})]})}),t.jsxs(Ie,{expanded:u,className:"p-6 space-y-5",children:[t.jsxs("div",{className:"flex items-center justify-between gap-4",children:[t.jsxs("div",{children:[t.jsx("p",{className:"text-sm font-semibold text-slate-900 dark:text-white",children:"Sell gift cards online"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400 mt-0.5",children:"Opens your public gift card page and checkout. Off until you switch it on; turning it off later pauses new online sales — cards already sold keep working."})]}),t.jsx(q,{value:I.onlineSaleEnabled,disabled:M,ariaLabel:"Sell gift cards online",initialLoadComplete:F,onChange:e=>E({onlineSaleEnabled:e})})]}),t.jsxs("div",{className:"flex items-center justify-between gap-4 border-t border-slate-100 dark:border-slate-800 pt-5",children:[t.jsxs("div",{children:[t.jsx("p",{className:"text-sm font-semibold text-slate-900 dark:text-white",children:"Accept gift cards at online checkout"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400 mt-0.5 max-w-md",children:"Let customers pay booking deposits and event tickets with a gift card on your public pages. When a part-paid booking or ticket is refunded, the card portion refunds first and the rest goes back onto the gift card."})]}),t.jsx(q,{value:I.acceptAtOnlineCheckout,disabled:M,ariaLabel:"Accept gift cards at online checkout",initialLoadComplete:F,onChange:e=>E({acceptAtOnlineCheckout:e})})]}),[{key:"acceptForTableOrders",feature:"orderAndPay",label:"Accept gift cards for table orders",help:"Let customers pay for an order placed at the table with a gift card. Separate from the online-checkout switch above, so you can accept cards for bookings and tickets without accepting them on orders (or the other way round)."},{key:"acceptForCollectionOrders",feature:"orderCollection",label:"Accept gift cards for collection orders",help:"Let customers pay for a collection order with a gift card. Until you set it yourself, this follows the table switch."},{key:"acceptForDeliveryOrders",feature:"orderDelivery",label:"Accept gift cards for delivery orders",help:"Let customers pay for a delivery order with a gift card. Until you set it yourself, this follows the table switch."}].map(e=>{const a=R(P,e.feature),s=I[e.key];return t.jsxs("div",{className:"flex items-center justify-between gap-4 border-t border-slate-100 dar
7k:border-slate-800 pt-5",children:[t.jsxs("div",{children:[t.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[t.jsx("p",{className:"text-sm font-semibold text-slate-900 dark:text-white",children:e.label}),!a&&t.jsx($e,{feature:e.feature})]}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400 mt-0.5 max-w-md",children:e.help})]}),t.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[t.jsx(q,{value:s,disabled:M||!a&&!s,ariaLabel:e.label,initialLoadComplete:F,onChange:t=>E({[e.key]:t})}),t.jsx(Fe,{kind:"feature",gateKey:e.feature,label:e.label})]})]},e.key)}),t.jsxs("div",{className:"flex items-center justify-between gap-4 border-t border-slate-100 dark:border-slate-800 pt-5",children:[t.jsxs("div",{children:[t.jsx("p",{className:"text-sm font-semibold text-slate-900 dark:text-white",children:"Pass the ResoFlow fee to the buyer"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400 mt-0.5 max-w-md",children:"If ResoFlow charges a platform fee on online gift card sales, this adds it to what the buyer pays (card value + fee) instead of you absorbing it. The gift card platform fee is currently £0, so this changes nothing today."})]}),t.jsx(q,{value:I.passFeeToBuyer,disabled:M,ariaLabel:"Pass the ResoFlow fee to the buyer",initialLoadComplete:F,onChange:e=>E({passFeeToBuyer:e})})]}),t.jsxs("div",{className:"flex items-start justify-between gap-4 border-t border-slate-100 dark:border-slate-800 pt-5",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsx("p",{className:"text-sm font-semibold text-slate-900 dark:text-white",children:"Hold new online purchases before first use"}),t.jsx(Me,{value:"0 — no hold",changed:"0"!==I.settleHoldHours,className:"mt-1"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400 mt-0.5 max-w-md",children:"Optional fraud protection: a gift card bought online can't be redeemed until this many hours after purchase, giving the card payment time to settle. 0 means no hold (the default). Cards sold at the venue are never held."})]}),t.jsxs("div",{className:"shrink-0 w-24",children:[t.jsx("label",{className:"sr-only",htmlFor:"gc-settle-hold",children:"Settle-hold hours"}),t.jsx("input",{id:"gc-settle-hold",type:"number",min:"0",max:"168",step:"1",disabled:M,value:I.settleHoldHours,onChange:e=>E({settleHoldHours:e.target.value}),className:Xa}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1 text-right",children:"hours"})]})]})]})]}),t.jsxs("section",{className:"rounded-dash-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm overflow-hidden",children:[t.jsx("div",{className:"px-6 py-4 border-b border-slate-100 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50 cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors",...We(()=>x(!p),p),children:t.jsxs("div",{className:"flex items-center justify-between gap-4",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("div",{className:"w-9 h-9 rounded-dash-lg bg-primary/10 flex items-center justify-center shrink-0",children:t.jsx(la,{size:18,className:"text-primary"})}),t.jsxs("div",{children:[t.jsx("h3",{className:"text-sm font-bold text-slate-900 dark:text-white",children:"Amounts & expiry"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:wt(I)})]})]}),t.jsx("div",{className:"shrink-0",children:t.jsx(oa,{size:20,className:"text-slate-500 dark:text-slate-400 transition-transform duration-200 "+(p?"rotate-180":"")})})]})}),t.jsxs(Ie,{expanded:p,className:"p-6 space-y-5",children:[t.jsxs("div",{className:"space-y-2",children:[t.jsx("p",{className:"text-sm font-semibold text-slate-900 dark:text-white",children:"Quick-pick amounts"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:"The one-tap amount tiles on your gift card page (up to 6). Buyers can always enter a custom amount between your limits below."}),t.jsxs("div",{className:"flex flex-wrap items-center gap-2 pt-1",children:[I.quickPicks.map(e=>t.jsxs("span",{className:"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-dash-md bg-slate-100 dar
7k:bg-slate-800 text-sm font-semibold text-slate-700 dark:text-slate-200",children:[et(e),!M&&t.jsx("button",{type:"button","aria-label":`Remove ${et(e)}`,onClick:()=>E({quickPicks:I.quickPicks.filter(t=>t!==e)}),className:"text-slate-500 dark:text-slate-400 hover:text-slate-600 dark:hover:text-slate-200",children:t.jsx(we,{size:12})})]},e)),!M&&t.jsxs("span",{className:"inline-flex items-center gap-1",children:[t.jsx("input",{type:"number",min:"1",step:"0.01",inputMode:"decimal",value:d,onChange:e=>c(e.target.value),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),T())},placeholder:"£","aria-label":"New quick-pick amount in pounds",className:"w-20 px-2 py-1 rounded-dash-md border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 text-sm text-slate-900 dark:text-white dark:[color-scheme:dark]"}),t.jsx("button",{type:"button",onClick:T,"aria-label":"Add amount",className:"p-1.5 rounded-dash-md border border-slate-200 dark:border-slate-700 text-slate-500 hover:bg-slate-50 dark:hover:bg-slate-800",children:t.jsx(da,{size:13})})]})]})]}),t.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-3 border-t border-slate-100 dark:border-slate-800 pt-5",children:[t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-min",children:"Minimum amount (£)"}),t.jsx(Me,{value:`£${Number(is.minPounds)}`,changed:I.minPounds!==is.minPounds,className:"ml-2"}),t.jsx("input",{id:"gc-min",type:"number",min:"5",step:"0.01",disabled:M,value:I.minPounds,onChange:e=>E({minPounds:e.target.value}),className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:`£${Number(is.minPounds)} is the floor.`})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-max",children:"Maximum amount (£)"}),t.jsx(Me,{value:`£${Number(is.maxPounds)}`,changed:I.maxPounds!==is.maxPounds,className:"ml-2"}),t.jsx("input",{id:"gc-max",type:"number",min:"5",step:"0.01",disabled:M,value:I.maxPounds,onChange:e=>E({maxPounds:e.target.value}),className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:`Up to £${Number(is.maxPounds)}.`})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-expiry",children:"Cards last (months)"}),t.jsx(Me,{value:"24 months",changed:"24"!==I.expiryMonths,className:"ml-2"}),t.jsx("input",{id:"gc-expiry",type:"number",min:"12",max:"120",step:"1",disabled:M,value:I.expiryMonths,onChange:e=>E({expiryMonths:e.target.value}),className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"At least 12 months, from the day of sale."})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-schedule-days",children:"Schedule ahead limit (days)"}),t.jsx(Me,{value:"90 days",changed:"90"!==I.scheduleMaxDays,className:"ml-2"}),t.jsx("input",{id:"gc-schedule-days",type:"number",min:"1",max:"365",step:"1",disabled:M,value:I.scheduleMaxDays,onChange:e=>E({scheduleMaxDays:e.target.value}),className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"How far ahead buyers can schedule a gift delivery. Up to 365 days; 90 by default."})]})]})]})]}),t.jsxs("div",{className:"flex items-start gap-2 bg-slate-50 dark:bg-slate-900 p-4 rounded-dash-lg border border-slate-100 dark:border-slate-800",children:[t.jsx(m,{size:16,className:"text-slate-500 dark:text-slate-400 mt-0.5 shrink-0"}),t.jsx("p",{className:"text-xs text-slate-600 dark:text-slate-400 leading-relaxed",children:"Gift cards you sell are redeemable at your venue however you choose — staff can always redeem a card in person from the Scanner. Online, the two switches above control exactly where customers can spend them through ResoFlow: the online checkout switch covers bookings, deposits and event tickets, and the table-orders switch covers Order & Pay."})]}),t.jsxs("section",{className:"rounded-dash-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm overflow-hidden",children:[t.jsx("div",{className:"px-6 py-4 border-b border-slate-100 dar
7k:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50 cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors",...We(()=>f(!b),b),children:t.jsxs("div",{className:"flex items-center justify-between gap-4",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("div",{className:"w-9 h-9 rounded-dash-lg bg-primary/10 flex items-center justify-center shrink-0",children:t.jsx(ca,{size:18,className:"text-primary"})}),t.jsxs("div",{children:[t.jsx("h3",{className:"text-sm font-bold text-slate-900 dark:text-white",children:"Bonus promotion"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:Nt(I)})]})]}),t.jsx("div",{className:"shrink-0",children:t.jsx(oa,{size:20,className:"text-slate-500 dark:text-slate-400 transition-transform duration-200 "+(b?"rotate-180":"")})})]})}),t.jsxs(Ie,{expanded:b,className:"p-6 space-y-5",children:[t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:"Add extra value on top of what buyers pay — e.g. buy £50, get £60."}),t.jsxs("div",{className:"flex items-center justify-between gap-4",children:[t.jsxs("div",{children:[t.jsx("p",{className:"text-sm font-semibold text-slate-900 dark:text-white",children:"Run a bonus promotion"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400 mt-0.5 max-w-md",children:"While it's on, your gift page shows the offer and every qualifying online purchase is loaded with the extra value automatically. You cover the bonus when it's spent — and if a purchase is refunded, any unspent bonus is simply withdrawn, never paid out. Turning it off keeps your numbers for next time. Add start and end dates below and it switches itself on and off — no need to come back."})]}),t.jsx(q,{value:I.promoEnabled,disabled:M,ariaLabel:"Run a bonus promotion",initialLoadComplete:F,onChange:e=>E({promoEnabled:e})})]}),I.promoEnabled&&t.jsxs("div",{className:"border-t border-slate-100 dark:border-slate-800 pt-5 space-y-4",children:[t.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center gap-3",children:[t.jsx("p",{className:Qa,children:"Bonus type"}),t.jsx(Ve,{ariaLabel:"Bonus type",size:"sm",value:I.promoKind,onChange:e=>{M||E({promoKind:e})},options:[{value:"fixed",label:"Fixed amount extra"},{value:"percent",label:"Percentage extra"}]})]}),t.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:["fixed"===I.promoKind?t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-promo-fixed",children:"Extra value (£)"}),t.jsx("input",{id:"gc-promo-fixed",type:"number",min:"0.01",max:"500",step:"0.01",inputMode:"decimal",disabled:M,value:I.promoFixedPounds,onChange:e=>E({promoFixedPounds:e.target.value}),className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"Added to every qualifying card. Up to £500."})]}):t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-promo-percent",children:"Extra value (%)"}),t.jsx("input",{id:"gc-promo-percent",type:"number",min:"1",max:"100",step:"1",disabled:M,value:I.promoPercent,onChange:e=>E({promoPercent:e.target.value}),className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"A percentage of what the buyer pays (1–100)."})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-promo-minspend",children:"Minimum spend (£)"}),t.jsx("input",{id:"gc-promo-minspend",type:"number",min:"0",step:"0.01",inputMode:"decimal",disabled:M,value:I.promoMinSpendPounds,onChange:e=>E({promoMinSpendPounds:e.target.value}),placeholder:"No minimum",className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"Only purchases at or above this qualify. Leave blank and every purchase qualifies."})]})]}),t.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-promo-start",children:"Start date"}),t.jsx("input",{id:"gc-promo-start",type:"date",disabled:M,value:I.promoStartDate,max:I.promoEndDate||void 0,onChange:e=>E({promoStartDate:e.target.value}),className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"Leave blank to start straight away."})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-promo-end",children:"End date"}),t.jsx("input",{id:"gc-promo-end",type:"date",disabled:M,value:I.promoEndDate,min:I.promoStartDate||void 0,onChange:e=>E({promoEndDate:e.target.value}),className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"Included — the offer runs to the end of this day, then switches itself off. Leave blank to run until you turn it off."})]})]}),(()=>{const e=Ct(I);if(!e)return t.jsx("div",{className:"rounded-dash-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 px-4 py-3 text-sm text-amber-800 dark:text-amber-200",children:"Please check the bonus amounts and dates — the promotion can't go live until they're valid."});const a=St(I,A),s=Pt(I,A);return t.jsxs("div",{className:"space-y-2",children:["ended"!==a&&t.jsxs("div",{className:"rounded-dash-lg border border-primary/20 bg-primary/5 px-4 py-3 flex items-start gap-2.5",children:[t.jsx(ca,{size:16,className:"text-primary mt-0.5 shrink-0"}),t.jsxs("p",{className:"text-sm text-slate-700 dark:text-slate-300 leading-relaxed",children:["scheduled"===a?"From the start date, customers will see: ":"On your gift page, customers will see: ",t.jsxs("span",{className:"font-semibold",children:["“",e,"”"]})]})]}),s&&t.jsx("div",{className:"rounded-dash-lg border px-4 py-3 text-sm "+("ended"===a?"border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 text-amber-800 dark:text-amber-200":"scheduled"===a?"border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200":"border-emerald-200 dark:border-emerald-800 bg-emerald-50 dark:bg-emerald-900/20 text-emerald-800 dark:text-emerald-200"),children:s})]})})()]})]})]}),t.jsxs("section",{className:"rounded-dash-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm overflow-hidden",children:[t.jsx("div",{className:"px-6 py-4 border-b border-slate-100 dar
7k:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50 cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors",...We(()=>k(!v),v),children:t.jsxs("div",{className:"flex items-center justify-between gap-4",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("div",{className:"w-9 h-9 rounded-dash-lg bg-primary/10 flex items-center justify-center shrink-0",children:t.jsx(ma,{size:18,className:"text-primary"})}),t.jsxs("div",{children:[t.jsx("h3",{className:"text-sm font-bold text-slate-900 dark:text-white",children:"Price discount"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:At(I)})]})]}),t.jsx("div",{className:"shrink-0",children:t.jsx(oa,{size:20,className:"text-slate-500 dark:text-slate-400 transition-transform duration-200 "+(v?"rotate-180":"")})})]})}),t.jsxs(Ie,{expanded:v,className:"p-6 space-y-5",children:[t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:"Cut the price buyers pay — e.g. pay £45 for a £50 card. The card keeps its full value."}),t.jsxs("div",{className:"flex items-center justify-between gap-4",children:[t.jsxs("div",{children:[t.jsx("p",{className:"text-sm font-semibold text-slate-900 dark:text-white",children:"Run a price discount"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400 mt-0.5 max-w-md",children:"While it's on, your gift page shows the offer and every qualifying online purchase is charged the discounted price — the card is still loaded with its full value. If a purchase is refunded, the buyer gets back what they actually paid. Only one offer can run at a time, so give this and the bonus promotion dates that don't overlap (or run just one). Turning it off keeps your numbers for next time."})]}),t.jsx(q,{value:I.discountEnabled,disabled:M,ariaLabel:"Run a price discount",initialLoadComplete:F,onChange:e=>E({discountEnabled:e})})]}),I.discountEnabled&&t.jsxs("div",{className:"border-t border-slate-100 dark:border-slate-800 pt-5 space-y-4",children:[t.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center gap-3",children:[t.jsx("p",{className:Qa,children:"Discount type"}),t.jsx(Ve,{ariaLabel:"Discount type",size:"sm",value:I.discountKind,onChange:e=>{M||E({discountKind:e})},options:[{value:"fixed",label:"Fixed amount off"},{value:"percent",label:"Percentage off"}]})]}),t.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:["fixed"===I.discountKind?t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-discount-fixed",children:"Money off (£)"}),t.jsx("input",{id:"gc-discount-fixed",type:"number",min:"0.01",max:"500",step:"0.01",inputMode:"decimal",disabled:M,value:I.discountFixedPounds,onChange:e=>E({discountFixedPounds:e.target.value}),className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"Taken off every qualifying purchase. Up to £500 — the price a buyer pays never drops below 30p."})]}):t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-discount-percent",children:"Money off (%)"}),t.jsx("input",{id:"gc-discount-percent",type:"number",min:"1",max:"90",step:"1",disabled:M,value:I.discountPercent,onChange:e=>E({discountPercent:e.target.value}),className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"A percentage off the price (1–90)."})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-discount-minspend",children:"Minimum spend (£)"}),t.jsx("input",{id:"gc-discount-minspend",type:"number",min:"0",step:"0.01",inputMode:"decimal",disabled:M,value:I.discountMinSpendPounds,onChange:e=>E({discountMinSpendPounds:e.target.value}),placeholder:"No minimum",className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"Only purchases at or above this qualify. Leave blank and every purchase qualifies."})]})]}),t.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-discount-start",children:"Start date"}),t.jsx("input",{id:"gc-discount-start",type:"date",disabled:M,value:I.discountStartDate,max:I.discountEndDate||void 0,onChange:e=>E({discountStartDate:e.target.value}),className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"Leave blank to start straight away."})]}),t.jsxs("div",{children:[t.jsx("label",{className:Qa,htmlFor:"gc-discount-end",children:"End date"}),t.jsx("input",{id:"gc-discount-end",type:"date",disabled:M,value:I.discountEndDate,min:I.discountStartDate||void 0,onChange:e=>E({discountEndDate:e.target.value}),className:`${Xa} mt-1`}),t.jsx("p",{className:"text-[11px] text-slate-500 dark:text-slate-400 mt-1",children:"Included — the offer runs to the end of this day, then switches itself off. Leave blank to run until you turn it off."})]})]}),(()=>{const e=$t(I),a=Ft(I);if(!e)return t.jsx("div",{className:"rounded-dash-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 px-4 py-3 text-sm text-amber-800 dark:text-amber-200",children:"Please check the discount amounts and dates — the offer can't go live until they're valid."});const s=St(a,A),r=Pt(a,A),n=I.promoEnabled&&vt({...I.promoStartDate&&{startDate:I.promoStartDate},...I.promoEndDate&&{endDate:I.promoEndDate}},{...I.discountStartDate&&{startDate:I.discountStartDate},...I.discountEndDate&&{endDate:I.discountEndDate}});return t.jsxs("div",{className:"space-y-2",children:[n&&t.jsx("div",{className:"rounded-dash-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 px-4 py-3 text-sm text-amber-800 dark:text-amber-200",children:"Only one gift card offer can run at a time. Give the bonus promotion and the price discount dates that don't overlap, or switch one of them off — this can't be saved as it is."}),"ended"!==s&&t.jsxs("div",{className:"rounded-dash-lg border border-primary/20 bg-primary/5 px-4 py-3 flex items-start gap-2.5",children:[t.jsx(ma,{size:16,className:"text-primary mt-0.5 shrink-0"}),t.jsxs("p",{className:"text-sm text-slate-700 dark:text-slate-300 leading-relaxed",children:["scheduled"===s?"From the start date, customers will see: ":"On your gift page, customers will see: ",t.jsxs("span",{className:"font-semibold",children:["“",e,"”"]})]})]}),r&&t.jsx("div",{className:"rounded-dash-lg border px-4 py-3 text-sm "+("ended"===s?"border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 text-amber-800 dark:text-amber-200":"scheduled"===s?"border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200":"border-emerald-200 dark:border-emerald-800 bg-emerald-50 dark:bg-emerald-900/20 text-emerald-800 dark:text-emerald-200"),children:r})]})})()]})]})]}),t.jsxs("section",{className:"rounded-dash-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm overflow-hidden",children:[t.jsx("div",{className:"px-6 py-4 border-b border-slate-100 dar
7k:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50",children:t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("div",{className:"w-9 h-9 rounded-dash-lg bg-primary/10 flex items-center justify-center shrink-0",children:t.jsx(ra,{size:18,className:"text-primary"})}),t.jsxs("div",{children:[t.jsx("h3",{className:"text-sm font-bold text-slate-900 dark:text-white",children:"Emails"}),t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:"What card holders hear from you after they spend."})]})]})}),t.jsx("div",{className:"p-6",children:t.jsxs("div",{className:"rounded-dash-lg border border-slate-200 dark:border-slate-700 bg-slate-50/60 dark:bg-slate-800/40 px-4 py-3 flex flex-wrap items-center justify-between gap-3",children:[t.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400 min-w-0",children:"The balance update email (“£X used, £Y left” after each redemption) is managed with every other customer message."}),t.jsx(j,{to:`${l}/settings/customer-notifications#gift-card-notifications`,className:"touch-hitslop shrink-0 text-xs font-semibold text-primary underline",children:"Manage notifications →"})]})})]}),t.jsxs("div",{className:"text-xs text-slate-500 dark:text-slate-400 space-y-0.5",children:[t.jsxs("p",{children:["Occasion designs live on the ",t.jsx(j,{to:"#designs",className:"font-semibold text-primary hover:underline",children:"Designs tab"}),"."]}),t.jsx("p",{children:R(P,"analytics")?t.jsxs(t.Fragment,{children:["The monthly gift card summary email is set up on ",t.jsx(j,{to:`${l}/analytics/reports`,className:"font-semibold text-primary hover:underline",children:"Analytics → Reports"}),"."]}):t.jsxs(t.Fragment,{children:["The monthly gift card summary email is set up in the ",t.jsx("a",{href:"#gift-card-summary",className:"font-semibold text-primary hover:underline",children:"Monthly summary section"})," on the Settings tab."]})})]}),$.blockerModal]})}export{rs as GiftCardsPage,rs as default};
8//# sourceMappingURL=GiftCardsPage-DpLiCjww.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.