UNPKG

@accounter/client

Version:
1 lines โ€ข 13.2 kB
import{s as e}from"./dist-BmACi7k_.js";import{i as t,o as n,t as r}from"./utils-BxkqV8PM.js";import{nn as i,rn as a,tn as o,un as s,zo as c}from"./error-handling-sQ-z99nE.js";import{S as l}from"./routes-C4NpBRv7.js";import{a as u,gt as d,ht as f,i as p,n as m,o as h,r as g,s as _,t as v}from"./select-BJv1AsCh.js";import{G as ee,i as y,lt as b,o as x,ot as S,qn as C,s as w,t as T,ur as E}from"./common-CzeXtlCH.js";import{t as D}from"./circle-check-BKIYWWg0.js";import{t as O}from"./circle-slash-BKiVCkGc.js";import{t as k}from"./info-CDRTs10n.js";import{n as A,t as j}from"./panel-left-open-b8NIPbkL.js";import{t as M}from"./button-BZ6z_NAl.js";import{i as N,n as P,r as F,t as te}from"./accordion-9ylHOouR.js";import{Kl as I,el as L}from"./table-4P1UQn5n.js";import{a as R,n as ne,o as re,t as ie}from"./card-BRoEyy6u.js";import{n as z,r as ae,t as B}from"./alert-inbp4t8N.js";import{t as V}from"./page-layout-zwz-Hp58.js";var H=d(`circle`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}]]),U=d(`skip-forward`,[[`path`,{d:`M21 4v16`,key:`7j8fe9`}],[`path`,{d:`M6.029 4.285A2 2 0 0 0 3 6v12a2 2 0 0 0 3.029 1.715l9.997-5.998a2 2 0 0 0 .003-3.432z`,key:`zs4d6`}]]),W=e(n(),1);function G(e){let[t,n]=(0,W.useState)({}),[r,i]=(0,W.useState)(null),a=(0,W.useMemo)(()=>{let n={};for(let r of e)n[r.id]=t[r.id]??`pending`;return n},[e,t]),o=(0,W.useMemo)(()=>e.findIndex(e=>(t[e.id]??`pending`)===`pending`),[e,t]),s=o===-1?e.length:o,c=r===null?-1:e.findIndex(e=>e.id===r),l=c===-1?s:c,u=(0,W.useCallback)(n=>{!e.some(e=>e.id===n)||(t[n]??`pending`)===`matched`||i(n)},[e,t]),d=(0,W.useCallback)(e=>{n(t=>({...t,[e]:`skipped`})),i(null)},[]),f=(0,W.useCallback)((e,t)=>{t&&(n(t=>({...t,[e]:`matched`})),i(null))},[]);return{items:e,activeIndex:l,activeItem:e[l]??null,isDone:s>=e.length,statusById:a,selectItem:u,skipItem:d,acceptItemStatus:f}}var K=t(),q=({suggestions:e,selectedIndex:t,onSelect:n})=>e.length<=1?null:(0,K.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,K.jsx)(`h3`,{className:`text-sm font-semibold text-gray-500`,children:`Alternative Suggestions`}),(0,K.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:e.map((e,r)=>(0,K.jsxs)(M,{variant:r===t?`default`:`outline`,size:`sm`,onClick:()=>n(r),"aria-pressed":r===t,children:[(0,K.jsxs)(`span`,{className:`font-semibold`,children:[`#`,r+1]}),(0,K.jsx)(`span`,{className:`max-w-40 truncate`,children:e.label}),(0,K.jsxs)(`span`,{className:`text-xs opacity-70`,children:[Math.round(e.confidenceScore*100),`%`]})]},e.chargeId))})]});function J(e){let t=e.minDocumentsDate??e.minEventDate??e.minDebitDate;return t?I(new Date(t),`dd/MM/yy`):void 0}function Y(e){return e.counterparty?.name??e.userDescription??`Unknown charge`}function X({label:e,value:t}){return t?(0,K.jsxs)(`div`,{className:`flex flex-col`,children:[(0,K.jsx)(`span`,{className:`text-xs text-gray-500`,children:e}),(0,K.jsx)(`span`,{className:`text-sm font-medium`,children:t})]}):null}var Z=({charge:e,confidenceScore:t,title:n})=>{let r=e.additionalDocuments??[],i=e.transactions??[],a=e.miscExpenses??[],o=r.find(e=>e.image),s=[...new Set(r.map(e=>e.documentType).filter(Boolean))].join(`, `),c=i.length>0||a.length>0;return(0,K.jsxs)(ie,{"data-testid":`charge-detail-card`,children:[(0,K.jsxs)(R,{className:`flex flex-row items-center justify-between`,children:[(0,K.jsx)(re,{className:`text-base`,children:n}),t!=null&&(0,K.jsx)(`div`,{className:`flex items-center gap-2`,"aria-label":`Match confidence score: ${Math.round(t*100)}%`,children:(0,K.jsx)(T,{value:Math.round(t*100),size:`sm`})})]}),(0,K.jsxs)(ne,{className:`flex flex-col gap-4`,children:[(0,K.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,K.jsx)(X,{label:`Date`,value:J(e)}),(0,K.jsx)(X,{label:`Amount`,value:e.totalAmount?.formatted}),(0,K.jsx)(X,{label:`Counterparty`,value:e.counterparty?.name}),(0,K.jsx)(X,{label:`Document type`,value:s})]}),(0,K.jsx)(X,{label:`Description`,value:e.userDescription}),o?.image?(0,K.jsx)(`a`,{href:o.file?.toString()??o.image.toString(),target:`_blank`,rel:`noreferrer`,children:(0,K.jsx)(`img`,{src:o.image.toString(),alt:`Document preview`,className:`max-h-56 w-auto rounded-md border object-contain`})}):(0,K.jsx)(`p`,{className:`text-xs text-gray-400`,children:`No document preview`}),c&&(0,K.jsx)(te,{type:`single`,collapsible:!0,children:(0,K.jsxs)(F,{value:`more-details`,children:[(0,K.jsx)(N,{className:`text-sm`,children:`More Details`}),(0,K.jsxs)(P,{className:`flex flex-col gap-3`,children:[i.length>0&&(0,K.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,K.jsx)(`span`,{className:`text-xs font-semibold text-gray-500`,children:`Transactions`}),(0,K.jsx)(`ul`,{className:`flex flex-col gap-1`,children:i.map(e=>(0,K.jsxs)(`li`,{className:`flex justify-between gap-2 text-sm`,children:[(0,K.jsxs)(`span`,{className:`truncate`,children:[e.eventDate,` ยท `,e.sourceDescription]}),(0,K.jsx)(`span`,{className:`shrink-0 font-medium`,children:e.amount.formatted})]},e.id))})]}),a.length>0&&(0,K.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,K.jsx)(`span`,{className:`text-xs font-semibold text-gray-500`,children:`Misc Expenses`}),(0,K.jsx)(`ul`,{className:`flex flex-col gap-1`,children:a.map(e=>(0,K.jsxs)(`li`,{className:`flex justify-between gap-2 text-sm`,children:[(0,K.jsx)(`span`,{className:`truncate`,children:e.description??`Misc expense`}),(0,K.jsx)(`span`,{className:`shrink-0 font-medium`,children:e.amount.formatted})]},e.id))})]})]})]})})]})]})},Q={businessId:null,fromDate:null,toDate:null,mode:null,sortBy:a.ByDate},oe=[`mode`,`fromDate`,`toDate`,`businessId`,`sortBy`],se=Object.values(i),ce=Object.values(a);function le(e){let t=e.get(`mode`),n=se.includes(t)?t:Q.mode,r=e.get(`sortBy`),i=ce.includes(r)?r:Q.sortBy;return{businessId:e.get(`businessId`)||null,fromDate:e.get(`fromDate`)||null,toDate:e.get(`toDate`)||null,mode:n,sortBy:i}}function ue(e){let t={};return e.mode&&(t.mode=e.mode),e.fromDate&&(t.fromDate=e.fromDate),e.toDate&&(t.toDate=e.toDate),e.businessId&&(t.businessId=e.businessId),e.sortBy!==Q.sortBy&&(t.sortBy=e.sortBy),t}var $=`ALL`,de=({filters:e,onFiltersChange:t})=>{let{selectableBusinesses:n,fetching:r}=b(),o=n=>{t({...e,...n})};return(0,K.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,K.jsxs)(`div`,{className:`flex flex-wrap items-end gap-4`,children:[(0,K.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,K.jsx)(h,{htmlFor:`charge-matching-mode`,children:`Mode`}),(0,K.jsxs)(v,{value:e.mode??$,onValueChange:e=>o({mode:e===$?null:e}),children:[(0,K.jsx)(p,{id:`charge-matching-mode`,className:`w-44`,children:(0,K.jsx)(u,{placeholder:`All`})}),(0,K.jsxs)(m,{children:[(0,K.jsx)(g,{value:$,children:`All`}),(0,K.jsx)(g,{value:i.DocBase,children:`Doc Base`}),(0,K.jsx)(g,{value:i.TransactionBase,children:`Transaction Base`})]})]})]}),(0,K.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,K.jsx)(h,{htmlFor:`charge-matching-from-date`,children:`From`}),(0,K.jsx)(_,{id:`charge-matching-from-date`,type:`date`,className:`w-40`,max:e.toDate??void 0,value:e.fromDate??``,onChange:e=>o({fromDate:e.target.value||null})})]}),(0,K.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,K.jsx)(h,{htmlFor:`charge-matching-to-date`,children:`To`}),(0,K.jsx)(_,{id:`charge-matching-to-date`,type:`date`,className:`w-40`,min:e.fromDate??void 0,value:e.toDate??``,onChange:e=>o({toDate:e.target.value||null})})]}),(0,K.jsxs)(`div`,{className:`flex flex-col gap-1 min-w-52`,children:[(0,K.jsx)(h,{children:`Business`}),(0,K.jsx)(S,{data:n,disabled:r,placeholder:`All businesses`,value:e.businessId,onChange:e=>o({businessId:e})})]}),(0,K.jsxs)(`div`,{className:`flex flex-col gap-1 ml-auto`,children:[(0,K.jsx)(h,{children:`Sort by`}),(0,K.jsx)(y,{value:e.sortBy,onValueChange:e=>o({sortBy:e}),children:(0,K.jsxs)(x,{children:[(0,K.jsx)(w,{value:a.ByDate,children:`Date`}),(0,K.jsx)(w,{value:a.ByScore,children:`Match Score`})]})})]})]}),e.sortBy===a.ByScore&&(0,K.jsxs)(B,{children:[(0,K.jsx)(k,{className:`size-4`}),(0,K.jsx)(z,{children:`Note: Score-based sorting currently evaluates only the 100 most recent unmatched charges.`})]})]})};function fe({status:e}){switch(e){case`matched`:return(0,K.jsx)(D,{className:`size-4 shrink-0 text-green-600`,"aria-label":`Matched`});case`skipped`:return(0,K.jsx)(O,{className:`size-4 shrink-0 text-gray-400`,"aria-label":`Skipped`});default:return(0,K.jsx)(H,{className:`size-4 shrink-0 text-gray-300`,"aria-label":`Pending`})}}var pe=({items:e,statusById:t,activeId:n,collapsed:i,onToggleCollapsed:a,onSelectItem:o})=>(0,K.jsxs)(`div`,{className:r(`flex flex-col gap-2 border-r pr-3 transition-all`,i?`w-10`:`w-72 shrink-0`),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between`,children:[!i&&(0,K.jsx)(`h3`,{className:`text-sm font-semibold`,children:`Awaiting Matches`}),(0,K.jsx)(M,{variant:`ghost`,size:`icon`,onClick:a,"aria-label":i?`Show sidebar`:`Hide sidebar`,children:i?(0,K.jsx)(j,{className:`size-4`}):(0,K.jsx)(A,{className:`size-4`})})]}),!i&&(0,K.jsx)(C,{className:`h-[calc(100vh-20rem)]`,children:(0,K.jsxs)(`ul`,{className:`flex flex-col gap-1`,children:[e.map(e=>{let i=t[e.id]??`pending`;return(0,K.jsx)(`li`,{children:(0,K.jsxs)(`button`,{type:`button`,disabled:i===`matched`,onClick:()=>o(e.id),"aria-current":e.id===n?`true`:void 0,className:r(`flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition-colors`,i!==`matched`&&`hover:bg-accent/60`,e.id===n&&`bg-accent`,i===`skipped`&&`opacity-50`,i===`matched`&&`cursor-not-allowed opacity-60`),children:[(0,K.jsx)(fe,{status:i}),(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-col`,children:[(0,K.jsx)(`span`,{className:`truncate font-medium`,children:e.title}),(0,K.jsx)(`span`,{className:`truncate text-xs text-gray-500`,children:[e.subtitle,e.amount].filter(Boolean).join(` ยท `)})]})]})},e.id)}),e.length===0&&(0,K.jsx)(`li`,{className:`px-2 py-1.5 text-sm text-gray-500`,children:`No charges awaiting match`})]})})]}),me=()=>{let[e,t]=l(),n=(0,W.useMemo)(()=>le(e),[e]),r=(0,W.useCallback)(e=>{t(t=>{let n=new URLSearchParams(t),r=ue(e);for(let e of oe){let t=r[e];t==null?n.delete(e):n.set(e,t)}return n},{replace:!0})},[t]),[i,a]=(0,W.useState)(!1),[{data:u,fetching:d,error:p}]=c({query:s,variables:{limit:20,offset:0,businessId:n.businessId,fromDate:n.fromDate,toDate:n.toDate,mode:n.mode,sortBy:n.sortBy}}),m=(0,W.useMemo)(()=>(u?.chargesAwaitingMatchQueue.baseCharges??[]).map(e=>{let t=L(o,e.baseCharge);return{id:t.id,baseCharge:t,suggestions:e.suggestions}}),[u]),h=G(m),g=(0,W.useMemo)(()=>m.map(e=>({id:e.id,title:Y(e.baseCharge),subtitle:J(e.baseCharge),amount:e.baseCharge.totalAmount?.formatted})),[m]),_=u?.chargesAwaitingMatchQueue.totalCount??0,{activeItem:v,selectItem:y,skipItem:b,acceptItemStatus:x}=h,[S,C]=(0,W.useState)(null),w=S&&S.itemId===v?.id?S.index:0,T=v?.suggestions[w],D=T?L(o,T.charge):null,O=(0,W.useMemo)(()=>(v?.suggestions??[]).map(e=>({chargeId:e.chargeId,confidenceScore:e.confidenceScore,label:Y(L(o,e.charge))})),[v]),{mergeCharges:k,fetching:A}=ee(),j=(0,W.useCallback)(()=>{v&&b(v.id)},[v,b]),N=(0,W.useCallback)(async()=>{if(!v||!T)return;let e=await k({baseChargeID:v.id,chargeIdsToMerge:[T.chargeId]});x(v.id,!!e)},[v,T,k,x]);return(0,K.jsxs)(V,{title:`Charge Matching`,description:`Review and merge suggested charge matches, one by one.`,children:[(0,K.jsx)(de,{filters:n,onFiltersChange:r}),p&&(0,K.jsxs)(B,{variant:`destructive`,children:[(0,K.jsx)(ae,{children:`Failed to load the matching queue`}),(0,K.jsx)(z,{children:p.message})]}),d?(0,K.jsxs)(`div`,{className:`flex gap-4`,children:[(0,K.jsx)(E,{className:`h-96 w-72`}),(0,K.jsx)(E,{className:`h-96 flex-1`})]}):p?null:(0,K.jsxs)(`div`,{className:`flex gap-4`,children:[(0,K.jsx)(pe,{items:g,statusById:h.statusById,activeId:v?.id??null,collapsed:i,onToggleCollapsed:()=>a(e=>!e),onSelectItem:y}),(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-4`,children:[(0,K.jsxs)(`p`,{className:`text-sm text-gray-500`,children:[`Showing `,m.length,` of `,_,` charges awaiting match`]}),(0,K.jsxs)(`div`,{className:`grid grid-cols-1 gap-4 lg:grid-cols-2`,children:[v?(0,K.jsx)(Z,{charge:v.baseCharge,title:`Base Charge`}):(0,K.jsxs)(`section`,{className:`rounded-lg border p-4`,children:[(0,K.jsx)(`h3`,{className:`mb-2 text-sm font-semibold text-gray-500`,children:`Base Charge`}),(0,K.jsx)(`p`,{className:`text-sm text-gray-500`,children:m.length===0?`No charges awaiting match.`:`Queue completed ๐ŸŽ‰`})]}),D?(0,K.jsx)(Z,{charge:D,title:`Suggested Match`,confidenceScore:T?.confidenceScore}):(0,K.jsxs)(`section`,{className:`rounded-lg border p-4`,children:[(0,K.jsx)(`h3`,{className:`mb-2 text-sm font-semibold text-gray-500`,children:`Suggested Match`}),(0,K.jsx)(`p`,{className:`text-sm text-gray-500`,children:v?`No suggestions for this charge.`:`โ€”`})]})]}),v&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsxs)(M,{onClick:N,disabled:!T||A,children:[(0,K.jsx)(f,{className:`size-4`}),`Accept`]}),(0,K.jsxs)(M,{variant:`outline`,onClick:j,disabled:A,children:[(0,K.jsx)(U,{className:`size-4`}),`Skip`]})]}),(0,K.jsx)(q,{suggestions:O,selectedIndex:w,onSelect:e=>v&&C({itemId:v.id,index:e})})]})]})]})};export{me as ChargeMatchingReviewScreen};