1import{by as P,r as c,g as y,i as E,j as e,c1 as f,c3 as v,aE as I,aS as F,U as u,c4 as w,M as z,bD as H,b as V,bH as M,J as U,K as $}from"./vendor-B3bqREfz.js";import{u as K,B as n,C,d as k,T as O,o as _,p as G,r as Q,D as J,h as W,j as X,k as Y,m as Z,f as g}from"./index-BHZdkTHk.js";import{A as ee}from"./AdminLayout-C31anzfd.js";import{T as se}from"./textarea-BFtGXtJd.js";import{L as T}from"./label-USjEtjxC.js";import{S as te,a as ae,b as le,c as re,d as o}from"./select-CdK0CD7c.js";import"./harbor-shoppers-logo-BwiOLETu.js";const ie={pending:"bg-amber-100 text-amber-800",confirmed:"bg-green-100 text-green-800",cancelled:"bg-red-100 text-red-700",completed:"bg-gray-100 text-gray-700"},S={day_trip:"Day Trip",multi_day:"Multi-Day",delivery:"Boat Delivery",instruction:"Sailing Instruction",charter:"Charter"};function pe(){const{toast:j}=K(),b=P(),[r,D]=c.useState("all"),[t,d]=c.useState(null),[l,x]=c.useState({status:"",adminNotes:""}),[m,q]=c.useState(!1),{data:a}=y({queryKey:["/api/admin/bookings/stats"],queryFn:()=>g("GET","/api/admin/bookings/stats").then(s=>s.json())}),{data:h,isLoading:R,refetch:A}=y({queryKey:["/api/admin/bookings",r],queryFn:()=>g("GET",`/api/admin/bookings?status=${r}`).then(s=>s.json())}),p=E({mutationFn:({id:s,body:i})=>g("PATCH",`/api/admin/bookings/${s}`,i).then(L=>L.json()),onSuccess:()=>{b.invalidateQueries({queryKey:["/api/admin/bookings"]}),b.invalidateQueries({queryKey:["/api/admin/bookings/stats"]}),d(null),j({title:"Booking updated"})},onError:s=>j({title:"Failed",description:s.message,variant:"destructive"})});function B(s){d(s),x({status:s.status,adminNotes:s.adminNotes??""})}const N=(h==null?void 0:h.bookings)??[];return e.jsx(ee,{children:e.jsxs("div",{className:"max-w-6xl mx-auto px-4 py-8 space-y-6",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"bg-blue-100 rounded-xl p-2.5",children:e.jsx(f,{className:"h-6 w-6 text-blue-700"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold",children:"Booking Requests"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Captain, crew, and vendor booking requests from customers"})]}),e.jsxs("div",{className:"ml-auto flex gap-2",children:[e.jsxs(n,{variant:"outline",size:"sm",className:"gap-1.5",onClick:()=>q(s=>!s),children:[e.jsx(v,{className:"h-3.5 w-3.5"})," ",m?"Hide Guide":"How it Works",m?e.jsx(I,{className:"h-3 w-3"}):e.jsx(F,{className:"h-3 w-3"})]}),e.jsxs(n,{variant:"outline",size:"sm",className:"gap-1.5",onClick:()=>A(),children:[e.jsx(u,{className:"h-3.5 w-3.5"})," Refresh"]})]})]}),m&&e.jsxs("div",{className:"rounded-xl border border-blue-200 bg-blue-50 p-5 space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx(v,{className:"h-5 w-5 text-blue-600"}),e.jsx("h2",{className:"font-semibold text-blue-900 text-base",children:"Booking Requests â Admin Guide"})]}),e.jsxs("p",{className:"text-sm text-blue-800",children:["This page manages all booking requests submitted by customers for ",e.jsx("strong",{children:"Nautical Trips captains, crew members, and vendors"}),". No external calendar app is required â everything is handled natively within HS3."]}),e.jsxs("div",{className:"grid md:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"bg-white rounded-lg p-4 border border-blue-100 space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2 font-medium text-sm text-blue-900",children:[e.jsx("span",{className:"bg-blue-100 text-blue-700 rounded-full w-5 h-5 flex items-center justify-center text-xs font-bold",children:"1"}),"How Customers Book"]}),e.jsxs("p",{className:"text-xs text-gray-600",children:["On the ",e.jsx("strong",{children:"Nautical Trips"})," page, each captain or crew card has a ",e.jsx("strong",{children:'"Book Now"'})," button. Clicking it opens a booking form where the customer enters their trip type, desired dates, party size, vessel info, and a message. The request is submitted and appears here immediately."]})]}),e.jsxs("div",{className:"bg-white rounded-lg p-4 border border-blue-100 space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2 font-medium text-sm text-blue-900",children:[e.jsx("span",{className:"bg-blue-100 text-blue-700 rounded-full w-5 h-5 flex items-center justify-center text-xs font-bold",children:"2"}),"Reviewing a Request"]}),e.jsxs("p",{className:"text-xs text-gray-600",children:["Click ",e.jsx(w,{className:"inline h-3 w-3"})," ",e.jsx("strong",{children:"View"})," to see the full request â customer contact details, requested dates, trip type, party size, and vessel information. Use the tabs to switch between ",e.jsx("em",{children:"Pending, Confirmed, Completed,"})," and ",e.jsx("em",{children:"Cancelled"})," requests."]})]}),e.jsxs("div",{className:"bg-white rounded-lg p-4 border border-blue-100 space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2 font-medium text-sm text-blue-900",children:[e.jsx("span",{className:"bg-blue-100 text-blue-700 rounded-full w-5 h-5 flex items-center justify-center text-xs font-bold",children:"3"}),"Confirming a Booking"]}),e.jsxs("p",{className:"text-xs text-gray-600",children:["Set the status to ",e.jsx("strong",{className:"text-green-700",children:"Confirmed"})," and add admin notes (e.g. meeting point, special instructions, pricing agreed). Then contact the customer directly via ",e.jsx(z,{className:"inline h-3 w-3"})," email or phone to finalise the details outside the platform."]})]}),e.jsxs("div",{className:"bg-white rounded-lg p-4 border border-blue-100 space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2 font-medium text-sm text-blue-900",children:[e.jsx("span",{className:"bg-blue-100 text-blue-700 rounded-full w-5 h-5 flex items-center justify-center text-xs font-bold",children:"4"}),"After the Trip"]}),e.jsxs("p",{className:"text-xs text-gray-600",children:["Once the experience has taken place, update the status to ",e.jsx("strong",{className:"text-gray-700",children:"Completed"}
1),". Cancelled requests should be set to",e.jsx("strong",{className:"text-red-700",children:" Cancelled"}),". Admin notes are stored internally and not visible to the customer."]})]})]}),e.jsxs("div",{className:"flex items-center gap-3 bg-white border border-blue-100 rounded-lg p-3",children:[e.jsx(H,{className:"h-5 w-5 text-blue-500 shrink-0"}),e.jsxs("p",{className:"text-xs text-gray-600",children:[e.jsx("strong",{children:"Crew Profiles:"})," Each booking is linked to a crew profile ID (captain or crew member). The captain's name and specialty are shown on the booking card. If a vendor ID is attached, it means the request came through a vendor's storefront rather than the Nautical Trips directory."]})]}),e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-2 pt-1",children:[{label:"Pending",desc:"New, awaiting response",color:"bg-amber-100 text-amber-800"},{label:"Confirmed",desc:"Accepted & being arranged",color:"bg-green-100 text-green-800"},{label:"Completed",desc:"Trip has taken place",color:"bg-gray-100 text-gray-700"},{label:"Cancelled",desc:"Request not proceeding",color:"bg-red-100 text-red-800"}].map(s=>e.jsxs("div",{className:`rounded-md px-3 py-2 text-xs font-medium ${s.color}`,children:[e.jsx("div",{className:"font-semibold",children:s.label}),e.jsx("div",{className:"text-xs opacity-80 mt-0.5",children:s.desc})]},s.label))})]}),e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-3",children:[{label:"Pending",val:(a==null?void 0:a.pending)??"0",color:"text-amber-700"},{label:"Confirmed",val:(a==null?void 0:a.confirmed)??"0",color:"text-green-700"},{label:"Completed",val:(a==null?void 0:a.completed)??"0",color:"text-gray-700"},{label:"Total",val:(a==null?void 0:a.total)??"0",color:"text-blue-700"}].map(s=>e.jsx(C,{children:e.jsxs(k,{className:"pt-4 pb-3",children:[e.jsx("div",{className:`text-2xl font-bold ${s.color}`,children:s.val}),e.jsx("div",{className:"text-xs text-gray-500",children:s.label})]})},s.label))}),e.jsxs(O,{value:r,onValueChange:D,children:[e.jsx(_,{children:["all","pending","confirmed","completed","cancelled"].map(s=>e.jsxs(G,{value:s,className:"capitalize",children:[s,s==="pending"&&parseInt((a==null?void 0:a.pending)??"0")>0&&r!=="pending"&&e.jsx("span",{className:"ml-1.5 text-xs bg-amber-100 text-amber-800 px-1.5 rounded-full",children:a==null?void 0:a.pending})]},s))}),e.jsx(Q,{value:r,className:"mt-4",children:R?e.jsxs("div",{className:"py-16 text-center text-gray-400 flex items-center justify-center gap-2",children:[e.jsx(u,{className:"h-4 w-4 animate-spin"})," Loadingâ¦"]}):N.length===0?e.jsx(C,{children:e.jsxs(k,{className:"py-16 text-center",children:[e.jsx(f,{className:"h-10 w-10 mx-auto text-gray-200 mb-3"}),e.jsxs("p",{className:"text-gray-500 font-medium",children:["No ",r!=="all"?r:""," booking requests"]}),e.jsx("p",{className:"text-gray-400 text-sm mt-1",children:"Bookings submitted from the crew directory will appear here"})]})}):e.jsx("div",{className:"border rounded-lg overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-gray-50 border-b",children:e.jsxs("tr",{children:[e.jsx("th",{className:"text-left px-4 py-3 font-medium text-gray-600",children:"Customer"}),e.jsx("th",{className:"text-left px-4 py-3 font-medium text-gray-600 hidden md:table-cell",children:"Captain / Vendor"}),e.jsx("th",{className:"text-left px-4 py-3 font-medium text-gray-600 hidden lg:table-cell",children:"Trip Type"}),e.jsx("th",{className:"text-left px-4 py-3 font-medium text-gray-600 hidden sm:table-cell",children:"Date"}),e.jsx("th",{className:"text-left px-4 py-3 font-medium text-gray-600",children:"Status"}),e.jsx("th",{className:"text-right px-4 py-3 font-medium text-gray-600",children:"Actions"})]})}),e.jsx("tbody",{className:"divide-y",children:N.map(s=>e.jsxs("tr",{className:"hover:bg-gray-50",children:[e.jsxs("td",{className:"px-4 py-3",children:[e.jsx("div",{className:"font-medium text-sm",children:s.customerName}),e.jsx("div",{className:"text-xs text-gray-400",children:s.customerEmail})]}),e.jsx("td",{className:"px-4 py-3 hidden md:table-cell",children:e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(V,{className:"h-3.5 w-3.5 text-blue-400 flex-shrink-0"}),e.jsx("span",{className:"text-sm",children:s.crewName??`Vendor #${s.vendorId}`??"â"})]})}),e.jsx("td",{className:"px-4 py-3 hidden lg:table-cell text-xs text-gray-600",children:S[s.tripType??""]??s.tripType??"â"}),e.jsxs("td",{className:"px-4 py-3 hidden sm:table-cell text-xs text-gray-500",children:[s.requestedDate?new Date(s.requestedDate).toLocaleDateString():"Flexible",s.duration&&e.jsx("div",{className:"text-gray-400",children:s.duration})]}),e.jsx("td",{className:"px-4 py-3",children:e.jsx("span",{className:`text-xs px-2 py-0.5 rounded-full font-medium ${ie[s.status]??"bg-gray-100 text-gray-600"}`,children:s.status})}),e.jsx("td",{className:"px-4 py-3 text-right",children:e.jsxs(n,{variant:"ghost",size:"sm",className:"h-7 text-xs gap-1",onClick:()=>B(s),children:[e.jsx(w,{className:"h-3.5 w-3.5"})," Review"]})})]},s.id))})]})})})]}),e.jsx(J,{open:!!t,onOpenChange:s=>!s&&d(null),children:e.jsxs(W,{className:"max-w-lg",children:[e.jsx(X,{children:e.jsxs(Y,{children:["Booking #",t==null?void 0:t.id]})}),t&&e.jsxs("div",{className:"space-y-4 text-sm",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3 bg-gray-50 rounded-lg p-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-xs text-gray-500",children:"Customer"}),e.jsx("p",{className:"font-medium",children:t.customerName}),e.jsx("p",{className:"text-xs text-gray-400",children:t.customerEmail}),t.customerPhone&&e.jsx("p",{className:"text-xs text-gray-400",children:t.customerPhone})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-xs text-gray-500",children:"Captain / Crew"}),e.jsx("p",{className:"font-medium",children:t.crewName??"â"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-xs text-gray-500",children:"Trip Type"}),e.jsx("p",{children:S[t.tripType??""]??t.tripType??"â"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-xs text-gray-500",children:"Party Size"}),e.jsx("p",{children:t.partySize??"â"})]}),t.requestedDate&&e.jsxs("div",{children:[e.jsx("p",{className:"text-xs text-gray-500",children:"Requested Date"}),e.jsx("p",{children:new Date(t.requestedDate).toLocaleDateString()}),t.endDate&&e.jsxs("p",{className:"text-xs text-gray-400",children:["to ",new Date(t.endDate).toLocaleDateString()]})]}),t.duration&&e.jsxs("div",{children:[e.jsx("p",{className:"text-xs text-gray-500",children:"Duration"}),e.jsx("p",{children:t.duration})]}),t.vesselInfo&&e.jsxs("div",{className:"col-span-2",children:[e.jsx("p",{className:"text-xs text-gray-500",children:"Vessel Info"}),e.jsx("p",{children:t.vesselInfo})]}),t.message&&e.jsxs("div",{className:"col-span-2",children:[e.jsx("p",{className:"text-xs text-gray-500",children:"Message"}),e.jsx("p",{className:"text-gray-700",children:t.message})]})]}),e.jsxs("div",{className:"flex items-center gap-2 text-xs text-gray-400",children:[e.jsx(M,{className:"h-3.5 w-3.5"}
1),"Submitted ",new Date(t.createdAt).toLocaleString()]}),e.jsxs("div",{className:"space-y-3 border-t pt-3",children:[e.jsxs("div",{children:[e.jsx(T,{className:"text-xs",children:"Update Status"}),e.jsxs(te,{value:l.status,onValueChange:s=>x(i=>({...i,status:s})),children:[e.jsx(ae,{className:"mt-1 h-8 text-sm",children:e.jsx(le,{})}),e.jsxs(re,{children:[e.jsx(o,{value:"pending",children:"Pending"}),e.jsx(o,{value:"confirmed",children:"Confirm"}),e.jsx(o,{value:"cancelled",children:"Cancel"}),e.jsx(o,{value:"completed",children:"Completed"})]})]})]}),e.jsxs("div",{children:[e.jsx(T,{className:"text-xs",children:"Notes to Customer"}),e.jsx(se,{rows:3,className:"mt-1 text-sm",placeholder:"Confirmation details, next stepsâ¦",value:l.adminNotes,onChange:s=>x(i=>({...i,adminNotes:s.target.value}))})]})]})]}),e.jsxs(Z,{children:[e.jsx(n,{variant:"outline",onClick:()=>d(null),children:"Close"}),e.jsxs(n,{onClick:()=>t&&p.mutate({id:t.id,body:{status:l.status,adminNotes:l.adminNotes||void 0}}),disabled:p.isPending,className:l.status==="confirmed"?"bg-green-600 hover:bg-green-700":l.status==="cancelled"?"bg-red-600 hover:bg-red-700":"",children:[p.isPending?e.jsx(u,{className:"h-4 w-4 animate-spin mr-1"}):l.status==="confirmed"?e.jsx(U,{className:"h-4 w-4 mr-1"}):l.status==="cancelled"?e.jsx($,{className:"h-4 w-4 mr-1"}):null,"Save"]})]})]})})]})})}export{pe 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.