1import{u as D,a as P,b as U,j as e,f as re,t as k}from"./vendor-ui-CGzpp04F.js";import{r as h}from"./vendor-react-BAKR1cxU.js";import{p as ve,s as j,C as ie,a as ce,b as le,d as de,c as oe,L as T,S as ue,f as g,u as Se}from"./index-B6g8kMT1.js";import{T as Ce,a as Te,b as me,c as _,d as Le,e as N}from"./table-CMFtMv6u.js";import{B as w}from"./badge-BC2UN5bO.js";import{D as Q,a as $,b as G,c as H,d as Y,e as z}from"./dialog-CU1Q5w2r.js";import{T as he}from"./textarea-Bvm7CZt9.js";import{L as A}from"./label-5k2SFvuI.js";import{W as De}from"./WeatherCalendar-BcN4gQgr.js";import{c as Ee,d as Re,B as Ae,a as qe,b as W,i as Fe,f as x,e as F,s as Be,g as pe,l as fe,w as Oe,h as Ie,j as xe,k as ge,p as ye,m as M,r as Ke,n as Me,o as se,q as te,t as ae,u as Pe,v as Ue}from"./allBookings-DLHHFRXA.js";import{S as Qe,a as $e,b as Ge,c as He,d as Ye}from"./sheet-BhQr9km_.js";import{S as q}from"./separator-Cp3gUNAN.js";import{C as ze}from"./CurrencyInput-Daw--LNB.js";import{M as We}from"./message-circle-B_bowpBS.js";import"./vendor-supabase-D-vHfFRB.js";import"./calendar-WQzD4V64.js";import"./chevron-left-4BHMHdmL.js";import"./useTripAvailability-Cmy2egd1.js";import"./useTripReservationCounts-B8zYXkHc.js";import"./tripAvailability-U6lc8RIx.js";import"./thresholdUtils-BH2ya7mc.js";import"./departureCutoff-BORI05h2.js";import"./witaDate-Cp36P7bS.js";import"./useTickingNow-CputP63u.js";import"./paymentService-Dje5jD2-.js";/** 2 * @license lucide-react v0.309.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 Xe=ve("CalendarClock",[["path",{d:"M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5",key:"1osxxc"}],["path",{d:"M16 2v4",key:"4m81vk"}],["path",{d:"M8 2v4",key:"1cmpym"}],["path",{d:"M3 10h5",key:"r794hk"}],["path",{d:"M17.5 17.5 16 16.25V14",key:"re2vv1"}],["path",{d:"M22 16a6 6 0 1 1-12 0 6 6 0 0 1 12 0Z",key:"ame013"}]]),I=500,Ve=40,je=["all-bookings"],Ze=` 7 id, 8 booking_reference, 9 passenger_name, 10 passenger_email, 11 whatsapp_number, 12 passengers, 13 total_price, 14 payment_status, 15 payment_reference, 16 created_at, 17 needs_scheduling, 18 scheduling_note, 19 scheduling_dismissed_at, 20 scheduling_dismissed_reason, 21 attribution, 22 refunded_amount, 23 refund_status, 24 ticket_passengers ( 25 id, 26 first_name, 27 last_name, 28 email, 29 whatsapp, 30 is_primary, 31 pass_reference, 32 trip_reservations ( 33 id, 34 status, 35 schedule_trip:schedule_trips ( 36 id, 37 scheduled_departure, 38 status, 39 schedule:schedules ( id, schedule_date, name ), 40 trip:trips ( id, name, origin, destination ) 41 ) 42 ) 43 ) 44`.replace(/\s+/g,"");async function Je(){const s=[];for(let t=0;t<Ve;t++){const n=t*I,{data:a,error:r}=await j.from("tickets").select(Ze).order("created_at",{ascending:!1}).order("id",{ascending:!1}).range(n,n+I-1);if(r)throw r;const i=a??[];if(s.push(...i),i.length<I)break}return s}function es(){return D({queryKey:je,queryFn:Je,refetchInterval:60*1e3,refetchIntervalInBackground:!1,refetchOnWindowFocus:"always"})}function ss(){return D({queryKey:["shopify-conversion-status"],queryFn:async()=>{const{data:s,error:t}=await j.from("tickets").select("id, booking_reference, passenger_name, passenger_email, whatsapp_number, passengers, created_at, needs_scheduling, scheduling_note, scheduling_dismissed_at, scheduling_dismissed_reason").like("booking_reference","SH-%");if(t)throw t;const n=new Map;for(const a of s??[]){const r=String(a.booking_reference).replace(/^SH-/,"");n.set(r,{id:a.id,booking_reference:a.booking_reference,passenger_name:a.passenger_name??null,passenger_email:a.passenger_email??null,whatsapp_number:a.whatsapp_number??null,passengers:a.passengers??null,created_at:a.created_at??null,needs_scheduling:!!a.needs_scheduling,scheduling_note:a.scheduling_note??null,scheduling_dismissed_at:a.scheduling_dismissed_at??null,scheduling_dismissed_reason:a.scheduling_dismissed_reason??null})}return n},refetchInterval:30*1e3})}function ts(){return D({queryKey:["schedule-coverage"],queryFn:async()=>{var r,i,c;const{data:s,error:t}=await j.from("trips").select("origin, destination");if(t)throw t;const n=[],a=1e3;for(let u=0;;u+=a){const{data:o,error:l}=await j.from("schedule_trips").select("status, trips(origin, destination), schedules(schedule_date)").neq("status","cancelled").range(u,u+a-1);if(l)throw l;if(!o||o.length===0)break;for(const p of o){const f=((r=p.schedules)==null?void 0:r.schedule_date)??null,m=((i=p.trips)==null?void 0:i.origin)??null,y=((c=p.trips)==null?void 0:c.destination)??null;f&&m&&y&&n.push({schedule_date:f,origin:m,destination:y})}if(o.length<a)break}return{trips:s??[],scheduleTrips:n}},staleTime:5*60*1e3})}function as(s){return D({queryKey:["ticket-passengers",s],enabled:!!s,queryFn:async()=>{const{data:t,error:n}=await j.from("ticket_passengers").select("id, first_name, last_name, created_at").eq("ticket_id",s).order("created_at",{ascending:!0});if(n)throw n;return t??[]}})}function ns(){const s=P();return U({mutationFn:async({ticketId:t,reservations:n})=>{if(!n||n.length===0)throw new Error("No passengers to schedule.");const a=n.map(o=>({ticket_passenger_id:o.ticketPassengerId,schedule_trip_id:o.scheduleTripId,status:"confirmed"})),{data:r,error:i}=await j.from("trip_reservations").insert(a).select();if(i)throw i;if(!r||r.length===0)throw new Error("Failed to create reservations. Please try again.");const{data:c,error:u}=await j.from("tickets").update({needs_scheduling:!1,scheduling_note:null}).eq("id",t).select();if(u)throw u;if(!c||c.length===0)throw new Error("Reservations were created but the ticket could not be updated. You may not have permission.");return{reservations:r,ticket:c[0]}},onSuccess:()=>{s.invalidateQueries({queryKey:["shopify-conversion-status"]}),s.invalidateQueries({queryKey:["needs-scheduling-count"]}),s.invalidateQueries({queryKey:["weatherRebookStats"]}),s.invalidateQueries({queryKey:["tripAvailability"]}),s.invalidateQueries({queryKey:["tripManifest"]})}})}function rs(){const s=P();return U({mutationFn:async({ticketId:t,reason:n})=>{const a=(n??"").trim();if(!a)throw new Error("A reason is required to dismiss.");const{data:r,error:i}=await j.from("tickets").update({scheduling_dismissed_at:new Date().toISOString(),scheduling_dismissed_reason:a}).eq("id",t).select();if(i)throw i;if(!r||r.length===0)throw new Error("Could not dismiss this ticket. You may not have permission.");return r[0]},onSuccess:()=>{s.invalidateQueries({queryKey:["shopify-conversion-status"]}),s.invalidateQueries({queryKey:["needs-scheduling-count"]})}})}const is={ready:{backgroundColor:"#dcfce7",color:"#166534"},needsDate:{backgroundColor:"#dbeafe",color:"#1e40af"},notOperated:{backgroundColor:"#fee2e2",color:"#991b1b"},needsReview:{backgroundColor:"#fef9c3",color:"#854d0e"}};function ne(s){return(s.bucket==="ready"||s.bucket==="needsDate")&&s.legs.length===1}function cs(){const{data:s}=ss(),{data:t}=ts(),[n,a]=h.useState(null),[r,i]=h.useState(null),c=h.useMemo(()=>s?Array.from(s.values()).filter(o=>o.needs_scheduling&&!o.scheduling_dismissed_at):[],[s]),u=h.useMemo(()=>{const o=new Map;if(!t)return o;for(const l of c){const p=Ee(l,t.trips,t.scheduleTrips);if(!p)continue;const f=Re(l.scheduling_note);(o.get(p)??o.set(p,[]).get(p)).push({ticket:l,bucket:p,legs:f})}return o},[c,t]);return c.length===0?null:e.jsxs(ie,{children:[e.jsxs(ce,{children:[e.jsxs(le,{className:"flex items-center gap-2",children:[e.jsx(Xe,{className:"h-5 w-5"}),"Needs scheduling",e.jsx(w,{variant:"secondary",children:c.length})]}),e.jsx(de,{children:"Paid orders not yet attached to a trip. Schedule the ones with a matching sailing, or dismiss the ones that cannot be (route not operated, no date, unreadable)."})]}),e.jsx(oe,{className:"space-y-6",children:t?Ae.filter(o=>{var l;return(((l=u.get(o))==null?void 0:l.length)??0)>0}
44).map(o=>e.jsx(ls,{bucket:o,rows:u.get(o),onSchedule:a,onDismiss:i},o)):e.jsxs("div",{className:"flex items-center gap-2 text-sm text-gray-500 py-4",children:[e.jsx(T,{className:"h-4 w-4 animate-spin"})," Checking current schedulesâ¦"]})}),n&&e.jsx(os,{row:n,onClose:()=>a(null)}),r&&e.jsx(us,{row:r,onClose:()=>i(null)})]})}function ls({bucket:s,rows:t,onSchedule:n,onDismiss:a}){return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx("span",{className:"inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium",style:is[s],children:qe[s]}),e.jsx("span",{className:"text-xs text-gray-400",children:t.length})]}),e.jsx("div",{className:"space-y-2",children:t.map(r=>e.jsx(ds,{row:r,onSchedule:n,onDismiss:a},r.ticket.id))})]})}function ds({row:s,onSchedule:t,onDismiss:n}){const a=(s.bucket==="ready"||s.bucket==="needsDate")&&!ne(s);return e.jsxs("div",{className:"flex items-start justify-between gap-3 rounded-md border p-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"font-medium",children:s.ticket.booking_reference}),e.jsx("span",{className:"text-sm text-gray-500",children:s.ticket.passenger_name??"â"}),e.jsxs(w,{variant:"outline",children:[s.ticket.passengers??"?"," pax"]})]}),e.jsx("p",{className:"text-xs text-gray-500 mt-1 break-words",children:s.ticket.scheduling_note}),s.ticket.created_at&&e.jsxs("p",{className:"text-[11px] text-gray-400 mt-0.5",children:["Imported ",re(new Date(s.ticket.created_at),"d MMM yyyy")]})]}),e.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[ne(s)&&e.jsx(g,{size:"sm",onClick:()=>t(s),children:"Schedule"}),a&&e.jsx("span",{className:"text-xs text-gray-400 whitespace-nowrap",children:"Multi-leg · auto-matches nightly"}),e.jsx(g,{size:"sm",variant:"ghost",onClick:()=>n(s),children:"Dismiss"})]})]})}function os({row:s,onClose:t}){const n=s.legs[0],{data:a,isLoading:r}=as(s.ticket.id),i=ns(),[c,u]=h.useState(null),o=async()=>{if(!(!c||!a||a.length===0))try{await i.mutateAsync({ticketId:s.ticket.id,reservations:a.map(l=>({ticketPassengerId:l.id,scheduleTripId:c.scheduleTripId}))}),k.success(`Scheduled ${a.length} passenger(s) for ${s.ticket.booking_reference}`),t()}catch(l){k.error((l==null?void 0:l.message)||"Failed to schedule")}};return e.jsx(Q,{open:!0,onOpenChange:l=>{l||t()},children:e.jsxs($,{className:"max-w-2xl max-h-[85vh] overflow-y-auto",children:[e.jsxs(G,{children:[e.jsxs(H,{
44children:["Schedule ",s.ticket.booking_reference]}),e.jsxs(Y,{children:[n.origin," â ",n.destination,n.date?` on ${n.date}`:" â pick a date"," ·"," ",s.ticket.passengers??(a==null?void 0:a.length)??"?"," passenger(s)"]})]}),e.jsx(De,{showTripPopover:!0,showLegend:!0,fromLocation:n.origin.toLowerCase(),toLocation:n.destination.toLowerCase(),onTripSelect:(l,p,f)=>u({scheduleTripId:l,date:p,departureTime:f}),selectedTripId:c==null?void 0:c.scheduleTripId}),c&&e.jsxs("div",{className:"rounded-md border border-primary/20 bg-primary/5 px-4 py-2 text-sm flex items-center gap-2",children:[e.jsx(ue,{className:"h-4 w-4 text-primary"}),e.jsxs("span",{className:"font-medium",children:[re(c.date,"EEE, MMM d")," at ",c.departureTime]})]}),e.jsxs(z,{children:[e.jsx(g,{variant:"outline",onClick:t,disabled:i.isPending,children:"Cancel"}),e.jsxs(g,{onClick:o,disabled:!c||r||!(a!=null&&a.length)||i.isPending,children:[i.isPending&&e.jsx(T,{className:"h-4 w-4 mr-2 animate-spin"}),"Confirm & schedule"]})]})]})})}function us({row:s,onClose:t}){const n=rs(),[a,r]=h.useState(""),i=async()=>{try{await n.mutateAsync({ticketId:s.ticket.id,reason:a}),k.success(`Dismissed ${s.ticket.booking_reference}`),t()}catch(c){k.error((c==null?void 0:c.message)||"Failed to dismiss")}};return e.jsx(Q,{open:!0,onOpenChange:c=>{c||t()}
44,children:e.jsxs($,{children:[e.jsxs(G,{children:[e.jsxs(H,{children:["Dismiss ",s.ticket.booking_reference,"?"]}),e.jsx(Y,{children:"Removes this order from the queue without booking it. The needs-scheduling flag stays set for the record. A reason is required."})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(A,{htmlFor:"dismiss-reason",children:"Reason"}),e.jsx(he,{id:"dismiss-reason",value:a,onChange:c=>r(c.target.value),placeholder:"e.g. route not operated â refunded via Shopify"})]}),e.jsxs(z,{children:[e.jsx(g,{variant:"outline",onClick:t,disabled:n.isPending,children:"Cancel"}),e.jsxs(g,{variant:"destructive",onClick:i,disabled:!a.trim()||n.isPending,children:[n.isPending&&e.jsx(T,{className:"h-4 w-4 mr-2 animate-spin"}),"Dismiss"]})]})]})})}const ms="id, order_name, shopify_order_id, source, financial_status, total_price, currency, shopify_created_at, raw";function hs(s){return D({queryKey:["shopify-order-by-name",s],enabled:!!s,queryFn:async()=>{const{data:t,error:n}=await j.from("shopify_orders_received").select(ms).eq("order_name",s).maybeSingle();if(n)throw n;return t??null},staleTime:1/0})}const _e=new Set(["utm_source","utm_medium","utm_campaign","utm_content","utm_term"]);function ps(s){if(!s)return[];const t=s.indexOf("?");if(t===-1)return[];const n=[],a=new URLSearchParams(s.slice(t+1));for(const[r,i]of a.entries()){const c=r.toLowerCase();_e.has(c)&&i&&n.push({key:c,value:i})}return n}function fs(s){const t=Array.isArray(s==null?void 0:s.note_attributes)?s.note_attributes:[],n=[];for(const a of t){const r=String((a==null?void 0:a.name)??"").toLowerCase(),i=a==null?void 0:a.value;_e.has(r)&&typeof i=="string"&&i&&n.push({key:r,value:i})}return n}function xs(s){const t=s==null?void 0:s.raw;if(!t||typeof t!="object")return null;const n=typeof t.landing_site=="string"?t.landing_site:null,a=typeof t.referring_site=="string"?t.referring_site:null,r=typeof t.source_name=="string"?t.source_name:null,i=[],c=new Set;for(const u of[...ps(n),...fs(t)])c.has(u.key)||(c.add(u.key),i.push(u));return n===null&&a===null&&r===null&&i.length===0?null:{entryUrl:n,referrer:a,utm:i,channel:r}}const Ne=s=>["ticket-refunds",s??null];function gs(s,t=!0){return D({queryKey:Ne(s),enabled:t&&!!s,queryFn:async()=>{const{data:n,error:a}=await j.from("ticket_refunds").select("id, ticket_id, reference_id, amount, currency, kind, status, reason, note, failure_code, origin, initiated_by, refunded_at, created_at").eq("ticket_id",s).order("created_at",{ascending:!1});if(a)throw a;return n??[]}})}async function ys(s){const t=s==null?void 0:s.context;if(t&&typeof t.json=="function")try{const n=await t.json();if(typeof(n==null?void 0:n.message)=="string"&&n.message)return n.message}catch{}return(s==null?void 0:s.message)||"The refund failed. Please try again."}function js(){const s=P();return U({mutationFn:async t=>{const{data:n,error:a}=await j.functions.invoke("issue-refund",{body:{ticket_id:t.ticketId,request_key:t.requestKey,amount:t.amount,reason:t.reason,note:t.note??null}});if(a)throw new Error(await ys(a));if(!n||!n.refund)throw new Error("The refund failed. Please try again.");return n},onSettled:(t,n,a)=>{s.invalidateQueries({queryKey:Ne(a.ticketId)}),s.invalidateQueries({queryKey:je})}})}const K=[{value:"REQUESTED_BY_CUSTOMER",label:"Requested by customer"},{value:"CANCELLATION",label:"Trip cancelled"},{value:"DUPLICATE",label:"Duplicate payment"},{value:"FRAUDULENT",label:"Fraudulent payment"},{value:"OTHERS",label:"Other"}],_s={requested:"Awaiting Xendit",pending:"Processing",succeeded:"Refunded",failed:"Failed",cancelled:"Cancelled"};function R(s){const t=typeof s=="number"?s:Number(s??0);return Number.isFinite(t)?t:0}function Ns(){return crypto.randomUUID()}function ws(){const{isOwner:s,pageKeys:t}=Se();return s||(t??[]).includes("refunds")}function bs({booking:s}){const t=ws(),n=W(s.booking_reference)==="direct"&&(s.booking_reference??"").startsWith("BKG-")&&Fe(s.payment_status),{data:a,isLoading:r}=gs(s.id,t&&n);return!t||!n?null:e.jsx(ks,{booking:s,refunds:a??[],loading:r})}function ks({booking:s,refunds:t,loading:n}){const a=js(),[r,i]=h.useState(!1),[c,u]=h.useState(""),[o,l]=h.useState("full"),[p,f]=h.useState(0),[m,y]=h.useState(K[0].value),[S,X]=h.useState(""),[b,V]=h.useState(!1),Z=R(s.total_price),J=Math.max(R(s.refunded_amount),t.filter(d=>d.status==="succeeded").reduce((d,O)=>d+R(O.amount),0)),B=h.useMemo(()=>t.filter(d=>d.status==="requested"||d.status==="pending"),[t]),we=B.reduce((d,O)=>d+R(O.amount),0),C=Math.max(0,Z-J-we),L=o==="full"?C:p,E=L>0&&L<=C&&Number.isInteger(L),be=()=>{u(Ns()),l("full"),f(0),y(K[0].value),X(""),i(!0)},ee=()=>{b||i(!1)},ke=async()=>
44{if(!(!E||b)){V(!0);try{const d=await a.mutateAsync({ticketId:s.id,requestKey:c,amount:o==="full"?null:L,reason:m,note:S.trim()||null});d.warning==="xendit_unreachable"?k.warning(d.message||"Xendit could not be reached. The refund will be checked again automatically."):d.replayed?k.info("This refund was already submitted."):d.refund.status==="succeeded"?k.success(`Refunded ${x(d.refund.amount)}`):k.success(`Refund of ${x(d.refund.amount)} submitted. Xendit is processing it.`),i(!1)}catch(d){k.error((d==null?void 0:d.message)||"The refund failed. Please try again.")}finally{V(!1)}}};return e.jsxs(e.Fragment,{children:[e.jsx(q,{}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("p",{className:"text-[11px] uppercase tracking-wide text-gray-400",children:"Refunds"}),e.jsx(g,{size:"sm",variant:"outline",onClick:be,disabled:C<=0||B.length>0,children:"Refund"})]}),e.jsxs("p",{className:"text-xs text-gray-500",children:["Paid ",x(Z)," · Refunded ",x(J)," · Left ",x(C),B.length>0?" · a refund is being processed":""]}),n?e.jsxs("p",{className:"flex items-center gap-2 text-sm text-gray-500",children:[e.jsx(T,{className:"h-3.5 w-3.5 animate-spin"}),"Loading refundsâ¦"]}):t.length===0?e.jsx("p",{className:"text-sm text-gray-500",children:"No refunds."}):e.jsx("ul",{className:"space-y-1",children:t.map(d=>e.jsxs("li",{className:"flex items-center justify-between gap-2 text-sm",children:[e.jsxs("span",{children:[x(d.amount),e.jsxs("span",{className:"text-gray-500",children:[" · ",F(d.refunded_at??d.created_at),d.origin==="external"?" · issued in Xendit":"",d.failure_code&&d.status==="failed"?` · ${d.failure_code}`:""]})]}),e.jsx(w,{variant:d.status==="failed"?"destructive":"secondary",children:_s[d.status]??d.status})]},d.id))}),e.jsx(Q,{open:r,onOpenChange:d=>{d||ee()}
44,children:e.jsxs($,{children:[e.jsxs(G,{children:[e.jsxs(H,{children:["Refund ",s.booking_reference]}),e.jsx(Y,{children:"The money goes back to the card or account that paid. This cannot be undone."})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex gap-2",role:"radiogroup","aria-label":"Refund amount",children:[e.jsxs(g,{type:"button",role:"radio","aria-checked":o==="full",variant:o==="full"?"default":"outline",size:"sm",onClick:()=>l("full"),disabled:b,children:["Full (",x(C),")"]}),e.jsx(g,{type:"button",role:"radio","aria-checked":o==="partial",variant:o==="partial"?"default":"outline",size:"sm",onClick:()=>l("partial"),disabled:b,children:"Partial"})]}),o==="partial"&&e.jsxs("div",{className:"space-y-1",children:[e.jsx(A,{htmlFor:"refund-amount",children:"Amount"}),e.jsx(ze,{id:"refund-amount",value:p,onChange:f}),p>C&&e.jsxs("p",{className:"text-xs text-red-600",children:["No more than ",x(C)," is left to refund."]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(A,{htmlFor:"refund-reason",children:"Reason"}),e.jsx("select",{id:"refund-reason",className:"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",value:m,onChange:d=>y(d.target.value),disabled:b,children:K.map(d=>e.jsx("option",{value:d.value,children:d.label},d.value))})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(A,{htmlFor:"refund-note",children:"Note (staff only)"}),e.jsx(he,{id:"refund-note",value:S,onChange:d=>X(d.target.value),rows:2,disabled:b})]}),e.jsxs("p",{className:"rounded-md bg-gray-50 px-3 py-2 text-sm",children:["You are about to refund ",e.jsx("strong",{children:x(E?L:0)})," on"," ",s.booking_reference,".",o==="full"?" Its remaining seats will be released and it can no longer be checked in or rebooked.":""]})]}),e.jsxs(z,{children:[e.jsx(g,{variant:"outline",onClick:ee,disabled:b,children:"Cancel"}),e.jsxs(g,{variant:"destructive",onClick:ke,disabled:b||!E,children:[b&&e.jsx(T,{className:"h-4 w-4 mr-2 animate-spin"}),"Refund ",x(E?L:0)]})]})]})})]})]})}const vs={confirmed:"Not checked in",used:"Checked in",no_show:"No show",cancelled:"Cancelled",released:"Seat released (unpaid)"};function Ss(s,t){return s?s.toLowerCase()==="released"&&t==="full"?"Seat released (refunded)":vs[s.toLowerCase()]??s:"Unknown"}function Cs(s){switch(s==null?void 0:s.toLowerCase()){case"used":return"text-green-700";case"no_show":case"cancelled":case"released":return"text-gray-400";default:return"text-gray-600"}}function v({label:s,children:t}){return e.jsxs("div",{className:"space-y-0.5",children:[e.jsx("p",{className:"text-[11px] uppercase tracking-wide text-gray-400",children:s}),e.jsx("div",{className:"text-sm text-gray-900 break-words",children:t})]})}function Ts({booking:s,onClose:t}){const n=Be(s==null?void 0:s.booking_reference),{data:a,isLoading:r}=hs(n);return e.jsx(Qe,{open:s!==null,onOpenChange:i=>{i||t()},children:e.jsx($e,{className:"w-full sm:max-w-lg overflow-y-auto",children:s&&e.jsx(Ls,{booking:s,shopifyOrder:a??null,orderLoading:r&&n!==null})})})}function Ls({booking:s,shopifyOrder:t,orderLoading:n}){const a=pe(s),r=W(s.booking_reference),i=fe(s),c=Oe(s.whatsapp_number),u=s.ticket_passengers??[],o=r==="shopify"?xs(t):Ie(s);return e.jsxs(e.Fragment,{children:[e.jsxs(Ge,{className:"space-y-2",children:[e.jsxs(He,{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{children:s.booking_reference??"Booking"}),e.jsx(w,{variant:"outline",children:r==="shopify"?"Shopify":"Direct"}),e.jsx(w,{variant:"secondary",children:xe[a]})]}),e.jsxs(Ye,{children:[ge(s)," · ",ye(s)," pax ·"," ",x(s.total_price)]})]}),e.jsxs("div",{className:"mt-6 space-y-6",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsx(v,{label:"WhatsApp",children:c?e.jsxs("a",{href:c,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1.5 text-primary hover:underline",children:[e.jsx(We,{className:"h-3.5 w-3.5"}),s.whatsapp_number]}):"â"}),e.jsx(v,{label:"Email",children:s.passenger_email||"â"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsx(v,{label:"Payment reference",children:e.jsx("span",{className:"font-mono text-xs",children:s.payment_reference||"â"})}),e.jsx(v,{label:"Booked",children:F(s.created_at)})]}),e.jsx(bs,{booking:s}),e.jsx(q,{}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-[11px] uppercase tracking-wide text-gray-400",children:"Trip"}),i.length===0?e.jsxs("p",{className:"text-sm text-gray-500",children:["No trip attached yet.",s.scheduling_note?` ${s.scheduling_note}`:""]}):e.jsx("ul",{className:"space-y-1.5",children:i.map(l=>e.jsxs("li",{className:"text-sm",children:[e.jsx("span",{className:l.source==="none"?"text-gray-400 italic":"",children:l.label}
44),e.jsx("span",{className:"text-gray-500",children:l.scheduleDate?` · ${M(l.scheduleDate,l.scheduledDeparture)}`:""})]},l.key))})]}),s.scheduling_dismissed_at&&e.jsxs(v,{label:"Dismissed",children:[F(s.scheduling_dismissed_at),s.scheduling_dismissed_reason?` â ${s.scheduling_dismissed_reason}`:""]}),e.jsx(q,{}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("p",{className:"text-[11px] uppercase tracking-wide text-gray-400",children:["Passengers (",u.length,")"]}),u.length===0?e.jsx("p",{className:"text-sm text-gray-500",children:"No passenger records."}):e.jsx("ul",{className:"space-y-3",children:u.map(l=>{const p=[l.first_name,l.last_name].map(m=>(m??"").trim()).filter(Boolean).join(" ")||"â",f=l.trip_reservations??[];return e.jsxs("li",{className:"rounded-md border px-3 py-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 flex-wrap",children:[e.jsx("span",{className:"text-sm font-medium",children:p}),l.is_primary&&e.jsx(w,{variant:"outline",className:"text-[10px]",children:"Lead"})]}),l.pass_reference&&e.jsx("p",{className:"mt-0.5 font-mono text-[11px] text-gray-500",children:l.pass_reference}),f.length===0?e.jsx("p",{className:"mt-1 text-xs text-gray-400",children:"No trip booked"}):e.jsx("ul",{className:"mt-1 space-y-0.5",children:f.map(m=>{var y,S;return e.jsxs("li",{className:"text-xs",children:[e.jsxs("span",{className:"text-gray-500",children:[Ke(m.schedule_trip).label,(S=(y=m.schedule_trip)==null?void 0:y.schedule)!=null&&S.schedule_date?` · ${M(m.schedule_trip.schedule.schedule_date,m.schedule_trip.scheduled_departure)}`:""]})," ",e.jsx("span",{className:Cs(m.status),children:Ss(m.status,s.refund_status)})]},m.id)})})]},l.id)})})]}),e.jsx(q,{}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-[11px] uppercase tracking-wide text-gray-400",children:"Source"}),n?e.jsxs("p",{className:"flex items-center gap-2 text-sm text-gray-500",children:[e.jsx(T,{className:"h-3.5 w-3.5 animate-spin"}),"Loading the Shopify orderâ¦"]}):e.jsx(Ds,{attribution:o,source:r})]})]})]})}function Ds({attribution:s,source:t}){return s?e.jsxs("div",{className:"space-y-3",children:[e.jsx(v,{label:"Referrer",children:Me(s)?e.jsx("span",{className:"text-gray-600",children:"Direct â no referrer"}):s.referrer||"â"}),s.entryUrl&&e.jsx(v,{label:"Landing page",children:e.jsx("span",{className:"font-mono text-xs break-all",children:s.entryUrl})}),s.channel&&e.jsx(v,{label:"Channel",children:s.channel}),s.utm.length>0&&e.jsx(v,{label:"Campaign",children:e.jsx("div",{className:"flex flex-wrap gap-1.5",children:s.utm.map(n=>e.jsxs(w,{variant:"outline",className:"font-normal",children:[n.key.replace("utm_",""),": ",n.value]},n.key))})})]}):e.jsx("p",{className:"text-sm text-gray-500",children:t==="shopify"?"No arrival details on the stored Shopify order.":"No attribution recorded for this booking."})}const Es={refunded:{backgroundColor:"#ede9fe",color:"#5b21b6"},booked:{backgroundColor:"#dcfce7",color:"#166534"},"needs-trip":{backgroundColor:"#fef9c3",color:"#854d0e"},unpaid:{backgroundColor:"#ffedd5",color:"#9a3412"},cancelled:{backgroundColor:"#fee2e2",color:"#991b1b"},dismissed:{backgroundColor:"#f3f4f6",color:"#4b5563"}};function Rs({status:s}){return e.jsx("span",{className:"inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium whitespace-nowrap",style:Es[s],children:xe[s]})}function rt(){const{data:s,isLoading:t,error:n}=es(),[a,r]=h.useState("all"),[i,c]=h.useState(null),u=h.useMemo(()=>s??[],[s]),o=h.useMemo(()=>i?u.find(m=>m.id===i.id)??i:null,[i,u]),l=h.useMemo(()=>new Date,[u]),p=h.useMemo(()=>{const m={};for(const y of se)m[y]=u.filter(S=>te(S,y,l)).length;return m},[u,l]),f=h.useMemo(()=>u.filter(m=>te(m,a,l)),[u,a,l]);return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-bold text-gray-900 flex items-center gap-2",children:[e.jsx(ue,{className:"h-6 w-6"}),"All Bookings"]}),e.jsx("p",{className:"text-sm text-gray-500 mt-1",children:"Every booking on the system: orders imported from the old goboat.id Shopify store (SH-) alongside direct sales taken on this site (BKG-). Click a row for c
44ontact details, passengers and where the booking came from."})]}),e.jsx(cs,{}),e.jsxs(ie,{children:[e.jsxs(ce,{className:"space-y-3",children:[e.jsxs("div",{children:[e.jsx(le,{children:"Bookings"}),e.jsxs(de,{children:[t?"Loadingâ¦":`${f.length} of ${u.length} booking(s)`," ","â newest first."]})]}),e.jsx("div",{className:"flex flex-wrap gap-2",children:se.map(m=>e.jsxs(g,{type:"button",size:"sm",variant:a===m?"default":"outline","aria-pressed":a===m,onClick:()=>r(m),children:[ae[m],e.jsx("span",{className:"ml-1.5 tabular-nums opacity-70",children:p[m]})]},m))})]}),e.jsx(oe,{children:t?e.jsxs("div",{className:"flex items-center justify-center py-12 text-gray-500",children:[e.jsx(T,{className:"h-5 w-5 animate-spin mr-2"}),"Loading bookingsâ¦"]}):n?e.jsxs("div",{className:"py-8 text-center text-red-600 text-sm",children:["Failed to load bookings: ",n.message]}):u.length===0?e.jsx("div",{className:"py-12 text-center text-gray-500 text-sm",children:"No bookings yet."}):f.length===0?e.jsxs("div",{className:"py-12 text-center text-gray-500 text-sm",children:["No bookings under ",ae[a],"."]}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs(Ce,{children:[e.jsx(Te,{children:e.jsxs(me,{children:[e.jsx(_,{children:"Reference"}),e.jsx(_,{children:"Source"}),e.jsx(_,{children:"Customer"}),e.jsx(_,{children:"Contact"}),e.jsx(_,{className:"whitespace-nowrap",children:"Booked"}),e.jsx(_,{className:"whitespace-nowrap",children:"Departs"}),e.jsx(_,{className:"text-center",children:"Pax"}),e.jsx(_,{children:"Trip"}),e.jsx(_,{children:"Total"}),e.jsx(_,{children:"Status"})]})}),e.jsx(Le,{children:f.map(m=>e.jsx(As,{booking:m,onOpen:()=>c(m)},m.id))})]})})})]}),e.jsx(Ts,{booking:o,onClose:()=>c(null)})]})}function As({booking:s,onOpen:t}){const n=fe(s),a=n[0],r=Pe(s),i=r?M(r.scheduleDate,r.scheduledDeparture):null,c=Math.max(0,n.length-1),u=W(s.booking_reference);return e.jsxs(me,{className:"cursor-pointer",tabIndex:0,onClick:t,onKeyDown:o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),t())},children:[e.jsx(N,{className:"font-medium whitespace-nowrap",children:s.booking_reference??"â"}),e.jsx(N,{children:e.jsx(w,{variant:u==="shopify"?"secondary":"outline",children:u==="shopify"?"Shopify":"Direct"})}),e.jsx(N,{children:ge(s)}),e.jsx(N,{className:"text-sm text-gray-500 whitespace-nowrap",children:s.whatsapp_number||s.passenger_email||"â"}),e.jsx(N,{className:"text-sm text-gray-500 whitespace-nowrap",children:F(s.created_at)}),e.jsx(N,{className:"text-sm whitespace-nowrap",children:i?e.jsx("span",{className:"text-gray-700",children:i}):e.jsx("span",{className:"text-gray-400",children:"â"})}),e.jsx(N,{className:"text-center font-medium",children:ye(s)}),e.jsx(N,{className:"text-sm",children:a?e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:a.source==="none"?"text-gray-400 italic":"",children:a.label}),c>0&&e.jsxs(w,{variant:"outline",className:"text-[10px] font-normal",children:["+",c," leg",c>1?"s":""]})]}):e.jsx("span",{className:"text-gray-400",children:"â"})}),e.jsx(N,{className:"whitespace-nowrap",children:x(s.total_price)}),e.jsx(N,{children:e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx(Rs,{status:pe(s)}),Ue(s)&&e.jsx(w,{variant:"outline",className:"text-[10px] font-normal whitespace-nowrap",children:"Part refunded"})]})})]})}export{rt as AllBookingsPage};
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.