PageSourceSearch

https://www.truworx.co.uk/assets/AdminCallBookings-FQwQD_JT.js

js truworx.co.uk collected 2026-09-30 06:39:40 UTC 10,959 bytes, 3 lines download raw bytes

1import{r as x,j as e,R as T,B as c,W as r,s as j,p as E,a2 as L,M as O,a6 as F,X as P}from"./index-CJsdPNqw.js";import{C as I,a as G,b as V,d as W}from"./card-Dw44dnhl.js";import{n as Z}from"./phone-CSRAejs_.js";import{S as q,a as H,b as X,c as Y,d as u}from"./select-BIWU_ehh.js";import{A as J}from"./arrow-left-CUlcOyzi.js";import{D}from"./download-CuHIM3OL.js";import{R as K}from"./refresh-cw-B1XwVrXL.js";import{E as Q}from"./external-link-wdhcDu5f.js";import{M as ee}from"./mail-BC9ivzZp.js";import{M as se}from"./message-circle-BlgWfrnz.js";import{L as k}from"./loader-circle-jLJENuxj.js";import{T as te}from"./trash-2-BYJJeFAb.js";import"./index-BdQq_4o_.js";import"./index-3yhWZ5di.js";import"./chevron-up-CQbWMB49.js";const je=()=>{const[d,w]=x.useState([]),[p,v]=x.useState(!0),[R,g]=x.useState(null),[$,B]=x.useState(()=>Date.now()),[i,z]=x.useState("upcoming"),y=async()=>{v(!0);const{data:s,error:n}=await j.from("website_signups").select("*").eq("booking_type","1-to-1 Call").order("call_slot_iso",{ascending:!0});!n&&s&&w(s),B(Date.now()),v(!1)};x.useEffect(()=>{y()},[]);const b=async(s,n)=>{g(s);try{const{data:a,error:l}=await j.functions.invoke("mark-call-attendance",{body:{booking_id:s,status:n}});if(l)throw l;if(w(o=>o.map(t=>t.id===s?{...t,call_attendance_status:n}:t)),n==="Failed to Attend"){const o=(a==null?void 0:a.messagesSent)||{};r.success(`Marked as Failed to Attend${o.whatsapp||o.sms?" — rebook message sent":""}.`)}else r.success("Marked as Attended")}catch(a){r.error(a.message||"Failed to update")}finally{g(null)}},U=async s=>{if(confirm("Delete this booking? This will free up the slot.")){g(s);try{const{error:n}=await j.functions.invoke("delete-call-booking",{body:{booking_id:s}});if(n)throw n;w(a=>a.filter(l=>l.id!==s)),r.success("Booking deleted")}catch(n){r.error(n.message||"Failed to delete")}finally{g(null)}}},M=async s=>{const n=window.open("about:blank","_blank"),a=s.email||`${s.first_name||""} ${s.last_name||""}`.trim()||s.phone||"",l=`https://crm.zoho.eu/crm/search?searchword=${encodeURIComponent(a)}`;try{let o=l;if(s.email){const{data:t}=await j.from("crm_campaign_leads").select("zoho_lead_id").ilike("lead_email",s.email).limit(1).maybeSingle();t!=null&&t.zoho_lead_id&&(o=`https://crm.zoho.eu/crm/tab/Leads/${t.zoho_lead_id}`)}n?n.location.href=o:window.open(o,"_blank")}catch{n?n.location.href=l:window.open(l,"_blank")}},C=$,N=d.filter(s=>!s.call_attendance_status&&s.call_slot_iso&&new Date(s.call_slot_iso).getTime()>=C),m=d.filter(s=>!s.call_attendance_status&&(!s.call_slot_iso||new Date(s.call_slot_iso).getTime()<C)),A=d.filter(s=>s.call_attendance_status==="Attended"),h=d.filter(s=>s.call_attendance_status==="Failed to Attend"),f=new Map;N.forEach(s=>{const a=new Date(s.call_slot_iso).toLocaleDateString("en-GB",{weekday:"long",day:"numeric",month:"long"});f.has(a)||f.set(a,[]),f.get(a).push(s)});const S=s=>{const n=s.call_slot_iso?new Date(s.call_slot_iso).toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"}):"—",a=s.phone?Z(s.phone):null,l=R===s.id;return e.jsxs("div",{className:"border rounded-lg p-4 bg-card flex flex-col gap-3",children:[e.jsxs("div",{className:"flex flex-col md:flex-row md:items-center gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2 md:w-32",children:[e.jsx(E,{className:"h-4 w-4 text-primary"}),e.jsx("span",{className:"font-bold text-base",children:n})]}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsxs("button",{type:"button",onClick:()=>M(s),className:"font-semibold text-base text-primary hover:underline inline-flex items-center gap-1 group",title:"Open in Zoho CRM",children:[s.first_name," ",s.last_name,e.jsx(Q,{className:"h-3 w-3 opacity-50 group-hover:opacity-100"})]}),s.call_attendance_status&&e.jsx("span",{className:`text-[10px] font-bold uppercase tracking-wide px-2 py-0.5 rounded-full ${s.call_attendance_status==="Attended"?"bg-green-100 text-green-700":s.call_attendance_status==="Failed to Attend"?"bg-red-100 text-red-700":"bg-muted text-muted-foreground"}`,children:s.call_attendance_status})]}),e.jsxs("div",{className:"text-sm text-muted-foreground flex flex-wrap gap-x-4 gap-y-1 mt-1",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(L,{className:"h-3 w-3"})," ",s.phone]}),s.email&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(ee,{className:"h-3 w-3"})," ",s.email]}),s.postcode&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(O,{className:"h-3 w-3"})," ",s.postcode]})]}),(()=>{const o=s.page_url||"";let t="Unknown";if(/bookacallTA/i.test(o))t="Book a Call TA";else if(/bookacall/i.test(o))t="Book a Call";else if(/taonline|ta-online|llcourses|ll-courses/i.test(o))t="TA Online";else try{t=new URL(o).pathname||o}catch{t=o}return e.jsxs("div",{className:"text-xs text-muted-foreground mt-1",children:["Booked via ",e.jsx("span",{className:"font-semibold text-foreground",children:t}),s.course_id&&e.jsxs(e.Fragment,{children:[" · ",e.jsx("span",{className:"font-semibold text-foreground",children:s.course_id})]})]})})()]})]}
1),e.jsxs("div",{className:"grid grid-cols-5 gap-1.5 md:gap-2 pt-2 border-t",children:[e.jsx(c,{asChild:!0,size:"sm",variant:"outline",className:"h-9 text-[11px] md:text-xs px-1 md:px-3",disabled:!(a!=null&&a.mobile),children:e.jsxs("a",{href:a?`tel:${a.international}`:"#",children:[e.jsx(L,{className:"h-3 w-3 md:mr-1"})," ",e.jsx("span",{className:"hidden md:inline",children:"Call"})]})}),e.jsx(c,{asChild:!0,size:"sm",variant:"outline",className:"h-9 text-[11px] md:text-xs px-1 md:px-3 bg-green-50 hover:bg-green-100 text-green-700 border-green-200",disabled:!(a!=null&&a.digits),children:e.jsxs("a",{href:a?`https://wa.me/44${a.digits}`:"#",target:"_blank",rel:"noopener noreferrer",children:[e.jsx(se,{className:"h-3 w-3 md:mr-1"})," ",e.jsx("span",{className:"hidden md:inline",children:"WhatsApp"})]})}),e.jsxs(c,{size:"sm",variant:s.call_attendance_status==="Attended"?"default":"outline",className:"h-9 text-[11px] md:text-xs px-1 md:px-3",disabled:l,onClick:()=>b(s.id,"Attended"),children:[l?e.jsx(k,{className:"h-3 w-3 animate-spin md:mr-1"}):e.jsx(F,{className:"h-3 w-3 md:mr-1"}),e.jsx("span",{className:"hidden md:inline",children:"Attended"}),e.jsx("span",{className:"md:hidden",children:"Yes"})]}),e.jsxs(c,{size:"sm",variant:s.call_attendance_status==="Failed to Attend"?"destructive":"outline",className:"h-9 text-[11px] md:text-xs px-1 md:px-3",disabled:l,onClick:()=>b(s.id,"Failed to Attend"),children:[l?e.jsx(k,{className:"h-3 w-3 animate-spin md:mr-1"}):e.jsx(P,{className:"h-3 w-3 md:mr-1"}),e.jsx("span",{className:"hidden md:inline",children:"No-show"}),e.jsx("span",{className:"md:hidden",children:"No"})]}),e.jsxs(c,{size:"sm",variant:"outline",className:"h-9 text-[11px] md:text-xs px-1 md:px-3 text-destructive border-destructive/40 hover:bg-destructive/10",disabled:l,onClick:()=>U(s.id),children:[l?e.jsx(k,{className:"h-3 w-3 animate-spin md:mr-1"}):e.jsx(te,{className:"h-3 w-3 md:mr-1"}),e.jsx("span",{className:"hidden md:inline",children:"Delete"}),e.jsx("span",{className:"md:hidden",children:"Del"})]})]})]},s.id)};return e.jsx("div",{className:"min-h-screen bg-background p-4 md:p-8",children:e.jsxs("div",{className:"max-w-5xl mx-auto",children:[e.jsxs(T,{to:"/admin",className:"inline-flex items-center gap-2 text-sm text-primary hover:underline mb-4",children:[e.jsx(J,{className:"h-4 w-4"})," Back to Admin Dashboard"]}),e.jsxs("div",{className:"flex items-center justify-between mb-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl md:text-3xl font-bold",children:"Call Bookings"}),e.jsx("p",{className:"text-muted-foreground text-sm",children:"5-minute 1:1 phone call bookings from landing pages"})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(c,{onClick:()=>{const s=h.map(t=>[`${t.first_name||""} ${t.last_name||""}`.trim(),t.phone||"",t.email||"",t.postcode||"",t.course_id||"",t.call_slot_iso?new Date(t.call_slot_iso).toLocaleString("en-GB"):""]),n=[["Name","Phone","Email","Postcode","Course","Slot"],...s].map(t=>t.map(_=>`"${String(_).replace(/"/g,'""')}"`).join(",")).join(`
2`),a=new Blob([n],{type:"text/csv;charset=utf-8;"}),l=URL.createObjectURL(a),o=document.createElement("a");o.href=l,o.download=`no-show-call-bookings-${new Date().toISOString().slice(0,10)}.csv`,o.click(),URL.revokeObjectURL(l),r.success(`Downloaded ${h.length} no-show contacts`)},variant:"outline",size:"sm",disabled:p||h.length===0,children:[e.jsx(D,{className:"h-4 w-4 mr-2"}),"No-Show Report (",h.length,")"]}),e.jsxs(c,{onClick:()=>{const s=m.map(t=>[t.first_name||"",t.last_name||"",t.phone||"",t.email||"",t.postcode||""]),n=[["First Name","Last Name","Mobile","Email","Postcode"],...s].map(t=>t.map(_=>`"${String(_).replace(/"/g,'""')}"`).join(",")).join(`
3`),a=new Blob([n],{type:"text/csv;charset=utf-8;"}),l=URL.createObjectURL(a),o=document.createElement("a");o.href=l,o.download=`awaiting-outcome-call-bookings-${new Date().toISOString().slice(0,10)}.csv`,o.click(),URL.revokeObjectURL(l),r.success(`Downloaded ${m.length} awaiting-outcome contacts`)},variant:"outline",size:"sm",disabled:p||m.length===0,children:[e.jsx(D,{className:"h-4 w-4 mr-2"}),"Awaiting Outcome (",m.length,")"]}),e.jsxs(c,{onClick:y,variant:"outline",size:"sm",disabled:p,children:[e.jsx(K,{className:`h-4 w-4 mr-2 ${p?"animate-spin":""}`}),"Refresh"]})]})]}),(()=>{const s=i==="upcoming"?N:i==="past"?m:i==="attended"?A:i==="noshow"?h:d,n=i==="upcoming"?"Upcoming":i==="past"?"Past (awaiting outcome)":i==="attended"?"Attended":i==="noshow"?"No-shows":"All bookings";return e.jsxs(I,{children:[e.jsxs(G,{className:"flex flex-row items-center justify-between gap-3 flex-wrap",children:[e.jsxs(V,{className:i==="attended"?"text-green-700":"",children:[i==="attended"&&"✓ ",n," (",s.length,")"]}),e.jsxs(q,{value:i,onValueChange:a=>z(a),children:[e.jsx(H,{className:"w-[180px] h-9",children:e.jsx(X,{})}),e.jsxs(Y,{children:[e.jsxs(u,{value:"upcoming",children:["Upcoming (",N.length,")"]}),e.jsxs(u,{value:"past",children:["Past — awaiting outcome (",m.length,")"]}),e.jsxs(u,{value:"attended",children:["Attended (",A.length,")"]}),e.jsxs(u,{value:"noshow",children:["No-shows (",h.length,")"]}),e.jsxs(u,{value:"all",children:["All (",d.length,")"]})]})]})]}),e.jsx(W,{children:p?e.jsx("p",{className:"text-muted-foreground",children:"Loading…"}):s.length===0?e.jsx("p",{className:"text-muted-foreground",children:"Nothing to show in this view."}):i==="upcoming"?e.jsx("div",{className:"space-y-6",children:Array.from(f.entries()).map(([a,l])=>e.jsxs("div",{children:[e.jsx("h3",{className:"font-bold text-sm uppercase tracking-wider text-muted-foreground mb-3",children:a}),e.jsx("div",{className:"space-y-3",children:l.map(S)})]},a))}):e.jsx("div",{className:`space-y-3 ${i==="attended"?"opacity-80":""}`,children:s.map(S)})})]})})()]})})};export{je 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.