PageSourceSearch

https://smb1001.ai/assets/proposal-microsite-CPVkDaJr.js

js smb1001.ai collected 2026-10-05 15:08:12 UTC 14,866 bytes, 1 lines download raw bytes

1import{z as ee,n as se,l as te,m as M,j as e,L as D}from"./index-CYWzIoL_.js";import{b as l}from"./vendor-recharts-CNbq9ujH.js";import{c as p,b as x}from"./card-4V0TQtKc.js";import{B as u}from"./button-CKTFDFlx.js";import{I as N}from"./input-aYsR2GAX.js";import{L as f}from"./label-Dmr4QUlJ.js";import{C as G}from"./checkbox-Bq2Y5IKj.js";import{S as re}from"./separator-YNqh6GoB.js";import{B as ae}from"./badge-hGuU_1lf.js";import{S as ne}from"./signature-pad-Cr-52p0n.js";import{l as oe}from"./currency-locale-DNKyBopl.js";import{L as ie}from"./lock-C0Ry-sCi.js";import{C as A}from"./circle-x-D62yCLPF.js";import{S as le}from"./shield-4y0JuBi_.js";import{C as O}from"./circle-check-big-DJDiQ2bd.js";import{D as de}from"./download-DZBUAaJp.js";import{F as ce}from"./file-text-5H6scefd.js";import{C as me}from"./chevron-up-DfIIpUd0.js";import{C as pe}from"./chevron-down-DSXWubwf.js";import{D as xe}from"./dollar-sign-Cfqyqn0o.js";import"./animations-8dOrGFrp.js";import"./index-ZLblNrkv.js";import"./check-Duy9todO.js";import"./pen-SceGjPVM.js";import"./type-BpIiFsM7.js";function E(h,a="AUD"){return new Intl.NumberFormat(oe(a),{style:"currency",currency:a}).format(h/100)}async function ue(h,a){const m={};a&&(m["X-Proposal-Password"]=a);const d=await fetch(`/api/public/proposals/${h}`,{headers:m});if(!d.ok){const j=await d.json().catch(()=>({message:d.statusText}));throw Object.assign(new Error(j.message||"Failed to load proposal"),{status:d.status,requiresPassword:j.requiresPassword})}return d.json()}function Ue(){const[,h]=ee("/proposal/:token"),a=h?.token??"",{toast:m}=se(),[d,j]=l.useState(""),[c,z]=l.useState(""),[J,L]=l.useState(!1),[y,K]=l.useState(new Set),[Q,v]=l.useState(!1),[i,b]=l.useState({name:"",email:"",title:"",agreed:!1}),[I,Y]=l.useState(null),[$,_]=l.useState(new Set([0])),[q,V]=l.useState(!1),{data:r,isLoading:k,isError:C,error:P,refetch:R}=te({queryKey:["/api/public/proposals",a,c],queryFn:()=>ue(a,c),enabled:!!a,retry:!1}),w=C&&(P?.status===401||P?.message?.toLowerCase().includes("password")),S=M({mutationFn:async s=>{const t={"Content-Type":"application/json"};c&&(t["X-Proposal-Password"]=c);const n=await fetch(`/api/public/proposals/${a}/accept`,{method:"POST",headers:t,body:JSON.stringify(s)});if(!n.ok){const o=await n.json().catch(()=>({message:n.statusText}));throw new Error(o.message||"Failed to accept proposal")}return n.json()},onSuccess:()=>{R(),v(!1),m({title:"Proposal accepted",description:"You will receive a confirmation email shortly."})},onError:s=>m({title:"Failed to accept",description:s.message,variant:"destructive"})}),B=M({mutationFn:async()=>{const s={};c&&(s["X-Proposal-Password"]=c);const t=await fetch(`/api/public/proposals/${a}/reject`,{method:"POST",headers:s});if(!t.ok){const n=await t.json().catch(()=>({message:t.statusText}));throw new Error(n.message||"Failed to decline")}return t.json()},onSuccess:()=>{R(),V(!0),m({title:"Proposal declined"})},onError:s=>m({title:"Failed",description:s.message,variant:"destructive"})}),H=r?.lineItems?.filter(s=>!s.isOptional).reduce((s,t)=>s+t.unitPrice*t.quantity,0)??0,W=r?.lineItems?.filter(s=>s.isOptional&&y.has(s.id)).reduce((s,t)=>s+t.unitPrice*t.quantity,0)??0,Z=H+W,F=r?.expiresAt?new Date(r.expiresAt)<new Date:!1,g=r?.status==="accepted",U=r?.status==="rejected";l.useEffect(()=>{r&&!w&&fetch(`/api/public/proposals/${a}/view`,{method:"POST"}).catch(()=>{})},[a,r,w]);function X(){L(!0),z(d)}if(k)return e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-background text-foreground",children:e.jsx(D,{className:"h-8 w-8 animate-spin text-purple-600 dark:text-purple-300"})});if(w){const s=J&&C;return e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-gray-50",children:e.jsx(p,{className:"w-full max-w-sm",children:e.jsxs(x,{className:"p-8 space-y-4",children:[e.jsx("div",{className:"flex justify-center mb-2",children:e.jsx("div",{className:"w-12 h-12 bg-purple-100 dark:bg-purple-500/15 rounded-full flex items-center justify-center",children:e.jsx(ie,{className:"h-5 w-5 text-purple-600 dark:text-purple-300"})})}),e.jsx("h2",{className:"text-center text-lg font-semibold text-foreground",children:"This proposal is protected"}),e.jsx("p",{className:"text-center text-sm text-muted-foreground",children:"Please enter the password provided by the sender."}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(f,{htmlFor:"pw",children:"Password"}),e.jsx(N,{id:"pw",type:"password",value:d,onChange:t=>{j(t.target.value),L(!1)},onKeyDown:t=>t.key==="Enter"&&X(),"data-testid":"input-proposal-password","aria-invalid":s})]}),s&&e.jsx("p",{className:"text-sm text-red-600 dark:text-red-300 text-center","data-testid":"text-password-error",children:"Incorrect password. Please try again."}),e.jsx(u,{className:"w-full bg-purple-600 hover:bg-purple-700",onClick:X,disabled:!d||k,"data-testid":"button-unlock-proposal",children:k?e.jsx(D,{className:"h-4 w-4 animate-spin"}):"Unlock Proposal"})]})})})}return C&&!w?e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-background text-foreground",children:e.jsx(p,{className:"w-full max-w-sm",children:e.jsxs(x,{className:"p-8 text-center space-y-3",children:[e.jsx(A,{className:"h-10 w-10 text-red-500 dark:text-red-300 mx-auto"}),e.jsx("h2",{className:"text-lg font-semibold text-foreground",children:"Proposal not found"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:P?.message||"This link may have expired or is invali
1d."})]})})}):r?e.jsxs("div",{className:"min-h-screen bg-background text-foreground",children:[e.jsx("div",{className:"bg-purple-700 py-10 px-4",children:e.jsxs("div",{className:"max-w-3xl mx-auto text-white",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(le,{className:"h-5 w-5 opacity-70"}),e.jsx("span",{className:"text-sm opacity-70",children:"CyberGrape Proposal"})]}),e.jsx("h1",{className:"text-2xl font-bold mb-1",children:r.title}),e.jsxs("p",{className:"opacity-80 text-sm",children:["Prepared for ",r.recipientName,r.recipientCompany?` · ${r.recipientCompany}`:""]}),r.senderName&&e.jsxs("p",{className:"opacity-70 text-sm mt-1",children:["From ",r.senderName,r.senderTitle?`, ${r.senderTitle}`:""]})]})}),e.jsxs("div",{className:"max-w-3xl mx-auto px-4 py-8 space-y-6",children:[g&&e.jsxs("div",{className:"flex items-start gap-3 p-4 rounded-lg bg-green-50 dark:bg-green-500/10 border border-green-200 dark:border-green-500/30",children:[e.jsx(O,{className:"h-5 w-5 text-green-600 dark:text-green-300 shrink-0 mt-0.5"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"font-medium text-green-800 dark:text-green-200",children:"Proposal accepted"}),r.signedAt&&e.jsxs("p",{className:"text-sm text-green-700 dark:text-green-300",children:["Signed on ",new Date(r.signedAt).toLocaleString(),r.signedBy?` by ${r.signedBy}`:""]})]}),e.jsx("a",{href:`/api/public/proposals/${a}/pdf${c?"?pw=1":""}`,target:"_blank",rel:"noreferrer",className:"shrink-0",onClick:s=>{if(c){s.preventDefault();const t={"X-Proposal-Password":c};fetch(`/api/public/proposals/${a}/pdf`,{headers:t}).then(n=>n.blob()).then(n=>{const o=URL.createObjectURL(n),T=document.createElement("a");T.href=o,T.download="signed-proposal.pdf",T.click(),setTimeout(()=>URL.revokeObjectURL(o),5e3)}).catch(()=>m({title:"Download failed",variant:"destructive"}))}},children:e.jsxs(u,{size:"sm",variant:"outline",className:"text-green-700 dark:text-green-300 border-green-300 dark:border-green-500/40 hover:bg-green-50 dark:hover:bg-green-500/10","data-testid":"button-download-pdf",children:[e.jsx(de,{className:"h-3.5 w-3.5 mr-1.5"}),"Download PDF"]})})]}),(U||q)&&e.jsxs("div",{className:"flex items-center gap-3 p-4 rounded-lg bg-red-50 dark:bg-red-500/10 border border-red-200 dark:border-red-500/30",children:[e.jsx(A,{className:"h-5 w-5 text-red-600 dark:text-red-300 shrink-0"}),e.jsx("p",{className:"font-medium text-red-800 dark:text-red-200",children:"This proposal was declined."})]}),F&&!g&&e.jsxs("div",{className:"flex items-center gap-3 p-4 rounded-lg bg-amber-50 dark:bg-amber-500/10 border border-amber-200 dark:border-amber-500/30",children:[e.jsx(ce,{className:"h-5 w-5 text-amber-600 dark:text-amber-300 shrink-0"}),e.jsxs("p",{className:"font-medium text-amber-800 dark:text-amber-200",children:["This proposal expired on ",new Date(r.expiresAt).toLocaleDateString(),"."]})]}),r.introText&&e.jsx(p,{children:e.jsx(x,{className:"p-6 prose prose-sm max-w-none text-foreground dark:prose-invert leading-relaxed whitespace-pre-wrap",children:r.introText})}),r.sections.map((s,t)=>e.jsxs(p,{children:[e.jsx("button",{className:"w-full text-left",onClick:()=>_(n=>{const o=new Set(n);return o.has(t)?o.delete(t):o.add(t),o}),children:e.jsxs("div",{className:"flex items-center justify-between p-5",children:[e.jsx("h3",{className:"font-semibold text-foreground",children:s.title}),$.has(t)?e.jsx(me,{className:"h-4 w-4 text-muted-foreground"}):e.jsx(pe,{className:"h-4 w-4 text-muted-foreground"})]})}),$.has(t)&&s.content&&e.jsx(x,{className:"px-5 pb-5 pt-0 text-foreground text-sm leading-relaxed whitespace-pre-wrap border-t border-border",children:s.content})]},s.id)),r.lineItems.length>0&&e.jsx(p,{children:e.jsxs(x,{className:"p-6 space-y-4",children:[e.jsxs("h3",{className:"font-semibold text-foreground flex items-center gap-2",children:[e.jsx(xe,{className:"h-4 w-4 text-purple-600 dark:text-purple-300"}),"Investment Summary"]}),e.jsx("div",{className:"space-y-2",children:r.lineItems.filter(s=>!s.isOptional).map(s=>e.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border last:border-0",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-foreground",children:s.description}),s.quantity>1&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Qty: ",s.quantity]})]}),e.jsx("span",{className:"font-medium text-foreground",children:E(s.unitPrice*s.quantity,r.currency)})]},s.id))}),r.lineItems.some(s=>s.isOptional)&&e.jsxs(e.Fragment,{children:[e.jsx(re,{}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-foreground mb-2",children:"Optional Add-ons"}),e.jsx("div",{className:"space-y-2",children:r.lineItems.filter(s=>s.isOptional).map(s=>e.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border last:border-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[!g&&!F&&e.jsx(G,{id:`opt-${s.id}`,checked:y.has(s.id),onCheckedChange:t=>K(n=>{const o=new Set(n);return t?o.add(s.id):o.delete(s.id),o}),"data-testid":`checkbox-optional-${s.id}`}),e.jsx("label",{htmlFor:`opt-${s.id}`,className:"text-sm text-foreground cursor-pointer",children:s.description}),e.jsx(ae,{variant:"outline",className:"text-xs",children:"Optional"})]}),e.jsx("span",{className:"text-foreground",children:E(s.unitPrice*s.quantity,r.currency)})]},s.id))})]})]}),e.jsxs("div",{className:"flex justify-between items-center pt-2 border-t border-border",children:[e.jsx("span",{className:"font-semibold text-foreground",children:"Total"}),e.jsx("span",{className:"text-lg font-bold text-purple-700 dark:text-purple-300",children:E(Z,r.currency)})]}),r.expiresAt&&!g&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Valid until ",new Date(r.expiresAt).toLocaleDateString()]})]})}),!g&&!U&&!q&&!F&&e.jsx(p,{children:e.jsx(x,{className:"p-6 space-y-4",children:Q?e.jsxs("div",{className:"space-y-4",children:[e.jsx("h3",{className:"font-semibold text-foreground",children:"Electronic Signature"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"By completing this form, you confirm your acceptance of this proposal on behalf of yourself or your organisation."}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(f,{htmlFor:"sig-name",children:"Full Name *"}),e.jsx(N,{id:"sig-name",value:i.name,onChange:s=>b(t=>({...t,name:s.target.value})),"data-testid":"input-sig-name"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(f,{htmlFor:"sig-email",children:"Email *"}),e.jsx(N,{id:"sig-email",type:"email",value:i.email,onChange:s=>b(t=>({...t,email:s.target.value})),"data-testid":"input-sig-email"})]}),e.jsxs("div",{className:"col-span-2 space-y-1",children:[e.jsx(f,{htmlFor:"sig-title",children:"Job Title"}),e.jsx(N,{id:"sig-title",value:i.title,onChange:s=>b(t=>({...t,title:s.target.value})),"data-testid":"input-sig-title"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(f,{children:"Signature *"}),e.jsx("div",{className:"bg-white border rounded-lg p-3",children:e.jsx(ne,{onChange:Y,width:560,height:150,disabled:!1})}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Draw your signature or type your name. Your signature constitutes a legally binding electronic signature."})]}),e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(G,{id:"sig-agree",checked:i.agreed,onCheckedChange:s=>b(t=>({...t,agreed:!!s})),"data-testid":"checkbox-agree"}),e.jsx("label",{htmlFor:"sig-agree",className:"text-sm text-foreground leading-relaxed cursor-pointer",children:"I confirm that I have read and agree to all terms in this proposal, and I am authorised to sign on behalf of my organisation."})]}),e.jsxs("div",{className:"flex gap-3",children:[e.jsx(u,{variant:"outline",onClick:()=>v(!1),children:"Cancel"}),e.jsxs(u,{className:"flex-1 bg-purple-600 hover:bg-purple-700 text-white",onClick:()=>S.mutate({signatoryName:i.name,signatoryEmail:i.email,signatoryTitle:i.title,signatureData:I,selectedOptionals:Array.from(y)}),disabled:S.isPending||!i.name||!i.email||!I||!i.agreed,"data-testid":"button-submit-signature",children:[S.isPending?e.jsx(D,{className:"h-4 w-4 mr-2 animate-spin"}):e.jsx(O,{className:"h-4 w-4 mr-2"}),"Confirm & Accept"]})]})]}):e.jsxs("div",{className:"flex flex-col sm:flex-row gap-3",children:[e.jsxs(u,{className:"flex-1 bg-purple-600 hover:bg-purple-700 text-white",onClick:()=>v(!0),"data-testid":"button-accept-proposal",children:[e.jsx(O,{className:"h-4 w-4 mr-2"}),"Accept Proposal"]}),e.jsxs(u,{variant:"outline",className:"flex-1 text-red-600 dark:text-red-300 border-red-200 dark:border-red-500/40 hover:bg-red-50 dark:hover:bg-red-500/10",onClick:()=>{confirm("Are you sure you want to decline this proposal?")&&B.mutate()},disabled:B.isPending,"data-testid":"button-reject-proposal",children:[e.jsx(A,{className:"h-4 w-4 mr-2"}),"Decline"]})]})})}),e.jsxs("div",{className:"text-center text-xs text-gray-400 pb-6",children:[e.jsxs("p",{children:["Powered by ",e.jsx("a",{href:"https://cybergrape.io",className:"text-purple-600 dar
1k:text-purple-300 hover:underline",target:"_blank",rel:"noreferrer",children:"CyberGrape GRC"})]}),e.jsx("p",{className:"mt-1",children:"This is a secure, confidential proposal."})]})]})]}):null}export{Ue 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.