PageSourceSearch

https://www.abbeytheatre.co.uk/assets/SeatSelection-DlFfS8Dk.js

js abbeytheatre.co.uk collected 2026-09-25 08:03:56 UTC 16,072 bytes, 13 lines download raw bytes

1import{r as l,a5 as Se,l as Ne,q as f,s as j,j as t,B as p,A as Q,Z as ee,a as te,ah as se,N as ae,O as _e,P as ke,ai as $e}from"./index-tvAeWDDu.js";import{Z as re,a as ne}from"./zoom-out-DkxNJGna.js";const Y=768;function Ce(){const[o,S]=l.useState(void 0);return l.useEffect(()=>{const m=window.matchMedia(`(max-width: ${Y-1}px)`),b=()=>{S(window.innerWidth<Y)};return m.addEventListener("change",b),S(window.innerWidth<Y),()=>m.removeEventListener("change",b)},[]),!!o}function Me(){const{showtimeId:o}=Se(),S=Ne(),[m,b]=l.useState(!0),[_,ie]=l.useState(null),[v,R]=l.useState([]),[d,T]=l.useState([]),[U,oe]=l.useState([]),[u,le]=l.useState(null),[w,ce]=l.useState({x:0,y:0,width:400,height:60}),[X,de]=l.useState(!1),[F,k]=l.useState(1),[$,O]=l.useState({x:0,y:0}),[C,P]=l.useState(!1),[I,M]=l.useState({x:0,y:0}),[L,D]=l.useState(0),A=l.useRef(null),he=Ce();l.useEffect(()=>{const e=localStorage.getItem("pendingReservation");if(e&&o)try{const{showtimeId:a,selectedSeats:r}=JSON.parse(e);a===o&&r?.length>0&&(console.log("[SeatSelection] Found pending reservation with",r.length,"seats"),localStorage.setItem("pendingSeatsToRestore",JSON.stringify(r)))}catch(a){console.error("Error parsing pending reservation:",a)}const s=localStorage.getItem("activeReservation");if(s&&o)try{const{showtimeId:a,selectedSeats:r}=JSON.parse(s);a===o&&r?.length>0&&(localStorage.getItem("pendingSeatsToRestore")||(console.log("[SeatSelection] Found active reservation with",r.length,"seats"),localStorage.setItem("pendingSeatsToRestore",JSON.stringify(r.map(i=>({row:i.row,seat:i.seat}))))))}catch(a){console.error("Error parsing active reservation:",a)}},[o]),l.useEffect(()=>{o&&ue()},[o]),l.useEffect(()=>{if(v.length>0&&!m){const e=localStorage.getItem("pendingSeatsToRestore");if(e)try{const s=JSON.parse(e),a=[],r=v.map(n=>s.some(c=>c.row===n.row&&c.seat===n.seat)&&n.status==="available"?(a.push({...n,status:"selected"}),{...n,status:"selected"}):n);a.length>0?(R(r),T(a),f.success(`Restored ${a.length} previously selected seat${a.length>1?"s":""}`),console.log("[SeatSelection] Successfully restored",a.length,"seats"),localStorage.removeItem("pendingSeatsToRestore"),localStorage.removeItem("pendingReservation")):(localStorage.removeItem("pendingSeatsToRestore"),localStorage.removeItem("pendingReservation"))}catch(s){console.error("Error restoring seats:",s),localStorage.removeItem("pendingSeatsToRestore")}}},[v.length,m]);const ue=async()=>{try{b(!0);const{data:e,error:s}=await j.from("showtimes").select(`
2          *,
3          productions (title, slug, orphan_ticket_rule, is_cancelled)
4        `).eq("id",o).single();if(s)throw s;if(e.productions?.is_cancelled)throw new Error("This production has been cancelled and is no longer available for booking.");le(e),de(e.productions?.orphan_ticket_rule||!1);const{data:a,error:r}=await j.from("seating_plan_templates").select("*").eq("id",e.seating_plan_id).single();if(r)throw r;const{data:n,error:i}=await j.from("showtime_pricing").select(`
5          *,
6          production_pricing:pricing_id (
7            id,
8            category_name,
9            price,
10            description,
11            display_order
12          )
13        `).eq("showtime_id",o);if(i)throw i;const c=n.map(N=>N.production_pricing).filter(Boolean).sort((N,z)=>N.display_order-z.display_order);oe(c);const{data:g,error:x}=await j.from("showtime_unavailable_seats").select("row_index, seat_index").eq("showtime_id",o);if(x)throw x;const{data:{user:E}}=await j.auth.getUser(),{data:we}=await j.rpc("get_reserved_seats",{_showtime_id:o}),ye=(we||[]).filter(N=>!E||N.user_id!==E.id),y=a;if(y&&y.seats_data){const N=y.seats_data,z=new Set([...g.map(h=>`${h.row_index}-${h.seat_index}`),...(ye||[]).map(h=>`${h.seat_row}-${h.seat_number}`)]),je=N.map(h=>({row:h.row,seat:h.column,status:z.has(`${h.row}-${h.column}`)?"unavailable":"available",x:h.x,y:h.y,type:h.type}));R(je),ie(y),ce({x:y.stage_x||0,y:y.stage_y||0,width:y.stage_width||400,height:y.stage_height||60})}}catch(e){console.error("Error fetching showtime data:",e),f.error("Failed to load seating plan")}finally{b(!1)}},B=(e,s)=>{const a=v.findIndex(i=>i.row===e&&i.seat===s);if(a===-1)return;const r=v[a];if(r.status==="unavailable"||r.type==="unavailable")return;const n=[...v];if(r.status==="selected"){if(X&&me(e,s,n)){f.error("Deselecting this seat would leave a single seat isolated");return}n[a]={...r,status:"available",price_category:void 0},T(d.filter(i=>!(i.row===e&&i.seat===s)))}else{if(X&&ge(e,s,n)){f.error("Selecting this seat would leave a single seat isolated. Please select adjacent seats.");return}n[a]={...r,status:"selected"},T([...d,{...n[a]}])}R(n)},ge=(e,s,a)=>{const r=a.filter(x=>x.row===e).sort((x,E)=>x.seat-E.seat),n=r.find(x=>x.seat===s-1),i=r.find(x=>x.seat===s+1),c=J(n,r,s-1),g=J(i,r,s+1);return c||g},me=(e,s,a)=>{const r=a.filter(c=>c.row===e).sort((c,g)=>c.seat-g.seat),n=r.find(c=>c.seat===s-1),i=r.find(c=>c.seat===s+1);if(n&&i){const c=n.status!=="available",g=i.status!=="available";return c&&g}return!1},J=(e,s,a)=>
13{if(!e||e.status!=="available"||e.type==="unavailable")return!1;const r=s.find(g=>g.seat===a-1),n=s.find(g=>g.seat===a+1),i=!r||r.status!=="available"||r.type==="unavailable",c=!n||n.status!=="available"||n.type==="unavailable";return i&&c},xe=e=>{if(e.stopPropagation(),e.touches.length===2){const s=e.touches[0],a=e.touches[1],r=Math.hypot(s.clientX-a.clientX,s.clientY-a.clientY);D(r)}else e.touches.length===1&&(P(!0),M({x:e.touches[0].clientX,y:e.touches[0].clientY}))},pe=e=>{if(e.stopPropagation(),e.touches.length===2&&L>0){e.preventDefault();const s=e.touches[0],a=e.touches[1],r=Math.hypot(s.clientX-a.clientX,s.clientY-a.clientY),n=r/L;k(i=>Math.min(Math.max(i*n,.5),4)),D(r)}else if(e.touches.length===1&&C){e.preventDefault();const s=e.touches[0],a=s.clientX-I.x,r=s.clientY-I.y;O(n=>({x:n.x+a,y:n.y+r})),M({x:s.clientX,y:s.clientY})}},fe=()=>{P(!1),D(0)},W=e=>{e.preventDefault();const s=e.deltaY>0?.9:1.1;k(a=>Math.min(Math.max(a*s,.5),4))},be=e=>{e.button===0&&(P(!0),M({x:e.clientX,y:e.clientY}))},ve=e=>{if(C){const s=e.clientX-I.x,a=e.clientY-I.y;O(r=>({x:r.x+s,y:r.y+a})),M({x:e.clientX,y:e.clientY})}},Z=()=>{P(!1)},q=()=>{k(e=>Math.min(e*1.2,4))},G=()=>{k(e=>Math.max(e/1.2,.5))},K=()=>{k(1),O({x:0,y:0})},V=e=>e.seat+1,H=async()=>{if(d.length===0){f.error("Please select at least one seat");return}b(!0);try{const{data:{user:e}}=await j.auth.getUser();if(!e){localStorage.setItem("pendingReservation",JSON.stringify({showtimeId:o,selectedSeats:d.map(n=>({row:n.row,seat:n.seat})),returnUrl:`/seat-selection/${o}`})),f.info("Please sign in to complete your booking"),S(`/auth?redirect=${encodeURIComponent(`/seat-selection/${o}`)}`);return}const{data:s,error:a}=await j.functions.invoke("create-seat-reservations",{body:{showtimeId:o,seats:d.map(n=>({row:n.row,seat:n.seat}))}});if(a||!s){f.error("Failed to reserve seats. Please try again."),b(!1);return}localStorage.setItem("activeReservation",JSON.stringify({reservationIds:s.map(n=>n.id),showtimeId:o,selectedSeats:d,expiresAt:s[0].expires_at,showDetails:{title:u.productions.title,date:ae(new Date(u.date),"PPP"),time:u.time,pricingCategories:U}}));const r=parseFloat(U?.[0]?.price||"0");$e([{id:u.productions.id||o,name:u.productions.title,category:"Theatre Ticket",price:Number.isNaN(r)?0:r,quantity:d.length}],(Number.isNaN(r)?0:r)*d.length),S("/basket"),f.success("Seats reserved for 15 minutes")}catch(e){console.error("Checkout error:",e),f.error("Checkout failed. Please try again.")}finally{b(!1)}};return m?t.jsx("div",{className:"min-h-screen bg-background flex items-center justify-center",children:t.jsx("p",{children:"Loading seating plan..."})}):_?he?t.jsxs("div",{className:"fixed inset-0 flex flex-col bg-background overflow-hidden",children:[t.jsx("div",{className:"flex-shrink-0 border-b bg-background z-10",children:t.jsxs("div",{className:"flex items-center justify-between p-4",children:[t.jsxs(p,{variant:"ghost",size:"sm",onClick:()=>S(`/shows/${u?.productions?.slug||""}`),children:[t.jsx(Q,{className:"h-4 w-4 mr-2"}),"Back"]}),t.jsxs("div",{className:"text-sm font-medium",children:[d.length," seat",d.length!==1?"s":""]})]})}),t.jsxs("div",{ref:A,className:"flex-1 relative bg-muted/20 touch-none overflow-hidden",onTouchStart:xe,onTouchMove:pe,onTouchEnd:fe,onWheel:W,children:[t.jsx("div",{className:"absolute inset-0",style:{transform:`translate(${$.x}px, ${$.y}px) scale(${F})`,transformOrigin:"center center",transition:C?"none":"transform 0.2s ease-out"},children:t.jsxs("div",{className:"absolute top-1/2 left-1/2",style:{width:_?.plan_width||800,height:_?.plan_height||600,transform:"translate(-50%, -50%)"},children:[v.map(e=>{const s=e.type==="wheelchair",a=e.type==="carer",r=e.type==="unavailable";return t.jsx("button",{onClick:()=>B(e.row,e.seat),disabled:e.status==="unavailable"||r,style:{position:"absolute",left:`${e.x}px`,bottom:`${e.y||0}px`,width:"32px",height:"32px"},className:`rounded border text-xs font-medium transition-all active:scale-95 flex items-center justify-center ${e.status==="available"?s?"bg-blue-500 active:bg-blue-600 border-blue-600 text-white":a?"bg-green-500 active:bg-green-600 border-green-600 text-white":"bg-primary active:bg-primary/80 border-primary text-primary-foreground":e.status==="selected"?"bg-primary/70 text-primary-foreground border-primary ring-2 ring-primary":"bg-muted cursor-not-allowed opacity-50 border-muted-foreground
13/20"}`,children:s?"♿":a?"👤":`${String.fromCharCode(65+e.row)}${V(e)}`},`${e.row}-${e.seat}`)}),t.jsx("div",{className:"absolute text-sm font-semibold text-center text-primary-foreground bg-primary border-2 border-primary z-10 flex items-center justify-center",style:{height:`${w.height}px`,width:`${w.width}px`,left:`${w.x}px`,bottom:`${w.y}px`},children:"STAGE"})]})}),t.jsxs("div",{className:"absolute top-4 right-4 flex flex-col gap-2",children:[t.jsx(p,{variant:"secondary",size:"icon",onClick:q,"aria-label":"Zoom in",children:t.jsx(re,{className:"h-4 w-4"})}),t.jsx(p,{variant:"secondary",size:"icon",onClick:G,"aria-label":"Zoom out",children:t.jsx(ne,{className:"h-4 w-4"})}),t.jsx(p,{variant:"secondary",size:"icon",onClick:K,"aria-label":"Reset view",children:t.jsx(ee,{className:"h-4 w-4"})})]})]}),t.jsx("div",{className:"flex-shrink-0 border-t bg-background p-4",children:t.jsxs("div",{className:"flex items-center justify-between gap-4",children:[t.jsxs("div",{className:"text-sm font-semibold",children:[d.length," seat",d.length!==1?"s":""," selected"]}),t.jsx(p,{onClick:H,disabled:d.length===0||m,size:"lg",children:m?t.jsxs(t.Fragment,{children:[t.jsx(te,{className:"h-4 w-4 mr-2 animate-spin"}),"Processing..."]}):t.jsxs(t.Fragment,{children:[t.jsx(se,{className:"h-4 w-4 mr-2"}),"Continue"]})})]})})]}):t.jsxs("div",{className:"fixed inset-0 flex bg-background overflow-hidden",children:[t.jsxs("div",{className:"flex-1 flex flex-col border-r",children:[t.jsx("div",{className:"flex-shrink-0 border-b p-4",children:t.jsxs("div",{className:"flex items-center justify-between",children:[t.jsxs(p,{variant:"ghost",size:"sm",onClick:()=>S(`/shows/${u?.productions?.slug||""}`),children:[t.jsx(Q,{className:"h-4 w-4 mr-2"}),"Back"]}),t.jsxs("div",{className:"text-center flex-1",children:[t.jsx("h1",{className:"text-lg font-bold",children:u?.productions?.title}),t.jsxs("p",{className:"text-sm text-muted-foreground",children:[u&&ae(new Date(u.date),"EEE, MMM d, yyyy")," at ",u?.time&&_e(u.time)]})]}),t.jsx("div",{className:"w-24"})]})}),t.jsxs("div",{ref:A,className:"flex-1 relative bg-muted/20 overflow-hidden cursor-move select-none",onMouseDown:be,onMouseMove:ve,onMouseUp:Z,onMouseLeave:Z,onWheel:W,children:[t.jsx("div",{className:"absolute inset-0 flex items-center justify-center",style:{transform:`translate(${$.x}px, ${$.y}px) scale(${F})`,transition:C?"none":"transform 0.2s ease-out"},children:t.jsxs("div",{style:{position:"relative",width:_?.plan_width||800,height:_?.plan_height||600},children:[v.map(e=>{const s=e.type==="wheelchair",a=e.type==="carer",r=e.type==="unavailable";return t.jsx("button",{onClick:()=>B(e.row,e.seat),disabled:e.status==="unavailable"||r,style:{position:"absolute",left:`${e.x}px`,bottom:`${e.y||0}px`,width:"32px",height:"32px"},className:`rounded border text-xs font-medium transition-all hover:scale-110 hover:z-20 flex items-center justify-center ${e.status==="available"?s?"bg-blue-500 hover:bg-blue-600 border-blue-600 text-white cursor-pointer":a?"bg-green-500 hover:bg-green-600 border-green-600 text-white cursor-pointer":"bg-primary hover:bg-primary/80 border-primary text-primary-foreground cursor-pointer":e.status==="selected"?"bg-primary/70 text-primary-foreground border-primary ring-2 ring-primary":"bg-muted cursor-not-allowed opacity-50 border-muted-foreground/20"}`,children:s?"♿":a?"👤":`${String.fromCharCode(65+e.row)}${V(e)}`},`${e.row}-${e.seat}`)}),t.jsx("div",{className:"absolute text-sm font-semibold text-center text-primary-foreground bg-primary border-2 border-primary z-10 flex items-center justify-center",style:{height:`${w.height}px`,width:`${w.width}px`,left:`${w.x}px`,bottom:`${w.y}px`},children:"STAGE"})]})}),t.jsxs("div",{className:"absolute bottom-4 right-4 flex gap-2 bg-background/80 backdrop-blur-sm rounded-lg p-2 border",children:[t.jsx(p,{variant:"ghost",size:"icon",onClick:G,"aria-label":"Zoom out",children:t.jsx(ne,{className:"h-4 w-4"})}),t.jsx(p,{variant:"ghost",size:"icon",onClick:K,"aria-label":"Reset view",children:t.jsx(ee,{className:"h-4 w-4"})}),t.jsx(p,{variant:"ghost",size:"icon",onClick:q,"aria-label":"Zoom in",children:t.jsx(re,{className:"h-4 w-4"})})]})]}),t.jsx("div",{className:"flex-shrink-0 border-t p-4",children:t.jsxs("div",{className:"flex gap-6 justify-center text-xs flex-wrap",children:[t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("div",{className:"w-5 h-5 bg-primary/20 rounded border border-primary/40"}),t.jsx("span",{children:"Available"})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("div",{className:"w-5 h-5 bg-primary rounded border border-primary"}),t.jsx("span",{children:"Selected"})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("div",{className:"w-5 h-5 bg-blue-500 rounded border border-blue-600 text-white flex items-center justify-center text-xs",children:"♿"}),t.jsx("span",{children:"Wheelchair"})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("div",{className:"w-5 h-5 bg-green-500 rounded border border-green-600 text-white flex items-center justify-center text-xs",children:"👤"}),t.jsx("span",{children:"Carer"})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("div",{className:"w-5 h-5 bg-muted rounded border border-muted-foreground
13/20 opacity-50"}),t.jsx("span",{children:"Unavailable"})]})]})})]}),t.jsxs("div",{className:"w-96 flex flex-col bg-card overflow-y-auto",children:[t.jsxs("div",{className:"flex-1 p-6 space-y-6",children:[t.jsxs("div",{children:[t.jsx("h2",{className:"text-xl font-bold mb-2",children:"Select Seats"}),t.jsx("p",{className:"text-sm text-muted-foreground",children:"Click seats on the map. You'll assign price categories in the next step."})]}),t.jsxs("div",{children:[t.jsxs("div",{className:"flex justify-between items-center",children:[t.jsx("span",{className:"text-sm font-medium",children:"Selected Seats"}),t.jsx(ke,{variant:"secondary",children:d.length})]}),d.length===0&&t.jsx("p",{className:"text-sm text-muted-foreground mt-2",children:"No seats selected"})]})]}),t.jsx("div",{className:"flex-shrink-0 border-t p-6 space-y-4 bg-background",children:t.jsx(p,{onClick:H,disabled:d.length===0||m,className:"w-full",size:"lg",children:m?t.jsxs(t.Fragment,{children:[t.jsx(te,{className:"h-4 w-4 mr-2 animate-spin"}),"Processing..."]}):t.jsxs(t.Fragment,{children:[t.jsx(se,{className:"h-4 w-4 mr-2"}),"Continue to Checkout"]})})})]})]}):t.jsx("div",{className:"min-h-screen bg-background flex items-center justify-center",children:t.jsx("p",{children:"No seating plan available"})})}export{Me 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.