PageSourceSearch

https://music-space-manager-groovegardenltd.replit.app/assets/admin-DuRPMAEY.js

js music-space-manager-groovegardenltd.replit.app collected 2026-10-03 03:57:17 UTC 72,265 bytes, 41 lines download raw bytes

1import{c as W,r as T,u as Ce,j as e,B as u,d as R,q as fe,k as js,b as ss,a as vs,g as ys,L as fs,m as Ns}from"./index-BQRzQg0n.js";import{u as _}from"./useQuery-DjaJdaZ3.js";import{u as M}from"./useMutation-Bg2L2sxv.js";import{H as Ue}from"./header-7qggKaOO.js";import{C as Y,b as de,c as le,a as J}from"./card-Dgfo2-sm.js";import{B as h}from"./badge-B5fSFUPa.js";import{D as se,e as Ne,a as te,b as ae,c as ie}from"./dialog-i_8UL9Dm.js";import{A as qe,a as Oe,b as ze,c as Ve,d as Ke,e as He,f as Qe,g as Ge,h as _e}from"./alert-dialog-BdLv5vm0.js";import{C as he}from"./calendar-DOvoHhJl.js";import{C as bs,a as ts}from"./chevron-right-a6QpLsck.js";import{M as Ee}from"./map-pin-CbYu7Qy_.js";import{P as Ye}from"./pencil-CYzEtLWT.js";import{T as ge}from"./trash-2-T4BO10KK.js";import{U as Ie}from"./user-BI3I8_pc.js";import{M as as}from"./mail-D3NuYEFO.js";import{C as be}from"./credit-card-CJ_-6FBQ.js";import{I as F}from"./input-BOhz-3KQ.js";import{L as k}from"./label-B2mOKxkc.js";import{S as is,a as ns,b as rs,c as ds,d as Re}from"./select-CU4hBc9v.js";import{C as Me}from"./checkbox-BXidzpr-.js";import{S as ks}from"./shield-BG_-Uqv5.js";import{K as ws}from"./key-DmtBD3ty.js";import{T as Be}from"./triangle-alert-Kv6qIbZl.js";import{R as ye}from"./refresh-cw-BUbyvCbO.js";import{P as ls}from"./plus-Cs04szp3.js";import{U as Je}from"./users-BKFJcja0.js";import{C as We}from"./circle-x-vgNv-I5h.js";import{C as Xe}from"./circle-check-big-CB0F4drS.js";import{C as Cs}from"./clock-BOP5EjsG.js";import{F as Ze}from"./file-text-BIqklTXW.js";import"./utils-km2FGkQ4.js";import"./groove-garden-logo-eu7koeSa.js";import"./chevron-down-Cl6G0RmI.js";import"./settings-D4Qcj4Tm.js";import"./index-BG1NX9jj.js";import"./Combination-CRs_MNlL.js";import"./index-CpVNNAvG.js";import"./index-CdAC2ICk.js";/**
2 * @license lucide-react v0.453.0 - ISC
3 *
4 * This source code is licensed under the ISC license.
5 * See the LICENSE file in the root directory of this source tree.
6 */const es=W("CalendarX",[["path",{d:"M8 2v4",key:"1cmpym"}],["path",{d:"M16 2v4",key:"4m81vk"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2",key:"1hopcy"}],["path",{d:"M3 10h18",key:"8toen8"}],["path",{d:"m14 14-4 4",key:"rymu2i"}],["path",{d:"m10 14 4 4",key:"3sz06r"}]]);/**
7 * @license lucide-react v0.453.0 - ISC
8 *
9 * This source code is licensed under the ISC license.
10 * See the LICENSE file in the root directory of this source tree.
11 */const Ts=W("Grid3x3",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M3 9h18",key:"1pudct"}],["path",{d:"M3 15h18",key:"5xshup"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"M15 3v18",key:"14nvp0"}]]);/**
12 * @license lucide-react v0.453.0 - ISC
13 *
14 * This source code is licensed under the ISC license.
15 * See the LICENSE file in the root directory of this source tree.
16 */const Ss=W("Link2",[["path",{d:"M9 17H7A5 5 0 0 1 7 7h2",key:"8i5ue5"}],["path",{d:"M15 7h2a5 5 0 1 1 0 10h-2",key:"1b9ql8"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12",key:"1jonct"}]]);/**
17 * @license lucide-react v0.453.0 - ISC
18 *
19 * This source code is licensed under the ISC license.
20 * See the LICENSE file in the root directory of this source tree.
21 */const Ds=W("List",[["path",{d:"M3 12h.01",key:"nlz23k"}],["path",{d:"M3 18h.01",key:"1tta3j"}],["path",{d:"M3 6h.01",key:"1rqtza"}],["path",{d:"M8 12h13",key:"1za7za"}],["path",{d:"M8 18h13",key:"1lx6n3"}],["path",{d:"M8 6h13",key:"ik3vkj"}]]);/**
22 * @license lucide-react v0.453.0 - ISC
23 *
24 * This source code is licensed under the ISC license.
25 * See the LICENSE file in the root directory of this source tree.
26 */const cs=W("Phone",[["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z",key:"foiqr5"}]]);/**
27 * @license lucide-react v0.453.0 - ISC
28 *
29 * This source code is licensed under the ISC license.
30 * See the LICENSE file in the root directory of this source tree.
31 */const Fe=W("Repeat",[["path",{d:"m17 2 4 4-4 4",key:"nntrym"}],["path",{d:"M3 11v-1a4 4 0 0 1 4-4h14",key:"84bu3i"}],["path",{d:"m7 22-4-4 4-4",key:"1wqhfi"}],["path",{d:"M21 13v1a4 4 0 0 1-4 4H3",key:"1rx37r"}]]);/**
32 * @license lucide-react v0.453.0 - ISC
33 *
34 * This source code is licensed under the ISC license.
35 * See the LICENSE file in the root directory of this source tree.
36 */const $s=W("Search",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]]);/**
37 * @license lucide-react v0.453.0 - ISC
38 *
39 * This source code is licensed under the ISC license.
40 * See the LICENSE file in the root directory of this source tree.
41 */const As=W("SquarePen",[["path",{d:"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7",key:"1m0v6g"}],["path",{d:"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z",key:"ohrbg2"}]]);function Ps(r){const g=new Intl.DateTimeFormat("en-GB",{timeZone:"Europe/London",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23"}).formatToParts(r),w=v=>{var E;return((E=g.find(P=>P.type===v))==null?void 0:E.value)??""};return{date:`${w("year")}-${w("month")}-${w("day")}`,time:`${w("hour")}:${w("minute")}`}}function ke(r,g,w=new Date){const v=Ps(w);return r<v.date?!0:r>v.date?!1:(g==="00:00"?"24:00":g)<=v.time}function Bs({bookings:r,blockedSlots:g}){const[w,v]=T.useState(new Date),[E,P]=T.useState(null),[c,f]=T.useState(null),[U,S]=T.useState(null),{toast:C}=Ce(),p=M({mutationFn:async n=>await R("PATCH",`/api/admin/bookings/${n}/cancel`),onSuccess:()=>
41{fe.invalidateQueries({queryKey:["/api/admin/bookings"]}),C({title:"Success",description:"Booking cancelled successfully"})},onError:n=>{C({title:"Error",description:n.message||"Failed to cancel booking",variant:"destructive"})}}),I=M({mutationFn:async n=>await R("PATCH",`/api/admin/blocked-slots/${n.id}`,{startTime:n.startTime,endTime:n.endTime,reason:n.reason}),onSuccess:()=>{fe.invalidateQueries({queryKey:["/api/admin/blocked-slots"]}),S(null),C({title:"Success",description:"Blocked slot updated successfully"})},onError:n=>{C({title:"Error",description:n.message||"Failed to update blocked slot",variant:"destructive"})}}),$=M({mutationFn:async n=>await R("DELETE",`/api/admin/blocked-slots/${n}`),onSuccess:()=>{fe.invalidateQueries({queryKey:["/api/admin/blocked-slots"]}),C({title:"Success",description:"Blocked slot deleted successfully"})},onError:n=>{C({title:"Error",description:n.message||"Failed to delete blocked slot",variant:"destructive"})}}),N=w.getMonth(),A=w.getFullYear(),X=()=>{v(new Date(A,N-1,1,12,0,0))},H=()=>{v(new Date(A,N+1,1,12,0,0))},Z=()=>{v(new Date)},o=r.filter(n=>n.status!=="cancelled"&&!n.groupCode).reduce((n,B)=>{const m=B.date;return n[m]||(n[m]=[]),n[m].push(B),n},{}),D=g.reduce((n,B)=>{const m=B.date;return n[m]||(n[m]=[]),n[m].push(B),n},{}),V=n=>(o[n]||[]).reduce((m,K)=>{const O=K.roomName;return m[O]=(m[O]||0)+1,m},{}),G=n=>{switch(n){case"Pod 1":return"bg-blue-500";case"Pod 2":return"bg-green-500";case"Live Room":return"bg-purple-500";default:return"bg-gray-500"}},Te=`${["January","February","March","April","May","June","July","August","September","October","November","December"][N]} ${A}`,Se=new Date(A,N+1,0,12,0,0).getDate(),ce=new Date(A,N,1,12,0,0).getDay(),ne=[];for(let n=0;n<ce;n++)ne.push(null);for(let n=1;n<=Se;n++)ne.push(n);const De=n=>{const B=A,m=(N+1).toString().padStart(2,"0"),K=n.toString().padStart(2,"0");return`${B}-${m}-${K}`},j=n=>{const[B,m,K]=n.split("-");return new Date(parseInt(B),parseInt(m)-1,parseInt(K),12,0,0).toLocaleDateString("en-US",{weekday:"long",year:"numeric",month:"long",day:"numeric"})},q=n=>new Date(n).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit",hour12:!0}),oe=(n,B,m)=>{if(n==="confirmed"&&ke(B,m))return e.jsx(h,{className:"bg-gray-100 text-gray-700",children:"Ended"});switch(n){case"completed":return e.jsx(h,{className:"bg-green-100 text-green-800",children:"Completed"});case"confirmed":return e.jsx(h,{className:"bg-music-amber text-white",children:"Upcoming"});case"cancelled":return e.jsx(h,{variant:"destructive",children:"Cancelled"});default:return e.jsx(h,{variant:"secondary",children:n})}},me=n=>{switch(n){case"verified":return e.jsx(h,{className:"bg-green-100 text-green-800",children:"✓ Verified"});case"pending":return e.jsx(h,{className:"bg-yellow-100 text-yellow-800",children:"⏳ Pending"});case"rejected":return e.jsx(h,{variant:"destructive",children:"✗ Rejected"});default:return e.jsx(h,{variant:"secondary",children:"Not submitted"})}};return e.jsxs(e.Fragment,{children:[e.jsxs(Y,{children:[e.jsx(de,{className:"pb-4",children:e.jsxs("div",{className:"flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4",children:[e.jsxs(le,{className:"flex items-center gap-2",children:[e.jsx(he,{className:"h-5 w-5 text-blue-500"}),e.jsx("span",{className:"hidden sm:inline",children:"Bookings Calendar"}),e.jsx("span",{className:"sm:hidden",children:"Calendar"})]}),e.jsxs("div",{className:"flex items-center gap-1 sm:gap-2 w-full sm:w-auto",children:[e.jsx(u,{variant:"outline",size:"sm",onClick:Z,"data-testid":"button-today",className:"text-xs sm:text-sm px-2 sm:px-3",children:"Today"}),e.jsx(u,{variant:"outline",size:"sm",onClick:X,"data-testid":"button-prev-month",className:"px-2 sm:px-3",children:e.jsx(bs,{className:"h-4 w-4"})}),e.jsx("span",{className:"font-medium px-2 sm:px-4 text-sm sm:text-base min-w-0 text-center","data-testid":"text-month-year",children:Te}),e.jsx(u,{variant:"outline",size:"sm",onClick:H,"data-testid":"button-next-month",className:"px-2 sm:px-3",children:e.jsx(ts,{className:"h-4 w-4"})})]})]})}),e.jsxs(J,{className:"px-2 sm:px-6",children:[e.jsx("div",{className:"grid grid-cols-7 gap-0.5 sm:gap-1 mb-2",children:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"].map(n=>e.jsxs("div",{className:"p-1 sm:p-2 text-center text-xs sm:text-sm font-medium text-gray-500",children:[e.jsx("span",{className:"hidden sm:inline",children:n}),e.jsx("span",{className:"sm:hidden",children:n.slice(0,1)})]},n))}),e.jsx("div",{className:"grid grid-cols-7 gap-0.5 sm:gap-1 overflow-hidden",children:ne.map((n,B)=>
41{if(n===null)return e.jsx("div",{className:"p-1 sm:p-2 h-16 sm:h-20 lg:h-24"},B);const m=De(n),K=V(m),O=Object.values(K).reduce((d,re)=>d+re,0),Q=O>0,ee=D[m]||[],ue=ee.length>0,xe=new Date,$e=`${xe.getFullYear()}-${String(xe.getMonth()+1).padStart(2,"0")}-${String(xe.getDate()).padStart(2,"0")}`,Ae=m===$e,Pe=E===m;return e.jsxs(se,{children:[e.jsx(Ne,{asChild:!0,children:e.jsxs("button",{className:`p-1 sm:p-2 h-20 sm:h-24 border rounded-lg text-left transition-colors hover:bg-gray-50 ${Ae?"border-blue-500 bg-blue-50":"border-gray-200"} ${Pe?"ring-2 ring-blue-500":""}`,onClick:()=>P(m),"data-testid":`calendar-day-${n}`,children:[e.jsx("div",{className:"font-medium text-xs sm:text-sm truncate",children:n}),(Q||ue)&&e.jsxs("div",{className:"mt-1 space-y-1 overflow-hidden",children:[Q&&e.jsxs("div",{className:"text-xs sm:text-xs text-gray-600 truncate",children:[O,O>9?"+":"",e.jsxs("span",{className:"hidden sm:inline",children:[" booking",O!==1?"s":""]})]}),ue&&e.jsxs("div",{className:"text-xs sm:text-xs text-red-600 truncate",children:[ee.length,ee.length>9?"+":"",e.jsx("span",{className:"hidden sm:inline",children:" blocked"})]}),e.jsxs("div",{className:"flex flex-wrap gap-0.5 sm:gap-1",children:[Object.entries(K).map(([d,re])=>e.jsx("div",{className:`w-1.5 h-1.5 sm:w-2 sm:h-2 rounded-full ${G(d)}`,title:`${d}: ${re} booking${re!==1?"s":""}`},`booking-${d}`)),ue&&e.jsx("div",{className:"w-1.5 h-1.5 sm:w-2 sm:h-2 bg-red-500 transform rotate-45",title:`${ee.length} blocked time${ee.length!==1?"s":""}`})]})]})]})}),e.jsxs(te,{className:"max-w-4xl max-h-[80vh] overflow-y-auto",children:[e.jsx(ae,{children:e.jsxs(ie,{children:["Bookings for ",j(m)]})}),e.jsxs("div",{className:"space-y-4",children:[D[m]&&D[m].length>0&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2 text-red-600 font-medium",children:[e.jsx("div",{className:"w-3 h-3 bg-red-500 transform rotate-45"}),e.jsx("h3",{className:"text-lg",children:"Blocked Time Slots"})]}),D[m].map(d=>e.jsx("div",{className:"border rounded-lg p-4 bg-red-50 border-red-200",children:e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Ee,{className:"h-4 w-4 text-red-500"}),e.jsxs("span",{className:"font-medium",children:["Room ID: ",d.roomId]}),e.jsx(h,{variant:"destructive",children:"Blocked"})]}),e.jsxs("div",{className:"text-sm text-gray-600",children:[e.jsxs("div",{children:[d.startTime," - ",d.endTime]}),d.reason&&e.jsxs("div",{className:"mt-1 text-red-700",children:["Reason: ",d.reason]})]})]}),e.jsxs("div",{className:"space-y-2",children:[d.isRecurring&&e.jsxs(h,{variant:"outline",className:"bg-red-100 text-red-800 border-red-300",children:["Recurring",d.recurringUntil&&` until ${d.recurringUntil}`]}),e.jsxs("div",{className:"text-xs text-gray-500",children:[e.jsxs("div",{children:["Block ID: #",d.id]}),e.jsxs("div",{children:["Created: ",q(d.createdAt)]})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(u,{variant:"outline",size:"sm",onClick:()=>S(d),className:"flex-1","data-testid":`edit-blocked-slot-${d.id}`,children:[e.jsx(Ye,{className:"h-4 w-4 mr-1"}),"Edit"]}),e.jsxs(qe,{children:[e.jsx(Oe,{asChild:!0,children:e.jsxs(u,{variant:"destructive",size:"sm",className:"flex-1","data-testid":`delete-blocked-slot-${d.id}`,children:[e.jsx(ge,{className:"h-4 w-4 mr-1"}),"Delete"]})}),e.jsxs(ze,{children:[e.jsxs(Ve,{children:[e.jsx(Ke,{children:"Delete Blocked Slot?"}),e.jsx(He,{children:"This will permanently delete this blocked time slot. This action cannot be undone."})]}),e.jsxs(Qe,{children:[e.jsx(Ge,{children:"Cancel"}),e.jsx(_e,{onClick:()=>$.mutate(d.id),className:"bg-red-600 hover:bg-red-700",children:"Delete"})]})]})]})]})]})},`blocked-${d.id}`))]}),o[m]&&o[m].length>0&&e.jsxs("div",{className:"space-y-4",children:[D[m]&&D[m].length>0&&e.jsxs("div",{className:"flex items-center gap-2 text-blue-600 font-medium mt-6",children:[e.jsx(he,{className:"h-4 w-4"}),e.jsx("h3",{className:"text-lg",children:"Bookings"})]}),o[m].map(d=>e.jsx("div",{className:"border rounded-lg p-4 bg-gray-50",children:e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Ie,{className:"h-4 w-4 text-gray-500"}),e.jsx("span",{className:"font-medium",children:d.userName}),me(d.idVerificationStatus)]}),e.jsxs("div",{className:"flex items-center gap-2 text-sm text-gray-600",children:[e.jsx(as,{className:"h-4 w-4"}),e.jsx("span",{children:d.userEmail})]}),d.userPhone&&e.jsxs("div",{className:"flex items-center gap-2 text-sm text-gray-600",children:[e.jsx(cs,{className:"h-4 w-4"}),e.jsx("span",{children:d.userPhone})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Ee,{className:"h-4 w-4 text-gray-500"}),e.jsx("span",{className:"font-medium",children:d.roomName}),oe(d.status,d.date,d.endTime)]}),e.jsx("div",{className:"text-sm text-gray-600",children:e.jsxs("div",{children:[d.startTime," - ",d.endTime," 
41(",d.duration,"h)"]})}),e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(be,{className:"h-4 w-4 text-gray-500"}),e.jsxs("span",{className:"font-medium text-green-600",children:["£",d.totalPrice.toFixed(2)]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"text-sm",children:[e.jsx("div",{className:"text-gray-600",children:"Access Code:"}),e.jsxs("div",{className:"font-mono bg-white px-2 py-1 rounded border text-music-purple",children:[d.accessCode,"#"]})]}),e.jsxs("div",{className:"text-xs text-gray-500",children:[e.jsxs("div",{children:["Lock Access: ",d.status==="confirmed"&&ke(d.date,d.endTime)?"Code expired/removed":d.ttlockCodeMismatch===!0?"⚠️ Code mismatch":d.ttlockVerified===!0&&d.ttlockTimingVerified===!1?"⚠️ Timing mismatch":d.ttlockVerified===!0?"✅ Enabled":d.ttlockVerified===!1?d.accessCode||d.ttlockPasscodeId?"⚠️ Unverified":"❌ Disabled":d.lockAccessEnabled?"✅ Enabled":"❌ Disabled"]}),e.jsxs("div",{children:["Booked: ",q(d.createdAt)]}),e.jsxs("div",{children:["ID: #",d.id]})]}),e.jsxs("div",{className:"flex gap-2 mt-3",children:[e.jsxs(u,{variant:"outline",size:"sm",onClick:()=>f(d),disabled:d.status==="cancelled","data-testid":`button-edit-booking-${d.id}`,children:[e.jsx(Ye,{className:"h-3 w-3 mr-1"}),"Edit"]}),e.jsxs(qe,{children:[e.jsx(Oe,{asChild:!0,children:e.jsxs(u,{variant:"destructive",size:"sm",disabled:d.status==="cancelled"||p.isPending,"data-testid":`button-cancel-booking-${d.id}`,children:[e.jsx(ge,{className:"h-3 w-3 mr-1"}),"Cancel"]})}),e.jsxs(ze,{children:[e.jsxs(Ve,{children:[e.jsx(Ke,{children:"Cancel Booking?"}),e.jsxs(He,{children:["Are you sure you want to cancel this booking for ",d.userName,"? This will delete the access code and cannot be undone."]})]}),e.jsxs(Qe,{children:[e.jsx(Ge,{children:"No, Keep Booking"}),e.jsx(_e,{onClick:()=>p.mutate(d.id),className:"bg-red-600 hover:bg-red-700",children:"Yes, Cancel Booking"})]})]})]})]})]})]})},d.id))]}),(!o[m]||o[m].length===0)&&(!D[m]||D[m].length===0)&&e.jsxs("div",{className:"text-center py-8 text-gray-500",children:[e.jsx(he,{className:"h-12 w-12 mx-auto mb-4 text-gray-300"}),e.jsx("p",{children:"No bookings or blocked times for this date"})]})]})]})]},`${A}-${N}-${n}`)})}),e.jsxs("div",{className:"mt-4 flex flex-wrap items-center gap-4 text-sm",children:[e.jsx("span",{className:"text-gray-600",children:"Indicators:"}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("div",{className:"w-3 h-3 rounded-full bg-blue-500"}),e.jsx("span",{children:"Pod 1"})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("div",{className:"w-3 h-3 rounded-full bg-green-500"}),e.jsx("span",{children:"Pod 2"})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("div",{className:"w-3 h-3 rounded-full bg-purple-500"}),e.jsx("span",{children:"Live Room"})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("div",{className:"w-3 h-3 bg-red-500 transform rotate-45"}),e.jsx("span",{children:"Blocked Times"})]})]})]})]}),c&&e.jsx(se,{open:!0,onOpenChange:n=>!n&&f(null),children:e.jsxs(te,{className:"max-w-2xl max-h-[90vh] overflow-y-auto",children:[e.jsx(ae,{children:e.jsxs(ie,{children:["Edit Booking #",c.id]})}),e.jsx(Fs,{booking:c,onClose:()=>f(null)})]})}),U&&e.jsx(se,{open:!0,onOpenChange:n=>!n&&S(null),children:e.jsxs(te,{className:"max-w-lg max-h-[90vh] overflow-y-auto",children:[e.jsx(ae,{children:e.jsxs(ie,{children:["Edit Blocked Slot #",U.id]})}),e.jsx(Es,{blockedSlot:U,onClose:()=>S(null),onSave:n=>I.mutate(n)})]})})]})}function Fs({booking:r,onClose:g}){const[w,v]=T.useState(r.date),[E,P]=T.useState(r.startTime),[c,f]=T.useState(r.duration),{toast:U}=Ce(),C=(($,N)=>{const[A,X]=$.split(":").map(Number),H=A*60+X+N*60,Z=Math.floor(H/60)%24,t=H%60;return`${String(Z).padStart(2,"0")}:${String(t).padStart(2,"0")}`})(E,c),p=M({mutationFn:async $=>await R("PATCH",`/api/admin/bookings/${r.id}`,$),onSuccess:()=>{fe.invalidateQueries({queryKey:["/api/admin/bookings"]}),U({title:"Success",description:"Booking updated successfully"}),g()},onError:$=>{U({title:"Error",description:$.message||"Failed to update booking",variant:"destructive"})}}),I=$=>{$.preventDefault(),p.mutate({date:w,startTime:E,endTime:C,duration:c})};return e.jsxs("form",{onSubmit:I,className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"User"}),e.jsx("input",{type:"text",value:r.userName,disabled:!0,className:"w-full px-3 py-2 border rounded-md bg-gray-50"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Room"}),e.jsx("input",{type:"text",value:r.roomName,disabled:!0,className:"w-full px-3 py-2 border rounded-md bg-gray-50"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Date"}),e.jsx("input",{type:"date",value:w,onChange:$=>v($.target.value),className:"w-full px-3 py-2 border rounded-md",required:!0,"data-testid":"input-edit-booking-date"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Start Time"}),e.jsx("input",{type:"time",value:E,onChange:$=>P($.target.value),className:"w-full px-3 py-2 border rounded-md",required:!0,"data-testid":"input-edit-booking-start-time"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Duration (hours)"}),e.jsx("input",{type:"number",min:"1",max:"12",value:c,onChange:$=>f(parseInt($.target.value)),className:"w-full px-3 py-2 border rounded-md",required:!0,"data-testid":"input-edit-booking-duration"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"End Time (calculated)"}),e.jsx("input",{type:"text",value:C,disabled:!0,className:"w-full px-3 py-2 border rounded-md bg-gray-50"})]}),e.jsxs("div",{className:"flex justify-end gap-2 pt-4",children:[e.jsx(u,{type:"button",variant:"outline",onClick:g,disabled:p.isPending,children:"Cancel"}),e.jsx(u,{type:"submit",disabled:p.isPending,"data-testid":"button-save-booking-changes",children:p.isPending?"Saving...":"Save Changes"})]})]})}function Es({blockedSlot:r,onClose:g,onSave:w}){const[v,E]=T.useState(r.startTime),[P,c]=T.useState(r.endTime),[f,U]=T.useState(r.reason||""),S=C=>{C.preventDefault(),w({id:r.id,startTime:v,endTime:P,reason:f})};return e.jsxs("form",{onSubmit:S,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Room ID"}),e.jsx("input",{type:"text",value:`Room ${r.roomId}`,disabled:!0,className:"w-full px-3 py-2 border rounded-md bg-gray-50"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Date"}),e.jsx("input",{type:"text",value:r.date,disabled:!0,className:"w-full px-3 py-2 border rounded-md bg-gray-50"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Start Time"}
41),e.jsx("input",{type:"time",value:v,onChange:C=>E(C.target.value),className:"w-full px-3 py-2 border rounded-md",required:!0,"data-testid":"input-edit-blocked-slot-start-time"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"End Time"}),e.jsx("input",{type:"time",value:P,onChange:C=>c(C.target.value),className:"w-full px-3 py-2 border rounded-md",required:!0,"data-testid":"input-edit-blocked-slot-end-time"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Reason (Optional)"}),e.jsx("textarea",{value:f,onChange:C=>U(C.target.value),className:"w-full px-3 py-2 border rounded-md",rows:3,placeholder:"Maintenance, event, etc.","data-testid":"input-edit-blocked-slot-reason"})]}),e.jsxs("div",{className:"flex justify-end gap-2 pt-4",children:[e.jsx(u,{type:"button",variant:"outline",onClick:g,children:"Cancel"}),e.jsx(u,{type:"submit","data-testid":"button-save-blocked-slot-changes",className:"bg-blue-600 hover:bg-blue-700",children:"Save Changes"})]})]})}const we=T.forwardRef(({className:r,...g},w)=>e.jsx("textarea",{className:js("flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",r),ref:w,...g}));we.displayName="Textarea";function ft(){const{toast:r}=Ce(),g=ss(),[,w]=vs(),{user:v}=ys(),P=v&&["[email protected]","[email protected]"].includes(v.email),{data:c,isLoading:f,error:U}=_({queryKey:["/api/admin/id-verifications"],refetchInterval:3e4,enabled:!!P}),{data:S,isLoading:C}=_({queryKey:["/api/admin/blocked-slots"],enabled:!!P}),{data:p}=_({queryKey:["/api/rooms"],enabled:!!P}),{data:I,isLoading:$}=_({queryKey:["/api/admin/bookings"],enabled:!!P,refetchInterval:6e4}),{data:N}=_({queryKey:["/api/admin/lock-code-count",p],queryFn:async()=>{var l;const s=(l=p==null?void 0:p[0])==null?void 0:l.lockId;if(!s)return null;const i=await fetch(`/api/admin/lock-code-count?lockId=${s}`,{headers:Ns(),credentials:"include"});return i.ok?i.json():null},enabled:!!P,refetchInterval:5*60*1e3}),{data:A}=_({queryKey:["/api/admin/bookings/old-count"],enabled:!!P}),[X,H]=T.useState(!1),[Z,t]=T.useState(!1),[o,D]=T.useState(null),[V,G]=T.useState("calendar"),[pe,Te]=T.useState(""),[Se,ce]=T.useState(!1),[ne,De]=T.useState(new Set),[j,q]=T.useState({roomId:"",date:"",startTime:"",endTime:"",reason:"",isRecurring:!1,recurringUntil:"",groupCode:"",groupName:""}),oe=M({mutationFn:s=>R("POST",`/api/admin/id-verifications/${s}/approve`),onSuccess:()=>{g.invalidateQueries({queryKey:["/api/admin/id-verifications"]}),r({title:"✅ User Approved",description:"User has been verified and can now make bookings."})},onError:()=>{r({title:"❌ Approval Failed",description:"Failed to approve ID verification. Please try again.",variant:"destructive"})}}),me=M({mutationFn:s=>R("POST",`/api/admin/id-verifications/${s}/reject`,{reason:"ID verification requirements not met"}),onSuccess:()=>{g.invalidateQueries({queryKey:["/api/admin/id-verifications"]}),r({title:"❌ User Rejected",description:"User's verification was rejected and future bookings cancelled."})},onError:()=>{r({title:"❌ Rejection Failed",description:"Failed to reject ID verification. Please try again.",variant:"destructive"})}}),n=M({mutationFn:s=>R("POST","/api/admin/blocked-slots",{roomId:parseInt(s.roomId),date:s.date,startTime:s.startTime,endTime:s.endTime,reason:s.reason||null,isRecurring:s.isRecurring,recurringUntil:s.isRecurring?s.recurringUntil:null,groupCode:s.groupCode||null,groupName:s.groupName||null}),onSuccess:s=>{g.invalidateQueries({queryKey:["/api/admin/blocked-slots"]}),H(!1),q({roomId:"",date:"",startTime:"",endTime:"",reason:"",isRecurring:!1,recurringUntil:"",groupCode:"",groupName:""});const i=Array.isArray(s)?s.length:1;r({title:"✅ Time Slot Blocked",description:`${i} time slot${i>1?"s":""} successfully blocked.`})},onError:()=>{r({title:"❌ Failed to Block Slot",description:"Failed to block the time slot. Please try again.",variant:"destructive"})}}),B=M({mutationFn:async()=>{var l;const s=(l=p==null?void 0:p[0])==null?void 0:l.lockId;if(!s)throw new Error("No lock configured");return(await R("POST","/api/admin/purge-lock-codes",{lockId:s})).json()},onSuccess:s=>{g.invalidateQueries({queryKey:["/api/admin/lock-code-count"]}),g.invalidateQueries({queryKey:["/api/admin/bookings"]}
41),r({title:"Purge complete",description:s.message})},onError:s=>{r({title:"Purge failed",description:s.message||"Unknown error",variant:"destructive"})}}),m=M({mutationFn:s=>R("PATCH",`/api/admin/blocked-slots/${s.id}`,{startTime:s.startTime,endTime:s.endTime,reason:s.reason}),onSuccess:()=>{g.invalidateQueries({queryKey:["/api/admin/blocked-slots"]}),t(!1),D(null),r({title:"✅ Block Updated",description:"The time slot block has been updated."})},onError:()=>{r({title:"❌ Failed to Update Block",description:"Failed to update the time slot block. Please try again.",variant:"destructive"})}}),K=M({mutationFn:s=>R("DELETE",`/api/admin/blocked-slots/${s}`),onSuccess:()=>{g.invalidateQueries({queryKey:["/api/admin/blocked-slots"]}),r({title:"✅ Block Removed",description:"The time slot block has been removed."})},onError:()=>{r({title:"❌ Failed to Remove Block",description:"Failed to remove the time slot block. Please try again.",variant:"destructive"})}}),O=M({mutationFn:async()=>await R("DELETE","/api/admin/bookings/old"),onSuccess:s=>{g.invalidateQueries({queryKey:["/api/admin/bookings"]}),g.invalidateQueries({queryKey:["/api/admin/bookings/old-count"]}),ce(!1),r({title:"✅ Cleanup Complete",description:`Deleted ${s.deletedCount} bookings older than ${s.daysOld} days.`})},onError:()=>{r({title:"❌ Cleanup Failed",description:"Failed to delete old bookings. Please try again.",variant:"destructive"})}}),Q=M({mutationFn:async({bookingId:s,notify:i})=>(await R("POST",`/api/admin/bookings/${s}/resync-code${i?"?notify=true":""}`)).json(),onSuccess:s=>{g.invalidateQueries({queryKey:["/api/admin/bookings"]}),s.locksSucceeded===0?r({title:"⚠️ Lock Full — Code Not Registered",description:"Code could not be sent to the lock (storage full). Run Purge Old Codes in Lock Management, then try again.",variant:"destructive"}):r({title:"✅ Code Resynced",description:s.message||"New code registered with the lock."})},onError:s=>{let i="Failed to resync the code. Check TTLock connection.";if(s!=null&&s.message){const l=s.message.match(/^\d+:\s*(.+)$/s),x=l?l[1]:s.message;try{const a=JSON.parse(x);a!=null&&a.message&&(i=a.message)}catch{x&&(i=x)}}r({title:"❌ Resync Failed",description:i,variant:"destructive"})}});T.useEffect(()=>{if(!v){r({title:"Access Denied",description:"Please log in to access this page.",variant:"destructive"}),w("/login?redirect=/admin");return}if(!["[email protected]","[email protected]"].includes(v.email)){r({title:"Unauthorized Access",description:"You don't have permission to access this page.",variant:"destructive"}),w("/");return}},[v,w,r]);const ee=s=>{oe.mutate(s)},ue=s=>{me.mutate(s)},xe=()=>{if(!j.roomId||!j.date||!j.startTime||!j.endTime){r({title:"Missing Information",description:"Please fill in all required fields.",variant:"destructive"});return}if(j.isRecurring&&!j.recurringUntil){r({title:"Missing Information",description:"Please select an end date for weekly recurring blocks.",variant:"destructive"});return}if(j.isRecurring&&new Date(j.recurringUntil)<=new Date(j.date)){r({title:"Invalid Date",description:"Recurring end date must be after the start date.",variant:"destructive"});return}n.mutate(j)},$e=s=>{D(s),t(!0)},Ae=()=>{if(o){if(!o.startTime||!o.endTime){r({title:"Missing Information",description:"Please fill in all required fields.",variant:"destructive"});return}m.mutate({id:o.id,startTime:o.startTime,endTime:o.endTime,reason:o.reason||""})}},Pe=(s,i=!1)=>{i&&r({title:"Delete Recurring Series?",description:"This will delete all recurring blocks in this series. This action cannot be undone."}),K.mutate(s)},d=s=>{if(!p||!Array.isArray(p))return`Room ${s}`;const i=p.find(l=>l.id===s);return(i==null?void 0:i.name)||`Room ${s}`},re=s=>{De(i=>{const l=new Set(i);return l.has(s)?l.delete(s):l.add(s),l})},os=s=>{switch(s){case"drivers_license":return"Driver's License";case"state_id":return"State ID";case"passport":return"Passport";case"military_id":return"Military ID";default:return s}},ms=s=>s||"Not provided",us=(s,i,l)=>{if(s==="confirmed"&&ke(i,l))return e.jsx(h,{className:"bg-gray-100 text-gray-700 border-gray-200",children:"Ended"});switch(s){case"confirmed":return e.jsx(h,{className:"bg-green-100 text-green-800 border-green-200",children:"Confirmed"});case"cancelled":return e.jsx(h,{className:"bg-red-100 text-red-800 border-red-200",children:"Cancelled"});case"completed":return e.jsx(h,{className:"bg-blue-100 text-blue-800 border-blue-200",children:"Completed"});default:return e.jsx(h,{variant:"secondary",children:s})}},xs=s=>{switch(s){case"verified":return e.jsx(h,{className:"bg-green-100 text-green-800 border-green-200",children:"✓ Verified"});
41case"pending":return e.jsx(h,{className:"bg-yellow-100 text-yellow-800 border-yellow-200",children:"⏳ Pending"});case"rejected":return e.jsx(h,{className:"bg-red-100 text-red-800 border-red-200",children:"✗ Rejected"});default:return e.jsx(h,{variant:"secondary",children:"Unknown"})}},hs=s=>{try{const i=new Date(s);return i.toLocaleDateString("en-US",{weekday:"short",month:"short",day:"numeric",year:"numeric"})+" at "+i.toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit"})}catch{return s}},gs=s=>{try{const[i,l,x]=s.split("-");return new Date(parseInt(i),parseInt(l)-1,parseInt(x),12,0,0).toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric",year:"numeric"})}catch{return s}};return P?e.jsxs("div",{className:"min-h-screen bg-gray-50",children:[e.jsx(Ue,{}),e.jsxs("div",{className:"max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-8",children:[e.jsx("div",{className:"mb-8",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(ks,{className:"h-8 w-8 text-music-purple"}),e.jsxs("div",{children:[e.jsx("h1",{"data-testid":"admin-title",className:"text-2xl font-bold text-gray-900",children:"Admin Panel"}),e.jsx("p",{className:"text-gray-600 mt-1",children:"Manage bookings, review ID verifications, and block time slots"})]})]}),e.jsx("div",{className:"flex gap-2",children:e.jsx(fs,{href:"/lock-management",children:e.jsxs(u,{variant:"outline",className:"gap-2","data-testid":"button-lock-management",children:[e.jsx(ws,{className:"h-4 w-4"}),"Lock Management"]})})})]})}),N&&N.percent>=70&&e.jsx("div",{className:`mb-4 rounded-lg border p-4 ${N.percent>=90?"border-red-300 bg-red-50":"border-amber-300 bg-amber-50"}`,children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Be,{className:`h-5 w-5 flex-shrink-0 ${N.percent>=90?"text-red-600":"text-amber-600"}`}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("p",{className:`font-semibold ${N.percent>=90?"text-red-800":"text-amber-800"}`,children:["Lock storage ",N.percent>=90?"critically full":"getting full"," — ",N.count,"/",N.limit," codes"]}),e.jsx("p",{className:`text-sm ${N.percent>=90?"text-red-700":"text-amber-700"}`,children:N.percent>=90?"New booking codes may fail. Go to Lock Management → Purge Old Codes immediately.":"Run Purge Old Codes in Lock Management soon to prevent issues."})]}),e.jsx(u,{size:"sm",variant:N.percent>=90?"destructive":"outline",className:"text-xs",disabled:B.isPending,onClick:()=>B.mutate(),children:B.isPending?e.jsxs(e.Fragment,{children:[e.jsx(ye,{className:"mr-1 h-3 w-3 animate-spin"}),"Purging..."]}):"Purge Now"})]})}),(()=>{const s=Date.now(),i=24*60*60*1e3,l=(I??[]).filter(x=>{if(x.status!=="confirmed"||!x.accessCode||x.ttlockPasscodeId)return!1;const[a,b,L]=x.date.split("-").map(Number),[y,z]=x.startTime.split(":").map(Number),ve=Date.UTC(a,b-1,L,y,z)-s;return ve>=0&&ve<=i});return l.length===0?null:e.jsx("div",{className:"mb-6 rounded-lg border border-amber-300 bg-amber-50 p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(Be,{className:"h-5 w-5 text-amber-600 flex-shrink-0 mt-0.5"}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("p",{className:"font-semibold text-amber-800",children:[l.length," booking",l.length>1?"s":""," not synced to lock"]}),e.jsx("p",{className:"text-sm text-amber-700 mb-3",children:"These customers won't be able to get in unless the code is resynced."}),e.jsx("div",{className:"flex flex-wrap gap-2",children:l.map(x=>e.jsxs("div",{className:"flex items-center gap-2 bg-white border border-amber-200 rounded px-3 py-1.5 text-sm",children:[e.jsx("span",{className:"font-medium",children:x.userName}),e.jsxs("span",{className:"text-gray-500",children:[x.date," ",x.startTime,"–",x.endTime]}),e.jsxs(u,{size:"sm",variant:"outline",className:"h-6 text-xs border-amber-400 text-amber-700 hover:bg-amber-50 px-2",onClick:()=>Q.mutate({bookingId:x.id,notify:!0}),disabled:Q.isPending,children:[e.jsx(ye,{className:"h-3 w-3 mr-1"}),"Resync & Email"]})]},x.id))})]})]})})})(),e.jsx("div",{className:"mb-8","data-testid":"section-admin-bookings",children:e.jsxs(Y,{children:[e.jsx(de,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs(le,{className:"flex items-center gap-2",children:[e.jsx(he,{className:"h-5 w-5 text-blue-500"}),V==="calendar"?"Bookings Calendar":"Recent Bookings"]}),e.jsxs("div",{className:"flex items-center gap-2",children:[A&&A.count>0&&e.jsxs(se,{open:Se,onOpenChange:ce,children:[e.jsx(Ne,{asChild:!0,children:e.jsxs(u,{variant:"outline",size:"sm",className:"text-orange-600 border-orange-300 hover:bg-orange-50","data-testid":"button-cleanup-old-bookings",children:[e.jsx(ge,{className:"h-4 w-4 mr-2"}),"Clean Up (",A.count,")"]})}),e.jsxs(te,{children:[e.jsx(ae,{children:e.jsx(ie,{children:"Delete Old Bookings"})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("p",{className:"text-gray-600",children:["This will permanently delete ",e.jsxs("strong",{children:[A.count," bookings"]})," that are older than ",A.daysOld," days."]}),e.jsx("p",{className:"text-sm text-gray-500",children:"This action cannot be undone. The automatic cleanup runs daily to keep your database clean."}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(u,{onClick:()=>O.mutate(),disabled:O.isPending,className:"flex-1 bg-red-600 hover:bg-red-700","data-testid":"button-confirm-cleanup",children:O.isPending?"Deleting...":"Delete Old Bookings"}),e.jsx(u,{variant:"outline",onClick:()=>ce(!1),className:"flex-1","data-testid":"button-cancel-cleanup",children:"Cancel"})]})]})]})]}),e.jsxs(u,{variant:V==="calendar"?"default":"outline",size:"sm",onClick:()=>G("calendar"),"data-testid":"button-calendar-view",children:[e.jsx(Ts,{className:"h-4 w-4 mr-2"}),"Calendar"]}),e.jsxs(u,{variant:V==="list"?"default":"outline",size:"sm",onClick:()=>G("list"),"data-testid":"button-list-view",children:[e.jsx(Ds,{className:"h-4 w-4 mr-2"}),"List"]})]})]})}),e.jsx(J,{children:$?e.jsxs("div",{className:"flex items-center justify-center py-8",children:[e.jsx("div",{className:"animate-spin rounded-full h-6 w-6 border-b-2 border-blue-500"}),e.jsx("span",{className:"ml-3 text-gray-600",children:"Loading bookings..."})]}):!I||I.length===0?e.jsxs("div",{className:"text-center py-8 text-gray-500",children:[e.jsx(he,{className:"h-12 w-12 mx-auto mb-4 text-gray-300"}),e.jsx("p",{children:"No bookings found"})]}):V==="calendar"?e.jsx(Bs,{bookings:I,blockedSlots:Array.isArray(S)?S:[]}):e.jsxs("div",{className:"space-y-4","data-testid":"admin-bookings-list",children:[e.jsxs("div",{className:"relative",children:[e.jsx($s,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400"}),e.jsx(F,{placeholder:"Search by name, email or room...",value:pe,onCh
41ange:s=>Te(s.target.value),className:"pl-9"})]}),(()=>{const s=new Date().toISOString().split("T")[0],i=pe.toLowerCase(),l=[...I].filter(a=>{var b,L,y;return!i||((b=a.userName)==null?void 0:b.toLowerCase().includes(i))||((L=a.userEmail)==null?void 0:L.toLowerCase().includes(i))||((y=a.roomName)==null?void 0:y.toLowerCase().includes(i))}).sort((a,b)=>{const L=a.date>=s,y=b.date>=s;return L&&!y?-1:!L&&y?1:L?a.date.localeCompare(b.date)||a.startTime.localeCompare(b.startTime):b.date.localeCompare(a.date)||b.startTime.localeCompare(a.startTime)}),x=i?l:l.slice(0,20);return e.jsxs(e.Fragment,{children:[x.map(a=>e.jsx("div",{className:"border rounded-lg p-4 bg-gray-50","data-testid":`admin-booking-${a.id}`,children:e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Ie,{className:"h-4 w-4 text-gray-500"}),e.jsx("span",{className:"font-medium","data-testid":`text-username-${a.id}`,children:a.userName}),e.jsx("span",{"data-testid":`badge-verification-${a.id}`,children:xs(a.idVerificationStatus)})]}),e.jsxs("div",{className:"flex items-center gap-2 text-sm text-gray-600",children:[e.jsx(as,{className:"h-4 w-4"}),e.jsx("span",{"data-testid":`text-email-${a.id}`,children:a.userEmail})]}),a.userPhone&&e.jsxs("div",{className:"flex items-center gap-2 text-sm text-gray-600",children:[e.jsx(cs,{className:"h-4 w-4"}),e.jsx("span",{"data-testid":`text-phone-${a.id}`,children:a.userPhone})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Ee,{className:"h-4 w-4 text-gray-500"}),e.jsx("span",{className:"font-medium","data-testid":`text-room-${a.id}`,children:a.roomName}),e.jsx("span",{"data-testid":`badge-status-${a.id}`,children:us(a.status,a.date,a.endTime)})]}),e.jsxs("div",{className:"text-sm text-gray-600","data-testid":`text-datetime-${a.id}`,children:[e.jsx("div",{children:gs(a.date)}),e.jsxs("div",{children:[a.startTime," - ",a.endTime," (",a.duration,"h)"]})]}),e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(be,{className:"h-4 w-4 text-gray-500"}),e.jsxs("span",{className:"font-medium text-green-600","data-testid":`text-price-${a.id}`,children:["£",a.totalPrice.toFixed(2)]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("div",{className:"text-sm",children:(()=>{const b=!a.ttlockPasscodeId&&a.status==="confirmed"&&(()=>{const[y,z,je]=a.date.split("-").map(Number),[ve,ps]=a.startTime.split(":").map(Number),Le=Date.UTC(y,z-1,je,ve,ps)-Date.now();return Le>=0&&Le<=864e5})(),L=!a.ttlockPasscodeId&&a.status==="confirmed"&&!b;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-1 text-gray-600",children:["Access Code:",b&&e.jsx("span",{title:"Code not registered with lock — resync needed",className:"text-amber-500",children:e.jsx(Be,{className:"h-3 w-3 inline"})})]}),e.jsxs("div",{className:`font-mono px-2 py-1 rounded border ${b?"bg-amber-50 border-amber-300 text-amber-700":"bg-white text-music-purple"}`,"data-testid":`text-access-code-${a.id}`,children:[a.accessCode,"#"]}
41),b&&e.jsx("div",{className:"text-xs text-amber-600 mt-1",children:"⚠️ Not synced to lock"}),L&&e.jsx("div",{className:"text-xs text-blue-500 mt-1",children:"🕐 Scheduled — auto-pushes within 24h of session"})]})})()}),e.jsxs("div",{className:"text-xs text-gray-500",children:[e.jsxs("div",{"data-testid":`text-lock-access-${a.id}`,children:["Lock Access: ",a.status==="confirmed"&&ke(a.date,a.endTime)?"Code expired/removed":a.ttlockCodeMismatch===!0?"⚠️ Code mismatch":a.ttlockVerified===!0&&a.ttlockTimingVerified===!1?"⚠️ Timing mismatch":a.ttlockVerified===!0?"✅ Enabled":a.ttlockVerified===!1?a.accessCode||a.ttlockPasscodeId?"⚠️ Unverified":"❌ Disabled":a.lockAccessEnabled?"✅ Enabled":"❌ Disabled"]}),e.jsxs("div",{"data-testid":`text-created-${a.id}`,children:["Booked: ",hs(a.createdAt)]}),e.jsxs("div",{"data-testid":`text-booking-id-${a.id}`,children:["ID: #",a.id]})]}),a.status==="confirmed"&&e.jsxs("div",{className:"flex gap-1",children:[e.jsxs(u,{size:"sm",variant:"outline",className:`text-xs h-7 ${a.ttlockPasscodeId?"border-gray-300 text-gray-600 hover:bg-gray-50":"border-amber-400 text-amber-700 hover:bg-amber-50"}`,onClick:()=>Q.mutate({bookingId:a.id,notify:!1}),disabled:Q.isPending,"data-testid":`btn-resync-${a.id}`,children:[e.jsx(ye,{className:"h-3 w-3 mr-1"}),Q.isPending?"Syncing…":"Resync Code"]}),e.jsxs(u,{size:"sm",variant:"outline",className:"text-xs h-7 border-blue-300 text-blue-700 hover:bg-blue-50",onClick:()=>Q.mutate({bookingId:a.id,notify:!0}),disabled:Q.isPending,"data-testid":`btn-resync-notify-${a.id}`,children:[e.jsx(ye,{className:"h-3 w-3 mr-1"}),"Resync & Email"]})]})]})]})},a.id)),!i&&l.length>20&&e.jsxs("div",{className:"text-center py-4 text-gray-500 text-sm","data-testid":"bookings-count-info",children:["Showing 20 of ",l.length," bookings — search by name or room to find others."]}),i&&l.length===0&&e.jsxs("div",{className:"text-center py-8 text-gray-500 text-sm",children:['No bookings match "',pe,'"']})]})})()]})})]})}),e.jsx("div",{className:"mb-8",children:e.jsxs(Y,{children:[e.jsx(de,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs(le,{className:"flex items-center gap-2",children:[e.jsx(es,{className:"h-5 w-5 text-red-500"}),"Blocked Time Slots"]}),e.jsxs(se,{open:X,onOpenChange:H,children:[e.jsx(Ne,{asChild:!0,children:e.jsxs(u,{className:"bg-red-600 hover:bg-red-700","data-testid":"add-blocked-slot",children:[e.jsx(ls,{className:"h-4 w-4 mr-2"}),"Block Time Slot"]})}),e.jsxs(te,{className:"max-h-[90vh] overflow-y-auto",children:[e.jsx(ae,{children:e.jsx(ie,{children:"Block Time Slot"})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx(k,{htmlFor:"room",children:"Room"}),e.jsxs(is,{value:j.roomId,onValueChange:s=>q(i=>({...i,roomId:s})),children:[e.jsx(ns,{children:e.jsx(rs,{placeholder:"Select a room"})}),e.jsx(ds,{children:Array.isArray(p)&&p.map(s=>e.jsx(Re,{value:s.id.toString(),children:s.name},s.id))})]})]}),e.jsxs("div",{children:[e.jsx(k,{htmlFor:"date",children:"Date"}),e.jsx(F,{id:"date",type:"date",value:j.date,onChange:s=>q(i=>({...i,date:s.target.value})),min:new Date().toISOString().split("T")[0]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx(k,{htmlFor:"startTime",children:"Start Time"}),e.jsx(F,{id:"startTime",type:"time",value:j.startTime,onChange:s=>q(i=>({...i,startTime:s.target.value}))})]}),e.jsxs("div",{children:[e.jsx(k,{htmlFor:"endTime",children:"End Time"}),e.jsx(F,{id:"endTime",type:"time",value:j.endTime,onChange:s=>q(i=>({...i,endTime:s.target.value}))})]})]}),e.jsxs("div",{children:[e.jsx(k,{htmlFor:"reason",children:"Reason (Optional)"}),e.jsx(we,{id:"reason",placeholder:"e.g., Maintenance, Cleaning, Equipment repair...",value:j.reason,onChange:s=>q(i=>({...i,reason:s.target.value}))})]}),e.jsxs("div",{className:"border rounded-lg p-4 space-y-3 bg-blue-50 border-blue-200",children:[e.jsx("div",{className:"text-sm font-medium text-blue-800",children:"Group Booking (Optional)"}),e.jsx("p",{className:"text-xs text-blue-600",children:"Link this block to an organisation so their members can book free slots within this window."}),e.jsxs("div",{children:[e.jsx(k,{htmlFor:"groupCode",children:"Access Code"}),e.jsx(F,{id:"groupCode",placeholder:"e.g., sheffield-hallam-2026",value:j.groupCode,onChange:s=>q(i=>({...i,groupCode:s.target.value.toLowerCase().replace(/\s+/g,"-")}))}),e.jsx("p",{className:"text-xs text-gray-500 mt-1",children:"URL-safe code students use to access their booking page"})]}),e.jsxs("div",{children:[e.jsx(k,{htmlFor:"groupName",children:"Organisation Name"}),e.jsx(F,{id:"groupName",placeholder:"e.g., Sheffield Hallam University",value:j.groupName,onChange:s=>q(i=>({...i,groupName:s.target.value}))})]}),j.groupCode&&e.jsxs("div",{className:"bg-white rounded border border-blue-200 p-3 space-y-1",children:[e.jsx("p",{className:"text-xs text-gray-500",children:"Shareable booking link:"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("code",{className:"text-xs bg-gray-100 px-2 py-1 rounded flex-1 truncate",children:[window.location.origin,"/book/",j.groupCode]}),e.jsx(u,{type:"button",variant:"outline",size:"sm",onClick:()=>{navigator.clipboard.writeText(`${window.location.origin}/book/${j.groupCode}`),r({title:"Copied!",description:"Link copied to clipboard"})},children:"Copy"})]})]})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Me,{id:"recurring",checked:j.isRecurring,onCheckedChange:s=>q(i=>({...i,isRecurring:!!s,recurringUntil:s?i.recurringUntil:""}))}),e.jsxs(k,{htmlFor:"recurring",className:"flex items-center gap-2",children:[e.jsx(Fe,{className:"h-4 w-4"}),"Repeat weekly"]})]}),j.isRecurring&&e.jsxs("div",{children:[e.jsx(k,{htmlFor:"recurringUntil",children:"Repeat until"}),e.jsx(F,{id:"recurringUntil",type:"date",value:j.recurringUntil,onCh
41ange:s=>q(i=>({...i,recurringUntil:s.target.value})),min:new Date(new Date(j.date).getTime()+7*24*60*60*1e3).toISOString().split("T")[0]}),e.jsxs("p",{className:"text-xs text-gray-500 mt-1",children:["This will create blocks every week from ",j.date," until the selected date"]})]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(u,{onClick:xe,disabled:n.isPending,className:"flex-1 bg-red-600 hover:bg-red-700",children:n.isPending?"Blocking...":"Block Time Slot"}),e.jsx(u,{variant:"outline",onClick:()=>H(!1),className:"flex-1",children:"Cancel"})]})]})]})]})]})}),e.jsx(J,{children:C?e.jsxs("div",{className:"flex items-center justify-center py-8",children:[e.jsx("div",{className:"animate-spin rounded-full h-6 w-6 border-b-2 border-red-500"}),e.jsx("span",{className:"ml-3 text-gray-600",children:"Loading blocked slots..."})]}):!S||!Array.isArray(S)||S.length===0?e.jsxs("div",{className:"text-center py-8 text-gray-500",children:[e.jsx(es,{className:"h-12 w-12 mx-auto mb-4 text-gray-300"}),e.jsx("p",{children:"No blocked time slots"})]}):e.jsx("div",{className:"space-y-3",children:Array.isArray(S)&&S.filter(s=>{const i=new Date;return i.setHours(0,0,0,0),new Date(s.date)>=i}).sort((s,i)=>{const l=s.date.localeCompare(i.date);return l!==0?l:s.isRecurring&&!s.parentBlockId?-1:i.isRecurring&&!i.parentBlockId?1:0}).map(s=>{const i=s.isRecurring&&s.parentBlockId===null,l=s.isRecurring&&s.parentBlockId!==null,x=l&&S.some(z=>z.id===s.parentBlockId),a=l&&!x,b=i?S.filter(z=>z.parentBlockId===s.id&&new Date(z.date)>=new Date(new Date().setHours(0,0,0,0))).length:0,L=ne.has(s.id),y=l&&!a&&!ne.has(s.parentBlockId);return e.jsxs("div",{className:`flex items-center justify-between p-3 border rounded-lg ${y?"hidden":""} ${i?"border-purple-300 bg-purple-50":a?"border-orange-200 bg-orange-50":l?"border-red-200 bg-red-50 ml-6":"border-red-200 bg-red-50"}`,children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-4 text-sm",children:[i&&e.jsx(u,{variant:"ghost",size:"sm",onClick:()=>re(s.id),className:"p-0 h-auto hover:bg-transparent","data-testid":`toggle-recurring-${s.id}`,children:e.jsx(ts,{className:`h-4 w-4 text-purple-600 transition-transform ${L?"rotate-90":""}`})}),e.jsx(h,{variant:"secondary",className:i?"bg-purple-100 text-purple-800":a?"bg-orange-100 text-orange-800":"bg-red-100 text-red-800",children:d(s.roomId)}),e.jsx("span",{className:"font-medium",children:s.date}),e.jsxs("span",{children:[s.startTime," - ",s.endTime]}),i&&e.jsxs(e.Fragment,{children:[e.jsxs(h,{variant:"outline",className:"bg-white text-purple-700 border-purple-300",children:[e.jsx(Fe,{className:"h-3 w-3 mr-1"}),"Weekly until ",s.recurringUntil]}),!L&&b>0&&e.jsxs(h,{variant:"outline",className:"bg-white text-gray-600 border-gray-300",children:[b," more"]})]}),a&&e.jsxs(h,{variant:"outline",className:"bg-white text-orange-700 border-orange-300",children:[e.jsx(Fe,{className:"h-3 w-3 mr-1"}),"Was recurring (series ended)"]}),l&&!a&&e.jsx(h,{variant:"outline",className:"bg-white text-gray-600 border-gray-300",children:"Recurring"})]}),s.reason&&e.jsx("p",{className:"text-xs text-gray-600 mt-1",children:s.reason}),s.groupCode&&e.jsxs("div",{className:"flex items-center gap-2 mt-1",children:[e.jsxs(h,{className:"bg-blue-100 text-blue-800 border-blue-200 text-xs",children:[e.jsx(Je,{className:"h-3 w-3 mr-1"}),s.groupName||s.groupCode]}),e.jsx("button",{className:"text-xs text-blue-600 hover:underline",onClick:()=>{navigator.clipboard.writeText(`${window.location.origin}/book/${s.groupCode}`),r({title:"Copied!",description:"Group booking link copied"})},children:"Copy link"})]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(u,{variant:"ghost",size:"sm",onClick:()=>$e(s),className:"hover:bg-blue-100 text-blue-600 hover:text-blue-700","data-testid":`edit-block-${s.id}`,title:"Edit this block",children:e.jsx(As,{className:"h-4 w-4"})}),e.jsx(u,{variant:"ghost",size:"sm",onClick:()=>Pe(s.id,i),disabled:K.isPending,className:`hover:bg-red-100 ${i?"text-purple-600 hover:text-purple-700":"text-red-600 hover:text-red-700"}`,"data-testid":`remove-block-${s.id}`,title:i?"Delete entire recurring series":"Delete this block",children:e.jsx(ge,{className:"h-4 w-4"})})]})]},s.id)})})})]})}),(()=>{if(!S||!Array.isArray(S))return null;const s=S.filter(l=>l.groupCode);if(s.length===0)return null;const i=new Map;
41return s.forEach(l=>{const x=i.get(l.groupCode);x?(x.roomIds.includes(l.roomId)||x.roomIds.push(l.roomId),x.dates.includes(l.date)||x.dates.push(l.date),x.slotCount++):i.set(l.groupCode,{groupName:l.groupName,roomIds:[l.roomId],dates:[l.date],slotCount:1})}),e.jsx("div",{className:"mb-8",children:e.jsxs(Y,{children:[e.jsx(de,{children:e.jsxs(le,{className:"flex items-center gap-2",children:[e.jsx(Je,{className:"h-5 w-5 text-blue-500"}),"Group Bookings"]})}),e.jsx(J,{children:e.jsx("div",{className:"space-y-3",children:Array.from(i.entries()).map(([l,x])=>{const a=(I==null?void 0:I.filter(y=>y.groupCode===l&&y.status!=="cancelled"))||[],b=[...x.dates].sort(),L=x.roomIds.map(y=>{if(!p||!Array.isArray(p))return`Room ${y}`;const z=p.find(je=>je.id===y);return(z==null?void 0:z.name)||`Room ${y}`});return e.jsxs("div",{className:"border rounded-lg p-4 bg-blue-50 border-blue-200",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"space-y-1 flex-1",children:[e.jsx("div",{className:"font-medium text-blue-900",children:x.groupName||l}),e.jsxs("div",{className:"text-sm text-blue-700",children:["Code: ",e.jsx("code",{className:"bg-white px-1 rounded",children:l})]}),e.jsxs("div",{className:"text-sm text-gray-600",children:[L.join(", ")," • ",b.length===1?b[0]:`${b[0]} – ${b[b.length-1]}`]}),e.jsxs("div",{className:"text-sm text-gray-600",children:[e.jsx("span",{className:"font-medium text-blue-800",children:a.length})," booking",a.length!==1?"s":""," made"]})]}),e.jsxs(u,{variant:"outline",size:"sm",className:"border-blue-300 text-blue-700 hover:bg-blue-100 shrink-0",onClick:()=>{navigator.clipboard.writeText(`${window.location.origin}/book/${l}`),r({title:"Copied!",description:"Group booking link copied to clipboard"})},children:[e.jsx(Ss,{className:"h-4 w-4 mr-1"}),"Copy Link"]})]}),a.length>0&&e.jsx("div",{className:"mt-3 border-t border-blue-200 pt-3 space-y-1",children:a.map(y=>e.jsxs("div",{className:"text-xs text-gray-600 flex items-center gap-2",children:[e.jsx("span",{className:"font-medium",children:y.userName}),e.jsxs("span",{children:[y.date," ",y.startTime,"–",y.endTime]}),e.jsx("span",{className:"text-gray-400",children:y.roomName})]},y.id))})]},l)})})})]})})})(),e.jsx(se,{open:Z,onOpenChange:t,children:e.jsxs(te,{className:"max-h-[90vh] overflow-y-auto",children:[e.jsx(ae,{children:e.jsx(ie,{children:"Edit Blocked Time Slot"})}),o&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx(k,{children:"Room"}),e.jsx(F,{value:d(o.roomId),disabled:!0,className:"bg-gray-100"})]}),e.jsxs("div",{children:[e.jsx(k,{children:"Date"}),e.jsx(F,{value:o.date,disabled:!0,className:"bg-gray-100"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx(k,{htmlFor:"edit-start-time",children:"Start Time"}),e.jsx(F,{id:"edit-start-time",type:"time",value:o.startTime,onChange:s=>D({...o,startTime:s.target.value}),"data-testid":"input-edit-start-time"})]}),e.jsxs("div",{children:[e.jsx(k,{htmlFor:"edit-end-time",children:"End Time"}),e.jsx(F,{id:"edit-end-time",type:"time",value:o.endTime,onChange:s=>D({...o,endTime:s.target.value}),"data-testid":"input-edit-end-time"})]})]}),e.jsxs("div",{children:[e.jsx(k,{htmlFor:"edit-reason",children:"Reason (Optional)"}),e.jsx(we,{id:"edit-reason",value:o.reason||"",onChange:s=>D({...o,reason:s.target.value}),placeholder:"Maintenance, event, etc.","data-testid":"input-edit-reason"})]}),e.jsxs("div",{className:"flex gap-2 pt-4",children:[e.jsx(u,{onClick:Ae,disabled:m.isPending,className:"flex-1 bg-blue-600 hover:bg-blue-700","data-testid":"button-save-edit-block",children:m.isPending?"Saving...":"Save Changes"}),e.jsx(u,{variant:"outline",onClick:()=>{t(!1),D(null)},className:"flex-1",children:"Cancel"})]})]})]})}),e.jsx(Is,{}),f?e.jsxs("div",{className:"flex items-center justify-center py-12",children:[e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-music-purple"}),e.jsx("span",{className:"ml-3 text-gray-600",children:"Loading pending verifications..."})]}):U?e.jsx(Y,{children:e.jsxs(J,{className:"py-8 text-center",children:[e.jsx(We,{className:"h-12 w-12 text-red-500 mx-auto mb-4"}),e.jsx("h3",{className:"text-lg font-semibold text-gray-900 mb-2",children:"Error Loading Data"}),e.jsx("p",{className:"text-gray-600",children:"Unable to fetch pending verifications. Please refresh the page."})]})}):!c||Array.isArray(c)&&c.length===0?e.jsx(Y,{children:e.jsxs(J,{className:"py-8 text-center",children:[e.jsx(Xe,{className:"h-12 w-12 text-green-500 mx-auto mb-4"}),e.jsx("h3",{className:"text-lg font-semibold text-gray-900 mb-2",children:"All Clear!"}),e.jsx("p",{className:"text-gray-600",children:"No pending ID verifications to review."})]})}):e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"bg-white rounded-lg border border-gray-200 p-4 mb-6",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Cs,{className:"h-5 w-5 text-orange-500"}),e.jsxs("span",{className:"font-medium text-gray-900",children:[Array.isArray(c)?c.length:0," Pending Review",Array.isArray(c)&&c.length!==1?"s":""]})]}),e.jsx(h,{variant:"outline",className:"bg-orange-50 text-orange-700 border-orange-200",children:"Requires Action"})]})}),Array.isArray(c)&&c.map(s=>e.jsxs(Y,{"data-testid":`user-card-${s.id}`,className:"overflow-hidden border-l-4 border-l-orange-400",children:[e.jsx(de,{className:"bg-orange-50/50",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs(le,{className:"flex items-center gap-2 text-lg",children:[e.jsx(Ie,{className:"h-5 w-5 text-gray-600"}),s.name||s.username]}),e.jsx(h,{variant:"secondary",className:"bg-orange-100 text-orange-800",children:s.idVerificationStatus})]})}),e.jsxs(J,{className:"p-6",children:[e.jsxs("div",{className:"grid md:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"space-y-3",children:[e.jsxs("h4",{className:"font-medium text-gray-900 flex items-center gap-2",children:[e.jsx(Ze,{className:"h-4 w-4"}),"User Information"]}),e.jsxs("div",{className:"space-y-2 text-sm",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"Username:"}),e.jsx("span",{className:"font-medium","data-testid":`username-${s.id}`,children:s.username})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"Email:"}),e.jsx("span",{className:"font-medium","data-testid":`email-${s.id}`,children:s.email})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"Phone:"}),e.jsx("span",{className:"font-medium","data-testid":`phone-${s.id}`,children:ms(s.phone)})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"ID Type:"}),e.jsx("span",{className:"font-medium","data-testid":`id-type-${s.id}`,children:os(s.idType)})]}),s.idNumber&&e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"ID Number:"}),e.jsxs("span",{className:"font-medium font-mono text-xs","data-testid":`id-number-${s.id}`,children:[s.idNumber.substring(0,4),"...",s.idNumber.substring(s.idNumber.length-4)]})]})]})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("h4",{className:"font-medium text-gray-900 flex items-center gap-2",children:[e.jsx(Ze,{className:"h-4 w-4"}),"Uploaded Documents"]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[s.idPhotoUrl&&e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-xs text-gray-600",children:"ID Photo"}),e.jsx("img",{src:s.idPhotoUrl,alt:"ID Document","data-testid":`id-photo-${s.id}`,className:"w-full h-24 object-cover rounded-lg border border-gray-200 cursor-pointer hover:opacity-90 transition-opacity",onClick:()=>window.open(s.idPhotoUrl,"_blank")})]}),s.selfiePhotoUrl&&e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-xs text-gray-600",children:"Selfie Photo"}),e.jsx("img",{src:s.selfiePhotoUrl,alt:"Selfie","data-testid":`selfie-photo-${s.id}`,className:"w-full h-24 object-cover rounded-lg border border-gray-200 cursor-pointer hover:opacity-90 transition-opacity",onClick:()=>window.open(s.selfiePhotoUrl,"_blank")})]})]}),e.jsx("p",{className:"text-xs text-gray-500 italic",children:"Click images to view full size"})]})]}),e.jsxs("div",{className:"flex gap-3 mt-6 pt-4 border-t border-gray-200",children:[e.jsxs(u,{onClick:()=>ee(s.id),disabled:oe.isPending,className:"flex-1 bg-green-600 hover:bg-green-700 text-white","data-testid":`approve-button-${s.id}`,children:[e.jsx(Xe,{className:"h-4 w-4 mr-2"}),oe.isPending?"Approving...":"Approve User"]}),e.jsxs(u,{onClick:()=>ue(s.id),disabled:me.isPending,variant:"destructive",className:"flex-1","data-testid":`reject-button-${s.id}`,children:[e.jsx(We,{className:"h-4 w-4 mr-2"}),me.isPending?"Rejecting...":"Reject User"]})]})]})]},s.id))]})]})]}):e.jsxs("div",{className:"min-h-screen bg-gray-50",children:[e.jsx(Ue,{}),e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx("div",{className:"text-gray-600",children:"Unauthorized access"})})]})}function Is(){const{toast:r}=Ce(),g=ss(),[w,v]=T.useState(!1),[E,P]=T.useState(null),[c,f]=T.useState({code:"",description:"",discountType:"percentage",discountValue:"",minBookingAmou
41nt:"",maxDiscountAmount:"",usageLimit:"",validFrom:"",validTo:"",applicableRoomIds:[],isActive:!0}),{data:U,isLoading:S}=_({queryKey:["/api/admin/promo-codes"]}),{data:C}=_({queryKey:["/api/rooms"]}),p=M({mutationFn:async t=>await(await R("POST","/api/admin/promo-codes",t)).json(),onSuccess:()=>{g.invalidateQueries({queryKey:["/api/admin/promo-codes"]}),r({title:"Promo code created successfully"}),v(!1),A()},onError:t=>{r({title:"Error creating promo code",description:t.message,variant:"destructive"})}}),I=M({mutationFn:async({id:t,data:o})=>await(await R("PUT",`/api/admin/promo-codes/${t}`,o)).json(),onSuccess:()=>{g.invalidateQueries({queryKey:["/api/admin/promo-codes"]}),r({title:"Promo code updated successfully"}),v(!1),A()},onError:t=>{r({title:"Error updating promo code",description:t.message,variant:"destructive"})}}),$=M({mutationFn:async({id:t,isActive:o})=>await(await R("PUT",`/api/admin/promo-codes/${t}/toggle`,{isActive:o})).json(),onSuccess:()=>{g.invalidateQueries({queryKey:["/api/admin/promo-codes"]}),r({title:"Promo code status updated"})},onError:t=>{r({title:"Error updating status",description:t.message,variant:"destructive"})}}),N=M({mutationFn:async t=>await(await R("DELETE",`/api/admin/promo-codes/${t}`)).json(),onSuccess:()=>{g.invalidateQueries({queryKey:["/api/admin/promo-codes"]}),r({title:"Promo code deleted"})},onError:t=>{r({title:"Error deleting promo code",description:t.message,variant:"destructive"})}}),A=()=>{f({code:"",description:"",discountType:"percentage",discountValue:"",minBookingAmount:"",maxDiscountAmount:"",usageLimit:"",validFrom:"",validTo:"",applicableRoomIds:[],isActive:!0}),P(null)},X=t=>{var D;P(t);const o=V=>{if(!V)return"";try{const G=typeof V=="string"?new Date(V):new Date;return isNaN(G.getTime())?"":G.toISOString().slice(0,16)}catch(G){return console.error("Error formatting date:",G,V),""}};f({code:t.code,description:t.description||"",discountType:t.discountType,discountValue:t.discountValue,minBookingAmount:t.minBookingAmount||"",maxDiscountAmount:t.maxDiscountAmount||"",usageLimit:((D=t.usageLimit)==null?void 0:D.toString())||"",validFrom:o(t.validFrom),validTo:o(t.validTo),applicableRoomIds:t.applicableRoomIds||[],isActive:t.isActive}),v(!0)},H=t=>{t.preventDefault();const o={...c,discountValue:parseFloat(c.discountValue),minBookingAmount:c.minBookingAmount?parseFloat(c.minBookingAmount):void 0,maxDiscountAmount:c.maxDiscountAmount?parseFloat(c.maxDiscountAmount):void 0,usageLimit:c.usageLimit?parseInt(c.usageLimit):void 0,validFrom:c.validFrom||void 0,validTo:c.validTo||void 0,applicableRoomIds:c.applicableRoomIds.length>0?c.applicableRoomIds:void 0};E?I.mutate({id:E.id,data:o}):p.mutate(o)},Z=t=>{f(o=>({...o,applicableRoomIds:o.applicableRoomIds.includes(t)?o.applicableRoomIds.filter(D=>D!==t):[...o.applicableRoomIds,t]}))};return e.jsx("div",{className:"mb-8","data-testid":"section-promo-codes",children:e.jsxs(Y,{children:[e.jsx(de,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs(le,{className:"flex items-center gap-2",children:[e.jsx(be,{className:"h-5 w-5 text-green-500"}),"Promo Codes"]}),e.jsxs(se,{open:w,onOpenChange:t=>{v(t),t||A()},children:[e.jsx(Ne,{asChild:!0,children:e.jsxs(u,{"data-testid":"button-create-promo-code",children:[e.jsx(ls,{className:"h-4 w-4 mr-2"}),"Create Promo Code"]})}),e.jsxs(te,{className:"max-w-2xl max-h-[90vh] overflow-y-auto",children:[e.jsx(ae,{children:e.jsx(ie,{children:E?"Edit Promo Code":"Create New Promo Code"})}),e.jsxs("form",{onSubmit:H,className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{htmlFor:"code",children:"Code *"}),e.jsx(F,{id:"code",value:c.code,onChange:t=>f({...c,code:t.target.value.toUpperCase()}),placeholder:"SAVE10",required:!0,"data-testid":"input-promo-code"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{htmlFor:"discountType",children:"Discount Type *"}),e.jsxs(is,{value:c.discountType,onValueChange:t=>f({...c,discountType:t}),children:[e.jsx(ns,{"data-testid":"select-discount-type",children:e.jsx(rs,{})}),e.jsxs(ds,{children:[e.jsx(Re,{value:"percentage",children:"Percentage (%)"}),e.jsx(Re,{value:"fixed",children:"Fixed Amount (£)"})]})]})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs(k,{htmlFor:"discountValue",children:["Discount Value * ",c.discountType==="percentage"?"(%)":"(£)"]}),e.jsx(F,{id:"discountValue",type:"number",step:"0.01",value:c.discountValue,onChange:t=>f({...c,discountValue:t.target.value}),placeholder:c.discountType==="percentage"?"10":"5.00",required:!0,"data-testid":"input-discount-value"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{htmlFor:"usageLimit",children:"Usage Limit (optional)"}),e.jsx(F,{id:"usageLimit",type:"number",value:c.usageLimit,onChange:t=>f({...c,usageLimit:t.target.value}),placeholder:"Unlimited","data-testid":"input-usage-limit"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{htmlFor:"description",children:"Description (optional)"}),e.jsx(we,{id:"description",value:c.description,onChange:t=>f({...c,description:t.target.value}),placeholder:"October promotion - 10% off all bookings","data-testid":"textarea-description"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{htmlFor:"minBookingAmou
41nt",children:"Min Booking Amount (£)"}),e.jsx(F,{id:"minBookingAmount",type:"number",step:"0.01",value:c.minBookingAmount,onChange:t=>f({...c,minBookingAmount:t.target.value}),placeholder:"0.00","data-testid":"input-min-amount"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{htmlFor:"maxDiscountAmount",children:"Max Discount (£)"}),e.jsx(F,{id:"maxDiscountAmount",type:"number",step:"0.01",value:c.maxDiscountAmount,onChange:t=>f({...c,maxDiscountAmount:t.target.value}),placeholder:"No limit","data-testid":"input-max-discount"})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{htmlFor:"validFrom",children:"Valid From (optional)"}),e.jsx(F,{id:"validFrom",type:"datetime-local",value:c.validFrom,onChange:t=>f({...c,validFrom:t.target.value}),"data-testid":"input-valid-from"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{htmlFor:"validTo",children:"Valid To (optional)"}),e.jsx(F,{id:"validTo",type:"datetime-local",value:c.validTo,onChange:t=>f({...c,validTo:t.target.value}),"data-testid":"input-valid-to"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{children:"Applicable Rooms (leave blank for all)"}),e.jsx("div",{className:"space-y-2",children:C==null?void 0:C.map(t=>e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Me,{id:`room-${t.id}`,checked:c.applicableRoomIds.includes(t.id),onCheckedChange:()=>Z(t.id),"data-testid":`checkbox-room-${t.id}`}),e.jsx("label",{htmlFor:`room-${t.id}`,className:"text-sm cursor-pointer",children:t.name})]},t.id))})]}),e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Me,{id:"isActive",checked:c.isActive,onCheckedChange:t=>f({...c,isActive:t}),"data-testid":"checkbox-is-active"}),e.jsx("label",{htmlFor:"isActive",className:"text-sm cursor-pointer",children:"Active (users can use this code)"})]}),e.jsxs("div",{className:"flex gap-3 pt-4",children:[e.jsx(u,{type:"button",variant:"outline",onClick:()=>{v(!1),A()},className:"flex-1",children:"Cancel"}),e.jsx(u,{type:"submit",disabled:p.isPending||I.isPending,className:"flex-1","data-testid":"button-submit-promo-code",children:p.isPending||I.isPending?"Saving...":E?"Update":"Create"})]})]})]})]})]})}),e.jsx(J,{children:S?e.jsxs("div",{className:"flex items-center justify-center py-8",children:[e.jsx("div",{className:"animate-spin rounded-full h-6 w-6 border-b-2 border-green-500"}),e.jsx("span",{className:"ml-3 text-gray-600",children:"Loading promo codes..."})]}):!U||U.length===0?e.jsxs("div",{className:"text-center py-8 text-gray-500",children:[e.jsx(be,{className:"h-12 w-12 mx-auto mb-4 text-gray-300"}),e.jsx("p",{children:"No promo codes yet. Create one to get started!"})]}):e.jsx("div",{className:"space-y-3",children:U.map(t=>e.jsx("div",{className:"border rounded-lg p-4 bg-gray-50","data-testid":`promo-code-${t.id}`,children:e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx("span",{className:"font-mono font-bold text-lg","data-testid":`text-code-${t.id}`,children:t.code}),e.jsx(h,{variant:t.isActive?"default":"secondary","data-testid":`badge-status-${t.id}`,children:t.isActive?"Active":"Inactive"}),t.usageLimit&&e.jsxs(h,{variant:"outline","data-testid":`badge-usage-${t.id}`,children:[t.currentUsage,"/",t.usageLimit," used"]})]}),t.description&&e.jsx("p",{className:"text-sm text-gray-600 mb-2",children:t.description}),e.jsxs("div",{className:"text-sm text-gray-700",children:[e.jsx("span",{className:"font-medium",children:t.discountType==="percentage"?`${t.discountValue}% off`:`£${parseFloat(t.discountValue).toFixed(2)} off`}),t.minBookingAmount&&e.jsxs("span",{className:"ml-2 text-gray-500",children:["(min £",parseFloat(t.minBookingAmount).toFixed(2),")"]})]}),(t.validFrom||t.validTo)&&e.jsxs("div",{className:"text-xs text-gray-500 mt-1",children:[t.validFrom&&(()=>{try{return`From ${new Date(t.validFrom).toLocaleDateString()}`}catch{return""}})(),t.validFrom&&t.validTo&&" - ",t.validTo&&(()=>{try{return`To ${new Date(t.validTo).toLocaleDateString()}`}catch{return""}})()]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(u,{variant:"outline",size:"sm",onClick:()=>X(t),"data-testid":`button-edit-${t.id}`,children:"Edit"}),e.jsx(u,{variant:t.isActive?"destructive":"default",size:"sm",onClick:()=>$.mutate({id:t.id,isActive:!t.isActive}),disabled:$.isPending,"data-testid":`button-toggle-${t.id}`,children:t.isActive?"Deactivate":"Activate"}),e.jsx(u,{variant:"ghost",size:"sm",onClick:()=>{confirm(`Delete promo code "${t.code}"? This cannot be undone.`)&&N.mutate(t.id)},disabled:N.isPending,className:"text-gray-400 hover:text-red-600","data-testid":`button-delete-${t.id}`,children:e.jsx(ge,{className:"h-4 w-4"})})]})]})},t.id))})})]})})}export{ft as default};

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.