1import{a9 as J,n as W,Q as X,r as i,u as V,j as e,B as F,I as Z,O as ee,X as se,b as E,ao as ae}from"./index-D2rUcUpe.js";import{u as te}from"./useMutation-N7h9ZAvw.js";import{H as re}from"./Helmet-D7MYuSoa.js";import{C as f,c as g}from"./card-Bto263fv.js";import{C as ne}from"./checkbox-BmaTvz5L.js";import{S as oe}from"./SignaturePad-x85j_pKw.js";import{L as j}from"./loader-circle-BLb9ftDd.js";import{C as T}from"./circle-check-D-x_fqZ5.js";import{C as R}from"./credit-card-BvSTV0g4.js";import{P as le}from"./pen-line-QPIFyMNl.js";import{C as ie}from"./camera-CUIzJ51Y.js";const q="https://gateway.sumup.com/gateway/ecom/card/v2/sdk.js";function ce(){return typeof window>"u"||window.SumUpCard?Promise.resolve():new Promise((d,b)=>{const n=document.querySelector(`script[src="${q}"]`);if(n){n.addEventListener("load",()=>d()),n.addEventListener("error",()=>b(new Error("Failed to load card widget")));return}const o=document.createElement("script");o.src=q,o.async=!0,o.onload=()=>d(),o.onerror=()=>b(new Error("Failed to load card widget")),document.head.appendChild(o)})}const A=d=>new Intl.NumberFormat("en-GB",{style:"currency",currency:"GBP"}).format(d),B=["I'm happy with the finished work","The work area has been left clean and tidy","Any waste and offcuts have been dealt with as agreed"];function Ne(){const[,d]=J("/job/:token/sign"),[,b]=W(),n=(d==null?void 0:d.token)||"",{toast:o}=X(),[D,I]=i.useState(!1),[L,_]=i.useState(()=>B.map(()=>!1)),[w,M]=i.useState(""),[U,G]=i.useState(""),[y,K]=i.useState(null),[v,C]=i.useState([]),[N,$]=i.useState(!1),k=i.useRef(null),[u,m]=i.useState("idle"),[O,x]=i.useState(null),h=V({queryKey:[`/api/job/${n}/customer`],enabled:!!n,staleTime:0,refetchOnMount:"always"});i.useEffect(()=>()=>{var s;try{(s=k.current)==null||s.unmount()}catch{}},[]);const z=async()=>{var s;x(null),m("loading");try{if(await ce(),!window.SumUpCard)throw new Error("Card widget unavailable");const t=await E(`/api/job/${n}/balance-checkout`,{method:"POST"});try{(s=k.current)==null||s.unmount()}catch{}k.current=window.SumUpCard.mount({id:"sumup-card-balance",checkoutId:t.id,showFooter:!1,onLoad:()=>m("ready"),onResponse:async(r,c)=>{if(r==="success"){m("processing");try{await E(`/api/job/${n}/balance-confirm`,{method:"POST",data:{checkoutId:t.id}}),m("done"),h.refetch(),o({title:"Payment received",description:"Thank you â your balance has been paid in full."})}catch(l){m("error"),x((l==null?void 0:l.message)||"Could not confirm payment")}}else r==="error"||r==="invalid"?(m("error"),x(c&&(c.message||c.error_message)||"Card payment failed. Please try again.")):(r==="cancel"||r==="close"||r==="aborted")&&(m("idle"),x("Payment was cancelled. You can try again below."))}})}catch(t){m("error"),x((t==null?void 0:t.message)||"Could not start card payment")}},S=te({mutationFn:()=>E(`/api/job/${n}/complete`,{method:"POST",data:{signature:y&&y.replace(/^data:image\/[a-z+]+;base64,/i,""),signName:w.trim(),notes:U.trim()||null,checks:B.map((s,t)=>({label:s,checked:L[t]})),media:v}}),onSuccess:()=>{I(!0),C([]),h.refetch(),ae.invalidateQueries({queryKey:[`/api/job/${n}`]}),o({title:"Signed off",description:"Thank you. The office has been notified that the job is complete."})},onError:s=>o({title:"Could not sign off",description:s==null?void 0:s.message,variant:"destructive"})}),H=()=>{if(!w.trim()){o({title:"Please enter your name",variant:"destructive"});return}if(!y){o({title:"Please sign in the box",variant:"destructive"});return}S.mutate()},Q=async s=>{const t=Array.from(s.target.files||[]);if(s.target.value="",t.length!==0){$(!0);try{for(const r of t){const c=new FormData;c.append("file",r);const l=await fetch(`/api/job/${n}/media`,{method:"POST",body:c});if(!l.ok){const p=await l.json().catch(()=>({}));throw new Error((p==null?void 0:p.error)||"Upload failed")}const P=await l.json();C(p=>[...p,P])}}catch(r){o({title:"Photo upload failed",description:r==null?void 0:r.message,variant:"destructive"})}finally{$(!1)}}};if(h.isLoading)return e.jsxs("div",{className:"max-w-2xl mx-auto px-4 py-16 text-center text-gray-500",children:[e.jsx(j,{className:"h-6 w-6 animate-spin mx-auto mb-2"})," Loadingâ¦"]});if(h.isError||!h.data)return e.jsxs("div",{className:"max-w-2xl mx-auto px-4 py-16 text-center",children:[e.jsx("h1",{className:"text-xl font-semibold mb-2",children:"Job not found"}),e.jsx("p",{className:"text-gray-500",children:"This link is invali
1d or has expired. Please contact Northwest Floors."})]});const a=h.data,Y=a.status==="done"||!!a.completedAt||D;return e.jsxs("div",{className:"max-w-2xl mx-auto px-4 py-8 space-y-5",children:[e.jsxs(re,{children:[e.jsx("title",{children:"Sign off your job â Northwest Floors"}),e.jsx("meta",{name:"robots",content:"noindex"})]}),e.jsxs("div",{className:"text-center",children:[e.jsx("img",{src:"/images/nw-floors-logo.png?v=2",alt:"Northwest Floors",className:"h-11 mx-auto mb-3 object-contain"}),a.jobNumber&&e.jsxs("p",{className:"text-sm text-gray-500",children:["Job no: ",a.jobNumber]})]}),a.workSummary&&e.jsx(f,{children:e.jsx(g,{className:"pt-6",children:e.jsx("h2",{className:"font-semibold text-lg text-center",children:a.workSummary})})}),a.balancePaidAt||u==="done"?e.jsx(f,{className:"border-green-300",children:e.jsx(g,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-center gap-2 text-green-700 bg-green-50 rounded-md p-4 text-sm",children:[e.jsx(T,{className:"h-5 w-5"}),"Your final balance",a.balanceAmount?` of ${A(a.balanceAmount)}`:""," has been paid. Thank you!"]})})}):a.balanceAmount&&a.balanceAmount>0?e.jsx(f,{className:"border-primary",children:e.jsxs(g,{className:"pt-6 space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(R,{className:"h-5 w-5 text-primary"}),e.jsx("h3",{className:"font-semibold text-lg",children:"Pay your final balance"})]}),e.jsxs("div",{className:"flex items-baseline justify-between border-b pb-3",children:[e.jsx("span",{className:"text-sm text-gray-600",children:"Balance due now"}),e.jsx("span",{className:"text-2xl font-bold",children:A(a.balanceAmount)})]}),a.canPayBalance?e.jsxs(e.Fragment,{children:[u==="idle"||u==="error"?e.jsxs(F,{size:"lg",className:"w-full",onClick:z,children:[e.jsx(R,{className:"h-4 w-4 mr-2"})," Pay ",A(a.balanceAmount)," securely by card"]}):null,u==="loading"&&e.jsxs("div",{className:"flex items-center justify-center gap-2 text-sm text-gray-500 py-4",children:[e.jsx(j,{className:"h-4 w-4 animate-spin"})," Loading secure card formâ¦"]}),e.jsx("div",{id:"sumup-card-balance",className:u==="ready"||u==="processing"?"":"hidden"}),u==="processing"&&e.jsxs("div",{className:"flex items-center justify-center gap-2 text-sm text-gray-500 py-2",children:[e.jsx(j,{className:"h-4 w-4 animate-spin"})," Confirming your paymentâ¦"]}),O&&e.jsx("p",{className:"text-sm text-red-600",children:O}),e.jsx("p",{className:"text-xs text-gray-400 text-center",children:"Payments are processed securely by SumUp. We never see your card details."})]}):e.jsx("p",{className:"text-sm text-gray-500",children:"Card payments aren't available right now. Please contact Northwest Floors on 01928 263 265 to settle your balance."})]})}):null,Y?e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-center gap-2 text-green-700 bg-green-50 rounded-md p-4 text-sm",children:[e.jsx(T,{className:"h-5 w-5"}),"Thank you â this job has been signed off as complete",a.customerSignName?` by ${a.customerSignName}`:"",a.completedAt?` on ${new Date(a.completedAt).toLocaleDateString("en-GB")}`:"","."]}),a.completionMedia.length>0&&e.jsx(f,{children:e.jsxs(g,{className:"pt-6",children:[e.jsx("h3",{className:"font-semibold mb-3",children:"Photos of the finished work"}),e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 gap-2",children:a.completionMedia.map(s=>s.type==="video"?e.jsx("video",{src:s.url,controls:!0,className:"w-full h-32 object-cover rounded-md border bg-black/5"},s.url):e.jsx("a",{href:s.url,target:"_blank",rel:"noreferrer",children:e.jsx("img",{src:s.url,alt:"Completion",className:"w-full h-32 object-cover rounded-md border"})},s.url))})]})})]}):e.jsx(f,{className:"border-primary",children:e.jsxs(g,{className:"pt-6 space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(le,{className:"h-5 w-5 text-primary"}),e.jsx("h3",{className:"font-semibold text-lg",children:"Customer sign-off"})]}),e.jsx("p",{className:"text-sm text-gray-600",children:"Thank you for choosing Northwest Floors. Now that the work is finished, please check it over, tick the boxes below to confirm you're happy, then add your name and sign. This is your record that the job has been completed to your satisfaction â we'll email you a signed copy for your records."}),e.jsx("div",{className:"space-y-2",children:B.map((s,t)=>e.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[e.jsx(ne,{checked:L[t],onCheckedChange:r=>_(c=>c.map((l,P)=>P===t?!!r:l)),className:"mt-0.5"}),e.jsx("span",{children:s})]},t))}),e.jsxs("div",{children:[e.jsx("label",{className:"text-sm font-medium block mb-1",children:"Your name"}),e.jsx(Z,{value:w,onChange:s=>M(s.target.value),placeholder:"Full name"})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"text-sm font-medium block mb-1",children:["Comments ",e.jsx("span",{className:"text-gray-400",children:"(optional)"})]}),e.jsx(ee,{rows:2,value:U,onChange:s=>G(s.target.value),placeholder:"Anything you'd like to add"})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"text-sm font-medium block mb-1",children:["Photos of the finished work ",e.jsx("span",{className:"text-gray-400",children:"(optional)"})]}),v.length>0&&e.jsx("div",{className:"grid grid-cols-3 sm:grid-cols-4 gap-2 mb-2",children:v.map((s,t)=>e.jsxs("div",{className:"relative",children:[s.type==="video"?e.jsx("video",{src:s.url,className:"w-full h-20 object-cover rounded-md border bg-black/5"}):e.jsx("img",{src:s.url,alt:"Completion",className:"w-full h-20 object-cover rounded-md border"}),e.jsx("button",{type:"button",onClick:()=>C(r=>r.filter((c,l)=>l!==t)),className:"absolute -top-2 -right-2 bg-white border rounded-full p-0.5 shadow-sm text-gray-600 hover:text-red-600","aria-label":"Remove photo",children:e.jsx(se,{className:"h-3.5 w-3.5"})})]},s.url))}),e.jsx(F,{asChild:!0,variant:"outline",className:"w-full sm:w-auto",disabled:N,children:e.jsxs("label",{htmlFor:"completion-photos",className:"cursor-pointer",children:[N?e.jsxs(e.Fragment,{children:[e.jsx(j,{className:"h-4 w-4 mr-2 animate-spin"})," Uploadingâ¦"]}):e.jsxs(e.Fragment,{children:[e.jsx(ie,{className:"h-4 w-4 mr-2"})," Add photos"]}),e.jsx("input",{id:"completion-photos",type:"file",accept:"image/*,video/*",multiple:!0,className:"hidden",onChange:Q,disabled:N})]})})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-sm font-medium block mb-1",children:"Signature"}),e.jsx(oe,{onChange:K})]}),e.jsx(F,{size:"lg",className:"w-full",onClick:H,disabled:S.isPending||N,children:S.isPending?e.jsxs(e.Fragment,{children:[e.jsx(j,{className:"h-4 w-4 mr-2 animate-spin"})," Submittingâ¦"]}):e.jsxs(e.Fragment,{children:[e.jsx(T,{className:"h-4 w-4 mr-2"})," Confirm & sign off"]})})]})}),e.jsx("div",{className:"text-center",children:e.jsx("button",{type:"button",onClick:()=>b(`/job/${n}`),className:"text-sm text-gray-400 hover:text-gray-600 underline",children:"Back to job sheet"})})]})}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.