Spaces:
Running
Running
| import{c as R,j as e,T as w,C as E,a as k}from"./index-B6LgHwxl.js";import{r as g,R as $}from"./vendor-C1HQAMsB.js";import{u as D}from"./LocaleProvider-Bp4ehmC6.js";import{G as M}from"./grip-vertical--tFW19VW.js";/** | |
| * @license lucide-react v0.555.0 - ISC | |
| * | |
| * This source code is licensed under the ISC license. | |
| * See the LICENSE file in the root directory of this source tree. | |
| */const S=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],T=R("download",S),z=({item:t,side:c,draggable:x=!1,onDragStart:m,onDragOver:n,onDrop:d,className:h="",highlighted:j=!1})=>{const{formatCurrency:o,formatDate:y}=D(),f=u=>{m&&(m(u,t),u.dataTransfer.effectAllowed="link")},p={matched:"border-green-500 bg-green-50 dark:bg-green-900/20",unmatched:"border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800",discrepancy:"border-orange-500 bg-orange-50 dark:bg-orange-900/20",pending:"border-blue-500 bg-blue-50 dark:bg-blue-900/20",reconciled:"border-green-500 bg-green-50 dark:bg-green-900/20"}[t.status]||"border-slate-200 bg-white",b=j?"ring-2 ring-blue-500 shadow-lg z-10":"";return e.jsxs("div",{draggable:x,onDragStart:f,onDragOver:n,onDrop:d,className:` | |
| relative p-3 rounded-lg border shadow-sm transition-all | |
| ${p} ${b} ${h} | |
| ${x?"cursor-grab active:cursor-grabbing hover:shadow-md":""} | |
| `,children:[e.jsxs("div",{className:"flex justify-between items-start gap-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[x&&e.jsx("div",{className:"text-slate-400 cursor-grab active:cursor-grabbing",children:e.jsx(M,{size:14})}),e.jsxs("div",{children:[e.jsx("div",{className:"font-semibold text-slate-800 dark:text-slate-200",children:o(t.amount,t.currency)}),e.jsx("div",{className:"text-xs text-slate-500 font-mono mt-0.5",children:y(t.date)})]})]}),t.status==="discrepancy"&&e.jsx(w,{size:16,className:"text-orange-500 flex-shrink-0"})]}),e.jsx("div",{className:"mt-2 text-xs text-slate-600 dark:text-slate-400 truncate",title:t.notes||"No description",children:t.notes||"Transaction"}),e.jsx("div",{id:`node-${t.id}`,className:`absolute top-1/2 w-2 h-2 rounded-full bg-slate-400 transform -translate-y-1/2 | |
| ${c==="left"?"-right-1 translate-x-1/2":"-left-1 -translate-x-1/2"} | |
| `})]})},A=({bankItems:t,ledgerItems:c,onMatch:x,className:m=""})=>{const[n,d]=g.useState(null),[h,j]=g.useState({x:0,y:0}),o=g.useRef(null),y=$.useMemo(()=>{const s=[];return t.forEach(r=>{c.forEach(l=>{Math.abs(r.amount-l.amount)<.01&&s.push({start:r.id,end:l.id,score:.95})})}),s},[t,c]),f=(s,r)=>{d(r),s.dataTransfer.setData("text/plain",r.id),s.dataTransfer.effectAllowed="link"},p=s=>{if(s.preventDefault(),s.dataTransfer.dropEffect="link",o.current){const r=o.current.getBoundingClientRect();j({x:s.clientX-r.left,y:s.clientY-r.top})}},b=(s,r,l)=>{s.preventDefault(),n&&n.id!==r.id&&x(n.id,r.id),d(null)},[u,N]=g.useState({}),a=()=>{if(!o.current)return;const s={},r=o.current.getBoundingClientRect();[...t,...c].forEach(l=>{var C;const i=(C=o.current)==null?void 0:C.querySelector(`#node-${l.id}`);if(i){const v=i.getBoundingClientRect();s[l.id]={x:v.left-r.left+v.width/2,y:v.top-r.top+v.height/2}}}),N(s)};return $.useLayoutEffect(()=>{const s=setTimeout(a,0);return window.addEventListener("resize",a),()=>{window.removeEventListener("resize",a),clearTimeout(s)}},[t,c]),e.jsxs("div",{className:`relative flex gap-8 h-[600px] ${m}`,ref:o,onDragOver:p,children:[e.jsxs("svg",{className:"absolute inset-0 w-full h-full pointer-events-none z-10 overflow-visible",children:[e.jsxs("defs",{children:[e.jsx("marker",{id:"arrowhead",markerWidth:"10",markerHeight:"7",refX:"9",refY:"3.5",orient:"auto",children:e.jsx("polygon",{points:"0 0, 10 3.5, 0 7",fill:"#94a3b8"})}),e.jsx("marker",{id:"arrowhead-active",markerWidth:"10",markerHeight:"7",refX:"9",refY:"3.5",orient:"auto",children:e.jsx("polygon",{points:"0 0, 10 3.5, 0 7",fill:"#3b82f6"})})]}),y.map((s,r)=>{const l=u[s.start],i=u[s.end];return!l||!i?null:e.jsxs("g",{children:[e.jsx("path",{d:`M ${l.x} ${l.y} C ${l.x+50} ${l.y}, ${i.x-50} ${i.y}, ${i.x} ${i.y}`,fill:"none",stroke:"#fbbf24",strokeWidth:"2",strokeDasharray:"5,5",className:"opacity-50"}),e.jsx("circle",{cx:(l.x+i.x)/2,cy:(l.y+i.y)/2,r:"10",fill:"#fbbf24",className:"opacity-80"}),e.jsx("text",{x:(l.x+i.x)/2,y:(l.y+i.y)/2,dy:"4",textAnchor:"middle",fill:"#fff",fontSize:"10",fontWeight:"bold",children:"?"})]},`match-${r}`)}),n&&(()=>{const s=u[n.id];return s?e.jsx("path",{d:`M ${s.x} ${s.y} C ${(s.x+h.x)/2} ${s.y}, ${(s.x+h.x)/2} ${h.y}, ${h.x} ${h.y}`,fill:"none",stroke:"#3b82f6",strokeWidth:"3",markerEnd:"url(#arrowhead-active)",className:"animate-pulse"}):null})()]}),e.jsxs("div",{className:"flex-1 flex flex-col gap-4 overflow-y-auto p-4 bg-slate-50 dark:bg-slate-900/50 rounded-xl border border-dashed border-slate-300 dark:border-slate-700",children:[e.jsx("h3",{className:"font-semibold text-slate-500 mb-2 uppercase text-xs tracking-wider sticky top-0 bg-slate-50 dark:bg-slate-900 py-2 z-10 backdrop-blur-sm bg-opacity-90",children:"Bank Feed"}),t.length===0&&e.jsx("div",{className:"text-slate-400 text-sm text-center italic py-10",children:"No unmatched items"}),t.map(s=>e.jsx(z,{item:s,side:"left",draggable:s.status!=="matched",onDragStart:f,onDragOver:r=>p(r),onDrop:r=>b(r,s)},s.id))]}),e.jsx("div",{className:"w-16 flex flex-col items-center justify-center gap-4 text-slate-300",children:e.jsx("div",{className:"w-0.5 h-full bg-slate-200 dark:bg-slate-800"})}),e.jsxs("div",{className:"flex-1 flex flex-col gap-4 overflow-y-auto p-4 bg-slate-50 dark:bg-slate-900/50 rounded-xl border border-dashed border-slate-300 dark:border-slate-700",children:[e.jsx("h3",{className:"font-semibold text-slate-500 mb-2 uppercase text-xs tracking-wider sticky top-0 bg-slate-50 dark:bg-slate-900 py-2 z-10 backdrop-blur-sm bg-opacity-90",children:"Internal Ledger"}),c.length===0&&e.jsx("div",{className:"text-slate-400 text-sm text-center italic py-10",children:"No unmatched items"}),c.map(s=>e.jsx(z,{item:s,side:"right",draggable:s.status!=="matched",onDragStart:f,onDragOver:r=>p(r),onDrop:r=>b(r,s)},s.id))]})]})},F=({items:t,onFlag:c,className:x=""})=>{const{formatCurrency:m,formatDate:n}=D();return e.jsxs("div",{className:`flex flex-col gap-3 ${x}`,children:[e.jsxs("h3",{className:"font-semibold text-slate-700 dark:text-slate-300 flex items-center gap-2",children:[e.jsx(w,{size:16,className:"text-orange-500"}),"Exceptions (",t.length,")"]}),e.jsxs("div",{className:"flex flex-col gap-2",children:[t.length===0&&e.jsx("div",{className:"text-sm text-slate-400 italic",children:"No exceptions found."}),t.map(d=>e.jsxs("div",{className:"p-3 bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-800 rounded-lg flex justify-between items-center group",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-slate-800 dark:text-slate-200",children:m(d.amount,d.currency)}),e.jsxs("div",{className:"text-xs text-slate-500",children:[d.source," • ",n(d.date)]}),e.jsx("div",{className:"text-xs text-orange-600 dark:text-orange-400 mt-1",children:d.notes||"Discrepancy detected"})]}),e.jsx("button",{onClick:()=>c(d.id),className:"opacity-0 group-hover:opacity-100 transition-opacity px-3 py-1.5 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded text-xs font-medium hover:bg-slate-50 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-300",children:"Flag"})]},d.id))]})]})},W=()=>{const[t,c]=g.useState(null),{formatCurrency:x,formatDate:m}=D(),[n,d]=g.useState([]),[h,j]=g.useState(!0),o=async()=>{try{j(!0);const a=await k.getReconciliationItems();d(Array.isArray(a)?a:[])}catch(a){console.error("Failed to load reconciliation items:",a)}finally{j(!1)}};g.useEffect(()=>{o()},[]);const y=async a=>{try{const s=n.find(r=>r.id===a);s&&(await k.reconcileTransaction(s.transactionId),d(r=>r.map(l=>l.id===a?{...l,status:"matched"}:l)),o())}catch(s){console.error(s)}},f=async a=>{try{const s=n.find(r=>r.id===a);s&&(await k.flagTransaction(s.transactionId,"User flagged from UI"),d(r=>r.map(l=>l.id===a?{...l,status:"discrepancy"}:l)),o())}catch(s){console.error(s)}},p=()=>{console.log("Download reconciliation report")},b=n.filter(a=>(a.source.includes("Bank")||a.source==="Bank Feed")&&a.status!=="matched"&&a.status!=="discrepancy"),u=n.filter(a=>(a.source.includes("Ledger")||a.source==="Internal Ledger")&&a.status!=="matched"&&a.status!=="discrepancy"),N=n.filter(a=>a.status==="discrepancy");return e.jsxs("div",{className:"page h-[calc(100vh-4rem)] flex flex-col overflow-hidden",children:[e.jsxs("header",{className:"flex-shrink-0 mb-4 flex justify-between items-center",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-slate-900 dark:text-white",children:"Reconciliation"}),e.jsx("p",{className:"text-slate-500 dark:text-slate-400",children:"Match transactions and resolve discrepancies"})]}),e.jsx("div",{className:"flex gap-2",children:e.jsx("button",{onClick:p,className:"btn btn-secondary",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(T,{size:16}),e.jsx("span",{children:"Export Report"})]})})})]}),h?e.jsxs("div",{className:"flex-1 grid grid-cols-12 gap-6 animate-pulse",children:[e.jsx("div",{className:"col-span-9 bg-slate-100 dark:bg-slate-800 rounded-xl"}),e.jsx("div",{className:"col-span-3 bg-slate-100 dark:bg-slate-800 rounded-xl"})]}):e.jsxs("div",{className:"flex-1 grid grid-cols-12 gap-6 min-h-0",children:[e.jsx("div",{className:"col-span-9 flex flex-col min-h-0",children:e.jsx(A,{bankItems:b,ledgerItems:u,onMatch:(a,s)=>y(a),className:"flex-1 min-h-0"})}),e.jsxs("div",{className:"col-span-3 flex flex-col gap-6 overflow-y-auto pr-2",children:[e.jsxs("div",{className:"p-4 bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-slate-800 shadow-sm",children:[e.jsx("h3",{className:"font-semibold text-slate-700 dark:text-slate-300 mb-3 text-sm uppercase tracking-wider",children:"Match Configuration"}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between text-xs mb-1",children:[e.jsx("span",{className:"text-slate-500",children:"Confidence Threshold"}),e.jsx("span",{className:"font-mono text-blue-600",children:"85%"})]}),e.jsx("input",{type:"range",className:"w-full h-1 bg-slate-200 rounded-lg appearance-none cursor-pointer",min:"50",max:"100",defaultValue:"85"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("span",{className:"text-xs font-semibold text-slate-500",children:"Algorithms"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"checkbox",id:"alg-fuzzy",defaultChecked:!0,className:"rounded border-slate-300 text-blue-600 focus:ring-blue-500"}),e.jsx("label",{htmlFor:"alg-fuzzy",className:"text-sm text-slate-600 dark:text-slate-400",children:"Fuzzy Match (Names)"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"checkbox",id:"alg-amount",defaultChecked:!0,className:"rounded border-slate-300 text-blue-600 focus:ring-blue-500"}),e.jsx("label",{htmlFor:"alg-amount",className:"text-sm text-slate-600 dark:text-slate-400",children:"Exact Amount"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"checkbox",id:"alg-date",defaultChecked:!0,className:"rounded border-slate-300 text-blue-600 focus:ring-blue-500"}),e.jsx("label",{htmlFor:"alg-date",className:"text-sm text-slate-600 dark:text-slate-400",children:"Date Window (±3d)"})]})]}),e.jsx("button",{className:"w-full py-2 bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 rounded-lg text-sm font-medium hover:bg-blue-100 dark:hover:bg-blue-900/40 transition-colors",children:"Run Auto-Match"})]})]}),e.jsxs("div",{className:"p-4 bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-slate-800 shadow-sm",children:[e.jsx("h3",{className:"font-semibold text-slate-700 dark:text-slate-300 mb-4",children:"Summary"}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsx("span",{className:"text-slate-500",children:"Match Rate"}),e.jsxs("span",{className:"font-medium text-green-600",children:[Math.round(n.filter(a=>a.status==="matched").length/n.length*100||0),"%"]})]}),e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsx("span",{className:"text-slate-500",children:"Pending"}),e.jsx("span",{className:"font-medium text-slate-700 dark:text-slate-300",children:b.length+u.length})]}),e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsx("span",{className:"text-slate-500",children:"Exceptions"}),e.jsx("span",{className:"font-medium text-orange-600",children:N.length})]})]})]}),e.jsx(F,{items:N,onFlag:f})]})]}),t&&e.jsxs("div",{className:"fixed inset-0 z-50 flex items-center justify-center p-4",children:[e.jsx("div",{className:"absolute inset-0 bg-black/50",onClick:()=>c(null),role:"button",tabIndex:0,onKeyDown:a=>a.key==="Escape"&&c(null),"aria-label":"Close modal"}),e.jsxs("div",{className:"relative bg-white dark:bg-slate-900 rounded-lg max-w-lg w-full p-6 shadow-xl z-10",role:"dialog","aria-modal":"true",tabIndex:-1,children:[e.jsx("h2",{className:"text-xl font-bold mb-4",children:"Transaction Details"}),e.jsxs("div",{className:"space-y-2 mb-6 text-sm text-slate-700 dark:text-slate-300",children:[e.jsxs("p",{children:[e.jsx("strong",{children:"Transaction ID:"})," ",e.jsx("span",{className:"font-mono",children:t.transactionId})]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Source:"})," ",t.source]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Amount:"})," ",x(t.amount,t.currency)]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Date:"})," ",m(t.date)]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Status:"})," ",e.jsx("span",{className:"capitalize",children:t.status})]}),t.discrepancyAmount&&e.jsxs("p",{className:"text-orange-600",children:[e.jsx("strong",{children:"Discrepancy:"})," ",x(t.discrepancyAmount,t.currency)]}),t.notes&&e.jsxs("p",{children:[e.jsx("strong",{children:"Notes:"})," ",t.notes]})]}),e.jsxs("div",{className:"flex justify-end gap-2",children:[t.status!=="matched"&&e.jsx("button",{onClick:()=>{y(t.id),c(null)},className:"btn btn-primary",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(E,{size:16}),e.jsx("span",{children:"Reconcile"})]})}),t.status==="discrepancy"&&e.jsx("button",{onClick:()=>{f(t.id),c(null)},className:"btn btn-danger",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(w,{size:16}),e.jsx("span",{children:"Flag"})]})}),e.jsx("button",{onClick:()=>c(null),className:"btn btn-secondary",children:"Close"})]})]})]})]})};export{W as default}; | |