@atyaio/ledgr-web 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/assets/badge-DCLlsDNI.js +55 -0
  2. package/dist/assets/{breakdown-D9nBrbad.js → breakdown-B7xclB2-.js} +1 -1
  3. package/dist/assets/{categories-B7jajln6.js → categories-C9LvkWNc.js} +1 -1
  4. package/dist/assets/{color-picker-DLlr-Cq6.js → color-picker-DUPZPbk3.js} +1 -1
  5. package/dist/assets/{custom-cell-Wgh3D7lb.js → custom-cell-DOJAsRPW.js} +1 -1
  6. package/dist/assets/data-BX7xFZfR.js +1 -0
  7. package/dist/assets/{download-CIyMPSgr.js → download-gNHw92Vi.js} +1 -1
  8. package/dist/assets/expenses-Ct1Tk3pC.js +1 -0
  9. package/dist/assets/index-B9WjaP25.js +31 -0
  10. package/dist/assets/index-YWd9JGBA.css +2 -0
  11. package/dist/assets/insights-C0cl4vss.js +1 -0
  12. package/dist/assets/integrations-CueFg-5F.js +1 -0
  13. package/dist/assets/{ledger-toolbar-yj0u4-Rm.js → ledger-toolbar-B_Gbv5Ws.js} +1 -1
  14. package/dist/assets/{media-Cr7juL5w.js → media-D6XgVZ7M.js} +1 -1
  15. package/dist/assets/{menu-BDGd2JUq.js → menu-C-8r2BNA.js} +1 -1
  16. package/dist/assets/{money-Ch2MLu6J.js → money-OFUBQ3gl.js} +1 -1
  17. package/dist/assets/{money-input-C8ZuBxvX.js → money-input-DQaEauAw.js} +1 -1
  18. package/dist/assets/{overview-Ddn6RbvU.js → overview-CZMXeLeG.js} +1 -1
  19. package/dist/assets/payments-D9NCfpzJ.js +1 -0
  20. package/dist/assets/project-CYHaWZqH.js +1 -0
  21. package/dist/assets/{pull-shift-sheet-DTwTC0rg.js → pull-shift-sheet-BaOiY46Z.js} +1 -1
  22. package/dist/assets/queries-CxLQqNqz.js +1 -0
  23. package/dist/assets/recurring-e7X3okBc.js +1 -0
  24. package/dist/assets/revenue-TPYHnUaW.js +1 -0
  25. package/dist/assets/{search-jkqZqVJy.js → search-CnrmI1BH.js} +1 -1
  26. package/dist/assets/settings-mDly_aVZ.js +4 -0
  27. package/dist/assets/{shift-sales-B0yokKuf.js → shift-sales-BpOCNuGY.js} +1 -1
  28. package/dist/assets/stakeholders-DzTfUHX0.js +1 -0
  29. package/dist/assets/{star-cwF2fEe6.js → star-DZj1Tpai.js} +1 -1
  30. package/dist/assets/{table-DQsx5_iN.js → table-QAdUTXQz.js} +1 -1
  31. package/dist/assets/{tooltip-CKyX36D7.js → tooltip-CYNpGhCZ.js} +7 -7
  32. package/dist/index.html +8 -8
  33. package/package.json +2 -2
  34. package/dist/assets/badge-BTiDEJlh.js +0 -55
  35. package/dist/assets/data-DLjPdfYn.js +0 -1
  36. package/dist/assets/expenses-DglPf9Hj.js +0 -1
  37. package/dist/assets/index-B3RS60Xw.css +0 -2
  38. package/dist/assets/index-DOwVPfdT.js +0 -31
  39. package/dist/assets/insights-C_lA_1Ig.js +0 -1
  40. package/dist/assets/integrations-C4NPnoJ4.js +0 -1
  41. package/dist/assets/payments-q8beCPp-.js +0 -1
  42. package/dist/assets/project-Bgpq3nFR.js +0 -1
  43. package/dist/assets/queries-IGiwF8nF.js +0 -1
  44. package/dist/assets/recurring-xqowgQWt.js +0 -1
  45. package/dist/assets/revenue-CB8ggUDa.js +0 -1
  46. package/dist/assets/settings-DJ670Ax6.js +0 -4
  47. package/dist/assets/stakeholders-wioC2mrf.js +0 -1
@@ -1 +0,0 @@
1
- import{d as e,dt as t,f as n,ft as r,gt as i,h as a,i as o,l as s,o as c,pt as l,s as u,v as d,y as f}from"./badge-BTiDEJlh.js";import{O as p,d as m,i as h,v as g}from"./queries-IGiwF8nF.js";import{n as _}from"./project-Bgpq3nFR.js";import{a as v,c as y,d as b,f as x,h as S,i as C,l as w,m as T,n as E,o as D,p as ee,r as te,s as O,t as k,u as A}from"./tooltip-CKyX36D7.js";import{a as j,i as M,o as N,r as P,s as F}from"./table-DQsx5_iN.js";import{a as I,c as L,t as R}from"./media-Cr7juL5w.js";import{C as z,D as B,_ as V,f as H,h as U,x as ne}from"./index-DOwVPfdT.js";import{r as re,t as W}from"./format-GDcQVAp4.js";import{t as G}from"./money-Ch2MLu6J.js";import{t as K}from"./breakdown-D9nBrbad.js";import{r as q}from"./shift-sales-B0yokKuf.js";var J=i(l()),ie=[`axis`,`item`],ae=(0,J.forwardRef)((e,t)=>J.createElement(C,{chartName:`BarChart`,defaultTooltipEventType:`axis`,validateTooltipEventTypes:ie,tooltipPayloadSearcher:b,categoricalChartProps:e,ref:t})),oe=r(),Y=t();function X({label:e,options:t,value:n,onChange:r,icon:i}){let[s,c]=(0,J.useState)(!1),l=(0,J.useRef)(null),u=(0,J.useRef)(null),[f,p]=(0,J.useState)(null),m=R(),{t:h}=d(),g=t.filter(e=>n.includes(e.id));(0,J.useEffect)(()=>{if(!s)return;let e=()=>{let e=l.current?.getBoundingClientRect();e&&p({top:e.bottom+6,left:Math.min(e.left,window.innerWidth-280)})};e();let t=e=>{let t=e.target;!l.current?.contains(t)&&!u.current?.contains(t)&&c(!1)},n=e=>e.key===`Escape`&&c(!1);return document.addEventListener(`mousedown`,t),document.addEventListener(`keydown`,n),window.addEventListener(`resize`,e),()=>{document.removeEventListener(`mousedown`,t),document.removeEventListener(`keydown`,n),window.removeEventListener(`resize`,e)}},[s]);let _=e=>r(n.includes(e)?n.filter(t=>t!==e):[...n,e]),v=g.length===0?h(`All`):g.length===1?g[0].label:h(`{n} selected`,{n:g.length}),y=(0,Y.jsxs)(`ul`,{className:`max-h-[320px] overflow-y-auto py-1`,children:[t.map(e=>{let t=n.includes(e.id);return(0,Y.jsx)(`li`,{children:(0,Y.jsxs)(`button`,{type:`button`,onClick:()=>_(e.id),className:`w-full flex items-center gap-2.5 px-3 h-10 md:h-9 text-start text-[14px] md:text-[13.5px] hover:bg-card-hover`,children:[(0,Y.jsx)(`span`,{className:a(`size-[18px] rounded-[5px] border inline-flex items-center justify-center shrink-0`,t?`bg-accent border-accent text-white`:`border-line-strong`),children:t&&(0,Y.jsx)(z,{className:`size-3`})}),e.color&&(0,Y.jsx)(o,{color:e.color}),(0,Y.jsx)(`span`,{className:`flex-1 truncate`,children:e.label}),e.hint&&(0,Y.jsx)(`span`,{className:`text-[12px] text-ink-3`,children:e.hint})]})},e.id)}),!t.length&&(0,Y.jsx)(`li`,{className:`px-3 py-3 text-[13px] text-ink-3`,children:h(`Nothing to filter by yet.`)})]});return(0,Y.jsxs)(`div`,{ref:l,className:`relative inline-block`,children:[(0,Y.jsxs)(`button`,{type:`button`,onClick:()=>c(e=>!e),className:a(`h-9 ps-3 pe-2 inline-flex items-center gap-1.5 rounded-full border text-[13.5px] font-medium whitespace-nowrap`,g.length?`bg-primary text-primary-ink border-primary`:`bg-card border-line text-ink-2 hover:text-ink`),children:[i,(0,Y.jsxs)(`span`,{className:`opacity-70`,children:[e,`:`]}),` `,v,g.length?(0,Y.jsx)(`span`,{role:`button`,"aria-label":h(`Clear {label}`,{label:e}),onClick:e=>{e.stopPropagation(),r([])},className:`ms-0.5 inline-flex size-5 items-center justify-center rounded-full hover:bg-white/20`,children:(0,Y.jsx)(L,{className:`size-3.5`})}):(0,Y.jsx)(F,{className:`size-4 opacity-70`})]}),s&&(0,oe.createPortal)(m?(0,Y.jsxs)(`div`,{className:`fixed inset-0 z-50 flex items-end`,children:[(0,Y.jsx)(`div`,{className:`absolute inset-0 bg-black/40`,onClick:()=>c(!1)}),(0,Y.jsxs)(`div`,{ref:u,className:`relative w-full bg-card rounded-t-[24px] pb-[max(12px,var(--safe-bottom))] shadow-2xl`,children:[(0,Y.jsx)(`div`,{className:`mx-auto mt-2.5 h-1.5 w-10 rounded-full bg-line-strong`}),(0,Y.jsx)(`div`,{className:`px-4 pt-3 pb-1 text-[15px] font-semibold`,children:e}),y]})]}):(0,Y.jsx)(`div`,{ref:u,style:{position:`fixed`,top:f?.top??0,left:f?.left??0,zIndex:60,visibility:f?`visible`:`hidden`},className:`w-[270px] card shadow-[var(--shadow-pop)]`,children:y}),document.body)]})}var se=[{id:`both`,label:`Both`},{id:`revenue`,label:`Revenue`},{id:`expenses`,label:`Expenses`}];function ce(){let{t,name:r}=d(),{range:i}=H(),[a,o]=B(),c=a.get(`ledger`)||`both`,l=(a.get(`cats`)??``).split(`,`).filter(Boolean),f=(a.get(`methods`)??``).split(`,`).filter(Boolean),_=a.get(`partner`)??``,v=a.get(`g`)??``,y=e=>o(t=>{let n=new URLSearchParams(t);for(let[t,r]of Object.entries(e))r?n.set(t,r):n.delete(t);return n},{replace:!0}),b=h(void 0,!1),x=g(),S=p(),C=m((0,J.useMemo)(()=>({from:i.from,to:i.to,ledger:c,categoryIds:l.join(`,`)||void 0,paymentMethodIds:f.join(`,`)||void 0,stakeholderId:_||void 0,granularity:v||void 0}),[i,c,l.join(`,`),f.join(`,`),_,v])),w=(0,J.useMemo)(()=>(b.data?.items??[]).filter(e=>c===`both`||e.kind===(c===`revenue`?`revenue`:`expense`)).map(e=>({id:e.id,label:r(e),color:e.color,hint:t(e.kind)})),[b.data,c,r,t]),T=(0,J.useMemo)(()=>(x.data?.items??[]).map(e=>({id:e.id,label:r(e),color:e.color})),[x.data,r]);return(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(e,{title:t(`Insights`),subtitle:t(`Slice the ledger by category, payment method and partner, compared with the previous period.`)}),(0,Y.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap mb-4`,children:[(0,Y.jsx)(n,{value:c,onChange:e=>y({ledger:e===`both`?null:e,cats:null}),items:se.map(e=>({id:e.id,label:t(e.label)}))}),(0,Y.jsx)(X,{label:t(`Categories`),icon:(0,Y.jsx)(V,{className:`size-4`}),options:w,value:l,onChange:e=>y({cats:e.join(`,`)||null})}),(0,Y.jsx)(X,{label:t(`Payment`),icon:(0,Y.jsx)(ne,{className:`size-4`}),options:T,value:f,onChange:e=>y({methods:e.join(`,`)||null})}),(0,Y.jsxs)(`div`,{className:`inline-flex items-center gap-1.5 h-9 ps-3 pe-1 rounded-full border border-line bg-card text-[13.5px] text-ink-2`,children:[(0,Y.jsx)(U,{className:`size-4`}),(0,Y.jsxs)(I,{compact:!0,className:`h-7 border-0 bg-transparent ps-1 pe-7 w-[150px] rounded-full`,value:_,onChange:e=>y({partner:e.target.value||null}),children:[(0,Y.jsx)(`option`,{value:``,children:t(`Partner: all`)}),S.data?.items.map(e=>(0,Y.jsx)(`option`,{value:e.id,children:r(e)},e.id))]})]}),(0,Y.jsx)(`div`,{className:`flex-1`}),(0,Y.jsx)(n,{size:`xs`,value:v||`auto`,onChange:e=>y({g:e===`auto`?null:e}),items:[{id:`auto`,label:t(`Auto`)},{id:`day`,label:t(`Day`)},{id:`week`,label:t(`Week`)},{id:`month`,label:t(`Month`)}]})]}),C.isPending&&(0,Y.jsx)(s,{label:t(`Slicing the ledger`)}),C.isError&&(0,Y.jsx)(u,{title:t(`Could not load insights`),description:C.error.message}),C.data&&(0,Y.jsx)(le,{d:C.data,ledger:c,filtered:!!(l.length||f.length||_)})]})}function Z({value:e,invert:t}){let{t:n}=d();if(e===null||!Number.isFinite(e))return(0,Y.jsx)(`span`,{className:`text-ink-3 text-[12px]`,children:n(`no previous period`)});Math.abs(e)<.05&&(e=0);let r=e>0,i=t?!r:r,o=e===0?ee:r?T:S;return(0,Y.jsxs)(`span`,{className:a(`inline-flex items-center gap-0.5 text-[12px] font-medium`,e===0?`text-ink-3`:i?`text-good`:`text-critical`),children:[(0,Y.jsx)(o,{className:`size-3.5`}),re(e,1),` `,(0,Y.jsx)(`span`,{className:`font-normal text-ink-3`,children:n(`vs previous`)})]})}function le({d:e,ledger:t,filtered:n}){let{t:r,lang:i}=d(),{money:s,date:l}=_(),f=t!==`expenses`,p=t!==`revenue`,m=e.totals;return(0,Y.jsxs)(`div`,{className:a(`space-y-4`,n&&`fade-up`),children:[(0,Y.jsxs)(`div`,{className:`grid grid-cols-2 md:grid-cols-4 gap-3`,children:[f&&(0,Y.jsx)(Q,{label:r(`Revenue`),value:s(m.revenueMinor),sub:(0,Y.jsx)(Z,{value:e.delta.revenuePct}),extra:r(`{n} entries · avg {avg}`,{n:m.revenueCount,avg:s(m.avgRevenuePerEntryMinor,{compact:!0})})}),p&&(0,Y.jsx)(Q,{label:r(`Expenses`),value:s(m.expenseMinor),sub:(0,Y.jsx)(Z,{value:e.delta.expensePct,invert:!0}),extra:r(`{n} entries · avg {avg}`,{n:m.expenseCount,avg:s(m.avgExpensePerEntryMinor,{compact:!0})})}),f&&p&&(0,Y.jsx)(Q,{label:r(`Net`),value:s(m.netMinor,{signed:!0}),tone:m.netMinor<0?`bad`:void 0,sub:(0,Y.jsx)(Z,{value:e.delta.netPct}),extra:m.marginPct===null?r(`no revenue`):r(`margin {pct}`,{pct:W(m.marginPct,1)})}),f?(0,Y.jsx)(Q,{label:r(`Per day`),value:s(m.avgRevenuePerDayMinor),sub:(0,Y.jsx)(`span`,{className:`text-[12px] text-ink-3`,children:r(`{active} of {days} days active`,{active:m.activeDays,days:e.range.days})}),extra:m.bestDay?r(`best {date} · {amount}`,{date:l(m.bestDay.date,`short`),amount:s(m.bestDay.revenueMinor,{compact:!0})}):void 0}):(0,Y.jsx)(Q,{label:r(`Per day`),value:s(m.avgExpensePerDayMinor),sub:(0,Y.jsx)(`span`,{className:`text-[12px] text-ink-3`,children:r(`{active} of {days} days active`,{active:m.activeDays,days:e.range.days})})})]}),(0,Y.jsx)(c,{title:r(`Trend`),subtitle:r(`By {granularity} · dotted line is the previous period ({from} – {to})`,{granularity:r(e.range.granularity),from:l(e.range.previousFrom,`short`),to:l(e.range.previousTo)}),children:(0,Y.jsx)(`div`,{className:`h-[280px]`,children:(0,Y.jsx)(de,{d:e,showRev:f,showExp:p})})}),(0,Y.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4`,children:[f&&(0,Y.jsx)(c,{title:r(`Revenue by category`),children:(0,Y.jsx)(K,{items:e.revenueByCategory.map(e=>({id:e.id,name:e.name,nameAr:e.nameAr,color:e.color,amountMinor:e.revenueMinor,pct:e.pct,count:e.count})),emptyLabel:r(`No revenue`)})}),p&&(0,Y.jsx)(c,{title:r(`Expenses by category`),children:(0,Y.jsx)(K,{items:e.expensesByCategory.map(e=>({id:e.id,name:e.name,nameAr:e.nameAr,color:e.color,amountMinor:e.expenseMinor,pct:e.pct,count:e.count})),emptyLabel:r(`No expenses`)})}),(0,Y.jsx)(c,{title:r(`By payment method`),subtitle:f&&p?r(`Revenue and expenses combined`):void 0,children:(0,Y.jsx)($,{groups:e.byPaymentMethod,showRev:f,showExp:p})}),(0,Y.jsx)(c,{title:r(`By partner`),subtitle:r(`Received by / paid by`),children:(0,Y.jsx)($,{groups:e.byStakeholder,showRev:f,showExp:p})}),(0,Y.jsx)(c,{title:r(`Weekday pattern`),subtitle:r(`Average per day of the week`),className:a(f&&p&&`xl:col-span-2`),children:(0,Y.jsx)(`div`,{className:`h-[220px]`,children:(0,Y.jsx)(fe,{d:e,showRev:f,showExp:p})})})]}),f&&e.posSales&&(0,Y.jsx)(ue,{s:e.posSales}),(0,Y.jsxs)(`div`,{className:`grid grid-cols-1 xl:grid-cols-3 gap-4`,children:[(0,Y.jsx)(c,{className:`xl:col-span-2`,title:r(`Month by month`),flush:!0,children:(0,Y.jsxs)(P,{children:[(0,Y.jsx)(`thead`,{children:(0,Y.jsxs)(`tr`,{children:[(0,Y.jsx)(j,{children:r(`Month`)}),f&&(0,Y.jsx)(j,{align:`right`,children:r(`Revenue`)}),p&&(0,Y.jsx)(j,{align:`right`,children:r(`Expenses`)}),f&&p&&(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(j,{align:`right`,children:r(`Net`)}),(0,Y.jsx)(j,{align:`right`,children:r(`Margin`)})]}),(0,Y.jsx)(j,{align:`right`,children:r(`Entries`)})]})}),(0,Y.jsx)(`tbody`,{children:e.byMonth.map(e=>(0,Y.jsxs)(N,{children:[(0,Y.jsx)(M,{className:`font-medium`,children:new Intl.DateTimeFormat(void 0,{month:`long`,year:`numeric`,timeZone:`UTC`}).format(new Date(`${e.month}-01T00:00:00Z`))}),f&&(0,Y.jsx)(M,{align:`right`,children:(0,Y.jsx)(G,{minor:e.revenueMinor})}),p&&(0,Y.jsx)(M,{align:`right`,children:(0,Y.jsx)(G,{minor:e.expenseMinor})}),f&&p&&(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(M,{align:`right`,children:(0,Y.jsx)(G,{minor:e.netMinor,tone:`flow`,signed:!0})}),(0,Y.jsx)(M,{align:`right`,className:`num text-ink-2`,children:e.marginPct===null?`—`:W(e.marginPct,0)})]}),(0,Y.jsx)(M,{align:`right`,className:`num text-ink-2`,children:(f?e.revenueCount:0)+(p?e.expenseCount:0)})]},e.month))})]})}),(0,Y.jsx)(c,{title:r(f?`Largest revenue`:`Largest expenses`),flush:!0,children:(0,Y.jsxs)(`ul`,{className:`divide-y divide-line`,children:[(f?e.topRevenue:e.topExpenses).slice(0,8).map(e=>(0,Y.jsxs)(`li`,{className:`px-4 md:px-5 py-2.5 flex items-center gap-3`,children:[(0,Y.jsx)(o,{color:e.groupColor,size:9}),(0,Y.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,Y.jsx)(`div`,{dir:`auto`,className:`text-[14px] font-medium truncate`,children:e.description}),(0,Y.jsxs)(`div`,{className:`text-[12px] text-ink-3`,children:[e.groupNameAr&&i===`ar`?e.groupNameAr:r(e.groupName),` · `,l(e.date)]})]}),(0,Y.jsx)(G,{minor:e.amountMinor,className:`font-semibold`})]},e.id)),!(f?e.topRevenue:e.topExpenses).length&&(0,Y.jsx)(`li`,{children:(0,Y.jsx)(u,{title:r(`Nothing here`)})})]})})]})]})}function ue({s:e}){let{t}=d(),{money:n,locale:r}=_(),i=e.netMinor>0&&e.costMinor>0?(e.netMinor-e.costMinor)/e.netMinor*100:null;return(0,Y.jsxs)(`div`,{className:`grid grid-cols-1 xl:grid-cols-3 gap-4`,children:[(0,Y.jsx)(c,{className:`xl:col-span-2`,title:t(`Best sellers`),subtitle:t(`From {n} Loyverse shifts in this range · {qty} items · {amount} net`,{n:e.shifts,qty:q(e.quantity,r),amount:n(e.netMinor,{compact:!0})}),flush:!0,children:(0,Y.jsxs)(P,{children:[(0,Y.jsx)(`thead`,{children:(0,Y.jsxs)(`tr`,{children:[(0,Y.jsx)(j,{children:t(`Item`)}),(0,Y.jsx)(j,{children:t(`Category`)}),(0,Y.jsx)(j,{align:`right`,children:t(`Qty`)}),(0,Y.jsx)(j,{align:`right`,children:t(`Net sales`)}),(0,Y.jsx)(j,{align:`right`,children:t(`Share`)})]})}),(0,Y.jsx)(`tbody`,{children:e.byItem.map(e=>(0,Y.jsxs)(N,{children:[(0,Y.jsx)(M,{children:(0,Y.jsxs)(`div`,{dir:`auto`,className:`font-medium truncate max-w-[320px]`,children:[e.itemName,e.variantName?(0,Y.jsxs)(`span`,{className:`text-ink-3 font-normal`,children:[` · `,e.variantName]}):null]})}),(0,Y.jsx)(M,{className:`text-ink-2 text-[13px]`,children:e.categoryName??(0,Y.jsx)(`span`,{className:`text-ink-4`,children:`—`})}),(0,Y.jsx)(M,{align:`right`,className:`num text-ink-2`,children:q(e.quantity,r)}),(0,Y.jsx)(M,{align:`right`,children:(0,Y.jsx)(G,{minor:e.netMinor,className:`font-medium`})}),(0,Y.jsx)(M,{align:`right`,className:`num text-ink-2`,children:W(e.pct,0)})]},`${e.itemName}|${e.variantName??``}`))})]})}),(0,Y.jsx)(c,{title:t(`Sales by category`),subtitle:i===null?void 0:t(`gross margin {pct} after item costs`,{pct:W(i,0)}),children:(0,Y.jsx)(K,{items:e.byCategory.map((e,n)=>({id:e.name||null,name:e.name||t(`Uncategorised`),color:f[n%f.length],amountMinor:e.netMinor,pct:e.pct,count:Math.round(e.quantity)})),emptyLabel:t(`No sales`)})})]})}function Q({label:e,value:t,sub:n,extra:r,tone:i}){return(0,Y.jsxs)(`div`,{className:`card p-4`,children:[(0,Y.jsx)(`div`,{className:`label`,children:e}),(0,Y.jsx)(`div`,{className:a(`num text-[22px] md:text-[24px] font-semibold tracking-tight mt-1`,i===`bad`&&`text-critical`),children:t}),(0,Y.jsx)(`div`,{className:`mt-1 min-h-[18px]`,children:n}),r&&(0,Y.jsx)(`div`,{className:`text-[12px] text-ink-3 mt-0.5 truncate`,children:r})]})}function $({groups:e,showRev:t,showExp:n}){let{t:r,lang:i}=d(),{money:a}=_();if(!e.length)return(0,Y.jsx)(`div`,{className:`text-[13.5px] text-ink-3 py-8 text-center`,children:r(`Nothing in this range`)});let s=e=>(t?e.revenueMinor:0)+(n?e.expenseMinor:0),c=Math.max(1,...e.map(s));return(0,Y.jsx)(`ul`,{className:`space-y-3`,children:e.map(e=>(0,Y.jsxs)(`li`,{children:[(0,Y.jsxs)(`div`,{className:`flex items-center justify-between text-[13.5px] mb-1.5`,children:[(0,Y.jsxs)(`span`,{className:`inline-flex items-center gap-2 truncate`,children:[(0,Y.jsx)(o,{color:e.color,size:9}),e.nameAr&&i===`ar`?e.nameAr:r(e.name),(0,Y.jsx)(`span`,{className:`num text-[12px] text-ink-3`,children:e.count})]}),(0,Y.jsxs)(`span`,{className:`num font-medium`,children:[a(s(e)),t&&n&&e.revenueMinor&&e.expenseMinor?(0,Y.jsxs)(`span`,{className:`text-ink-3 font-normal text-[12px]`,children:[` · `,r(`in {in} / out {out}`,{in:a(e.revenueMinor,{compact:!0}),out:a(e.expenseMinor,{compact:!0})})]}):null]})]}),(0,Y.jsxs)(`div`,{className:`h-2 rounded-full bg-sunken overflow-hidden flex gap-[2px]`,children:[t&&e.revenueMinor>0&&(0,Y.jsx)(`div`,{className:`h-full rounded-full`,style:{width:`${e.revenueMinor/c*100}%`,background:n?`var(--s-revenue)`:e.color}}),n&&e.expenseMinor>0&&(0,Y.jsx)(`div`,{className:`h-full rounded-full`,style:{width:`${e.expenseMinor/c*100}%`,background:t?`var(--s-expense)`:e.color}})]})]},e.id??`none`))})}function de({d:e,showRev:t,showExp:n}){let{t:r}=d(),{money:i,date:a,toMajor:o,locale:s}=_(),c=e.range.granularity,l=e=>new Intl.NumberFormat(s,{notation:`compact`,maximumFractionDigits:1}).format(o(e)),u=e=>c===`month`?new Intl.DateTimeFormat(s,{month:`short`,year:`2-digit`,timeZone:`UTC`}).format(new Date(`${e}T00:00:00Z`)):a(e,`short`),f=e.series.map(e=>({...e,label:u(e.bucket)})),p=[...t?[{label:r(`Revenue`),color:`var(--s-revenue)`}]:[],...n?[{label:r(`Expenses`),color:`var(--s-expense)`}]:[],{label:r(`Previous period`),color:`var(--ink-3)`,kind:`line`}];return(0,Y.jsxs)(`div`,{className:`h-full flex flex-col`,children:[(0,Y.jsx)(`div`,{className:`pb-2`,children:(0,Y.jsx)(E,{items:p})}),(0,Y.jsx)(`div`,{className:`flex-1 -ms-3`,children:(0,Y.jsx)(x,{width:`100%`,height:`100%`,children:(0,Y.jsxs)(te,{data:f,margin:{top:12,right:12,bottom:0,left:0},barGap:2,barCategoryGap:`28%`,children:[(0,Y.jsx)(w,{vertical:!1,stroke:`var(--line)`}),(0,Y.jsx)(D,{dataKey:`label`,tickLine:!1,axisLine:{stroke:`var(--line)`},tick:{fill:`var(--ink-3)`,fontSize:11},interval:`preserveStartEnd`,minTickGap:28}),(0,Y.jsx)(v,{tickLine:!1,axisLine:!1,tickFormatter:l,width:48,tick:{fill:`var(--ink-3)`,fontSize:11}}),(0,Y.jsx)(A,{cursor:{fill:`var(--card-hover)`,opacity:.8},content:({active:e,payload:o})=>{if(!e||!o?.length)return null;let s=o[0].payload;return(0,Y.jsx)(k,{title:c===`day`?a(s.bucket,`long`):c===`week`?r(`Week of {date}`,{date:a(s.bucket)}):u(s.bucket),rows:[...t?[{label:r(`Revenue`),value:`${i(s.revenueMinor)} · ${s.revenueCount}`,color:`var(--s-revenue)`},{label:r(`Prev. revenue`),value:i(s.prevRevenueMinor)}]:[],...n?[{label:r(`Expenses`),value:`${i(s.expenseMinor)} · ${s.expenseCount}`,color:`var(--s-expense)`},{label:r(`Prev. expenses`),value:i(s.prevExpenseMinor)}]:[]]})}}),t&&(0,Y.jsx)(O,{dataKey:`revenueMinor`,fill:`var(--s-revenue)`,radius:[4,4,0,0],maxBarSize:24,isAnimationActive:!1}),n&&(0,Y.jsx)(O,{dataKey:`expenseMinor`,fill:`var(--s-expense)`,radius:[4,4,0,0],maxBarSize:24,isAnimationActive:!1}),t&&(0,Y.jsx)(y,{type:`monotone`,dataKey:`prevRevenueMinor`,stroke:`var(--s-revenue)`,strokeDasharray:`4 4`,strokeOpacity:.7,strokeWidth:1.5,dot:!1,isAnimationActive:!1}),n&&(0,Y.jsx)(y,{type:`monotone`,dataKey:`prevExpenseMinor`,stroke:`var(--s-expense)`,strokeDasharray:`4 4`,strokeOpacity:.7,strokeWidth:1.5,dot:!1,isAnimationActive:!1})]})})})]})}function fe({d:e,showRev:t,showExp:n}){let{t:r,lang:i}=d(),{money:a,toMajor:o,locale:s}=_(),c=e=>new Intl.NumberFormat(s,{notation:`compact`,maximumFractionDigits:1}).format(o(e)),l=e.byWeekday.map(e=>({...e,full:r(e.label),label:i===`ar`?r(e.label):r(e.label).slice(0,3)}));return(0,Y.jsx)(x,{width:`100%`,height:`100%`,children:(0,Y.jsxs)(ae,{data:l,margin:{top:12,right:8,bottom:0,left:-8},barGap:2,barCategoryGap:`30%`,children:[(0,Y.jsx)(w,{vertical:!1,stroke:`var(--line)`}),(0,Y.jsx)(D,{dataKey:`label`,tickLine:!1,axisLine:{stroke:`var(--line)`},tick:{fill:`var(--ink-3)`,fontSize:11}}),(0,Y.jsx)(v,{tickLine:!1,axisLine:!1,tickFormatter:c,width:48,tick:{fill:`var(--ink-3)`,fontSize:11}}),(0,Y.jsx)(A,{cursor:{fill:`var(--card-hover)`,opacity:.8},content:({active:e,payload:i})=>{if(!e||!i?.length)return null;let o=i[0].payload;return(0,Y.jsx)(k,{title:r(`{day} · {n} days`,{day:o.full,n:o.days}),rows:[...t?[{label:r(`Avg revenue`),value:a(o.avgRevenueMinor),color:`var(--s-revenue)`}]:[],...n?[{label:r(`Avg expenses`),value:a(o.avgExpenseMinor),color:`var(--s-expense)`}]:[]]})}}),t&&(0,Y.jsx)(O,{dataKey:`avgRevenueMinor`,fill:`var(--s-revenue)`,radius:[4,4,0,0],maxBarSize:28,isAnimationActive:!1}),n&&(0,Y.jsx)(O,{dataKey:`avgExpenseMinor`,fill:`var(--s-expense)`,radius:[4,4,0,0],maxBarSize:28,isAnimationActive:!1})]})})}export{ce as InsightsPage};
@@ -1 +0,0 @@
1
- import{O as e,d as t,dt as n,g as r,gt as i,h as a,i as o,l as s,n as c,o as l,pt as u,s as d,v as f}from"./badge-BTiDEJlh.js";import{f as p,i as m,m as h,p as g,v as _}from"./queries-IGiwF8nF.js";import{n as v}from"./project-Bgpq3nFR.js";import{a as y,i as b,o as x,r as S,t as C}from"./table-DQsx5_iN.js";import{t as w}from"./download-CIyMPSgr.js";import{n as T,t as E}from"./search-jkqZqVJy.js";import{n as D,t as O}from"./pull-shift-sheet-DTwTC0rg.js";import{a as k,i as A,n as j,r as M,s as N,t as P}from"./media-Cr7juL5w.js";import{C as ee,b as F,c as te,d as I,g as ne,l as L,m as R,p as z}from"./index-DOwVPfdT.js";import{n as B}from"./format-GDcQVAp4.js";var V={name:`external-link`,size:24,node:[[`path`,{d:`M15 3h6v6`,key:`1q9fwt`}],[`path`,{d:`M10 14 21 3`,key:`gplh6r`}],[`path`,{d:`M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`,key:`a6xqqp`}]]};V.node;var H=r(V),U={name:`unplug`,size:24,node:[[`path`,{d:`m19 5 3-3`,key:`yk6iyv`}],[`path`,{d:`m2 22 3-3`,key:`19mgm9`}],[`path`,{d:`M6.3 20.3a2.4 2.4 0 0 0 3.4 0L12 18l-6-6-2.3 2.3a2.4 2.4 0 0 0 0 3.4Z`,key:`goz73y`}],[`path`,{d:`M7.5 13.5 10 11`,key:`7xgeeb`}],[`path`,{d:`M10.5 16.5 13 14`,key:`10btkg`}],[`path`,{d:`m12 6 6 6 2.3-2.3a2.4 2.4 0 0 0 0-3.4l-2.6-2.6a2.4 2.4 0 0 0-3.4 0Z`,key:`1snsnr`}]]};U.node;var W=r(U),G=i(u(),1),K=n(),q=`https://r.loyverse.com/dashboard/#/integrations/tokens`;function J(){let{t:e}=f(),n=p(),[r,i]=(0,G.useState)(!1);return(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(t,{title:e(`Integrations`),subtitle:e(`Pull data from the systems your business already runs on.`)}),n.isPending?(0,K.jsx)(s,{}):n.isError?(0,K.jsx)(d,{title:e(`Could not load integrations`),description:n.error.message}):n.data.connected?(0,K.jsx)(Z,{i:n.data,onReconnect:()=>i(!0)}):(0,K.jsxs)(`div`,{className:`grid grid-cols-1 xl:grid-cols-3 gap-4`,children:[(0,K.jsx)(l,{className:`xl:col-span-2`,children:(0,K.jsxs)(`div`,{className:`flex items-start gap-4 py-2`,children:[(0,K.jsx)(Y,{}),(0,K.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,K.jsx)(`h3`,{className:`text-[17px] font-semibold tracking-tight`,children:`Loyverse`}),(0,K.jsx)(c,{children:e(`Point of sale`)})]}),(0,K.jsx)(`p`,{className:`text-[13.5px] text-ink-2 mt-1 max-w-[52ch]`,children:e(`Keep the item catalogue in sync and turn each closed shift into a revenue row with one tap, cash only by default.`)}),(0,K.jsx)(`div`,{className:`mt-4`,children:(0,K.jsx)(I,{variant:`primary`,icon:(0,K.jsx)(F,{className:`size-4`}),onClick:()=>i(!0),children:e(`Connect Loyverse`)})})]})]})}),(0,K.jsx)(l,{title:e(`How it works`),children:(0,K.jsxs)(`ol`,{className:`text-[13.5px] text-ink-2 space-y-2 list-decimal ps-4`,children:[(0,K.jsx)(`li`,{children:e(`Create an access token in the Loyverse Back Office and paste it here.`)}),(0,K.jsx)(`li`,{children:e(`Sync items to see the catalogue with its categories.`)}),(0,K.jsx)(`li`,{children:e(`On the Revenue page, tap “Pull last shift” after closing the till.`)})]})})]}),(0,K.jsx)(X,{open:r,onClose:()=>i(!1)})]})}function Y(){return(0,K.jsx)(`span`,{className:`size-12 rounded-[14px] bg-[#1e9e6a]/12 text-[#1e9e6a] inline-flex items-center justify-center shrink-0 font-bold text-[18px] tracking-tight select-none`,"aria-hidden":!0,children:`L`})}function X({open:e,onClose:t}){let{t:n}=f(),r=R(),{connect:i}=h(),[a,o]=(0,G.useState)(``);(0,G.useEffect)(()=>{e&&o(``)},[e]);let s=async()=>{try{let e=await i.mutateAsync({accessToken:a.trim()});r.success(n(`Connected to {name}`,{name:e.merchantName??`Loyverse`}),n(`{stores} stores · {types} payment types`,{stores:e.stores.length,types:e.paymentTypes.length})),t()}catch(e){r.error(n(`Could not connect`),z(e))}},c=a.trim().length>=10;return(0,K.jsx)(L,{open:e,onClose:t,title:n(`Connect Loyverse`),description:n(`A personal access token gives ledgr read access to this Loyverse account.`),width:480,footer:(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(I,{variant:`ghost`,size:`md`,onClick:t,children:n(`Cancel`)}),(0,K.jsx)(I,{variant:`primary`,size:`md`,onClick:s,loading:i.isPending,disabled:!c,children:n(`Connect`)})]}),children:(0,K.jsxs)(`form`,{className:`space-y-4`,onSubmit:e=>{e.preventDefault(),c&&s()},children:[(0,K.jsx)(M,{label:n(`Access token`),required:!0,hint:(0,K.jsxs)(`a`,{className:`inline-flex items-center gap-1 text-accent`,href:q,target:`_blank`,rel:`noreferrer`,children:[n(`Back Office → Integrations → Access tokens`),` `,(0,K.jsx)(H,{className:`size-3`})]}),children:(0,K.jsx)(A,{mono:!0,autoFocus:!0,value:a,onChange:e=>o(e.target.value),placeholder:`fMYgxHEYtcyT8cvtvgi1Za5DRs4vArSy…`,autoComplete:`off`,spellCheck:!1})}),(0,K.jsx)(`p`,{className:`text-[12.5px] text-ink-3`,children:n(`The token is stored in this project’s database only. Its currency must match the project currency.`)})]})})}function Z({i:t,onReconnect:n}){let{t:r,name:i}=f(),{locale:o}=v(),s=R(),{syncItems:u,disconnect:d,settings:p}=h(),g=m(`revenue`),y=_(!0),[b,x]=(0,G.useState)(!1),[S,C]=(0,G.useState)(!1),[E,D]=(0,G.useState)(t.settings.storeIds),[A,P]=(0,G.useState)(t.settings.paymentTypeIds),[F,L]=(0,G.useState)(t.settings.methodMap),[V,H]=(0,G.useState)(t.settings.categoryId??``),[U,q]=(0,G.useState)(t.settings.subtractPayouts??!0);(0,G.useEffect)(()=>{D(t.settings.storeIds),P(t.settings.paymentTypeIds),L(t.settings.methodMap),H(t.settings.categoryId??``),q(t.settings.subtractPayouts??!0)},[t.settings]);let J=A.length?A:t.paymentTypes.filter(e).map(e=>e.id),X=JSON.stringify({storeIds:E,typeIds:A,methodMap:F,categoryId:V,subtractPayouts:U})!==JSON.stringify({storeIds:t.settings.storeIds,typeIds:t.settings.paymentTypeIds,methodMap:t.settings.methodMap,categoryId:t.settings.categoryId??``,subtractPayouts:t.settings.subtractPayouts??!0}),Z=async()=>{try{await p.mutateAsync({storeIds:E,paymentTypeIds:J,methodMap:F,categoryId:V||null,subtractPayouts:U}),s.success(r(`Integration settings saved`))}catch(e){s.error(r(`Could not save`),z(e))}},$=(e,t)=>e.includes(t)?e.filter(e=>e!==t):[...e,t],ie=(y.data?.items??[]).filter(e=>!e.archived);return(0,K.jsxs)(`div`,{className:`space-y-4`,children:[t.lastError&&(0,K.jsxs)(`div`,{className:`card px-4 py-3 flex items-start gap-3 border-warning/40`,children:[(0,K.jsx)(ne,{className:`size-5 text-warning shrink-0 mt-0.5`}),(0,K.jsxs)(`div`,{className:`min-w-0 text-[13.5px]`,children:[(0,K.jsx)(`span`,{className:`font-medium`,children:r(`Last Loyverse call failed`)}),(0,K.jsx)(`div`,{className:`text-ink-3 break-words`,children:t.lastError})]})]}),(0,K.jsxs)(`div`,{className:`grid grid-cols-1 xl:grid-cols-3 gap-4`,children:[(0,K.jsx)(l,{className:`xl:col-span-2`,children:(0,K.jsxs)(`div`,{className:`flex items-start gap-4 py-1`,children:[(0,K.jsx)(Y,{}),(0,K.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,K.jsx)(`h3`,{className:`text-[17px] font-semibold tracking-tight truncate`,children:t.merchantName??`Loyverse`}),(0,K.jsxs)(c,{tone:`good`,children:[(0,K.jsx)(ee,{className:`size-3`}),` `,r(`Connected`)]}),t.currency&&(0,K.jsx)(c,{children:t.currency})]}),(0,K.jsxs)(`dl`,{className:`mt-2 grid grid-cols-2 sm:grid-cols-4 gap-x-4 gap-y-1 text-[12.5px]`,children:[(0,K.jsx)(Q,{label:r(`Stores`),value:String(t.stores.length)}),(0,K.jsx)(Q,{label:r(`Items`),value:String(t.itemCount),sub:t.lastItemsSyncAt?r(`synced {when}`,{when:B(t.lastItemsSyncAt,o)}):r(`not synced yet`)}),(0,K.jsx)(Q,{label:r(`Categories`),value:String(t.categoryCount)}),(0,K.jsx)(Q,{label:r(`Shifts pulled`),value:String(t.shiftCount),sub:t.lastShiftPullAt?r(`last {when}`,{when:B(t.lastShiftPullAt,o)}):void 0})]}),(0,K.jsxs)(`div`,{className:`mt-4 flex flex-wrap gap-2`,children:[(0,K.jsx)(I,{variant:`primary`,icon:(0,K.jsx)(T,{className:a(`size-4`,u.isPending&&`animate-spin`)}),loading:u.isPending,onClick:async()=>{try{let e=await u.mutateAsync();s.success(r(`Items synced`),r(`{items} items · {categories} categories{removed}`,{items:e.items,categories:e.categories,removed:e.removed?` · ${r(`{n} removed`,{n:e.removed})}`:``}))}catch(e){s.error(r(`Sync failed`),z(e))}},children:r(`Sync items`)}),(0,K.jsx)(I,{variant:`secondary`,icon:(0,K.jsx)(w,{className:`size-4`}),onClick:()=>C(!0),children:r(`Pull last shift`)}),(0,K.jsx)(I,{variant:`ghost`,onClick:n,children:r(`Replace token`)}),(0,K.jsx)(I,{variant:`ghost`,className:`text-critical`,icon:(0,K.jsx)(W,{className:`size-4`}),onClick:()=>x(!0),children:r(`Disconnect`)})]})]})]})}),(0,K.jsx)(l,{title:r(`Shift pulls`),subtitle:r(`What goes on the revenue row`),actions:X?(0,K.jsx)(I,{size:`xs`,variant:`primary`,loading:p.isPending,onClick:Z,children:r(`Save`)}):void 0,children:(0,K.jsxs)(`div`,{className:`space-y-4`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`div`,{className:`label mb-1.5`,children:r(`Payment types to pull`)}),(0,K.jsxs)(`ul`,{className:`space-y-1.5`,children:[t.paymentTypes.map(t=>(0,K.jsxs)(`li`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(j,{label:(0,K.jsxs)(`span`,{dir:`auto`,children:[t.name,` `,(0,K.jsx)(`span`,{className:`text-ink-3 text-[12px]`,children:e(t)?r(`cash`):t.type===`NONINTEGRATEDCARD`?r(`card`):t.type.toLowerCase()})]}),checked:J.includes(t.id),onChange:()=>P($(J,t.id))}),J.includes(t.id)&&(0,K.jsxs)(k,{compact:!0,className:`ms-auto w-[150px]`,value:F[t.id]??``,onChange:e=>L(()=>{let n={...F};return e.target.value?n[t.id]=e.target.value:delete n[t.id],n}),title:r(`ledgr payment method`),children:[(0,K.jsx)(`option`,{value:``,children:r(`→ “{name}” (auto)`,{name:e(t)?r(`Cash`):t.name})}),ie.map(e=>(0,K.jsxs)(`option`,{value:e.id,children:[`→ `,i(e)]},e.id))]})]},t.id)),!t.paymentTypes.length&&(0,K.jsx)(`li`,{className:`text-[13px] text-ink-3`,children:r(`No payment types found in Loyverse.`)})]}),(0,K.jsx)(`p`,{className:`text-[12px] text-ink-3 mt-1.5`,children:r(`Cash-like types are summed into one Cash amount. Unticked types stay in Loyverse (shown on the shift, not added to the ledger).`)})]}),t.stores.length>1&&(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`div`,{className:`label mb-1.5`,children:r(`Stores`)}),(0,K.jsx)(`ul`,{className:`space-y-1.5`,children:t.stores.map(e=>(0,K.jsx)(`li`,{children:(0,K.jsx)(j,{label:e.name,checked:!E.length||E.includes(e.id),onChange:()=>D(E.length?$(E,e.id):t.stores.filter(t=>t.id!==e.id).map(e=>e.id))})},e.id))})]}),(0,K.jsx)(N,{checked:U,onChange:q,label:r(`Subtract cash pay-outs`),description:r(`Money taken out of the drawer during the shift (supplies, petty cash) comes off the cash amount.`)}),(0,K.jsx)(M,{label:r(`Revenue category`),hint:r(`for the shift rows`),children:(0,K.jsxs)(k,{value:V,onChange:e=>H(e.target.value),children:[(0,K.jsx)(`option`,{value:``,children:r(`Default category`)}),(g.data?.items??[]).filter(e=>!e.archived).map(e=>(0,K.jsx)(`option`,{value:e.id,children:i(e)},e.id))]})})]})})]}),(0,K.jsx)(re,{i:t}),(0,K.jsx)(O,{open:S,onClose:()=>C(!1)}),(0,K.jsx)(te,{open:b,onClose:()=>x(!1),loading:d.isPending,title:r(`Disconnect Loyverse?`),description:r(`The token and the cached catalogue are removed. Revenue rows already pulled stay in the ledger.`),onConfirm:async()=>{try{await d.mutateAsync(),x(!1),s.success(r(`Loyverse disconnected`))}catch(e){s.error(r(`Failed`),z(e))}}})]})}function Q({label:e,value:t,sub:n}){return(0,K.jsxs)(`div`,{className:`min-w-0`,children:[(0,K.jsx)(`dt`,{className:`text-ink-3`,children:e}),(0,K.jsxs)(`dd`,{className:`num text-[15px] font-semibold text-ink`,children:[t,n&&(0,K.jsx)(`span`,{className:`block num text-[11.5px] font-normal text-ink-3 truncate`,children:n})]})]})}function re({i:e}){let{t}=f(),{money:n}=v(),r=P(),[i,s]=(0,G.useState)(``),[c,u]=(0,G.useState)(``),[p,m]=(0,G.useState)(``);(0,G.useEffect)(()=>{let e=setTimeout(()=>m(i.trim()),200);return()=>clearTimeout(e)},[i]);let h=g((0,G.useMemo)(()=>({q:p||void 0,categoryId:c||void 0}),[p,c])),_=h.data?.items??[],w=h.data?.categories.filter(e=>!e.deletedAt)??[];return!e.itemCount&&!h.data?.total&&!p&&!c?(0,K.jsx)(l,{flush:!0,children:(0,K.jsx)(d,{icon:(0,K.jsx)(D,{}),title:t(`No items yet`),description:t(`Sync items to see the Loyverse catalogue here with its categories, prices and costs.`)})}):(0,K.jsx)(l,{title:t(`Items`),subtitle:h.data?t(`{n} items in {c} categories`,{n:h.data.total,c:w.length}):void 0,flush:!0,actions:(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsxs)(k,{compact:!0,value:c,onChange:e=>u(e.target.value),className:`w-[150px]`,children:[(0,K.jsx)(`option`,{value:``,children:t(`All categories`)}),w.map(e=>(0,K.jsxs)(`option`,{value:e.id,children:[e.name,` (`,e.itemCount,`)`]},e.id)),(0,K.jsx)(`option`,{value:`none`,children:t(`Uncategorised`)})]}),(0,K.jsxs)(`div`,{className:`relative`,children:[(0,K.jsx)(E,{className:`size-4 absolute start-2.5 top-1/2 -translate-y-1/2 text-ink-3 pointer-events-none`}),(0,K.jsx)(A,{compact:!0,value:i,onChange:e=>s(e.target.value),placeholder:t(`Search items`),className:`ps-8 w-[160px] md:w-[220px]`})]})]}),children:r?(0,K.jsxs)(`ul`,{className:`divide-y divide-line`,children:[_.map(e=>(0,K.jsxs)(`li`,{className:`px-4 py-3 flex items-center gap-3`,children:[(0,K.jsx)(o,{color:$(e.category?.color),size:10}),(0,K.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,K.jsx)(`div`,{dir:`auto`,className:`text-[14.5px] font-medium truncate`,children:e.name}),(0,K.jsxs)(`div`,{className:`text-[12.5px] text-ink-3 truncate`,children:[e.category?.name??t(`Uncategorised`),e.sku?` · ${e.sku}`:``,e.variantCount>1?` · ${t(`{n} variants`,{n:e.variantCount})}`:``]})]}),(0,K.jsx)(`div`,{className:`text-end num text-[14px]`,children:e.priceMinor===null?(0,K.jsx)(`span`,{className:`text-ink-4`,children:`—`}):n(e.priceMinor)})]},e.id)),!_.length&&(0,K.jsx)(`li`,{className:`px-4 py-8 text-center text-[13px] text-ink-3`,children:t(`No items match.`)})]}):(0,K.jsxs)(S,{children:[(0,K.jsx)(`thead`,{children:(0,K.jsxs)(`tr`,{children:[(0,K.jsx)(y,{children:t(`Item`)}),(0,K.jsx)(y,{children:t(`Category`)}),(0,K.jsx)(y,{children:t(`SKU`)}),(0,K.jsx)(y,{align:`right`,children:t(`Price`)}),(0,K.jsx)(y,{align:`right`,children:t(`Cost`)}),(0,K.jsx)(y,{align:`right`,children:t(`Margin`)})]})}),(0,K.jsxs)(`tbody`,{children:[h.isPending&&(0,K.jsx)(C,{colSpan:6,children:t(`Loading…`)}),!h.isPending&&!_.length&&(0,K.jsx)(C,{colSpan:6,children:t(`No items match.`)}),_.map(e=>{let r=e.priceMinor&&e.costMinor!==null?(e.priceMinor-e.costMinor)/e.priceMinor*100:null;return(0,K.jsxs)(x,{children:[(0,K.jsxs)(b,{children:[(0,K.jsx)(`div`,{dir:`auto`,className:`font-medium truncate max-w-[360px]`,children:e.name}),e.variantCount>1&&(0,K.jsx)(`div`,{className:`text-[12px] text-ink-3`,children:t(`{n} variants`,{n:e.variantCount})})]}),(0,K.jsx)(b,{children:e.category?(0,K.jsxs)(`span`,{className:`inline-flex items-center gap-1.5 text-[13px] text-ink-2`,children:[(0,K.jsx)(o,{color:$(e.category.color)}),e.category.name]}):(0,K.jsx)(`span`,{className:`text-ink-4`,children:`—`})}),(0,K.jsx)(b,{className:`mono text-[12.5px] text-ink-2`,children:e.sku??(0,K.jsx)(`span`,{className:`text-ink-4`,children:`—`})}),(0,K.jsx)(b,{align:`right`,className:`num`,children:e.priceMinor===null?(0,K.jsx)(`span`,{className:`text-ink-4`,children:`—`}):n(e.priceMinor)}),(0,K.jsx)(b,{align:`right`,className:`num text-ink-2`,children:e.costMinor===null?(0,K.jsx)(`span`,{className:`text-ink-4`,children:`—`}):n(e.costMinor)}),(0,K.jsx)(b,{align:`right`,className:a(`num`,r!==null&&r<0&&`text-critical`),children:r===null?(0,K.jsx)(`span`,{className:`text-ink-4`,children:`—`}):`${Math.round(r)}%`})]},e.id)})]})]})})}function $(e){return e&&{GREY:`#9aa0ab`,RED:`#e5484d`,PINK:`#e93d82`,ORANGE:`#f76b15`,YELLOW:`#f5b400`,GREEN:`#30a46c`,BLUE:`#3e63dd`,PURPLE:`#8e4ec6`}[e.toUpperCase()]||`var(--s-other)`}export{J as IntegrationsPage};
@@ -1 +0,0 @@
1
- import{a as e,c as t,d as n,dt as r,gt as i,h as a,i as o,l as s,n as c,o as l,pt as u,s as d,v as f,y as p}from"./badge-BTiDEJlh.js";import{_ as m,v as h}from"./queries-IGiwF8nF.js";import{n as g,r as _,t as v}from"./star-cwF2fEe6.js";import{a as y,i as b,n as x,o as S,r as C,t as w}from"./menu-BDGd2JUq.js";import{i as T,n as E,r as D,s as O}from"./media-Cr7juL5w.js";import{c as k,d as A,l as j,m as M,p as N,x as P,y as F}from"./index-DOwVPfdT.js";import{t as I}from"./color-picker-DLlr-Cq6.js";var L=i(u(),1),R=r();function z({open:e,onClose:t,method:n}){let r=M(),{t:i}=f(),{create:a,update:o}=m(),[s,c]=(0,L.useState)(``),[l,u]=(0,L.useState)(``),[d,h]=(0,L.useState)(p[0]),[g,_]=(0,L.useState)(!1),[v,y]=(0,L.useState)(!1);(0,L.useEffect)(()=>{e&&(c(n?.name??``),u(n?.nameAr??``),h(n?.color??p[Math.floor(Math.random()*7)]),_(n?.isDefault??!1),y(n?.archived??!1))},[e,n]);let b=s.trim().length>0,x=a.isPending||o.isPending,S=async()=>{let e={name:s.trim(),nameAr:l.trim()||null,color:d,isDefault:g,archived:v};try{n?await o.mutateAsync({id:n.id,...e}):await a.mutateAsync(e),r.success(i(n?`Payment method updated`:`Payment method added`)),t()}catch(e){r.error(i(`Could not save`),N(e))}};return(0,R.jsx)(j,{open:e,onClose:t,title:i(n?`Edit payment method`:`New payment method`),footer:(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(A,{variant:`ghost`,size:`md`,onClick:t,children:i(`Cancel`)}),(0,R.jsx)(A,{variant:`primary`,size:`md`,onClick:S,loading:x,disabled:!b,children:i(n?`Save`:`Add`)})]}),children:(0,R.jsxs)(`form`,{className:`space-y-4`,onSubmit:e=>{e.preventDefault(),b&&S()},children:[(0,R.jsx)(D,{label:i(`Name`),required:!0,children:(0,R.jsx)(T,{value:s,onChange:e=>c(e.target.value),autoFocus:!0,placeholder:i(`Cash, Visa, Instapay, PayPal…`)})}),(0,R.jsx)(D,{label:i(`Arabic name`),hint:i(`optional`),children:(0,R.jsx)(T,{lang:`ar`,dir:`rtl`,value:l,onChange:e=>u(e.target.value),placeholder:`كاش، فيزا، إنستاباي…`})}),(0,R.jsx)(I,{value:d,onChange:h}),(0,R.jsx)(O,{checked:g,onChange:_,label:i(`Default for new entries`),description:i(`The expense and revenue forms ask for this method's amount first. Only one method can be the default.`)}),n&&(0,R.jsx)(O,{checked:!v,onChange:e=>y(!e),label:i(`Active`),description:i(v?`Archived: hidden from forms, history kept`:`Shown in forms, filters and exports`)})]})})}var B=[`Cash`,`Visa`,`Mastercard`,`Bank transfer`,`Instapay`,`Vodafone Cash`,`PayPal`,`Stripe`,`Online payment`];function V(){let[r,i]=(0,L.useState)(!1),u=h(!0),{create:p,update:T,remove:D}=m(),O=M(),{t:j,name:I}=f(),[V,H]=(0,L.useState)(void 0),[U,W]=(0,L.useState)(null),G=u.data?.items??[],K=G.filter(e=>r||!e.archived),q=B.filter(e=>!G.some(t=>t.name.toLowerCase()===e.toLowerCase()));return(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(n,{title:j(`Payment methods`),subtitle:j(`Cash, cards, online… Each expense and revenue row can hold an amount per method. Shown in tables, analytics and exports.`),actions:(0,R.jsx)(A,{variant:`primary`,size:`sm`,className:`rounded-full`,icon:(0,R.jsx)(F,{className:`size-4`}),onClick:()=>H(null),children:j(`New method`)})}),(0,R.jsx)(`div`,{className:`flex items-center justify-end mb-4`,children:(0,R.jsx)(E,{label:j(`Archived`),checked:r,onChange:e=>i(e.target.checked)})}),(0,R.jsxs)(`div`,{className:`grid grid-cols-1 xl:grid-cols-3 gap-4`,children:[(0,R.jsx)(l,{className:`xl:col-span-2`,flush:!0,children:u.isPending?(0,R.jsx)(s,{}):K.length?(0,R.jsx)(`ul`,{className:`divide-y divide-line`,children:K.map(n=>(0,R.jsxs)(`li`,{className:a(`flex items-center`,n.archived&&`opacity-60`),children:[(0,R.jsx)(t,{className:`flex-1`,leading:(0,R.jsx)(e,{color:n.color,children:(0,R.jsx)(o,{color:n.color,size:12})}),title:(0,R.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[I(n),n.isDefault&&(0,R.jsx)(c,{tone:`accent`,children:j(`default`)}),n.archived&&(0,R.jsx)(c,{children:j(`archived`)})]}),onClick:()=>H(n)}),(0,R.jsx)(`div`,{className:`pe-3`,children:(0,R.jsx)(w,{trigger:()=>(0,R.jsx)(`button`,{type:`button`,className:`size-9 inline-flex items-center justify-center rounded-full text-ink-3 hover:text-ink hover:bg-card-hover`,"aria-label":j(`Actions`),children:(0,R.jsx)(S,{className:`size-4`})}),children:e=>(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(x,{icon:(0,R.jsx)(y,{}),onClick:()=>{e(),H(n)},children:j(`Edit`)}),!n.archived&&(0,R.jsx)(x,{icon:(0,R.jsx)(v,{}),onClick:async()=>{e();try{await T.mutateAsync({id:n.id,isDefault:!n.isDefault})}catch(e){O.error(j(`Failed`),N(e))}},children:j(n.isDefault?`Remove as default`:`Make default`)}),(0,R.jsx)(x,{icon:n.archived?(0,R.jsx)(_,{}):(0,R.jsx)(g,{}),onClick:async()=>{e();try{await T.mutateAsync({id:n.id,archived:!n.archived})}catch(e){O.error(j(`Failed`),N(e))}},children:j(n.archived?`Restore`:`Archive`)}),(0,R.jsx)(C,{}),(0,R.jsx)(x,{icon:(0,R.jsx)(b,{}),danger:!0,onClick:()=>{e(),W(n)},children:j(`Delete`)})]})})})]},n.id))}):(0,R.jsx)(d,{icon:(0,R.jsx)(P,{}),title:j(`No payment methods yet`),description:j(`Add the ways this project gets paid. Pick from the suggestions or create your own.`),action:(0,R.jsx)(A,{variant:`soft`,onClick:()=>H(null),children:j(`Add one`)})})}),(0,R.jsx)(l,{title:j(`Quick add`),subtitle:j(`Common ones, one tap each`),children:q.length?(0,R.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:q.map(e=>(0,R.jsx)(A,{size:`sm`,variant:`secondary`,className:`rounded-full`,icon:(0,R.jsx)(F,{className:`size-3.5`}),loading:p.isPending&&p.variables?.name===e,onClick:async()=>{try{await p.mutateAsync({name:e,isDefault:G.length===0})}catch(e){O.error(j(`Could not add`),N(e))}},children:e},e))}):(0,R.jsx)(`p`,{className:`text-[13.5px] text-ink-3`,children:j(`All suggestions are already added.`)})})]}),(0,R.jsx)(z,{open:V!==void 0,onClose:()=>H(void 0),method:V??null}),(0,R.jsx)(k,{open:!!U,onClose:()=>W(null),onConfirm:async()=>{try{await D.mutateAsync(U.id),O.success(j(`Payment method deleted`)),W(null)}catch(e){O.error(j(`Could not delete`),N(e))}},loading:D.isPending,title:j(`Delete {name}?`,{name:I(U)}),description:j(`Only possible when no revenue uses it. Otherwise archive it instead.`)})]})}export{V as PaymentsPage};
@@ -1 +0,0 @@
1
- import{A as e,B as t,D as n,U as r,dt as i,gt as a,j as o,k as s,pt as c,v as l}from"./badge-BTiDEJlh.js";var u=a(c(),1),d=i(),f=(0,u.createContext)(null);function p(){return r({queryKey:[`project`],queryFn:()=>t.get(`/project`),staleTime:6e4})}function m({project:t,children:r}){let{intlLocale:i}=l(),a=(0,u.useMemo)(()=>{let{currency:r,weekStartsOn:a,fiscalYearStartMonth:c}=t.config,l=i(t.config.locale),u={short:new Intl.DateTimeFormat(l,{day:`2-digit`,month:`short`,timeZone:`UTC`}),medium:new Intl.DateTimeFormat(l,{day:`2-digit`,month:`short`,year:`numeric`,timeZone:`UTC`}),long:new Intl.DateTimeFormat(l,{weekday:`short`,day:`2-digit`,month:`long`,year:`numeric`,timeZone:`UTC`})};return{project:t,currency:r,locale:l,weekStartsOn:a,fiscalYearStartMonth:c,digits:o(r),money:(e,t)=>n(e,r,{locale:l,...t}),toMajor:t=>e(t,r),toMinor:e=>s(e,r),date:(e,t=`medium`)=>{if(!e)return``;let n=new Date(`${e.slice(0,10)}T00:00:00Z`);return Number.isNaN(n.getTime())?e:u[t].format(n)}}},[t,i]);return(0,d.jsx)(f.Provider,{value:a,children:r})}function h(){let e=(0,u.useContext)(f);if(!e)throw Error(`useProject outside ProjectProvider`);return e}export{h as n,p as r,m as t};
@@ -1 +0,0 @@
1
- import{B as e,G as t,J as n,K as r,Q as i,U as a,X as o,et as s,gt as c,ot as l,pt as u,rt as d,st as f,ut as p}from"./badge-BTiDEJlh.js";var m=class extends t{#e;#t;#n;#r;constructor(e){super(),this.#e=e.client,this.mutationId=e.mutationId,this.#n=e.mutationCache,this.#t=[],this.state=e.state||h(),this.setOptions(e.options),this.scheduleGc()}setOptions(e){this.options=e,this.updateGcTime(this.options.gcTime)}get meta(){return this.options.meta}addObserver(e){this.#t.includes(e)||(this.#t.push(e),this.clearGcTimeout(),this.#n.notify({type:`observerAdded`,mutation:this,observer:e}))}removeObserver(e){this.#t=this.#t.filter(t=>t!==e),this.scheduleGc(),this.#n.notify({type:`observerRemoved`,mutation:this,observer:e})}optionalRemove(){this.#t.length||(this.state.status===`pending`?this.scheduleGc():this.#n.remove(this))}continue(){return this.#r?.continue()??(this.state.status===`pending`?this.execute(this.state.variables):Promise.resolve())}async execute(e){let t=()=>{this.#i({type:`continue`})},n={client:this.#e,meta:this.options.meta,mutationKey:this.options.mutationKey},i=this.#r=r({fn:()=>this.options.mutationFn?this.options.mutationFn(e,n):Promise.reject(Error(`No mutationFn found`)),onFail:(e,t)=>{this.#i({type:`failed`,failureCount:e,error:t})},onPause:()=>{this.#i({type:`pause`})},onContinue:t,retry:this.options.retry??0,retryDelay:this.options.retryDelay,networkMode:this.options.networkMode,canRun:()=>this.#n.canRun(this)}),a=this.state.status===`pending`,o=!i.canStart();try{if(a)t();else{this.#i({type:`pending`,variables:e,isPaused:o}),this.#n.config.onMutate&&await this.#n.config.onMutate(e,this,n);let t=await this.options.onMutate?.(e,n);t!==this.state.context&&this.#i({type:`pending`,context:t,variables:e,isPaused:o})}let r=await i.start();return await this.#n.config.onSuccess?.(r,e,this.state.context,this,n),await this.options.onSuccess?.(r,e,this.state.context,n),await this.#n.config.onSettled?.(r,null,this.state.variables,this.state.context,this,n),await this.options.onSettled?.(r,null,e,this.state.context,n),this.#i({type:`success`,data:r}),r}catch(t){try{await this.#n.config.onError?.(t,e,this.state.context,this,n)}catch(e){Promise.reject(e)}try{await this.options.onError?.(t,e,this.state.context,n)}catch(e){Promise.reject(e)}try{await this.#n.config.onSettled?.(void 0,t,this.state.variables,this.state.context,this,n)}catch(e){Promise.reject(e)}try{await this.options.onSettled?.(void 0,t,e,this.state.context,n)}catch(e){Promise.reject(e)}throw this.#i({type:`error`,error:t}),t}finally{this.#r===i&&(this.#r=void 0),this.#n.runNext(this)}}#i(e){let t=t=>{switch(e.type){case`failed`:return{...t,failureCount:e.failureCount,failureReason:e.error};case`pause`:return{...t,isPaused:!0};case`continue`:return{...t,isPaused:!1};case`pending`:return{...t,context:e.context,data:void 0,failureCount:0,failureReason:null,error:null,isPaused:e.isPaused,status:`pending`,variables:e.variables,submittedAt:Date.now()};case`success`:return{...t,data:e.data,failureCount:0,failureReason:null,error:null,status:`success`,isPaused:!1};case`error`:return{...t,data:void 0,error:e.error,failureCount:t.failureCount+1,failureReason:e.error,isPaused:!1,status:`error`}}};this.state=t(this.state),n.batch(()=>{this.#t.forEach(t=>{t.onMutationUpdate(e)}),this.#n.notify({mutation:this,type:`updated`,action:e})})}};function h(){return{context:void 0,data:void 0,error:null,failureCount:0,failureReason:null,isPaused:!1,status:`idle`,variables:void 0,submittedAt:0}}var g=class extends o{#e;#t=void 0;#n;#r;constructor(e,t){super(),this.#e=e,this.setOptions(t),this.bindMethods(),this.#i()}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(e){let t=this.options;this.options=this.#e.defaultMutationOptions(e),l(this.options,t)||this.#e.getMutationCache().notify({type:`observerOptionsUpdated`,mutation:this.#n,observer:this}),t?.mutationKey&&this.options.mutationKey&&i(t.mutationKey)!==i(this.options.mutationKey)?this.reset():this.#n?.state.status===`pending`&&this.#n.setOptions(this.options)}onSubscribe(){this.listeners.size===1&&this.#n&&(this.#n.addObserver(this),this.#i())}onUnsubscribe(){this.hasListeners()||this.#n?.removeObserver(this)}onMutationUpdate(e){this.#i(),this.#a(e)}getCurrentResult(){return this.#t}reset(){this.#n?.removeObserver(this),this.#n=void 0,this.#i(),this.#a()}mutate(e,t){return this.#r=t,this.#n?.removeObserver(this),this.#n=this.#e.getMutationCache().build(this.#e,this.options),this.#n.addObserver(this),this.#n.execute(e)}#i(){let e=this.#n?.state??h();this.#t={...e,isPending:e.status===`pending`,isSuccess:e.status===`success`,isError:e.status===`error`,isIdle:e.status===`idle`,mutate:this.mutate,reset:this.reset}}#a(e){n.batch(()=>{let t=this.#r;if(t&&this.hasListeners()){let n=this.#t.variables,r=this.#t.context,i={client:this.#e,meta:this.options.meta,mutationKey:this.options.mutationKey};if(e?.type===`success`){try{t.onSuccess?.(e.data,n,r,i)}catch(e){Promise.reject(e)}try{t.onSettled?.(e.data,null,n,r,i)}catch(e){Promise.reject(e)}}else if(e?.type===`error`){try{t.onError?.(e.error,n,r,i)}catch(e){Promise.reject(e)}try{t.onSettled?.(void 0,e.error,n,r,i)}catch(e){Promise.reject(e)}}}this.listeners.forEach(e=>{e(this.#t)})})}},_=c(u(),1);function v(e,t){let r=p(t),[i]=_.useState(()=>new g(r,e));_.useEffect(()=>{i.setOptions(e)},[i,e]);let a=_.useSyncExternalStore(_.useCallback(e=>i.subscribe(n.batchCalls(e)),[i]),()=>i.getCurrentResult(),()=>i.getCurrentResult()),o=_.useCallback((...e)=>{i.mutate(e[0],e[1]).catch(d)},[i]);if(a.error&&f(i.options.throwOnError,[a.error]))throw a.error;return{...a,mutate:o,mutateAsync:a.mutate}}function y(e){return Array.isArray(e)?{items:e}:e}function b(){let e=p();return()=>Promise.all([e.invalidateQueries({queryKey:[`expenses`]}),e.invalidateQueries({queryKey:[`revenue`]}),e.invalidateQueries({queryKey:[`analytics`]}),e.invalidateQueries({queryKey:[`balances`]}),e.invalidateQueries({queryKey:[`distribution`]}),e.invalidateQueries({queryKey:[`budgets`]}),e.invalidateQueries({queryKey:[`settlements`]}),e.invalidateQueries({queryKey:[`stakeholders`]}),e.invalidateQueries({queryKey:[`categories`]}),e.invalidateQueries({queryKey:[`payment-methods`]}),e.invalidateQueries({queryKey:[`recurring`]}),e.invalidateQueries({queryKey:[`audit`]}),e.invalidateQueries({queryKey:[`project`]})])}var x=(t,n)=>a({queryKey:[`analytics`,t,n],queryFn:()=>e.get(`/analytics/overview`,{from:t,to:n}),placeholderData:s}),S=t=>a({queryKey:[`analytics`,`insights`,t],queryFn:()=>e.get(`/analytics/insights`,t),placeholderData:s}),C=()=>a({queryKey:[`stakeholders`],queryFn:()=>e.get(`/stakeholders`).then(e=>Array.isArray(e)?{items:e,shareTotal:e.filter(e=>e.active).reduce((e,t)=>e+t.sharePercent,0)}:e),staleTime:3e4}),w=(t,n)=>a({queryKey:[`balances`,t,n],queryFn:()=>e.get(`/stakeholders/balances`,{from:t,to:n}),placeholderData:s}),T=(t,n)=>a({queryKey:[`distribution`,t,n],queryFn:()=>e.get(`/stakeholders/distribution`,{from:t,to:n}),placeholderData:s});function E(){let t=b();return{create:v({mutationFn:t=>e.post(`/stakeholders`,t),onSuccess:t}),update:v({mutationFn:({id:t,...n})=>e.patch(`/stakeholders/${t}`,n),onSuccess:t}),remove:v({mutationFn:({id:t,force:n})=>e.delete(`/stakeholders/${t}`,{force:n}),onSuccess:t})}}var D=(t,n=!1)=>a({queryKey:[`categories`,t??`all`,n],queryFn:()=>e.get(`/categories`,{kind:t,includeArchived:n||void 0}).then(y),staleTime:3e4}),O=t=>a({queryKey:[`budgets`,t],queryFn:()=>e.get(`/categories/budgets`,{month:t}).then(e=>({month:(Array.isArray(e)?void 0:e.month)??t??new Date().toISOString().slice(0,7),items:Array.isArray(e)?e:e.items}))});function k(){let t=b();return{create:v({mutationFn:t=>e.post(`/categories`,t),onSuccess:t}),update:v({mutationFn:({id:t,...n})=>e.patch(`/categories/${t}`,n),onSuccess:t}),remove:v({mutationFn:t=>e.delete(`/categories/${t}`),onSuccess:t})}}var A=(t=!1)=>a({queryKey:[`payment-methods`,t],queryFn:()=>e.get(`/payment-methods`,{includeArchived:t||void 0}).then(y),staleTime:3e4});function j(){let t=b();return{create:v({mutationFn:t=>e.post(`/payment-methods`,t),onSuccess:t}),update:v({mutationFn:({id:t,...n})=>e.patch(`/payment-methods/${t}`,n),onSuccess:t}),remove:v({mutationFn:t=>e.delete(`/payment-methods/${t}`),onSuccess:t}),reorder:v({mutationFn:t=>e.post(`/payment-methods/reorder`,{ids:t}),onSuccess:t})}}var M=t=>a({queryKey:[`expenses`,t],queryFn:()=>e.get(`/expenses`,t),placeholderData:s}),N=t=>a({queryKey:[`revenue`,t],queryFn:()=>e.get(`/revenue`,t),placeholderData:s});function P(){let t=b();return{create:v({mutationFn:t=>e.post(`/expenses`,t),onSuccess:t}),update:v({mutationFn:({id:t,...n})=>e.patch(`/expenses/${t}`,n),onSuccess:t}),remove:v({mutationFn:t=>e.delete(`/expenses/${t}`),onSuccess:t}),bulkDelete:v({mutationFn:t=>e.post(`/expenses/bulk-delete`,{ids:t}),onSuccess:t}),recompute:v({mutationFn:t=>e.post(`/expenses/${t}/recompute-split`),onSuccess:t}),recomputeRange:v({mutationFn:t=>e.post(`/expenses/recompute-splits`,t),onSuccess:t}),setPayment:v({mutationFn:({id:t,paymentMethodId:n,amountMinor:r})=>e.put(`/expenses/${t}/payments/${n}`,{amountMinor:r}),onSuccess:t})}}function F(){let t=b();return{create:v({mutationFn:t=>e.post(`/revenue`,t),onSuccess:t}),update:v({mutationFn:({id:t,...n})=>e.patch(`/revenue/${t}`,n),onSuccess:t}),remove:v({mutationFn:t=>e.delete(`/revenue/${t}`),onSuccess:t}),bulkDelete:v({mutationFn:t=>e.post(`/revenue/bulk-delete`,{ids:t}),onSuccess:t}),setPayment:v({mutationFn:({id:t,paymentMethodId:n,amountMinor:r})=>e.put(`/revenue/${t}/payments/${n}`,{amountMinor:r}),onSuccess:t})}}var I=t=>a({queryKey:[`settlements`,t],queryFn:()=>e.get(`/settlements`,t),placeholderData:s});function L(){let t=b();return{create:v({mutationFn:t=>e.post(`/settlements`,t),onSuccess:t}),update:v({mutationFn:({id:t,...n})=>e.patch(`/settlements/${t}`,n),onSuccess:t}),remove:v({mutationFn:t=>e.delete(`/settlements/${t}`),onSuccess:t})}}var R=(t,n=!1)=>a({queryKey:[`custom-fields`,t??`all`,n],queryFn:()=>e.get(`/custom-fields`,{entity:t,includeArchived:n||void 0}).then(y),staleTime:6e4});function z(){let t=p(),n=()=>t.invalidateQueries({queryKey:[`custom-fields`]});return{create:v({mutationFn:t=>e.post(`/custom-fields`,t),onSuccess:n}),update:v({mutationFn:({id:t,...n})=>e.patch(`/custom-fields/${t}`,n),onSuccess:n}),remove:v({mutationFn:t=>e.delete(`/custom-fields/${t}`),onSuccess:n}),reorder:v({mutationFn:t=>e.post(`/custom-fields/reorder`,{ids:t}),onSuccess:n})}}var B=()=>a({queryKey:[`recurring`],queryFn:()=>e.get(`/recurring`).then(y)});function V(){let t=b();return{create:v({mutationFn:t=>e.post(`/recurring`,t),onSuccess:t}),update:v({mutationFn:({id:t,...n})=>e.patch(`/recurring/${t}`,n),onSuccess:t}),remove:v({mutationFn:t=>e.delete(`/recurring/${t}`),onSuccess:t}),run:v({mutationFn:t=>e.post(t?`/recurring/${t}/run`:`/recurring/run`),onSuccess:t})}}function H(){return{update:v({mutationFn:t=>e.patch(`/project`,t),onSuccess:b()})}}var U=t=>a({queryKey:[`audit`,t],queryFn:()=>e.get(`/audit`,t),placeholderData:s}),W=()=>a({queryKey:[`integrations`,`loyverse`],queryFn:()=>e.get(`/integrations/loyverse`),staleTime:3e4}),G=(t,n=!0)=>a({queryKey:[`integrations`,`loyverse`,`items`,t],queryFn:()=>e.get(`/integrations/loyverse/items`,t),placeholderData:s,enabled:n}),K=(t,n=10)=>a({queryKey:[`integrations`,`loyverse`,`shifts`,n],queryFn:()=>e.get(`/integrations/loyverse/shifts`,{limit:n}),enabled:t,staleTime:15e3}),q=t=>a({queryKey:[`integrations`,`loyverse`,`sales`,t],queryFn:()=>e.get(`/integrations/loyverse/shifts/${t}/sales`),enabled:!!t,staleTime:6e4});function J(){let t=p(),n=b(),r=()=>t.invalidateQueries({queryKey:[`integrations`]});return{connect:v({mutationFn:t=>e.post(`/integrations/loyverse/connect`,t),onSuccess:r}),disconnect:v({mutationFn:()=>e.delete(`/integrations/loyverse`),onSuccess:()=>Promise.all([r(),n()])}),settings:v({mutationFn:t=>e.put(`/integrations/loyverse/settings`,t),onSuccess:r}),syncItems:v({mutationFn:()=>e.post(`/integrations/loyverse/sync-items`),onSuccess:r}),pullShift:v({mutationFn:t=>e.post(`/integrations/loyverse/pull-shift`,t),onSuccess:()=>Promise.all([r(),n()])})}}export{F as C,E as D,q as E,C as O,N as S,I as T,j as _,k as a,B as b,T as c,S as d,W as f,x as g,K as h,D as i,m as k,P as l,J as m,w as n,z as o,G as p,O as r,R as s,U as t,M as u,A as v,L as w,V as x,H as y};
@@ -1 +0,0 @@
1
- import{R as e,a as t,c as n,d as r,dt as i,f as a,g as o,gt as s,h as c,l,n as u,o as d,pt as f,s as p,v as m}from"./badge-BTiDEJlh.js";import{O as h,b as g,i as _,v,x as ee}from"./queries-IGiwF8nF.js";import{n as y}from"./project-Bgpq3nFR.js";import{a as b,i as x,n as S,o as C,r as w,t as T}from"./menu-BDGd2JUq.js";import{a as E,i as D,o as O,r as k,s as te}from"./media-Cr7juL5w.js";import{t as ne}from"./money-input-C8ZuBxvX.js";import{c as A,d as j,m as M,o as re,p as N,s as ie,u as ae,v as P,y as F}from"./index-DOwVPfdT.js";import{t as I}from"./money-Ch2MLu6J.js";var L={name:`pause`,size:24,node:[[`rect`,{x:`14`,y:`3`,width:`5`,height:`18`,rx:`1`,key:`kaeet6`}],[`rect`,{x:`5`,y:`3`,width:`5`,height:`18`,rx:`1`,key:`1wsw3u`}]]};L.node;var R=o(L),z={name:`play`,size:24,node:[[`path`,{d:`M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z`,key:`10ikf1`}]]};z.node;var B=o(z),V={name:`zap`,size:24,node:[[`path`,{d:`M15.914 4a1.5 1.5 0 00-2.474-1.561l-9 9A1.5 1.5 0 005.5 14h4.002a.5.5 0 01.471.666L8.086 20a1.5 1.5 0 002.475 1.56l9-9A1.5 1.5 0 0018.5 10h-3.997a.5.5 0 01-.472-.667z`,key:`1v7up4`}]]};V.node;var H=o(V),U=s(f(),1),W=i(),oe=[{id:`daily`,label:`Daily`},{id:`weekly`,label:`Weekly`},{id:`monthly`,label:`Monthly`},{id:`quarterly`,label:`Quarterly`},{id:`yearly`,label:`Yearly`}];function G({open:t,onClose:n,rule:r}){let i=M(),{t:o,name:s}=m(),{create:c,update:l}=ee(),u=h(),[d,f]=(0,U.useState)(`expense`),p=_(d),g=v(),[y,b]=(0,U.useState)(``),[x,S]=(0,U.useState)(``),[C,w]=(0,U.useState)(`monthly`),[T,A]=(0,U.useState)(1),[P,F]=(0,U.useState)(e()),[I,L]=(0,U.useState)(``),[R,z]=(0,U.useState)(!0),[B,V]=(0,U.useState)(``),[H,G]=(0,U.useState)(null),[K,q]=(0,U.useState)(``),[J,Y]=(0,U.useState)(``),[X,Z]=(0,U.useState)(``),[se,ce]=(0,U.useState)(``),[Q,le]=(0,U.useState)(`ownership`),[$,ue]=(0,U.useState)([]),[de,fe]=(0,U.useState)({});(0,U.useEffect)(()=>{t&&(f(r?.kind??`expense`),S(r?.name??``),w(r?.frequency??`monthly`),A(r?.interval??1),F(r?.startDate??e()),L(r?.endDate??``),z(r?.active??!0),V(r?.template.description??``),G(r?.template.amountMinor??null),q(r?.template.categoryId??``),Y(r?.template.partyStakeholderId??``),Z(r?.template.vendorOrSource??``),ce(r?.template.notes??``),le(r?.template.splitMode??`ownership`),ue(r?.template.customSplits??[]),fe(r?.template.customFields??{}),b(r?.template.paymentMethodId??``))},[t,r]),(0,U.useEffect)(()=>{if(!t||r||K)return;let e=p.data?.items.find(e=>e.isDefault&&!e.archived);e&&q(e.id)},[t,r,K,p.data]);let pe=x.trim()&&B.trim()&&H!==null&&H>0&&!!P&&(d===`revenue`||!!K)&&T>=1,me=c.isPending||l.isPending,he=async()=>{let e={kind:d,name:x.trim(),frequency:C,interval:T,startDate:P,endDate:I||null,active:R,template:{description:B.trim(),amountMinor:H,categoryId:K||null,partyStakeholderId:J||null,paymentMethodId:y||null,vendorOrSource:X.trim()||null,notes:se.trim()||null,splitMode:Q,customSplits:Q===`custom`?$:[],customFields:de}};try{if(r){let{kind:t,...n}=e;await l.mutateAsync({id:r.id,...n})}else await c.mutateAsync(e);i.success(o(r?`Rule updated`:`Recurring rule created`)),n()}catch(e){i.error(o(`Could not save rule`),N(e))}};return(0,W.jsx)(ae,{open:t,onClose:n,title:o(r?`Edit recurring rule`:`New recurring rule`),description:o(`Entries are generated automatically when they come due (checked hourly and on start).`),width:520,footer:(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(j,{variant:`ghost`,size:`md`,onClick:n,className:`max-md:hidden`,children:o(`Cancel`)}),(0,W.jsx)(j,{variant:`primary`,size:`lg`,onClick:he,loading:me,disabled:!pe,className:`w-full md:w-auto`,children:o(r?`Save`:`Create rule`)})]}),children:(0,W.jsxs)(`form`,{className:`space-y-4`,onSubmit:e=>{e.preventDefault(),pe&&he()},children:[!r&&(0,W.jsx)(a,{value:d,onChange:e=>{f(e),q(``)},items:[{id:`expense`,label:o(`Expense`)},{id:`revenue`,label:o(`Revenue`)}]}),(0,W.jsx)(k,{label:o(`Rule name`),required:!0,children:(0,W.jsx)(D,{value:x,onChange:e=>S(e.target.value),placeholder:o(`Office rent`),autoFocus:!r})}),(0,W.jsxs)(`div`,{className:`grid grid-cols-[1fr_80px] gap-3`,children:[(0,W.jsx)(k,{label:o(`Frequency`),children:(0,W.jsx)(E,{value:C,onChange:e=>w(e.target.value),children:oe.map(e=>(0,W.jsx)(`option`,{value:e.id,children:o(e.label)},e.id))})}),(0,W.jsx)(k,{label:o(`Every`),hint:o(`n`),children:(0,W.jsx)(D,{mono:!0,type:`number`,min:1,max:365,value:T,onChange:e=>A(Math.max(1,Number(e.target.value)||1))})})]}),(0,W.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,W.jsx)(k,{label:o(`First occurrence`),required:!0,children:(0,W.jsx)(D,{mono:!0,type:`date`,value:P,onChange:e=>F(e.target.value)})}),(0,W.jsx)(k,{label:o(`Ends`),hint:o(`optional`),children:(0,W.jsx)(D,{mono:!0,type:`date`,value:I,min:P,onChange:e=>L(e.target.value)})})]}),(0,W.jsx)(te,{checked:R,onChange:z,label:o(`Active`),description:o(R?`Generates entries when due`:`Paused: nothing is generated`)}),(0,W.jsx)(`div`,{className:`pt-4 mt-2 border-t border-line`,children:(0,W.jsx)(`span`,{className:`label`,children:o(`Entry template`)})}),(0,W.jsx)(k,{label:o(`Description`),required:!0,children:(0,W.jsx)(D,{value:B,onChange:e=>V(e.target.value)})}),(0,W.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,W.jsx)(k,{label:o(`Amount`),required:!0,children:(0,W.jsx)(ne,{value:H,onChange:G})}),(0,W.jsx)(k,{label:o(`Category`),required:d===`expense`,children:(0,W.jsxs)(E,{value:K,onChange:e=>q(e.target.value),children:[(0,W.jsx)(`option`,{value:``,children:o(d===`expense`?`Select…`:`Uncategorised`)}),p.data?.items.map(e=>(0,W.jsx)(`option`,{value:e.id,children:s(e)},e.id))]})})]}),(0,W.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,W.jsx)(k,{label:o(d===`expense`?`Paid by`:`Received by`),children:(0,W.jsxs)(E,{value:J,onChange:e=>Y(e.target.value),children:[(0,W.jsx)(`option`,{value:``,children:o(`Company pool`)}),u.data?.items.map(e=>(0,W.jsx)(`option`,{value:e.id,children:s(e)},e.id))]})}),(0,W.jsx)(k,{label:o(d===`expense`?`Vendor`:`Source`),children:(0,W.jsx)(D,{value:X,onChange:e=>Z(e.target.value)})})]}),(g.data?.items.length??0)>0&&(0,W.jsx)(k,{label:o(`Payment method`),hint:o(`blank = default`),children:(0,W.jsxs)(E,{value:y,onChange:e=>b(e.target.value),children:[(0,W.jsx)(`option`,{value:``,children:o(`Default method`)}),g.data?.items.map(e=>(0,W.jsx)(`option`,{value:e.id,children:s(e)},e.id))]})}),d===`expense`&&(0,W.jsx)(re,{stakeholders:u.data?.items??[],amountMinor:H,mode:Q,onMode:le,splits:$,onSplits:ue}),(0,W.jsx)(k,{label:o(`Notes`),children:(0,W.jsx)(O,{value:se,onChange:e=>ce(e.target.value)})}),(0,W.jsx)(ie,{entity:d,values:de,onChange:fe})]})})}var K={daily:`Every day`,weekly:`Every week`,monthly:`Every month`,quarterly:`Every quarter`,yearly:`Every year`},q={daily:`Every {n} days`,weekly:`Every {n} weeks`,monthly:`Every {n} months`,quarterly:`Every {n} quarters`,yearly:`Every {n} years`};function J(e,t){return e.interval===1?t(K[e.frequency]):t(q[e.frequency],{n:e.interval})}function Y(){let e=g(),{update:i,remove:a,run:o}=ee(),s=M(),{t:f}=m(),{date:h}=y(),[_,v]=(0,U.useState)(void 0),[E,D]=(0,U.useState)(null),O=e.data?.items??[],k=new Date().toISOString().slice(0,10);return(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(r,{title:f(`Recurring`),subtitle:f(`Rent, retainers, subscriptions: added automatically when due.`),actions:(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(j,{variant:`secondary`,size:`sm`,className:`rounded-full`,icon:(0,W.jsx)(H,{className:`size-4`}),onClick:async()=>{try{let e=await o.mutateAsync(void 0);s.success(e.generated.length?f(`Generated {n} entries`,{n:e.generated.length}):f(`Nothing due right now`))}catch(e){s.error(f(`Run failed`),N(e))}},loading:o.isPending,children:f(`Run due now`)}),(0,W.jsx)(j,{variant:`primary`,size:`sm`,className:`rounded-full`,icon:(0,W.jsx)(F,{className:`size-4`}),onClick:()=>v(null),children:f(`New rule`)})]})}),(0,W.jsx)(d,{flush:!0,children:e.isPending?(0,W.jsx)(l,{}):O.length?(0,W.jsx)(`ul`,{className:`divide-y divide-line`,children:O.map(e=>{let r=e.active&&e.nextRunAt<=k;return(0,W.jsxs)(`li`,{className:c(`flex items-center`,!e.active&&`opacity-60`),children:[(0,W.jsx)(n,{className:`flex-1`,leading:(0,W.jsx)(t,{color:e.kind===`expense`?`var(--s-expense)`:`var(--s-revenue)`,children:(0,W.jsx)(P,{className:`size-4`})}),title:(0,W.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[e.name,e.active?r?(0,W.jsx)(u,{tone:`warning`,children:f(`due`)}):null:(0,W.jsx)(u,{children:f(`paused`)})]}),subtitle:`${J(e,f)} · ${f(`next {date}`,{date:h(e.nextRunAt)})}${e.endDate?` · ${f(`ends {date}`,{date:h(e.endDate)})}`:``} · ${f(`{n} generated`,{n:e.generatedCount})}`,trailing:(0,W.jsx)(I,{minor:e.template.amountMinor,tone:e.kind===`expense`?`expense`:`revenue`,className:`text-[15px] font-semibold`}),onClick:()=>v(e)}),(0,W.jsx)(`div`,{className:`pe-3`,children:(0,W.jsx)(T,{trigger:()=>(0,W.jsx)(`button`,{type:`button`,className:`size-9 inline-flex items-center justify-center rounded-full text-ink-3 hover:text-ink hover:bg-card-hover`,"aria-label":f(`Actions`),children:(0,W.jsx)(C,{className:`size-4`})}),children:t=>(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(S,{icon:(0,W.jsx)(b,{}),onClick:()=>{t(),v(e)},children:f(`Edit`)}),(0,W.jsx)(S,{icon:(0,W.jsx)(H,{}),onClick:async()=>{t();try{let t=await o.mutateAsync(e.id);s.success(t.generated.length?f(`Generated {n}`,{n:t.generated.length}):f(`Nothing due`))}catch(e){s.error(f(`Run failed`),N(e))}},children:f(`Run now`)}),(0,W.jsx)(S,{icon:e.active?(0,W.jsx)(R,{}):(0,W.jsx)(B,{}),onClick:async()=>{t();try{await i.mutateAsync({id:e.id,active:!e.active})}catch(e){s.error(f(`Failed`),N(e))}},children:f(e.active?`Pause`:`Resume`)}),(0,W.jsx)(w,{}),(0,W.jsx)(S,{icon:(0,W.jsx)(x,{}),danger:!0,onClick:()=>{t(),D(e)},children:f(`Delete`)})]})})})]},e.id)})}):(0,W.jsx)(p,{icon:(0,W.jsx)(P,{}),title:f(`No recurring rules`),description:f(`Create one for rent, salaries or retainers and ledgr adds the entries on schedule.`),action:(0,W.jsx)(j,{variant:`soft`,onClick:()=>v(null),children:f(`New rule`)})})}),(0,W.jsx)(G,{open:_!==void 0,onClose:()=>v(void 0),rule:_??null}),(0,W.jsx)(A,{open:!!E,onClose:()=>D(null),onConfirm:async()=>{try{await a.mutateAsync(E.id),s.success(f(`Rule deleted`)),D(null)}catch(e){s.error(f(`Delete failed`),N(e))}},loading:a.isPending,title:f(`Delete “{name}”?`,{name:E?.name??``}),description:f(`Entries already generated stay in the ledger.`)})]})}export{Y as RecurringPage};
@@ -1 +0,0 @@
1
- import{H as e,d as t,dt as n,gt as r,h as i,i as a,n as ee,o,pt as s,r as te,s as ne,t as re,v as ie}from"./badge-BTiDEJlh.js";import{C as ae,O as oe,S as se,f as ce,i as le,s as ue,v as de}from"./queries-IGiwF8nF.js";import{n as fe}from"./project-Bgpq3nFR.js";import{a as c,i as l,n as u,o as pe,r as me,t as d}from"./table-DQsx5_iN.js";import{t as he}from"./download-CIyMPSgr.js";import{a as ge,i as f,n as p,o as m,r as _e,t as h}from"./menu-BDGd2JUq.js";import{a as g,i as ve,n as ye,r as be,t as xe}from"./ledger-toolbar-yj0u4-Rm.js";import{t as Se}from"./pull-shift-sheet-DTwTC0rg.js";import{n as _,t as Ce}from"./media-Cr7juL5w.js";import{c as v,d as y,f as we,i as Te,l as Ee,m as De,p as b,y as x}from"./index-DOwVPfdT.js";import{t as S}from"./money-Ch2MLu6J.js";import{t as C}from"./custom-cell-Wgh3D7lb.js";import{t as Oe}from"./shift-sales-B0yokKuf.js";var w=r(s(),1),T=n(),ke=50;function E(){let{t:n,name:r,label:s}=ie(),E=e=>r({name:e.name??``,nameAr:e.nameAr}),{range:D}=we(),{date:O,money:k}=fe(),A=ye(),j=De(),Ae=Ce(),je=le(`revenue`,!0),Me=oe(),Ne=ue(`revenue`),M=de(!0),N=!!ce().data?.connected,[Pe,Fe]=(0,w.useState)(!1),Ie=(0,w.useMemo)(()=>({from:D.from,to:D.to,q:A.q,categoryId:A.categoryId,stakeholderId:A.stakeholderId,paymentMethodId:A.paymentMethodId,sort:A.sort,order:A.order,page:A.page,pageSize:ke}),[D,A.q,A.categoryId,A.stakeholderId,A.paymentMethodId,A.sort,A.order,A.page]),P=se(Ie),{remove:Le,bulkDelete:Re}=ae(),[F,I]=(0,w.useState)(void 0),[L,R]=(0,w.useState)(null),[z,B]=(0,w.useState)(new Set),[V,H]=(0,w.useState)(!1),[ze,U]=(0,w.useState)(!1),[W,G]=(0,w.useState)(null),[Be,K]=(0,w.useState)(null),q=(0,w.useMemo)(()=>(M.data?.items??[]).filter(e=>!e.archived),[M.data]),J=P.data?.items??[],Y=Ne.data?.items??[],X=J.length>0&&J.every(e=>z.has(e.id)),Ve=()=>B(X?new Set:new Set(J.map(e=>e.id))),Z=e=>B(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n}),Q=e=>A.set({sort:e,order:A.sort===e&&A.order===`desc`?`asc`:`desc`}),$=e=>A.sort===e?A.order:null,He=(t=`xlsx`)=>e(`/export/revenue.${t}`,`revenue.${t}`,{from:D.from,to:D.to}).catch(e=>j.error(n(`Export failed`),b(e))),Ue=(0,w.useMemo)(()=>{let e=new Map;for(let t of J)e.set(t.date,[...e.get(t.date)??[],t]);return[...e.entries()]},[J]);return(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(t,{title:n(`Revenue`),subtitle:P.data?(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(S,{minor:P.data.totals.amountMinor,className:`text-ink font-medium`}),` `,n(`across {n} entries`,{n:P.data.totals.count})]}):n(`Loading…`),actions:(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(h,{trigger:()=>(0,T.jsx)(y,{variant:`secondary`,size:`sm`,icon:(0,T.jsx)(m,{className:`size-4`}),className:`rounded-full`,children:n(`More`)}),title:n(`Revenue`),children:e=>(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(p,{icon:V?(0,T.jsx)(g,{}):(0,T.jsx)(ve,{}),onClick:()=>{e(),H(e=>!e),B(new Set)},children:n(V?`Done selecting`:`Select entries`)}),(0,T.jsx)(_e,{}),(0,T.jsx)(p,{icon:(0,T.jsx)(f,{}),danger:!0,disabled:!z.size,onClick:()=>{e(),U(!0)},children:n(`Delete {n} selected`,{n:z.size||``})})]})}),N&&(0,T.jsx)(y,{variant:`primary`,size:`sm`,className:`rounded-full`,icon:(0,T.jsx)(he,{className:`size-4`}),onClick:()=>Fe(!0),children:n(`Pull last shift`)}),(0,T.jsx)(y,{variant:N?`secondary`:`primary`,size:`sm`,className:`rounded-full max-md:hidden`,icon:(0,T.jsx)(x,{className:`size-4`}),onClick:()=>I(null),children:n(`New revenue`)})]})}),(0,T.jsx)(`div`,{className:`mb-3`,children:(0,T.jsx)(xe,{categories:je.data?.items.filter(e=>!e.archived)??[],stakeholders:Me.data?.items??[],paymentMethods:M.data?.items.filter(e=>!e.archived)??[],stakeholderLabel:`Received by`,onExport:He})}),V&&J.length>0&&(0,T.jsxs)(`div`,{className:`mb-3 flex items-center justify-between gap-2 card px-4 py-2 fade-up`,children:[(0,T.jsx)(_,{label:n(X?`Deselect all on page`:`Select all on page`),checked:X,onChange:Ve}),(0,T.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,T.jsx)(y,{size:`xs`,variant:`ghost`,onClick:()=>{H(!1),B(new Set)},children:n(`Done`)}),(0,T.jsx)(y,{size:`xs`,variant:`danger`,disabled:!z.size,icon:(0,T.jsx)(f,{className:`size-3.5`}),onClick:()=>U(!0),children:n(`Delete {n}`,{n:z.size||``})})]})]}),Ae?(0,T.jsxs)(`div`,{className:`space-y-4`,children:[P.isPending&&(0,T.jsx)(o,{children:(0,T.jsx)(`div`,{className:`py-10 text-center text-ink-3`,children:n(`Loading…`)})}),!P.isPending&&!J.length&&(0,T.jsx)(o,{children:(0,T.jsx)(ne,{title:n(`No revenue`),description:n(`Nothing matches this period and filters.`)})}),Ue.map(([e,t])=>(0,T.jsxs)(`section`,{children:[(0,T.jsxs)(`div`,{className:`flex items-baseline justify-between px-1 mb-1.5`,children:[(0,T.jsx)(`span`,{className:`label`,children:O(e,`long`)}),(0,T.jsx)(`span`,{className:`num text-[12px] text-ink-3`,children:k(t.reduce((e,t)=>e+t.amountMinor,0))})]}),(0,T.jsx)(`ul`,{className:`card divide-y divide-line overflow-hidden`,children:t.map(e=>(0,T.jsx)(`li`,{children:(0,T.jsxs)(`button`,{type:`button`,onClick:()=>V?Z(e.id):G(e),className:i(`pressable w-full flex items-center gap-3 px-4 py-3 text-start`,z.has(e.id)&&`bg-accent-soft/50`),children:[V?(0,T.jsx)(`span`,{className:i(`size-6 rounded-full border-2 inline-flex items-center justify-center shrink-0`,z.has(e.id)?`bg-accent border-accent text-white`:`border-line-strong`),children:z.has(e.id)&&(0,T.jsx)(g,{className:`size-3.5`})}):(0,T.jsx)(`span`,{className:`inline-flex items-center justify-center size-10 rounded-[12px] shrink-0`,style:{background:`${e.category?.color??`var(--s-revenue)`}1f`},children:(0,T.jsx)(a,{color:e.category?.color??`var(--s-revenue)`,size:10})}),(0,T.jsxs)(`span`,{className:`flex-1 min-w-0`,children:[(0,T.jsxs)(`span`,{dir:`auto`,className:`block text-[15px] font-medium truncate`,children:[e.pos&&(0,T.jsx)(`span`,{className:`inline-block size-1.5 rounded-full bg-[#1e9e6a] me-1.5 align-middle`,title:`Loyverse`}),e.description]}),(0,T.jsxs)(`span`,{className:`block text-[12.5px] text-ink-3 truncate`,children:[e.payments.filter(e=>e.amountMinor>0).length?e.payments.filter(e=>e.amountMinor>0).map(e=>`${E(e)} ${k(e.amountMinor,{compact:!0})}`).join(` · `):e.category?r(e.category):n(`Uncategorised`),e.receivedBy?` · ${r(e.receivedBy)}`:``]})]}),(0,T.jsx)(S,{minor:e.amountMinor,tone:`revenue`,className:`text-[15px] font-semibold shrink-0`})]})},e.id))})]},e)),P.data&&(0,T.jsx)(`div`,{className:`card`,children:(0,T.jsx)(u,{page:P.data.page,pageSize:P.data.pageSize,total:P.data.total,onPage:e=>A.set({page:String(e)})})})]}):(0,T.jsxs)(o,{flush:!0,children:[(0,T.jsxs)(me,{children:[(0,T.jsx)(`thead`,{children:(0,T.jsxs)(`tr`,{children:[V&&(0,T.jsx)(c,{className:`w-10`,children:(0,T.jsx)(_,{checked:X,onChange:Ve,"aria-label":n(`Select all`)})}),(0,T.jsx)(c,{sortable:!0,sorted:$(`date`),onSort:()=>Q(`date`),className:`w-28`,children:n(`Date`)}),(0,T.jsx)(c,{sortable:!0,sorted:$(`description`),onSort:()=>Q(`description`),children:n(`Description`)}),(0,T.jsx)(c,{children:n(`Category`)}),(0,T.jsx)(c,{children:n(`Source`)}),(0,T.jsx)(c,{children:n(`Received by`)}),Y.map(e=>(0,T.jsx)(c,{align:e.type===`money`||e.type===`number`?`right`:`left`,children:s(e)},e.id)),q.map(e=>(0,T.jsx)(c,{align:`right`,children:(0,T.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,T.jsx)(a,{color:e.color}),r(e)]})},e.id)),(0,T.jsx)(c,{align:`right`,sortable:!0,sorted:$(`amountMinor`),onSort:()=>Q(`amountMinor`),className:`w-36`,children:q.length?n(`Total`):n(`Amount`)}),(0,T.jsx)(c,{className:`w-12`})]})}),(0,T.jsxs)(`tbody`,{children:[P.isPending&&(0,T.jsx)(d,{colSpan:8+Y.length+q.length,children:n(`Loading…`)}),!P.isPending&&!J.length&&(0,T.jsx)(d,{colSpan:8+Y.length+q.length,children:n(`No revenue in this period.`)}),J.map(e=>(0,T.jsxs)(pe,{selected:z.has(e.id),className:`cursor-pointer`,onClick:()=>V?Z(e.id):G(e),children:[V&&(0,T.jsx)(l,{onClick:e=>e.stopPropagation(),children:(0,T.jsx)(_,{checked:z.has(e.id),onChange:()=>Z(e.id),"aria-label":n(`Select`)})}),(0,T.jsx)(l,{className:`num text-ink-2 whitespace-nowrap`,children:O(e.date)}),(0,T.jsxs)(l,{children:[(0,T.jsx)(`div`,{dir:`auto`,className:`font-medium truncate max-w-[380px]`,children:e.description}),e.recurringRuleId&&(0,T.jsx)(`div`,{className:`text-[12px] text-ink-3`,children:n(`recurring`)}),e.pos&&(0,T.jsx)(`div`,{className:`text-[12px] text-ink-3`,children:n(`Loyverse shift · {n} receipts`,{n:e.pos.receipts})})]}),(0,T.jsx)(l,{children:e.category?(0,T.jsx)(te,{color:e.category.color,children:r(e.category)}):(0,T.jsx)(`span`,{className:`text-ink-4`,children:`—`})}),(0,T.jsx)(l,{className:`text-ink-2`,children:e.source??(0,T.jsx)(`span`,{className:`text-ink-4`,children:`—`})}),(0,T.jsx)(l,{children:e.receivedBy?(0,T.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[(0,T.jsx)(re,{name:r(e.receivedBy),color:e.receivedBy.color,size:22}),r(e.receivedBy)]}):(0,T.jsx)(`span`,{className:`text-ink-3`,children:n(`Company`)})}),Y.map(t=>(0,T.jsx)(l,{align:t.type===`money`||t.type===`number`?`right`:`left`,children:(0,T.jsx)(C,{def:t,value:e.customFields?.[t.key]})},t.id)),q.map(t=>{let i=e.payments.find(e=>e.paymentMethodId===t.id);return(0,T.jsx)(l,{align:`right`,onClick:e=>e.stopPropagation(),children:i&&i.amountMinor>0?(0,T.jsx)(`button`,{type:`button`,className:`num hover:text-accent`,title:n(`Edit {method} amount`,{method:r(t)}),onClick:()=>K({kind:`revenue`,entry:e,method:t}),children:k(i.amountMinor)}):(0,T.jsxs)(`button`,{type:`button`,className:`inline-flex items-center gap-1 text-[12.5px] font-medium text-accent/80 hover:text-accent whitespace-nowrap`,onClick:()=>K({kind:`revenue`,entry:e,method:t}),children:[(0,T.jsx)(x,{className:`size-3.5`}),n(`Add {method}`,{method:r(t)})]})},t.id)}),(0,T.jsx)(l,{align:`right`,children:(0,T.jsx)(S,{minor:e.amountMinor,className:`font-semibold`})}),(0,T.jsx)(l,{onClick:e=>e.stopPropagation(),children:(0,T.jsx)(h,{trigger:()=>(0,T.jsx)(`button`,{type:`button`,className:`size-8 inline-flex items-center justify-center rounded-full text-ink-3 hover:text-ink hover:bg-card-hover`,"aria-label":n(`Actions`),children:(0,T.jsx)(m,{className:`size-4`})}),children:t=>(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(p,{icon:(0,T.jsx)(ge,{}),onClick:()=>{t(),I(e)},children:n(`Edit`)}),(0,T.jsx)(_e,{}),(0,T.jsx)(p,{icon:(0,T.jsx)(f,{}),danger:!0,onClick:()=>{t(),R(e)},children:n(`Delete`)})]})})})]},e.id))]})]}),P.data&&(0,T.jsx)(u,{page:P.data.page,pageSize:P.data.pageSize,total:P.data.total,onPage:e=>A.set({page:String(e)})})]}),(0,T.jsx)(Ee,{open:!!W,onClose:()=>G(null),title:W?.description??``,description:W?`${O(W.date,`long`)} · ${W.category?r(W.category):n(`Uncategorised`)}`:``,width:460,footer:W&&(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(y,{variant:`danger`,size:`md`,onClick:()=>R(W),children:n(`Delete`)}),(0,T.jsx)(y,{variant:`primary`,size:`md`,onClick:()=>{I(W),G(null)},children:n(`Edit`)})]}),children:W&&(0,T.jsxs)(`div`,{className:`space-y-4`,children:[(0,T.jsx)(`div`,{className:`num text-[32px] font-semibold tracking-tight text-revenue`,children:k(W.amountMinor)}),(0,T.jsxs)(`dl`,{className:`grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-[14px]`,children:[W.payments.filter(e=>e.amountMinor>0).map(e=>(0,T.jsxs)(`span`,{className:`contents`,children:[(0,T.jsx)(`dt`,{className:`text-ink-3`,children:E(e)}),(0,T.jsx)(`dd`,{className:`num`,children:k(e.amountMinor)})]},e.paymentMethodId)),(0,T.jsx)(`dt`,{className:`text-ink-3`,children:n(`Received by`)}),(0,T.jsx)(`dd`,{className:`font-medium`,children:W.receivedBy?r(W.receivedBy):n(`Company account`)}),W.source&&(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`dt`,{className:`text-ink-3`,children:n(`Source`)}),(0,T.jsx)(`dd`,{children:W.source})]}),Y.map(e=>(0,T.jsxs)(`span`,{className:`contents`,children:[(0,T.jsx)(`dt`,{className:`text-ink-3`,children:s(e)}),(0,T.jsx)(`dd`,{children:(0,T.jsx)(C,{def:e,value:W.customFields?.[e.key]})})]},e.id)),W.notes&&(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`dt`,{className:`text-ink-3`,children:n(`Notes`)}),(0,T.jsx)(`dd`,{className:`whitespace-pre-wrap`,children:W.notes})]})]}),W.pos&&(0,T.jsxs)(`div`,{children:[(0,T.jsxs)(`div`,{className:`flex items-center gap-2 mb-2`,children:[(0,T.jsx)(ee,{tone:`revenue`,children:`Loyverse`}),(0,T.jsx)(`span`,{className:`text-[12.5px] text-ink-3`,children:n(`What sold this shift`)})]}),(0,T.jsx)(Oe,{shiftId:W.pos.shiftId})]})]})}),(0,T.jsx)(Te,{open:F!==void 0,onClose:()=>I(void 0),revenue:F??null}),(0,T.jsx)(be,{target:Be,onClose:()=>K(null)}),(0,T.jsx)(Se,{open:Pe,onClose:()=>Fe(!1)}),(0,T.jsx)(v,{open:!!L,onClose:()=>R(null),onConfirm:async()=>{try{await Le.mutateAsync(L.id),j.success(n(`Revenue deleted`)),R(null),G(null)}catch(e){j.error(n(`Delete failed`),b(e))}},loading:Le.isPending,title:n(`Delete this revenue entry?`),description:L?n(`{description} · {amount} on {date}`,{description:L.description,amount:k(L.amountMinor),date:O(L.date)}):``}),(0,T.jsx)(v,{open:ze,onClose:()=>U(!1),onConfirm:async()=>{try{await Re.mutateAsync([...z]),j.success(n(`{n} entries deleted`,{n:z.size})),B(new Set),H(!1),U(!1)}catch(e){j.error(n(`Delete failed`),b(e))}},loading:Re.isPending,title:n(`Delete {n} entries?`,{n:z.size}),description:n(`This cannot be undone.`)})]})}export{E as RevenuePage};
@@ -1,4 +0,0 @@
1
- import{I as e,b as t,c as n,d as r,dt as i,g as a,gt as o,h as s,l as c,n as l,o as u,p as d,pt as f,s as p,v as m,x as h}from"./badge-BTiDEJlh.js";import{o as g,s as _,t as v,y}from"./queries-IGiwF8nF.js";import{n as b}from"./project-Bgpq3nFR.js";import{n as x}from"./table-DQsx5_iN.js";import{a as S,i as C,n as w,o as T,r as E,t as D}from"./menu-BDGd2JUq.js";import{a as O,i as k,n as A,o as j,r as M}from"./media-Cr7juL5w.js";import{c as N,d as P,l as ee,m as F,n as I,p as L,t as R,y as te}from"./index-DOwVPfdT.js";import{n as z}from"./format-GDcQVAp4.js";var B={name:`arrow-down`,size:24,node:[[`path`,{d:`M12 5v14`,key:`s699le`}],[`path`,{d:`m19 12-7 7-7-7`,key:`1idqje`}]]};B.node;var V=a(B),H={name:`arrow-up`,size:24,node:[[`path`,{d:`m5 12 7-7 7 7`,key:`hav0vg`}],[`path`,{d:`M12 19V5`,key:`x0mq9r`}]]};H.node;var ne=a(H),U={name:`share`,size:24,node:[[`path`,{d:`M12 2v13`,key:`1km8f5`}],[`path`,{d:`m16 6-4-4-4 4`,key:`13yo43`}],[`path`,{d:`M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8`,key:`1b2hhj`}]]};U.node;var W=a(U),G={name:`smartphone`,size:24,node:[[`rect`,{width:`14`,height:`20`,x:`5`,y:`2`,rx:`2`,ry:`2`,key:`1yt0o3`}],[`path`,{d:`M12 18h.01`,key:`mhygvu`}]]};G.node;var K=a(G),q=o(f(),1),J=null;typeof window<`u`&&window.addEventListener(`beforeinstallprompt`,e=>{e.preventDefault(),J=e,window.dispatchEvent(new Event(`ledgr:installable`))});function Y(){let[e,t]=(0,q.useState)(!!J),[n,r]=(0,q.useState)(!1);return(0,q.useEffect)(()=>{let e=()=>t(!0),n=()=>{r(!0),t(!1)};return window.addEventListener(`ledgr:installable`,e),window.addEventListener(`appinstalled`,n),()=>{window.removeEventListener(`ledgr:installable`,e),window.removeEventListener(`appinstalled`,n)}},[]),{canInstall:e,install:async()=>{if(!J)return;await J.prompt();let{outcome:e}=await J.userChoice;e===`accepted`&&r(!0),J=null,t(!1)},installed:n,isIOS:/iphone|ipad|ipod/i.test(navigator.userAgent),isStandalone:window.matchMedia(`(display-mode: standalone)`).matches||navigator.standalone===!0}}var X=i(),re={text:`Text`,number:`Number`,money:`Money`,date:`Date`,boolean:`Yes / no`,select:`Select (options)`},ie={expense:`New expense field`,revenue:`New revenue field`,stakeholder:`New stakeholder field`};function ae({open:t,onClose:n,field:r,entity:i}){let a=F(),{t:o}=m(),{create:s,update:c}=g(),[l,u]=(0,q.useState)(``),[d,f]=(0,q.useState)(``),[p,_]=(0,q.useState)(``),[v,y]=(0,q.useState)(!1),[b,x]=(0,q.useState)(`text`),[S,C]=(0,q.useState)(``),[w,T]=(0,q.useState)(!1);(0,q.useEffect)(()=>{t&&(u(r?.label??``),f(r?.labelAr??``),_(r?.key??``),y(!!r),x(r?.type??`text`),C(r?.options.join(`
2
- `)??``),T(r?.required??!1))},[t,r]),(0,q.useEffect)(()=>{v||_(e(l))},[l,v]);let E=S.split(`
3
- `).map(e=>e.trim()).filter(Boolean),D=l.trim()&&/^[a-z][a-z0-9_]*$/.test(p)&&(b!==`select`||E.length>0),N=s.isPending||c.isPending,I=async()=>{try{if(r)await c.mutateAsync({id:r.id,label:l.trim(),labelAr:d.trim()||null,type:b,options:E,required:w});else{let e={entity:i,key:p,label:l.trim(),labelAr:d.trim()||null,type:b,options:E,required:w};await s.mutateAsync(e)}a.success(o(r?`Field updated`:`Field added`)),n()}catch(e){a.error(o(`Could not save field`),L(e))}};return(0,X.jsx)(ee,{open:t,onClose:n,title:o(r?`Edit custom field`:ie[i]),footer:(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(P,{variant:`ghost`,size:`md`,onClick:n,children:o(`Cancel`)}),(0,X.jsx)(P,{variant:`primary`,size:`md`,onClick:I,loading:N,disabled:!D,children:o(r?`Save`:`Add field`)})]}),children:(0,X.jsxs)(`form`,{className:`space-y-4`,onSubmit:e=>{e.preventDefault(),D&&I()},children:[(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,X.jsx)(M,{label:o(`Label`),required:!0,children:(0,X.jsx)(k,{value:l,onChange:e=>u(e.target.value),autoFocus:!0,placeholder:o(`Invoice no.`)})}),(0,X.jsx)(M,{label:o(`Key`),hint:o(`CSV column id`),children:(0,X.jsx)(k,{mono:!0,value:p,disabled:!!r,onChange:e=>{y(!0),_(e.target.value)}})})]}),(0,X.jsx)(M,{label:o(`Arabic label`),hint:o(`optional`),children:(0,X.jsx)(k,{lang:`ar`,dir:`rtl`,value:d,onChange:e=>f(e.target.value)})}),(0,X.jsx)(M,{label:o(`Type`),children:(0,X.jsx)(O,{value:b,onChange:e=>x(e.target.value),children:h.map(e=>(0,X.jsx)(`option`,{value:e,children:o(re[e])},e))})}),b===`select`&&(0,X.jsx)(M,{label:o(`Options`),hint:o(`one per line`),children:(0,X.jsx)(j,{value:S,onChange:e=>C(e.target.value),placeholder:[o(`Direct`),`Upwork`,o(`Referral`)].join(`
4
- `)})}),(0,X.jsx)(A,{label:o(`Required`),checked:w,onChange:e=>T(e.target.checked)}),r&&r.type!==b&&(0,X.jsx)(`p`,{className:`text-[11.5px] text-warning`,children:o(`Changing the type does not convert existing values; incompatible ones are shown as blank.`)})]})})}function oe(){let[e,t]=(0,q.useState)(`project`),{t:n}=m();return(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(r,{title:n(`Settings`)}),(0,X.jsx)(d,{className:`mb-4`,value:e,onChange:t,items:[{id:`project`,label:n(`Project`)},{id:`phone`,label:n(`Phone`)},{id:`fields`,label:n(`Custom fields`)},{id:`audit`,label:n(`Audit log`)}]}),e===`project`&&(0,X.jsx)(le,{}),e===`phone`&&(0,X.jsx)(ue,{}),e===`fields`&&(0,X.jsx)(fe,{}),e===`audit`&&(0,X.jsx)(pe,{})]})}var se=[`Sunday`,`Monday`,`Tuesday`,`Wednesday`,`Thursday`,`Friday`,`Saturday`],ce=[`January`,`February`,`March`,`April`,`May`,`June`,`July`,`August`,`September`,`October`,`November`,`December`];function le(){let{project:e}=b(),{update:t}=y(),n=F(),{t:r}=m(),i=e.config,[a,o]=(0,q.useState)(i.name),[s,c]=(0,q.useState)(i.nameAr??``),[d,f]=(0,q.useState)(i.currency),[p,h]=(0,q.useState)(i.locale),[g,_]=(0,q.useState)(i.weekStartsOn),[v,x]=(0,q.useState)(i.fiscalYearStartMonth);(0,q.useEffect)(()=>{o(i.name),c(i.nameAr??``),f(i.currency),h(i.locale),_(i.weekStartsOn),x(i.fiscalYearStartMonth)},[i]);let S=a!==i.name||s!==(i.nameAr??``)||d!==i.currency||p!==i.locale||g!==i.weekStartsOn||v!==i.fiscalYearStartMonth,C=async()=>{try{await t.mutateAsync({name:a.trim(),nameAr:s.trim(),currency:d.toUpperCase(),locale:p,weekStartsOn:g,fiscalYearStartMonth:v}),n.success(r(`Project updated`))}catch(e){n.error(r(`Could not save`),L(e))}};return(0,X.jsxs)(`div`,{className:`grid grid-cols-1 xl:grid-cols-3 gap-4`,children:[(0,X.jsx)(u,{className:`xl:col-span-2`,title:r(`Project`),children:(0,X.jsxs)(`form`,{className:`space-y-4 max-w-lg`,onSubmit:e=>{e.preventDefault(),C()},children:[(0,X.jsx)(M,{label:r(`Name`),children:(0,X.jsx)(k,{value:a,onChange:e=>o(e.target.value)})}),(0,X.jsx)(M,{label:r(`Arabic name`),hint:r(`optional`),children:(0,X.jsx)(k,{lang:`ar`,dir:`rtl`,value:s,onChange:e=>c(e.target.value)})}),(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,X.jsx)(M,{label:r(`Currency`),hint:`ISO 4217`,children:(0,X.jsx)(k,{mono:!0,maxLength:3,value:d,onChange:e=>f(e.target.value.toUpperCase())})}),(0,X.jsx)(M,{label:r(`Locale`),hint:r(`formatting`),children:(0,X.jsx)(k,{mono:!0,value:p,onChange:e=>h(e.target.value),placeholder:`en-US`})})]}),(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,X.jsx)(M,{label:r(`Week starts on`),children:(0,X.jsx)(O,{value:g,onChange:e=>_(Number(e.target.value)),children:se.map((e,t)=>(0,X.jsx)(`option`,{value:t,children:r(e)},e))})}),(0,X.jsx)(M,{label:r(`Fiscal year starts`),children:(0,X.jsx)(O,{value:v,onChange:e=>x(Number(e.target.value)),children:ce.map((e,t)=>(0,X.jsx)(`option`,{value:t+1,children:r(e)},e))})})]}),d!==i.currency&&(0,X.jsx)(`p`,{className:`text-[13px] text-warning`,children:r(`Changing currency relabels amounts; it does not convert them.`)}),(0,X.jsx)(P,{type:`submit`,variant:`primary`,size:`md`,disabled:!S,loading:t.isPending,children:r(`Save changes`)})]})}),(0,X.jsxs)(`div`,{className:`space-y-4`,children:[(0,X.jsx)(u,{title:r(`Appearance`),children:(0,X.jsxs)(`div`,{className:`space-y-3`,children:[(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`div`,{className:`label mb-1.5`,children:r(`Theme`)}),(0,X.jsx)(I,{})]}),(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`div`,{className:`label mb-1.5`,children:r(`Language`)}),(0,X.jsx)(R,{})]})]})}),(0,X.jsxs)(u,{title:r(`About this project`),children:[(0,X.jsxs)(`dl`,{className:`grid grid-cols-[auto_1fr] gap-x-5 gap-y-2 text-[13.5px]`,children:[(0,X.jsx)(`dt`,{className:`text-ink-3`,children:r(`Auth`)}),(0,X.jsx)(`dd`,{children:i.auth.mode===`supabase`?(0,X.jsx)(l,{tone:`good`,children:r(`Supabase · admins only`)}):(0,X.jsx)(l,{tone:`warning`,children:r(`None · local only`)})}),(0,X.jsx)(`dt`,{className:`text-ink-3`,children:r(`Entries`)}),(0,X.jsx)(`dd`,{className:`num`,children:r(`{expenses} expenses · {revenue} revenue`,{expenses:e.stats.expenses,revenue:e.stats.revenue})}),(0,X.jsx)(`dt`,{className:`text-ink-3`,children:r(`Period`)}),(0,X.jsx)(`dd`,{className:`num`,children:r(`{from} → {to}`,{from:e.stats.firstEntryDate??`—`,to:e.stats.lastEntryDate??`—`})}),(0,X.jsx)(`dt`,{className:`text-ink-3`,children:r(`Version`)}),(0,X.jsxs)(`dd`,{className:`num`,children:[`ledgr `,e.version]})]}),(0,X.jsxs)(`p`,{className:`text-[12.5px] text-ink-3 mt-3 leading-relaxed`,children:[r(`Data lives in`),` `,(0,X.jsx)(`code`,{className:`mono`,children:`.ledgr/data.db`}),` `,r(`next to this project. Auth settings are in`),` `,(0,X.jsx)(`code`,{className:`mono`,children:`.ledgr/config.json`}),r(`; restart after changing them.`)]})]})]})]})}function ue(){let{canInstall:e,install:t,installed:n,isIOS:r,isStandalone:i}=Y(),{t:a}=m(),o=typeof window<`u`?window.location.origin:``;return(0,X.jsxs)(`div`,{className:`grid grid-cols-1 xl:grid-cols-3 gap-4`,children:[(0,X.jsx)(u,{className:`xl:col-span-2`,title:a(`Add ledgr to your home screen`),subtitle:a(`Works like an app: full screen, its own icon, quick-add shortcuts.`),children:(0,X.jsxs)(`div`,{className:`space-y-4 text-[14px]`,children:[i&&(0,X.jsx)(`div`,{className:`rounded-[14px] bg-good/10 p-4`,children:a(`You are already running ledgr as an installed app.`)}),!i&&e&&(0,X.jsxs)(`div`,{className:`flex items-center gap-3 flex-wrap`,children:[(0,X.jsx)(P,{variant:`primary`,size:`md`,icon:(0,X.jsx)(K,{className:`size-4`}),onClick:t,children:a(`Install ledgr`)}),(0,X.jsx)(`span`,{className:`text-ink-3 text-[13px]`,children:a(n?`Installed. Open it from your home screen.`:`One tap, no app store.`)})]}),!i&&!e&&(0,X.jsx)(`ol`,{className:`space-y-3 list-decimal ps-5 text-ink-2 leading-relaxed`,children:r?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`li`,{children:[a(`Open this page in`),` `,(0,X.jsx)(`strong`,{className:`text-ink`,children:`Safari`}),a(`, tap`),` `,(0,X.jsx)(W,{className:`inline size-4 -mt-0.5`}),` `,(0,X.jsx)(`strong`,{className:`text-ink`,children:a(`Share`)}),`.`]}),(0,X.jsxs)(`li`,{children:[a(`Choose`),` `,(0,X.jsx)(`strong`,{className:`text-ink`,children:a(`Add to Home Screen`)}),a(`, then`),` `,(0,X.jsx)(`strong`,{className:`text-ink`,children:a(`Add`)}),`.`]})]}):(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`li`,{children:[a(`Open this page in Chrome, tap the`),` `,(0,X.jsx)(`strong`,{className:`text-ink`,children:a(`⋮ menu`)}),`.`]}),(0,X.jsxs)(`li`,{children:[a(`Choose`),` `,(0,X.jsx)(`strong`,{className:`text-ink`,children:a(`Add to Home screen`)}),` (`,a(`or`),` `,(0,X.jsx)(`strong`,{className:`text-ink`,children:a(`Install app`)}),`).`]})]})}),(0,X.jsxs)(`div`,{className:`rounded-[14px] border border-line p-4`,children:[(0,X.jsx)(`div`,{className:`font-medium mb-1`,children:a(`Quick-add shortcuts`)}),(0,X.jsxs)(`p`,{className:`text-ink-2 text-[13.5px] leading-relaxed`,children:[a(`On Android, long-press the installed icon to get the`),` `,(0,X.jsx)(`strong`,{className:`text-ink`,children:a(`Add expense`)}),` `,a(`and`),` `,(0,X.jsx)(`strong`,{className:`text-ink`,children:a(`Add revenue`)}),` `,a(`shortcuts.`),` `,a(`On iPhone, add these two links to your home screen the same way (Safari → Share → Add to Home Screen); each opens straight into the form, like a widget:`)]}),(0,X.jsx)(`ul`,{className:`mt-3 space-y-2`,children:[{path:`/add/expense`,label:`Add expense`,color:`var(--s-expense)`},{path:`/add/revenue`,label:`Add revenue`,color:`var(--s-revenue)`}].map(e=>(0,X.jsxs)(`li`,{className:`flex items-center justify-between gap-3 rounded-[12px] bg-sunken/60 px-3.5 py-2.5`,children:[(0,X.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 min-w-0`,children:[(0,X.jsx)(`span`,{className:`size-7 rounded-[8px] inline-flex items-center justify-center text-white font-bold`,style:{background:e.color},children:`+`}),(0,X.jsxs)(`span`,{className:`truncate`,children:[(0,X.jsx)(`span`,{className:`font-medium`,children:a(e.label)}),` `,(0,X.jsxs)(`span`,{className:`mono text-[12px] text-ink-3`,children:[o,e.path]})]})]}),(0,X.jsx)(`a`,{href:e.path,className:`text-accent text-[13px] font-medium shrink-0`,children:a(`Open`)})]},e.path))}),(0,X.jsx)(`p`,{className:`text-[12.5px] text-ink-3 mt-3`,children:a(`iPhone Shortcuts app users can also create a shortcut that opens one of these URLs and place it as a real home-screen widget.`)})]})]})}),(0,X.jsx)(u,{title:a(`Why not a native widget?`),children:(0,X.jsx)(`p`,{className:`text-[13.5px] text-ink-2 leading-relaxed`,children:a(`True home-screen widgets need a native iOS/Android app. ledgr is a web app that runs anywhere you host it, so it offers the next best thing: an installable app icon, OS-level shortcuts on Android, and single-purpose links that behave like widgets on iPhone.`)})})]})}var de={expense:`Expense`,revenue:`Revenue`,stakeholder:`Stakeholder`},Z={expense:`No custom fields on expenses`,revenue:`No custom fields on revenues`,stakeholder:`No custom fields on stakeholders`};function fe(){let[e,r]=(0,q.useState)(`expense`),{t:i,label:a}=m(),o=_(e,!0),{remove:f,reorder:h}=g(),v=F(),[y,b]=(0,q.useState)(void 0),[x,O]=(0,q.useState)(null),k=(0,q.useMemo)(()=>[...o.data?.items??[]].sort((e,t)=>e.sortOrder-t.sortOrder),[o.data]),A=async(e,t)=>{let n=k.map(e=>e.id),r=e+t;if(!(r<0||r>=n.length)){[n[e],n[r]]=[n[r],n[e]];try{await h.mutateAsync(n)}catch(e){v.error(i(`Reorder failed`),L(e))}}};return(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`div`,{className:`flex items-center justify-between gap-3 mb-4`,children:[(0,X.jsx)(d,{value:e,onChange:r,items:t.map(e=>({id:e,label:i(de[e])})),className:`md:w-auto`}),(0,X.jsx)(P,{variant:`primary`,size:`sm`,className:`rounded-full shrink-0`,icon:(0,X.jsx)(te,{className:`size-4`}),onClick:()=>b(null),children:i(`New field`)})]}),(0,X.jsx)(u,{flush:!0,children:o.isPending?(0,X.jsx)(c,{}):k.length?(0,X.jsx)(`ul`,{className:`divide-y divide-line`,children:k.map((e,t)=>(0,X.jsxs)(`li`,{className:s(`flex items-center`,e.archived&&`opacity-50`),children:[(0,X.jsxs)(`div`,{className:`ps-3 flex flex-col`,children:[(0,X.jsx)(`button`,{type:`button`,className:`size-7 inline-flex items-center justify-center rounded-full text-ink-3 hover:text-ink hover:bg-card-hover disabled:opacity-30`,disabled:t===0,onClick:()=>A(t,-1),"aria-label":i(`Move up`),children:(0,X.jsx)(ne,{className:`size-3.5`})}),(0,X.jsx)(`button`,{type:`button`,className:`size-7 inline-flex items-center justify-center rounded-full text-ink-3 hover:text-ink hover:bg-card-hover disabled:opacity-30`,disabled:t===k.length-1,onClick:()=>A(t,1),"aria-label":i(`Move down`),children:(0,X.jsx)(V,{className:`size-3.5`})})]}),(0,X.jsx)(n,{className:`flex-1`,title:(0,X.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[a(e),e.required&&(0,X.jsx)(l,{tone:`accent`,children:i(`required`)}),e.archived&&(0,X.jsx)(l,{children:i(`archived`)})]}),subtitle:(0,X.jsxs)(`span`,{children:[(0,X.jsx)(`span`,{className:`mono`,children:e.key}),` · `,i(e.type),e.options.length?` · ${e.options.join(`, `)}`:``]}),onClick:()=>b(e)}),(0,X.jsx)(`div`,{className:`pe-3`,children:(0,X.jsx)(D,{trigger:()=>(0,X.jsx)(`button`,{type:`button`,className:`size-9 inline-flex items-center justify-center rounded-full text-ink-3 hover:text-ink hover:bg-card-hover`,"aria-label":i(`Actions`),children:(0,X.jsx)(T,{className:`size-4`})}),children:t=>(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(w,{icon:(0,X.jsx)(S,{}),onClick:()=>{t(),b(e)},children:i(`Edit`)}),(0,X.jsx)(E,{}),(0,X.jsx)(w,{icon:(0,X.jsx)(C,{}),danger:!0,onClick:()=>{t(),O(e)},children:i(`Delete`)})]})})})]},e.id))}):(0,X.jsx)(p,{title:i(Z[e]),description:i(`Add columns like “Client”, “Invoice no.” or “Reimbursable”.`),action:(0,X.jsx)(P,{variant:`soft`,onClick:()=>b(null),children:i(`Add a field`)})})}),(0,X.jsx)(ae,{open:y!==void 0,onClose:()=>b(void 0),field:y??null,entity:e}),(0,X.jsx)(N,{open:!!x,onClose:()=>O(null),onConfirm:async()=>{try{await f.mutateAsync(x.id),v.success(i(`Field deleted`)),O(null)}catch(e){v.error(i(`Delete failed`),L(e))}},loading:f.isPending,title:i(`Delete field “{name}”?`,{name:x?a(x):``}),description:i(`Existing values stay in the records but are no longer shown or exported.`)})]})}function pe(){let[e,t]=(0,q.useState)(1),[n,r]=(0,q.useState)(``),[i,a]=(0,q.useState)(``),o=v({page:e,pageSize:50,entity:n||void 0,action:i||void 0}),[s,d]=(0,q.useState)(null),{t:f}=m(),{locale:h}=b();return(0,X.jsxs)(u,{title:f(`Audit log`),flush:!0,actions:(0,X.jsxs)(`div`,{className:`flex gap-2`,children:[(0,X.jsxs)(O,{compact:!0,className:`w-36`,value:n,onChange:e=>{r(e.target.value),t(1)},children:[(0,X.jsx)(`option`,{value:``,children:f(`All entities`)}),[`expense`,`revenue`,`stakeholder`,`category`,`settlement`,`customField`,`recurringRule`,`project`,`import`,`backup`].map(e=>(0,X.jsx)(`option`,{value:e,children:f(e)},e))]}),(0,X.jsxs)(O,{compact:!0,className:`w-32`,value:i,onChange:e=>{a(e.target.value),t(1)},children:[(0,X.jsx)(`option`,{value:``,children:f(`All actions`)}),[`create`,`update`,`delete`,`import`,`settle`,`recompute`,`generate`,`restore`].map(e=>(0,X.jsx)(`option`,{value:e,children:f(e)},e))]})]}),children:[o.isPending&&(0,X.jsx)(c,{}),o.data&&!o.data.items.length&&(0,X.jsx)(p,{title:f(`Nothing recorded yet`)}),(0,X.jsx)(`ul`,{className:`divide-y divide-line`,children:o.data?.items.map(e=>(0,X.jsx)(`li`,{children:(0,X.jsxs)(`button`,{type:`button`,onClick:()=>d(s===e.id?null:e.id),className:`w-full text-start px-4 md:px-5 py-3 row-hover`,children:[(0,X.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap text-[13.5px]`,children:[(0,X.jsx)(l,{tone:e.action===`delete`?`critical`:e.action===`create`||e.action===`import`?`good`:`neutral`,children:f(e.action)}),(0,X.jsx)(`span`,{className:`font-medium`,children:f(e.entity)}),(0,X.jsx)(`span`,{className:`text-ink-3 truncate`,children:e.actorEmail}),(0,X.jsx)(`span`,{className:`ms-auto text-ink-3 num text-[12.5px]`,title:new Date(e.at).toLocaleString(),children:z(e.at,h)})]}),(0,X.jsx)(`div`,{className:`text-[12.5px] text-ink-3 mt-1 truncate`,children:me(e.before,e.after,f)}),s===e.id&&(0,X.jsx)(`pre`,{className:`mono whitespace-pre-wrap max-h-64 overflow-auto text-[11.5px] bg-sunken rounded-[10px] p-3 mt-2`,children:JSON.stringify({before:e.before,after:e.after},null,2)})]})},e.id))}),o.data&&(0,X.jsx)(x,{page:o.data.page,pageSize:o.data.pageSize,total:o.data.total,onPage:t})]})}function me(e,t,n){let r=e??{},i=t??{};if(!e&&t)return Q(i);if(e&&!t)return Q(r);let a=Object.keys({...r,...i}).filter(e=>JSON.stringify(r[e])!==JSON.stringify(i[e])&&![`updatedAt`,`splits`].includes(e));return a.length?a.map(e=>`${e}: ${$(r[e])} → ${$(i[e])}`).join(` · `):n(`no visible change`)}function Q(e){return[`description`,`name`,`label`,`amountMinor`,`date`,`inserted`,`count`].filter(t=>t in e).map(t=>`${t}: ${$(e[t])}`).join(` · `)||JSON.stringify(e).slice(0,120)}function $(e){return e==null?`∅`:typeof e==`object`?JSON.stringify(e).slice(0,40):String(e).slice(0,40)}export{oe as SettingsPage};
@@ -1 +0,0 @@
1
- import{P as e,c as t,d as n,dt as r,g as i,gt as a,h as o,l as s,n as c,o as l,p as u,pt as d,s as f,t as p,v as m,y as h,z as g}from"./badge-BTiDEJlh.js";import{D as _,O as v,T as y,c as b,n as x,s as S,w as C}from"./queries-IGiwF8nF.js";import{n as w}from"./project-Bgpq3nFR.js";import{n as T}from"./table-DQsx5_iN.js";import{a as E,i as D,n as O,o as k,r as A,t as j}from"./menu-BDGd2JUq.js";import{i as M,o as N,r as P,s as ee}from"./media-Cr7juL5w.js";import{D as F,c as I,d as L,f as R,l as z,m as B,p as V,r as H,s as U,u as W,y as G}from"./index-DOwVPfdT.js";import{t as K}from"./format-GDcQVAp4.js";import{t as te}from"./color-picker-DLlr-Cq6.js";import{t as q}from"./money-Ch2MLu6J.js";import{t as J}from"./custom-cell-Wgh3D7lb.js";var Y={name:`arrow-right`,size:24,node:[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]};Y.node;var X=i(Y),Z=a(d(),1),Q=r();function $({open:e,onClose:t,stakeholder:n,suggestedShare:r}){let{t:i}=m(),a=B(),{create:o,update:s}=_(),[c,l]=(0,Z.useState)(``),[u,d]=(0,Z.useState)(``),[f,p]=(0,Z.useState)(``),[v,y]=(0,Z.useState)(`0`),[b,x]=(0,Z.useState)(!0),[S,C]=(0,Z.useState)(``),[w,T]=(0,Z.useState)(``),[E,D]=(0,Z.useState)(h[0]),[O,k]=(0,Z.useState)({}),[A,j]=(0,Z.useState)({});(0,Z.useEffect)(()=>{e&&(j({}),l(n?.name??``),d(n?.nameAr??``),p(n?.email??``),y(String(n?.sharePercent??r??0)),x(n?.active??!0),C(n?.joinedAt??``),T(n?.notes??``),D(n?.color??h[0]),k(n?.customFields??{}))},[e,n,r]);let F=Number(v),I=c.trim().length>0&&Number.isFinite(F)&&F>=0&&F<=100,R=o.isPending||s.isPending,z=async()=>{let e={name:c.trim(),nameAr:u.trim()||null,email:f.trim()||null,sharePercent:F,active:b,joinedAt:S||null,notes:w.trim()||null,color:E,customFields:O};try{n?await s.mutateAsync({id:n.id,...e}):await o.mutateAsync(e),a.success(i(n?`Stakeholder updated`:`Stakeholder added`)),t()}catch(e){e instanceof g&&e.code===`CUSTOM_FIELDS`&&Array.isArray(e.details)&&j(Object.fromEntries(e.details.map(e=>[e.key,e.message]))),a.error(i(`Could not save`),V(e))}};return(0,Q.jsx)(W,{open:e,onClose:t,title:i(n?`Edit stakeholder`:`New stakeholder`),description:i(`Ownership share drives default expense splits and profit distribution.`),footer:(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(L,{variant:`ghost`,size:`md`,onClick:t,className:`max-md:hidden`,children:i(`Cancel`)}),(0,Q.jsx)(L,{variant:`primary`,size:`lg`,onClick:z,loading:R,disabled:!I,className:`w-full md:w-auto`,children:i(n?`Save changes`:`Add stakeholder`)})]}),children:(0,Q.jsxs)(`form`,{className:`space-y-4`,onSubmit:e=>{e.preventDefault(),I&&z()},children:[(0,Q.jsxs)(`div`,{className:`grid grid-cols-[1fr_auto] gap-3 items-end`,children:[(0,Q.jsx)(P,{label:i(`Name`),required:!0,children:(0,Q.jsx)(M,{value:c,onChange:e=>l(e.target.value),autoFocus:!n})}),(0,Q.jsx)(te,{value:E,onChange:D})]}),(0,Q.jsx)(P,{label:i(`Arabic name`),hint:i(`optional`),children:(0,Q.jsx)(M,{lang:`ar`,dir:`rtl`,value:u,onChange:e=>d(e.target.value)})}),(0,Q.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,Q.jsx)(P,{label:i(`Ownership share`),required:!0,hint:`%`,children:(0,Q.jsx)(M,{mono:!0,type:`number`,step:`0.01`,min:0,max:100,value:v,onChange:e=>y(e.target.value)})}),(0,Q.jsx)(P,{label:i(`Joined`),children:(0,Q.jsx)(M,{mono:!0,type:`date`,value:S,onChange:e=>C(e.target.value)})})]}),(0,Q.jsx)(P,{label:i(`Email`),children:(0,Q.jsx)(M,{type:`email`,value:f,onChange:e=>p(e.target.value),placeholder:i(`Optional`)})}),(0,Q.jsx)(ee,{checked:b,onChange:x,label:i(`Active partner`),description:i(b?`Included in ownership splits and distribution`:`Kept for history, excluded from new splits`)}),(0,Q.jsx)(P,{label:i(`Notes`),children:(0,Q.jsx)(N,{value:w,onChange:e=>T(e.target.value),placeholder:i(`Optional`)})}),(0,Q.jsx)(U,{entity:`stakeholder`,values:O,onChange:k,errors:A})]})})}function ne(){let{t}=m(),[r,i]=F(),a=r.get(`tab`)||`ownership`,s=e=>i(t=>{let n=new URLSearchParams(t);return n.set(`tab`,e),n.delete(`page`),n},{replace:!0}),c=v(),[l,d]=(0,Z.useState)(void 0),[f,p]=(0,Z.useState)({open:!1}),h=c.data?.shareTotal??0,g=e(100-h);return(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(n,{title:t(`Stakeholders`),subtitle:c.data?(0,Q.jsxs)(Q.Fragment,{children:[t(`{n} active partners`,{n:c.data.items.filter(e=>e.active).length}),` · `,t(`ownership`),` `,(0,Q.jsx)(`span`,{className:o(`num font-medium`,Math.abs(g)>.01?`text-warning`:`text-ink`),children:K(h,2)})]}):t(`Loading…`),actions:(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(L,{variant:`secondary`,size:`sm`,className:`rounded-full`,icon:(0,Q.jsx)(X,{className:`size-4 rtl-flip`}),onClick:()=>p({open:!0}),children:t(`Record settlement`)}),(0,Q.jsx)(L,{variant:`primary`,size:`sm`,className:`rounded-full`,icon:(0,Q.jsx)(G,{className:`size-4`}),onClick:()=>d(null),children:t(`New stakeholder`)})]})}),c.data&&Math.abs(g)>.01&&c.data.items.length>0&&(0,Q.jsxs)(`div`,{className:`mb-4 rounded-[14px] bg-warning/10 px-4 py-3 text-[13.5px]`,children:[t(`Ownership adds up to`),` `,(0,Q.jsx)(`span`,{className:`num font-medium`,children:K(h,2)}),`. `,t(`Splits use the active total, but you probably want 100%.`),` `,g>0?t(`{pct}% is unassigned.`,{pct:g.toFixed(2)}):t(`It is {pct}% over.`,{pct:Math.abs(g).toFixed(2)})]}),(0,Q.jsx)(u,{className:`mb-4`,value:a,onChange:s,items:[{id:`ownership`,label:t(`Ownership`)},{id:`balances`,label:t(`Balances`)},{id:`settlements`,label:t(`Settlements`)},{id:`distribution`,label:t(`Profit`)}]}),a===`ownership`&&(0,Q.jsx)(re,{onEdit:e=>d(e)}),a===`balances`&&(0,Q.jsx)(ie,{onSettle:e=>p({open:!0,prefill:e})}),a===`settlements`&&(0,Q.jsx)(ae,{onEdit:e=>p({open:!0,settlement:e})}),a===`distribution`&&(0,Q.jsx)(oe,{}),(0,Q.jsx)($,{open:l!==void 0,onClose:()=>d(void 0),stakeholder:l??null,suggestedShare:l===null?Math.max(0,g):void 0}),(0,Q.jsx)(H,{open:f.open,onClose:()=>p({open:!1}),settlement:f.settlement,prefill:f.prefill})]})}function re({onEdit:e}){let{t:n,name:r,label:i}=m(),a=v(),o=S(`stakeholder`),{remove:u}=_(),d=B(),{date:h}=w(),[g,y]=(0,Z.useState)(null),[b,x]=(0,Z.useState)(!1),[C,T]=(0,Z.useState)(null),M=o.data?.items??[];if(a.isPending)return(0,Q.jsx)(s,{});let N=a.data?.items??[],P=Math.max(a.data?.shareTotal??0,100);return(0,Q.jsxs)(Q.Fragment,{children:[N.length>0&&(0,Q.jsxs)(`div`,{className:`card p-4 md:p-5 mb-4`,children:[(0,Q.jsx)(`div`,{className:`label mb-2`,children:n(`Cap table`)}),(0,Q.jsx)(`div`,{className:`flex h-8 rounded-[10px] overflow-hidden bg-sunken gap-[2px]`,children:N.filter(e=>e.active&&e.sharePercent>0).map(e=>(0,Q.jsx)(`div`,{className:`h-full flex items-center justify-center text-[12px] font-semibold text-white overflow-hidden`,style:{width:`${e.sharePercent/P*100}%`,background:e.color},title:`${r(e)} ${e.sharePercent}%`,children:(0,Q.jsx)(`span`,{className:`truncate px-1.5`,children:e.sharePercent>=12?`${r(e).split(` `)[0]} ${e.sharePercent}%`:e.sharePercent>=6?`${e.sharePercent}%`:``})},e.id))})]}),(0,Q.jsxs)(l,{flush:!0,children:[!N.length&&(0,Q.jsx)(f,{title:n(`No stakeholders yet`),description:n(`Add the partners and their ownership percentage.`)}),(0,Q.jsx)(`ul`,{className:`divide-y divide-line`,children:N.map(i=>(0,Q.jsxs)(`li`,{className:`flex items-center`,children:[(0,Q.jsx)(t,{className:`flex-1`,leading:(0,Q.jsx)(p,{name:r(i),color:i.color,size:40}),title:(0,Q.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[r(i),!i.active&&(0,Q.jsx)(c,{children:n(`inactive`)})]}),subtitle:[i.email,i.joinedAt?n(`since {date}`,{date:h(i.joinedAt)}):null].filter(Boolean).join(` · `)||n(`No contact details`),trailing:(0,Q.jsxs)(`span`,{className:`num text-[17px] font-semibold`,children:[i.sharePercent.toFixed(i.sharePercent%1?2:0),`%`]}),onClick:()=>T(i)}),(0,Q.jsx)(`div`,{className:`pe-3`,children:(0,Q.jsx)(j,{trigger:()=>(0,Q.jsx)(`button`,{type:`button`,className:`size-9 inline-flex items-center justify-center rounded-full text-ink-3 hover:text-ink hover:bg-card-hover`,"aria-label":n(`Actions`),children:(0,Q.jsx)(k,{className:`size-4`})}),children:t=>(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(O,{icon:(0,Q.jsx)(E,{}),onClick:()=>{t(),e(i)},children:n(`Edit`)}),(0,Q.jsx)(A,{}),(0,Q.jsx)(O,{icon:(0,Q.jsx)(D,{}),danger:!0,onClick:()=>{t(),x(!1),y(i)},children:n(`Remove`)})]})})})]},i.id))})]}),(0,Q.jsx)(z,{open:!!C,onClose:()=>T(null),title:C?r(C):``,description:C?`${n(`{pct}% ownership`,{pct:C.sharePercent})} · ${C.active?n(`active`):n(`inactive`)}`:``,footer:C&&(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(L,{variant:`danger`,size:`md`,onClick:()=>{x(!1),y(C)},children:n(`Remove`)}),(0,Q.jsx)(L,{variant:`primary`,size:`md`,onClick:()=>{e(C),T(null)},children:n(`Edit`)})]}),children:C&&(0,Q.jsxs)(`dl`,{className:`grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-[14px]`,children:[(0,Q.jsx)(`dt`,{className:`text-ink-3`,children:n(`Email`)}),(0,Q.jsx)(`dd`,{children:C.email??`—`}),(0,Q.jsx)(`dt`,{className:`text-ink-3`,children:n(`Joined`)}),(0,Q.jsx)(`dd`,{children:C.joinedAt?h(C.joinedAt):`—`}),M.map(e=>(0,Q.jsxs)(`span`,{className:`contents`,children:[(0,Q.jsx)(`dt`,{className:`text-ink-3`,children:i(e)}),(0,Q.jsx)(`dd`,{children:(0,Q.jsx)(J,{def:e,value:C.customFields?.[e.key]})})]},e.id)),C.notes&&(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(`dt`,{className:`text-ink-3`,children:n(`Notes`)}),(0,Q.jsx)(`dd`,{className:`whitespace-pre-wrap`,children:C.notes})]})]})}),(0,Q.jsx)(I,{open:!!g,onClose:()=>y(null),onConfirm:async()=>{if(g)try{await u.mutateAsync({id:g.id,force:b}),d.success(n(`Stakeholder removed`)),y(null),x(!1),T(null)}catch(e){e.code===`HAS_RECORDS`&&x(!0),d.error(n(`Could not remove`),V(e))}},loading:u.isPending,confirmLabel:n(b?`Remove anyway`:`Remove`),title:n(`Remove {name}?`,{name:g?r(g):``}),description:n(b?`This stakeholder has expense splits, payments or settlements. Removing them deletes their split rows and un-assigns what they paid. Prefer marking them inactive.`:`If they have history you will be asked to confirm again. Consider marking them inactive instead.`)})]})}function ie({onSettle:e}){let{t,name:n}=m(),{range:r}=R(),{money:i}=w(),a=x(r.from,r.to);if(a.isPending)return(0,Q.jsx)(s,{});if(a.isError)return(0,Q.jsx)(f,{title:t(`Could not load balances`),description:a.error.message});let c=a.data,u=Math.max(1,...c.balances.map(e=>Math.abs(e.netMinor)));return(0,Q.jsxs)(`div`,{className:`grid grid-cols-1 xl:grid-cols-3 gap-4`,children:[(0,Q.jsxs)(l,{className:`xl:col-span-2`,title:t(`Who owes whom`),subtitle:t(`Expenses {total} in this period · company paid {pool}`,{total:i(c.totalExpenseMinor,{compact:!0}),pool:i(c.poolPaidMinor,{compact:!0})}),flush:!0,children:[(0,Q.jsx)(`ul`,{className:`divide-y divide-line`,children:c.balances.map(e=>(0,Q.jsxs)(`li`,{className:`px-4 md:px-5 py-3`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-3`,children:[e.stakeholderId===`pool`?(0,Q.jsx)(`span`,{className:`size-10 rounded-full border border-dashed border-line-strong inline-flex items-center justify-center text-[12px] text-ink-3 shrink-0`,children:t(`Co`)}):(0,Q.jsx)(p,{name:n(e),color:e.color,size:40}),(0,Q.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,Q.jsxs)(`div`,{className:`text-[14.5px] font-medium truncate`,children:[e.stakeholderId===`pool`?t(e.name):n(e),e.stakeholderId!==`pool`&&(0,Q.jsxs)(`span`,{className:`num text-[12.5px] text-ink-3 font-normal`,children:[` · `,e.sharePercent,`%`]})]}),(0,Q.jsxs)(`div`,{className:`text-[12.5px] text-ink-3 truncate`,children:[t(`Share {share} · paid {paid}`,{share:i(e.owedMinor,{compact:!0}),paid:i(e.paidMinor,{compact:!0})}),e.settledOutMinor||e.settledInMinor?` · ${t(`settled {out} / {in}`,{out:i(e.settledOutMinor,{compact:!0}),in:i(e.settledInMinor,{compact:!0})})}`:``]})]}),(0,Q.jsxs)(`div`,{className:`text-end shrink-0`,children:[(0,Q.jsx)(q,{minor:e.netMinor,tone:`flow`,signed:!0,className:`text-[15px] font-semibold block`}),(0,Q.jsx)(`span`,{className:`text-[11.5px] text-ink-3`,children:e.netMinor>0?t(`is owed`):e.netMinor<0?t(`owes`):t(`settled`)})]})]}),(0,Q.jsxs)(`div`,{className:`relative h-1.5 mt-2.5 ms-[52px]`,children:[(0,Q.jsx)(`span`,{className:`absolute left-1/2 top-0 bottom-0 w-px bg-line-strong`}),(0,Q.jsx)(`span`,{className:o(`absolute top-0 bottom-0 rounded-full`,e.netMinor>=0?`left-1/2 bg-good/70`:`right-1/2 bg-critical/70`),style:{width:`${Math.abs(e.netMinor)/u*50}%`}})]})]},e.stakeholderId))}),(0,Q.jsx)(`p`,{className:`px-4 md:px-5 py-3 text-[12.5px] text-ink-3 border-t border-line`,children:t(`Net = paid − share of expenses + settlements paid − settlements received. The company row is the shared account. All rows sum to zero.`)})]}),(0,Q.jsx)(l,{title:t(`Settle up`),subtitle:t(`Fewest transfers to clear everything`),flush:!0,children:c.suggestions.length?(0,Q.jsx)(`ul`,{className:`divide-y divide-line`,children:c.suggestions.map((r,i)=>(0,Q.jsxs)(`li`,{className:`px-4 md:px-5 py-3 flex items-center gap-3`,children:[(0,Q.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,Q.jsxs)(`div`,{className:`text-[14px] flex items-center gap-1.5 min-w-0`,children:[(0,Q.jsx)(`span`,{className:`font-medium truncate`,children:r.fromStakeholderId===`pool`?t(r.fromName):n({name:r.fromName,nameAr:r.fromNameAr})}),(0,Q.jsx)(X,{className:`size-4 text-ink-3 shrink-0 rtl-flip`}),(0,Q.jsx)(`span`,{className:`font-medium truncate`,children:r.toStakeholderId===`pool`?t(r.toName):n({name:r.toName,nameAr:r.toNameAr})})]}),(0,Q.jsx)(q,{minor:r.amountMinor,className:`text-[16px] font-semibold`})]}),(0,Q.jsx)(L,{size:`sm`,variant:`soft`,className:`rounded-full`,onClick:()=>e(r),children:t(`Record`)})]},i))}):(0,Q.jsx)(f,{title:t(`All square`),description:t(`Nobody owes anyone for this period.`)})})]})}function ae({onEdit:e}){let{t:n,name:r}=m(),{range:i}=R(),{date:a}=w(),[o,c]=F(),u=Number(o.get(`page`)??`1`)||1,d=y((0,Z.useMemo)(()=>({from:i.from,to:i.to,page:u,pageSize:50}),[i,u])),{remove:h}=C(),g=B(),[_,v]=(0,Z.useState)(null);return(0,Q.jsxs)(l,{flush:!0,children:[d.isPending&&(0,Q.jsx)(s,{}),d.data&&!d.data.items.length&&(0,Q.jsx)(f,{title:n(`No settlements`),description:n(`Record one from the Balances tab when a partner pays someone back.`)}),(0,Q.jsx)(`ul`,{className:`divide-y divide-line`,children:d.data?.items.map(i=>(0,Q.jsxs)(`li`,{className:`flex items-center`,children:[(0,Q.jsx)(t,{className:`flex-1`,leading:i.from&&(0,Q.jsx)(p,{name:r(i.from),color:i.from.color,size:40}),title:(0,Q.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[i.from?r(i.from):``,(0,Q.jsx)(X,{className:`size-4 text-ink-3 rtl-flip`}),i.to?r(i.to):n(`Company`)]}),subtitle:[a(i.date),i.note].filter(Boolean).join(` · `),trailing:(0,Q.jsx)(q,{minor:i.amountMinor,className:`text-[15px] font-semibold`})}),(0,Q.jsx)(`div`,{className:`pe-3`,children:(0,Q.jsx)(j,{trigger:()=>(0,Q.jsx)(`button`,{type:`button`,className:`size-9 inline-flex items-center justify-center rounded-full text-ink-3 hover:text-ink hover:bg-card-hover`,"aria-label":n(`Actions`),children:(0,Q.jsx)(k,{className:`size-4`})}),children:t=>(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(O,{icon:(0,Q.jsx)(E,{}),onClick:()=>{t(),e(i)},children:n(`Edit`)}),(0,Q.jsx)(A,{}),(0,Q.jsx)(O,{icon:(0,Q.jsx)(D,{}),danger:!0,onClick:()=>{t(),v(i)},children:n(`Delete`)})]})})})]},i.id))}),d.data&&(0,Q.jsx)(T,{page:d.data.page,pageSize:d.data.pageSize,total:d.data.total,onPage:e=>c(t=>{let n=new URLSearchParams(t);return n.set(`page`,String(e)),n},{replace:!0})}),(0,Q.jsx)(I,{open:!!_,onClose:()=>v(null),onConfirm:async()=>{try{await h.mutateAsync(_.id),g.success(n(`Settlement deleted`)),v(null)}catch(e){g.error(n(`Delete failed`),V(e))}},loading:h.isPending,title:n(`Delete this settlement?`)})]})}function oe(){let{t:e,name:t}=m(),{range:n}=R(),{money:r}=w(),i=b(n.from,n.to);if(i.isPending)return(0,Q.jsx)(s,{});if(i.isError)return(0,Q.jsx)(f,{title:e(`Could not load distribution`),description:i.error.message});let a=i.data;return(0,Q.jsxs)(`div`,{className:`space-y-4`,children:[(0,Q.jsx)(`div`,{className:`grid grid-cols-3 gap-3`,children:[{l:`Revenue`,v:a.revenueMinor,signed:!1},{l:`Expenses`,v:a.expenseMinor,signed:!1},{l:`Profit`,v:a.profitMinor,signed:!0}].map(t=>(0,Q.jsxs)(`div`,{className:`card p-4`,children:[(0,Q.jsx)(`div`,{className:`label`,children:e(t.l)}),(0,Q.jsx)(`div`,{className:o(`num text-[18px] md:text-[22px] font-semibold mt-1 tracking-tight`,t.signed&&t.v<0&&`text-critical`),children:r(t.v,{signed:t.signed,compact:!0})})]},t.l))}),(0,Q.jsxs)(l,{title:e(`Each partner's share`),subtitle:e(`By current ownership · shares total {pct}`,{pct:K(a.shareTotal,2)}),flush:!0,children:[(0,Q.jsxs)(`ul`,{className:`divide-y divide-line`,children:[a.items.map(n=>(0,Q.jsxs)(`li`,{className:`px-4 md:px-5 py-3 flex items-center gap-3`,children:[(0,Q.jsx)(p,{name:t(n),color:n.color,size:40}),(0,Q.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,Q.jsxs)(`div`,{className:`text-[14.5px] font-medium truncate`,children:[t(n),` `,(0,Q.jsxs)(`span`,{className:`num text-[12.5px] text-ink-3 font-normal`,children:[n.sharePercent,`%`]})]}),(0,Q.jsx)(`div`,{className:`text-[12.5px] text-ink-3 truncate`,children:e(`Revenue {rev} · expenses {exp}`,{rev:r(n.revenueShareMinor,{compact:!0}),exp:r(n.expenseShareMinor,{compact:!0})})})]}),(0,Q.jsxs)(`div`,{className:`text-end`,children:[(0,Q.jsx)(q,{minor:n.profitShareMinor,tone:`flow`,signed:!0,className:`text-[15px] font-semibold block`}),(0,Q.jsx)(`span`,{className:`text-[11.5px] text-ink-3`,children:e(`profit share`)})]})]},n.stakeholderId)),!a.items.length&&(0,Q.jsx)(`li`,{children:(0,Q.jsx)(f,{title:e(`No active stakeholders`)})})]}),(0,Q.jsx)(`p`,{className:`px-4 md:px-5 py-3 text-[12.5px] text-ink-3 border-t border-line`,children:e(`Uses current ownership shares for the selected period. Individual expense splits are snapshots and may differ if ownership changed.`)})]})]})}export{ne as StakeholdersPage};