PageSourceSearch

https://harbor-os.com/assets/AdminCalcom-CwHMkBOo.js

js harbor-os.com collected 2026-09-24 14:44:46 UTC 13,620 bytes, 1 lines download raw bytes

1import{bx as M,g as j,r as w,i as _,j as e,c0 as z,J as O,c1 as R,b as H,bl as Q,U as V,a1 as Y}from"./vendor-BeA4siBz.js";import{u as $,f as m,g as k,C as c,d as o,T as J,o as W,p as b,r as N,a as f,b as v,c as y,I as X,B as T}from"./index-C2NQ_9nj.js";import{A as Z}from"./AdminLayout-zgeex3qo.js";import"./harbor-shoppers-logo-BwiOLETu.js";import"./textarea-BzoSp81z.js";function F({name:d,currentUsername:r,onSave:a,isSaving:n}){const[p,t]=w.useState(!1),[g,l]=w.useState(r??"");function h(){a(g.trim()),t(!1)}return e.jsxs("div",{className:"flex items-center justify-between gap-4 py-3 border-b last:border-0",children:[e.jsx("div",{className:"flex items-center gap-3 min-w-0",children:e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-sm font-medium text-gray-900 truncate",children:d}),r?e.jsxs("a",{href:`https://cal.com/${r}`,target:"_blank",rel:"noopener noreferrer",className:"text-xs text-blue-600 hover:underline flex items-center gap-1",children:["cal.com/",r,e.jsx(Y,{className:"h-3 w-3"})]}):e.jsx("p",{className:"text-xs text-gray-400",children:"No booking link set"})]})}),e.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[r&&!p&&e.jsxs(k,{className:"bg-green-100 text-green-700 border-0 text-xs",children:[e.jsx(O,{className:"h-3 w-3 mr-1"}),"Linked"]}),p?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm text-gray-500",children:"cal.com/"}),e.jsx(X,{value:g,onChange:u=>l(u.target.value),onKeyDown:u=>u.key==="Enter"&&h(),placeholder:"username",className:"h-7 w-36 text-sm",autoFocus:!0}),e.jsx(T,{size:"sm",className:"h-7 text-xs",onClick:h,disabled:n,children:n?e.jsx(V,{className:"h-3 w-3 animate-spin"}):"Save"}),e.jsx(T,{size:"sm",variant:"ghost",className:"h-7 text-xs",onClick:()=>{t(!1),l(r??"")},children:"Cancel"})]}):e.jsx(T,{size:"sm",variant:"outline",className:"h-7 text-xs",onClick:()=>t(!0),children:r?"Edit":"Add Link"})]})]})}function ne(){var P;const{toast:d}=$(),r=M(),{data:a}=j({queryKey:["/api/calcom/status"],queryFn:()=>m("GET","/api/calcom/status").then(s=>s.json())}),{data:n,isLoading:p}=j({queryKey:["/api/calcom/crew-links"],queryFn:()=>m("GET","/api/calcom/crew-links").then(s=>s.json())}),{data:t,isLoading:g}=j({queryKey:["/api/calcom/vendor-links"],queryFn:()=>m("GET","/api/calcom/vendor-links").then(s=>s.json())}),{data:l,isLoading:h}=j({queryKey:["/api/calcom/bookings"],queryFn:()=>m("GET","/api/calcom/bookings").then(s=>s.json()),enabled:!!(a!=null&&a.configured)}),[u,C]=w.useState(null),[U,A]=w.useState(null),I=_({mutationFn:({id:s,calcomUsername:i})=>m("PATCH",`/api/calcom/crew-links/${s}`,{calcomUsername:i}).then(x=>x.json()),onSuccess:()=>{r.invalidateQueries({queryKey:["/api/calcom/crew-links"]}),d({title:"Booking link saved"}),C(null)},onError:s=>{d({title:"Failed to save",description:s.message,variant:"destructive"}),C(null)}}),S=_({mutationFn:({id:s,calcomUsername:i})=>m("PATCH",`/api/calcom/vendor-links/${s}`,{calcomUsername:i}).then(x=>x.json()),onSuccess:()=>{r.invalidateQueries({queryKey:["/api/calcom/vendor-links"]}),d({title:"Booking link saved"}),A(null)},onError:s=>{d({title:"Failed to save",description:s.message,variant:"destructive"}),A(null)}}),L=((n==null?void 0:n.profiles)??[]).filter(s=>s.calcomUsername).length,E=((t==null?void 0:t.vendors)??[]).filter(s=>s.calcomUsername).length;return e.jsx(Z,{children:e.jsxs("div",{className:"max-w-4xl 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(z,{className:"h-6 w-6 text-blue-700"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold",children:"Cal.com Booking Integration"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Connect captains and vendors with real-time booking pages"})]}),a!=null&&a.configured?e.jsxs(k,{className:"ml-auto bg-green-100 text-green-700 border-0",children:[e.jsx(O,{className:"h-3.5 w-3.5 mr-1"}),"API Connected"]}):e.jsxs(k,{className:"ml-auto bg-amber-100 text-amber-700 border-0",children:[e.jsx(R,{className:"h-3.5 w-3.5 mr-1"}),"API Key Not Set"]})]}),!(a!=null&&a.configured)&&e.jsx(c,{className:"border-amber-200 bg-amber-50",children:e.jsxs(o,{className:"py-4 flex items-start gap-3",children:[e.jsx(R,{className:"h-5 w-5 text-amber-600 flex-shrink-0 mt-0.5"}),e.jsxs("div",{className:"text-sm text-amber-800",children:[e.jsx("p",{className:"font-medium",children:"Cal.com API key not configured"}),e.jsxs("p",{className:"mt-0.5",children:["Add your ",e.jsx("code",{className:"bg-amber-100 px-1 rounded",children:"CALCOM_API_KEY"})," secret to enable the live bookings feed. Cal.com booking links still work without the API key — you just won't see bookings in this dashboard."]}),e.jsxs("p",{className:"mt-2 text-xs",children:["Get your API key: ",e.jsx("a",{href:"https://cal.com/settings/developer/api-keys",target:"_blank",rel:"noopener noreferrer",className:"underline font-medium",children:"cal.com/settings/developer/api-keys"})]})]})]})}),e.jsxs("div",{className:"grid grid-cols-3 gap-4",children:[e.jsx(c,{children:e.jsxs(o,{className:"pt-5 pb-4",children:[e.jsx("div",{className:"text-2xl font-bold text-blue-700",children:L}),e.jsx("div",{className:"text-xs text-gray-500 mt-0.5",children:"Captains with booking links"})]})}),e.jsx(c,{children:e.jsxs(o,{className:"pt-5 pb-4",children:[e.jsx("div",{className:"text-2xl font-bold text-violet-700",children:E}),e.jsx("div",{className:"text-xs text-gray-500 mt-0.5",children:"Vendors with booking links"})]})}),e.jsx(c,{children:e.jsxs(o,{className:"pt-5 pb-4",children:[e.jsx("div",{className:"text-2xl font-bold text-green-700",children:h?"…":((P=l==null?void 0:l.bookings)==null?void 0:P.length)??"—"}),e.jsx("div",{className:"text-xs text-gray-500 mt-0.5",children:"Recent bookings (API)"})]})})]}),e.jsxs(J,{defaultValue:"crew",children:[e.jsxs(W,{className:"mb-4",children:[e.jsxs(b,{value:"crew",children:[e.jsx(H,{className:"h-3.5 w-3.5 mr-1.5"}),"Captains & Crew",L>0&&e.jsx("span",{className:"ml-1.5 text-xs bg-blue-100 text-blue-700 px-1.5 rounded-full",children:L})]}),e.jsxs(b,{value:"vendors",children:[e.jsx(Q,{className:"h-3.5 w-3.5 mr-1.5"}),"Vendors",E>0&&e.jsx("span",{className:"ml-1.5 text-xs bg-violet-100 text-violet-700 px-1.5 rounded-full",children:E})]}),e.jsx(b,{value:"bookings",children:"Recent Bookings"}),e.jsx(b,{value:"setup",children:"Setup Guide"})]}),e.jsx(N,{value:"crew",children:e.jsxs(c,{children:[e.jsxs(f,{children:[e.jsx(v,{className:"text-base",children:"Captain & Crew Booking Links"}),e.jsx(y,{className:"text-xs",children:'Add a Cal.com username for each crew member. A "Book Now" button will appear on their crew directory card.'})]}),e.jsx(o,{children:p?e.jsx("div",{className:"py-8 text-center text-gray-400 text-sm",children:"Loading crew profiles…"}):((n==null?void 0:n.profiles)??[]).length===0?e.jsx("div",{className:"py-8 text-center text-gray-400 text-sm",children:"No crew profiles found. Add profiles in the Crew admin panel first."}):e.jsx("div",{children:((n==null?void 0:n.profiles)??[]).map(s=>e.jsx(F,{name:s.fullName,currentUsername:s.calcomUsername,isSaving:u===s.id&&I.isPending,onSave:i=>{C(s.id),I.mutate({id:s.id,calcomUsername:i})}},s.id))})})]})}),e.jsx(N,{value:"vendors",children:e.jsxs(c,{children:[e.jsxs(f,{children:[e.jsx(v,{className:"text-base",children:"Vendor Booking Links"}),e.jsx(y,{className:"text-xs",children:"Add a Cal.com username for each vend
1or to enable appointment booking on their store page."})]}),e.jsx(o,{children:g?e.jsx("div",{className:"py-8 text-center text-gray-400 text-sm",children:"Loading vendors…"}):((t==null?void 0:t.vendors)??[]).length===0?e.jsx("div",{className:"py-8 text-center text-gray-400 text-sm",children:"No vendor stores found."}):e.jsx("div",{children:((t==null?void 0:t.vendors)??[]).map(s=>e.jsx(F,{name:s.storeName,currentUsername:s.calcomUsername,isSaving:U===s.id&&S.isPending,onSave:i=>{A(s.id),S.mutate({id:s.id,calcomUsername:i})}},s.id))})})]})}),e.jsx(N,{value:"bookings",children:e.jsxs(c,{children:[e.jsxs(f,{children:[e.jsx(v,{className:"text-base",children:"Recent Bookings"}),e.jsx(y,{className:"text-xs",children:"Live feed from Cal.com API. Requires CALCOM_API_KEY to be configured."})]}),e.jsx(o,{children:a!=null&&a.configured?h?e.jsxs("div",{className:"py-8 text-center text-gray-400 text-sm flex items-center justify-center gap-2",children:[e.jsx(V,{className:"h-4 w-4 animate-spin"})," Loading bookings…"]}):((l==null?void 0:l.bookings)??[]).length===0?e.jsx("div",{className:"py-8 text-center text-gray-400 text-sm",children:"No recent bookings found."}):e.jsx("div",{className:"space-y-3",children:((l==null?void 0:l.bookings)??[]).map((s,i)=>{var x,B,q,G,K;return e.jsxs("div",{className:"flex items-start justify-between gap-4 py-3 border-b last:border-0",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium",children:s.title??((x=s.eventType)==null?void 0:x.title)??"Booking"}),e.jsxs("p",{className:"text-xs text-gray-500",children:[((q=(B=s.attendees)==null?void 0:B[0])==null?void 0:q.name)??"Unknown"," · ",(K=(G=s.attendees)==null?void 0:G[0])==null?void 0:K.email]}),s.startTime&&e.jsx("p",{className:"text-xs text-gray-400 mt-0.5",children:new Date(s.startTime).toLocaleString()})]}),e.jsx(k,{className:s.status==="ACCEPTED"?"bg-green-100 text-green-700 border-0":s.status==="CANCELLED"?"bg-red-100 text-red-700 border-0":"bg-blue-100 text-blue-700 border-0",children:s.status??"PENDING"})]},s.uid??i)})}):e.jsx("div",{className:"py-8 text-center text-gray-400 text-sm",children:"Configure your API key to view bookings here."})})]})}),e.jsx(N,{value:"setup",children:e.jsxs(c,{children:[e.jsxs(f,{children:[e.jsx(v,{className:"text-base",children:"Setup Guide"}),e.jsx(y,{className:"text-xs",children:"Get Cal.com working across all your brands in 3 steps"})]}),e.jsxs(o,{className:"space-y-6 text-sm",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"bg-blue-600 text-white rounded-full w-5 h-5 flex items-center justify-center text-xs font-bold flex-shrink-0",children:"1"}),e.jsx("p",{className:"font-semibold",children:"Create Cal.com accounts for each captain or vendor"})]}),e.jsxs("p",{className:"text-gray-600 ml-7",children:["Each person signs up at ",e.jsx("a",{href:"https://cal.com",target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 underline",children:"cal.com"}),' (free plan works). They set their availability, connect their Google/Outlook calendar, and set up event types (e.g. "Day Charter", "Consultation").']})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"bg-blue-600 text-white rounded-full w-5 h-5 flex items-center justify-center text-xs font-bold flex-shrink-0",children:"2"}),e.jsx("p",{className:"font-semibold",children:"Add their Cal.com username here"})]}),e.jsxs("p",{className:"text-gray-600 ml-7",children:["Go to the Captains & Crew or Vendors tab above. Enter each person's Cal.com username (from their profile URL: cal.com/",e.jsx("strong",{children:"username"}),'). The crew directory will automatically show a "Book Now" button on their card.']})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"bg-blue-600 text-white rounded-full w-5 h-5 flex items-center justify-center text-xs font-bold flex-shrink-0",children:"3"}),e.jsx("p",{className:"font-semibold",children:"(Optional) Connect the API for the live bookings dashboard"})]}),e.jsxs("p",{className:"text-gray-600 ml-7",children:["Create an API key at ",e.jsx("a",{href:"https://cal.com/settings/developer/api-keys",target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 underline",children:"cal.com/settings/developer/api-keys"}),", then add it as the ",e.jsx("code",{className:"bg-gray-100 px-1 rounded",children:"CALCOM_API_KEY"})," secret in your Replit environment. This enables the bookings feed in this dashboard. Booking links work without this step."]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"bg-blue-600 text-white rounded-full w-5 h-5 flex items-center justify-center text-xs font-bold flex-shrink-0",children:"4"}),e.jsx("p",{className:"font-semibold",children:"(Optional) Set up a webhook for booking confirmations"})]}),e.jsxs("p",{className:"text-gray-600 ml-7",children:["In Cal.com → Settings → Developer → Webhooks, add your endpoint: ",e.jsxs("code",{className:"bg-gray-100 px-1 rounded text-xs",children:[window.location.origin,"/api/calcom/webhooks/booking"]}),". Subscribe to ",e.jsx("strong",{children:"BOOKING_CREATED"})," and ",e.jsx("strong",{children:"BOOKING_RESCHEDULED"})," events. This will log new bookings to your server."]})]}),e.jsxs("div",{className:"bg-blue-50 rounded-lg p-4 border border-blue-100",children:[e.jsx("p",{className:"font-medium text-blue-900 mb-1",children:"Cal.com for Teams"}),e.jsxs("p",{className:"text-blue-800 text-xs",children:["For larger operations, consider Cal.com Teams — one organization with multiple member calendars. Customers can browse availability across all captains and pick who they want. ",e.jsx("a",{href:"https://cal.com/teams",target:"_blank",rel:"noopener noreferrer",className:"underline font-medium",children:"Learn more →"})]})]})]})]})})]})]})})}export{ne 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.