PageSourceSearch

https://buckettys.com.au/assets/staff-till-recon-Bg_vxcDp.js

js buckettys.com.au collected 2026-10-04 20:58:57 UTC 49,120 bytes, 11 lines download raw bytes

1import{T as oe,au as Ae,r as v,u as W,j as e,L as se,B as w,I as U,c as G,C as M,g as z,aE as Pe,as as Ee,z as H,i as J,A as X,k as O,y as L,R as ue,cL as me,bI as he}from"./index-CLsVjUEP.js";import{T as Re}from"./textarea-D4pf2qWA.js";import{A as pe,a as xe,b as fe,c as je,d as ge,e as ye,f as be,g as ve}from"./alert-dialog-B9M004GQ.js";import{u as Ne}from"./use-upload-BHVQzZiQ.js";import{r as _e}from"./resize-image-DYAesr3D.js";import{A as Ue}from"./arrow-left-BOkfCv0-.js";import{B as Z}from"./banknote-BQjK0agG.js";import{U as Me}from"./undo-2-DI5t7vMZ.js";import{C as re}from"./camera-BzVtkVXa.js";import{T as we}from"./trash-2-DijQlxkA.js";import{P as ze}from"./pencil-BSJG_kQW.js";import{H as Oe}from"./history-hSsfGFii.js";/**
2 * @license lucide-react v0.453.0 - ISC
3 *
4 * This source code is licensed under the ISC license.
5 * See the LICENSE file in the root directory of this source tree.
6 */const ke=oe("CalendarRange",[["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2",key:"1hopcy"}],["path",{d:"M16 2v4",key:"4m81vk"}],["path",{d:"M3 10h18",key:"8toen8"}],["path",{d:"M8 2v4",key:"1cmpym"}],["path",{d:"M17 14h-6",key:"bkmgh3"}],["path",{d:"M13 18H7",key:"bb0bb7"}],["path",{d:"M7 14h.01",key:"1qa3f1"}],["path",{d:"M17 18h.01",key:"1bdyru"}]]);/**
7 * @license lucide-react v0.453.0 - ISC
8 *
9 * This source code is licensed under the ISC license.
10 * See the LICENSE file in the root directory of this source tree.
11 */const Q=oe("ReceiptText",[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z",key:"q3az6g"}],["path",{d:"M14 8H8",key:"1l3xfs"}],["path",{d:"M16 12H8",key:"1fr5h0"}],["path",{d:"M13 16H8",key:"wsln4y"}]]);async function V(r,l,n){const i=[["/api/staff/till-recon"],["/api/staff/till-recon/admin-working"],["/api/staff/till-recon/petty-cash/archive",l]];n&&i.push(["/api/staff/till-recon/weekly-banking",l,n],["/api/staff/till-recon/petty-cash/history",l,n]),await Promise.all(i.map(j=>r.invalidateQueries({queryKey:j})))}function $e(r,l){const n=Object.keys(r).map(Number).filter(s=>Number.isInteger(s)&&s>0&&(r[String(s)]??0)>0).sort((s,h)=>s-h),i=[];for(const s of n){let h=Math.floor(r[String(s)]??0),C=1;for(;h>0;){const y=Math.min(C,h),N=s*y;N<=l&&i.push({denomination:s,quantity:y,value:N}),h-=y,C*=2}}const j=new Uint8Array(l+1),t=new Array(l+1).fill(null),d=new Float64Array(l+1);d.fill(Number.NEGATIVE_INFINITY),j[0]=1,d[0]=0;for(const s of i){const C=Math.max(0,1e4-s.denomination)*s.quantity;for(let y=l;y>=s.value;y--){const N=y-s.value;if(!j[N])continue;const S=d[N]+C;(!j[y]||S>d[y])&&(j[y]=1,t[y]={denomination:s.denomination,quantity:s.quantity,previous:t[N]},d[y]=S)}}let x=l;for(;x>0&&!j[x];)x--;const g={};for(let s=t[x];s;s=s.previous)g[s.denomination]=(g[s.denomination]??0)+s.quantity;const _={};let m=0;for(const s of n){const h=(r[String(s)]??0)-(g[s]??0);h>0&&(_[s]=h,m+=h*s)}return{keep:g,bank:_,keepTotal:x,bankTotal:m,shortfall:l-x}}const u=r=>`$${(r/100).toLocaleString("en-AU",{minimumFractionDigits:2,maximumFractionDigits:2})}`,Y=r=>r>=100?`$${r/100}`:`${r}c`,ce=r=>`${r>0?"+":""}${u(r)}`;function ae(r,l){const n=new Date(`${r}T12:00:00Z`);return n.setUTCDate(n.getUTCDate()+l),n.toISOString().slice(0,10)}function ne(r){if(!/^\d{4}-\d{2}-\d{2}$/.test(r))return!1;const l=new Date(`${r}T12:00:00Z`);return!Number.isNaN(l.getTime())&&l.toISOString().slice(0,10)===r}function ie(r){if(!ne(r))return"";const l=new Date(`${r}T12:00:00Z`),n=l.getUTCDay();return l.setUTCDate(l.getUTCDate()-(n===0?6:n-1)),l.toISOString().slice(0,10)}const de=r=>new Date(`${r}T12:00:00Z`).toLocaleDateString("en-AU",{day:"2-digit",month:"2-digit",year:"numeric",timeZone:"UTC"}),R=r=>new Date(`${r}T12:00:00Z`).toLocaleDateString("en-AU",{weekday:"short",day:"2-digit",month:"2-digit",timeZone:"UTC"}),Ce=r=>new Date(r).toLocaleString("en-AU",{dateStyle:"medium",timeStyle:"short",timeZone:"Australia/Sydney"});function Se(r,l){if(r.key!=="Enter")return;r.preventDefault();const n=Array.from(document.querySelectorAll(`[data-till-count-grid="${l}"]`)),i=n.indexOf(r.currentTarget),j=n[i+(r.shiftKey?-1:1)];j&&(j.focus(),j.select())}function Le({tillNumber:r,denominations:l,floatCents:n}){const[i,j]=v.useState(!1),t=v.useMemo(()=>$e(l,n),[l,n]),d=g=>Object.keys(g).map(Number).sort((_,m)=>_-m),x=g=>Object.keys(g).map(Number).sort((_,m)=>m-_);return e.jsxs("div",{className:"border rounded-md",children:[e.jsxs("button",{type:"button",className:"w-full flex items-center justify-between gap-2 p-2 text-sm font-medium",onClick:()=>j(g=>!g),"data-testid":`button-refloat-${r}`,children:[e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(Z,{className:"w-4 h-4 text-yellow-500"})," Refloat instructions"]}),i?e.jsx(me,{className:"w-4 h-4"}):e.jsx(he,{className:"w-4 h-4"})]}),i&&e.jsxs("div",{className:"p-3 pt-0 space-y-3 text-sm","data-testid":`refloat-detail-${r}`,children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1",children:t.shortfall===0?e.jsxs(e.Fragment,{children:["Keep in till — ",u(t.keepTotal)," float"]}):e.jsxs(e.Fragment,{children:["Keep in till — ",u(t.keepTotal)," (can't make the exact float yet)"]})}),d(t.keep).length===0?e.jsx("p",{className:"text-muted-foreground",children:"Nothing — the till was empty."}):e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-0.5",children:d(t.keep).map(g=>e.jsxs("div",{className:"flex justify-between",children:[e.jsxs("span",{children:[t.keep[g]," × ",Y(g)]}),e.jsx("span",{className:"text-muted-foreground",children:u(t.keep[g]*g)})]},g))})]}),e.jsxs("div",{children:[e.jsxs("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1",children:["Banking bag → safe — ",u(t.bankTotal)]}),x(t.bank).length===0?e.jsx("p",{className:"text-muted-foreground",children:"Nothing to bank."}):e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-0.5",children:x(t.bank).map(g=>e.jsxs("div",{className:"flex justify-between",children:[e.jsxs("span",{children:[t.bank[g]," × ",Y(g)]}),e.jsx("span",{className:"text-muted-foreground",children:u(t.bank[g]*g)})]},g))})]}),t.shortfall>0&&e.jsx("p",{className:"text-xs text-destructive font-medium","data-testid":`text-refloat-sh
11ortfall-${r}`,children:t.bankTotal>0?e.jsxs(e.Fragment,{children:["The counted cash can’t make exactly $500 without exceeding it, so this plan leaves the float ",u(t.shortfall)," short."]}):e.jsxs(e.Fragment,{children:["The till only holds ",u(t.keepTotal)," — top it up with ",u(t.shortfall)," from the safe to restore the $500 float. Don't bank anything from this till."]})}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"This plan keeps the closest possible float up to $500, preserves useful change where possible, and sends larger notes to the safe first."})]})]})}function Ie({venue:r,date:l,tillNumber:n,existing:i,denominations:j,floatCents:t}){const{toast:d}=J(),x=X(),[g,_]=v.useState(!1),[m,s]=v.useState({}),[h,C]=v.useState(""),y=()=>{var k;const f={};for(const D of j){const c=(k=i==null?void 0:i.denominations)==null?void 0:k[String(D)];f[String(D)]=c?String(c):""}s(f),C((i==null?void 0:i.counted_by)??""),_(!0)},N=v.useMemo(()=>j.reduce((f,k)=>f+k*(parseInt(m[String(k)]||"0",10)||0),0),[m,j]),S=O({mutationFn:()=>{const f={};for(const k of j){const D=parseInt(m[String(k)]||"0",10)||0;D>0&&(f[String(k)]=D)}return L("POST","/api/staff/till-recon/opening",{venue:r,service_date:l,till_number:n,denominations:f,counted_by:h.trim()})},onSuccess:()=>{_(!1),x.invalidateQueries({queryKey:["/api/staff/till-recon"]}),d({title:`Till ${n} opening float recorded`})},onError:f=>d({title:"Couldn't save opening count",description:(f==null?void 0:f.message)||String(f),variant:"destructive"})}),b=j.filter(f=>f>=500),p=j.filter(f=>f<500),T=i?i.counted_cents-t:0;return e.jsxs("div",{className:"border rounded-md p-2 space-y-2","data-testid":`opening-float-${n}`,children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("span",{className:"text-sm font-medium flex items-center gap-2",children:["Opening float",i&&!g&&(T===0?e.jsxs(H,{variant:"secondary",className:"gap-1 text-green-700",children:[e.jsx(ue,{className:"w-3 h-3"})," ",u(i.counted_cents)," confirmed"]}):e.jsxs(H,{variant:"destructive",className:"gap-1",children:[u(i.counted_cents)," — ",T>0?"+":"",u(T)," vs float"]}))]}),i&&!g&&e.jsxs("span",{className:"text-xs text-muted-foreground",children:["by ",i.counted_by]})]}),g?e.jsxs("div",{className:"space-y-3",children:[[{label:"Notes",ds:b},{label:"Coins",ds:p}].map(f=>e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1",children:f.label}),e.jsx("div",{className:"grid grid-cols-3 sm:grid-cols-6 gap-2",children:f.ds.map(k=>{const D=`opening-denom-${n}-${k}`;return e.jsxs("div",{children:[e.jsx("label",{htmlFor:D,className:"text-xs text-muted-foreground",children:Y(k)}),e.jsx(U,{id:D,type:"number",inputMode:"numeric",min:0,placeholder:"0",value:m[String(k)]??"",onChange:c=>s(o=>({...o,[String(k)]:c.target.value})),onKeyDown:c=>Se(c,`opening-${n}`),"data-till-count-grid":`opening-${n}`,"data-testid":`input-opening-denom-${n}-${k}`})]},k)})})]},f.label)),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-muted-foreground",children:"Your name (required)"}),e.jsx(U,{value:h,onChange:f=>C(f.target.value),placeholder:"Who counted this float?","data-testid":`input-opening-name-${n}`})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2 flex-wrap",children:[e.jsxs("p",{className:"text-sm",children:["Counted: ",e.jsx("span",{className:`font-semibold ${N===t?"text-green-600":""}`,"data-testid":`text-opening-live-total-${n}`,children:u(N)}),N!==t&&N>0&&e.jsxs("span",{className:"text-destructive text-xs ml-2",children:[N>t?"+":"",u(N-t)," vs ",u(t)," float"]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(w,{variant:"outline",size:"sm",onClick:()=>_(!1),children:"Cancel"}),e.jsx(w,{size:"sm",onClick:()=>S.mutate(),disabled:S.isPending||N===0||h.trim().length<2,"data-testid":`button-submit-opening-${n}`,children:S.isPending?"Saving…":"Confirm opening float"})]})]}),h.trim().length<2&&e.jsx("p",{className:"text-xs text-destructive",children:"Enter your name to confirm the count."})]}):e.jsxs("div",{children:[e.jsx(w,{variant:i?"ghost":"default",size:"sm",onClick:y,"data-testid":`button-opening-count-${n}`,children:i?"Recount opening float":"Count opening float"}),!i&&e.jsxs("p",{className:"text-xs text-muted-foreground mt-1",children:["Count the till at the start of the day to confirm the ",u(t)," float is right before trading."]})]})]})}function Ke({venue:r,date:l,tillNumber:n,existing:i,opening:j,denominations:t,floatCents:d}){const{toast:x}=J(),g=X(),[_,m]=v.useState(!1),[s,h]=v.useState({}),[C,y]=v.useState(""),[N,S]=v.useState(!1),b=()=>{var $;const o={};for(const A of t){const P=($=i==null?void 0:i.denominations)==null?void 0:$[String(A)];o[String(A)]=P?String(P):""}h(o),y((i==null?void 0:i.submitted_by)??""),m(!0)},p=v.useMemo(()=>t.reduce((o,$)=>o+$*(parseInt(s[String($)]||"0",10)||0),0),[s,t]),T=O({mutationFn:()=>{const o={};for(const $ of t){const A=parseInt(s[String($)]||"0",10)||0;A>0&&(o[String($)]=A)}return L("POST","/api/staff/till-recon/tills",{venue:r,service_date:l,till_number:n,denominations:o,counted_by:C.trim()})},onSuccess:()=>{m(!1),g.invalidateQueries({queryKey:["/api/staff/till-recon"]}),x({title:`Till ${n} submitted`})},onError:o=>x({title:"Couldn't submit till",description:(o==null?void 0:o.message)||String(o),variant:"destructive"})}),f=O({mutationFn:()=>
11{if(!i)throw new Error("Till count not found");return L("DELETE",`/api/staff/till-recon/tills/${i.id}`)},onSuccess:async()=>{S(!1),m(!1),await g.invalidateQueries({queryKey:["/api/staff/till-recon"]}),x({title:`Till ${n} count undone`,description:"The end-of-night count was removed. You can now record the opening float."})},onError:o=>{S(!1),x({title:"Couldn't undo till count",description:(o==null?void 0:o.message)||String(o),variant:"destructive"})}}),k=t.filter(o=>o>=500),D=t.filter(o=>o<500),c=!!j;return e.jsxs(M,{"data-testid":`card-till-${n}`,children:[e.jsxs(z,{className:"p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("span",{className:"font-semibold flex items-center gap-2",children:["Till ",n,i&&!_&&e.jsxs(H,{variant:"secondary",className:"gap-1",children:[e.jsx(ue,{className:"w-3 h-3"})," Counted"]})]}),i&&!_&&e.jsxs("div",{className:"text-right",children:[e.jsx("p",{className:"font-semibold","data-testid":`text-till-total-${n}`,children:u(i.counted_cents)}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Counted by ",i.submitted_by," · ",Ce(i.updated_at)]})]})]}),e.jsx(Ie,{venue:r,date:l,tillNumber:n,existing:j,denominations:t,floatCents:d}),_?e.jsxs("div",{className:"space-y-3",children:[[{label:"Notes",ds:k},{label:"Coins",ds:D}].map(o=>e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1",children:o.label}),e.jsx("div",{className:"grid grid-cols-3 sm:grid-cols-6 gap-2",children:o.ds.map($=>{const A=`till-denom-${n}-${$}`;return e.jsxs("div",{children:[e.jsx("label",{htmlFor:A,className:"text-xs text-muted-foreground",children:Y($)}),e.jsx(U,{id:A,type:"number",inputMode:"numeric",min:0,placeholder:"0",value:s[String($)]??"",onChange:P=>h(I=>({...I,[String($)]:P.target.value})),onKeyDown:P=>Se(P,`till-${n}`),"data-till-count-grid":`till-${n}`,"data-testid":`input-denom-${n}-${$}`})]},$)})})]},o.label)),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-muted-foreground",children:"Your name (required)"}),e.jsx(U,{value:C,onChange:o=>y(o.target.value),placeholder:"Who counted this till?","data-testid":`input-till-count-name-${n}`})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("p",{className:"text-sm",children:["Counted total: ",e.jsx("span",{className:"font-semibold","data-testid":`text-till-live-total-${n}`,children:u(p)})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(w,{variant:"outline",size:"sm",onClick:()=>m(!1),children:"Cancel"}),e.jsx(w,{size:"sm",onClick:()=>T.mutate(),disabled:T.isPending||p===0||C.trim().length<2,"data-testid":`button-submit-till-${n}`,children:T.isPending?"Submitting…":"Submit count"})]})]}),C.trim().length<2&&e.jsx("p",{className:"text-xs text-destructive",children:"Enter your name to confirm the count."})]}):e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[e.jsx(w,{variant:i?"outline":c?"default":"outline",size:"sm",onClick:b,disabled:!i&&!c,"data-testid":`button-count-till-${n}`,children:i?"Recount":"Close this till"}),i&&e.jsxs(w,{variant:"outline",size:"sm",className:"text-destructive hover:text-destructive",onClick:()=>S(!0),"data-testid":`button-undo-till-${n}`,children:[e.jsx(Me,{className:"w-4 h-4 mr-1"}),"Undo count"]})]}),!i&&!c&&e.jsx("p",{className:"text-xs text-muted-foreground",children:"Count the opening float first to close this till."}),i&&e.jsx(Le,{tillNumber:n,denominations:i.denominations,floatCents:d})]})]}),e.jsx(pe,{open:N,onOpenChange:S,children:e.jsxs(xe,{"data-testid":`dialog-undo-till-${n}`,children:[e.jsxs(fe,{children:[e.jsxs(je,{children:["Undo Till ",n," count?"]}),e.jsxs(ge,{children:["This removes the submitted end-of-night count of ",e.jsx("strong",{children:i?u(i.counted_cents):""}),". It won’t remove the opening float or any petty cash receipts. You can enter the correct count again afterwards."]})]}),e.jsxs(ye,{children:[e.jsx(be,{disabled:f.isPending,children:"Cancel"}),e.jsx(ve,{onClick:o=>{o.preventDefault(),f.mutate()},disabled:f.isPending,className:"bg-destructive text-destructive-foreground hover:bg-destructive/90","data-testid":`button-confirm-undo-till-${n}`,children:f.isPending?"Undoing…":"Yes, undo count"})]})]})})]})}function We({venue:r,date:l,rows:n}){const{toast:i}=J(),j=X(),[t,d]=v.useState(!1),[x,g]=v.useState(""),[_,m]=v.useState(""),[s,h]=v.useState(""),{uploadFile:C,isUploading:y}=Ne({onSuccess:p=>h(p.objectPath),onError:p=>i({title:"Photo upload failed",description:p.message,variant:"destructive"})}),N=O({mutationFn:()=>L("POST","/api/staff/till-recon/petty-cash",{venue:r,service_date:l,amount_cents:Math.round(parseFloat(x)*100),description:_.trim(),...s?{photo_url:s}:{}}),onSuccess:async()=>{d(!1),g(""),m(""),h(""),await V(j,r),i({title:"Petty cash payout added"})},onError:p=>i({title:"Couldn't save receipt",description:(p==null?void 0:p.message)||String(p),variant:"destructive"})}),S=O({mutationFn:p=>L("DELETE",`/api/staff/till-recon/petty-cash/${p}`),onSuccess:async()=>{await V(j,r)},onError:p=>i({title:"Couldn't delete receipt",description:(p==null?void 0:p.message)||String(p),variant:"destructive"})}),b=!!x&&!isNaN(parseFloat(x))&&parseFloat(x)>0;return e.jsx(M,{"data-testid":"card-petty-cash",children:e.jsxs(z,{className:"p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("span",{className:"font-semibold flex items-center gap-2",children:[e.jsx(Q,{className:"w-4 h-4"})," Petty cash"]}),!t&&e.jsx(w,{variant:"outline",size:"sm",onClick:()=>d(!0),"data-testid":"button-add-petty-cash",children:"Add payout"})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Cash paid out of the till. A receipt photo is optional. Payouts reduce the expected cash for the night."}),t&&e.jsxs("div",{className:"space-y-2 border rounded-lg p-3",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-muted-foreground",children:"Amount ($)"}),e.jsx(U,{type:"number",inputMode:"decimal",min:0,step:"0.01",value:x,onChange:p=>g(p.target.value),"data-testid":"input-petty-amount"})]}),e.jsxs("div",{className:"flex flex-col",children:[e.jsx("label",{className:"text-xs text-muted-foreground",children:"Receipt photo (optional)"}),e.jsxs("label",{className:"mt-1 inline-flex items-center gap-2 text-sm cursor-pointer text-primary underline",children:[e.jsx("input",{type:"file",accept:"image/*",capture:"environment",className:"hidden",onChange:async p=>{var f;const T=(f=p.target.files)==null?void 0:f[0];p.target.value="",T&&C(await _e(T,1400))},"data-testid":"input-petty-photo"}),e.jsx(re,{className:"w-4 h-4"}),y?"Uploading…":s?"Replace photo":"Take / choose photo"]}),s&&e.jsx("img",{src:s,alt:"Receipt",className:"mt-1 w-16 h-16 rounded object-cover border"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-muted-foreground",children:"What was it for?"}
11),e.jsx(Re,{rows:2,value:_,onChange:p=>m(p.target.value),"data-testid":"input-petty-description"})]}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx(w,{variant:"outline",size:"sm",onClick:()=>d(!1),children:"Cancel"}),e.jsx(w,{size:"sm",onClick:()=>N.mutate(),disabled:!b||!_.trim()||y||N.isPending,"data-testid":"button-save-petty-cash",children:N.isPending?"Saving…":"Save payout"})]})]}),n.length>0&&e.jsx("div",{className:"space-y-2",children:n.map(p=>e.jsxs("div",{className:"flex items-center gap-3 border rounded-lg p-2","data-testid":`row-petty-${p.id}`,children:[p.photo_url?e.jsx("a",{href:p.photo_url,target:"_blank",rel:"noreferrer",children:e.jsx("img",{src:p.photo_url,alt:"Receipt",className:"w-12 h-12 rounded object-cover border"})}):e.jsx("div",{className:"w-12 h-12 rounded border bg-muted flex items-center justify-center text-muted-foreground",children:e.jsx(Q,{className:"w-5 h-5","aria-label":"No receipt photo"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-sm font-medium truncate",children:p.description}),e.jsx("p",{className:"text-xs text-muted-foreground",children:p.created_by})]}),e.jsx("span",{className:"font-semibold whitespace-nowrap",children:u(p.amount_cents)}),e.jsx("button",{onClick:()=>S.mutate(p.id),className:"p-1 text-muted-foreground","aria-label":"Delete receipt","data-testid":`button-delete-petty-${p.id}`,children:e.jsx(we,{className:"w-4 h-4"})})]},p.id))})]})})}function Be({venue:r}){const[l,n]=v.useState(!1),{data:i}=W({queryKey:["/api/staff/till-recon/petty-cash/archive",r],queryFn:()=>fetch(`/api/staff/till-recon/petty-cash/archive?venue=${r}`,{credentials:"include"}).then(t=>t.json()),enabled:l}),j=v.useMemo(()=>{const t=new Map;for(const d of i??[])t.has(d.service_date)||t.set(d.service_date,[]),t.get(d.service_date).push(d);return Array.from(t.entries())},[i]);return e.jsx(M,{"data-testid":"card-petty-archive",children:e.jsxs(z,{className:"p-4 space-y-3",children:[e.jsxs("button",{type:"button",className:"w-full flex items-center justify-between gap-2",onClick:()=>n(t=>!t),"data-testid":"button-toggle-archive",children:[e.jsxs("span",{className:"font-semibold flex items-center gap-2",children:[e.jsx(re,{className:"w-4 h-4"})," Receipt photo archive"]}),l?e.jsx(me,{className:"w-4 h-4"}):e.jsx(he,{className:"w-4 h-4"})]}),l&&(j.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:"No receipts yet."}):e.jsx("div",{className:"space-y-4",children:j.map(([t,d])=>e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1",children:new Date(t+"T12:00:00Z").toLocaleDateString("en-AU",{weekday:"short",day:"numeric",month:"short",year:"numeric",timeZone:"UTC"})}),e.jsx("div",{className:"grid grid-cols-3 sm:grid-cols-5 gap-2",children:d.filter(x=>!!x.photo_url).map(x=>e.jsxs("a",{href:x.photo_url,target:"_blank",rel:"noreferrer",className:"block","data-testid":`archive-photo-${x.id}`,children:[e.jsx("img",{src:x.photo_url,alt:x.description,className:"w-full aspect-square rounded object-cover border"}),e.jsxs("p",{className:"text-xs truncate mt-0.5",children:[u(x.amount_cents)," · ",x.description]})]},x.id))})]},t))}))]})})}function He({date:r}){const{data:l,isLoading:n,refetch:i,isFetching:j}=W({queryKey:["/api/staff/till-recon/admin-working",r],queryFn:()=>fetch(`/api/staff/till-recon/admin-working?date=${r}`,{credentials:"include"}).then(t=>{if(!t.ok)throw new Error("Failed to load admin working");return t.json()}),enabled:!!r});return e.jsx(M,{className:"border-yellow-400","data-testid":"card-admin-working",children:e.jsxs(z,{className:"p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("span",{className:"font-semibold flex items-center gap-2",children:[e.jsx(Z,{className:"w-4 h-4 text-yellow-500"})," Live cash position (all venues)"]}),e.jsx(w,{variant:"outline",size:"sm",onClick:()=>i(),disabled:j,"data-testid":"button-refresh-working",children:j?"Refreshing…":"Refresh"})]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["What each venue's cash position ",e.jsx("em",{children:"should"})," be right now (floats + cash takings after petty cash), even before tills are counted — use it to spot errors while counting."]}),n?e.jsxs("p",{className:"text-sm text-muted-foreground flex items-center gap-2",children:[e.jsx(G,{className:"w-4 h-4 animate-spin"})," Loading…"]}):e.jsx("div",{className:"grid gap-3 sm:grid-cols-3",children:((l==null?void 0:l.venues)??[]).map(t=>e.jsxs("div",{className:"border rounded-lg p-3 space-y-1","data-testid":`working-${t.venue}`,children:[e.jsx("p",{className:"font-semibold text-sm",children:t.label}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[t.square_location," · ",t.tills_submitted,"/",t.tills_expected," tills in"]}),e.jsxs("div",{className:"text-xs space-y-0.5",children:[t.square_error&&e.jsxs("p",{className:"text-destructive","data-testid":`working-square-unavailable-${t.venue}`,children:["Square cash unavailable: ",t.square_error]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsxs("span",{className:"text-muted-foreground",children:["Floats (",t.tills_expected," × $500)"]}),e.jsx("span",{children:u(t.floats_cents)})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsxs("span",{className:"text-muted-foreground",children:["Square cash ",t.square_cash_available?`(${t.square_cash_payments} pmts)`:""]}),e.jsx("span",{children:t.square_cash_available?u(t.square_cash_cents):"Unavailable"})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Petty cash"}),e.jsxs("span",{children:["−",u(t.petty_cash_cents)]})]}),e.jsxs("div",{className:"flex justify-between font-medium",children:[e.jsx("span",{children:"Cash takings after petty cash"}),e.jsx("span",{"data-testid":`working-net-cash-${t.venue}`,children:t.net_cash_takings_cents==null?"Unavailable":u(t.net_cash_takings_cents)})]}),e.jsxs("div",{className:"flex justify-between font-semibold border-t pt-0.5",children:[e.jsx("span",{children:"Should hold"}),e.jsx("span",{"data-testid":`working-expected-${t.venue}`,children:t.expected_cents==null?"—":u(t.expected_cents)})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Counted so far"}),e.jsx("span",{children:u(t.counted_so_far_cents)})]}),t.per_till.map(d=>e.jsxs("div",{className:"flex justify-between text-muted-foreground",children:[e.jsxs("span",{className:"pl-2",children:["Till ",d.till_number," (",d.submitted_by,")"]}),e.jsx("span",{children:u(d.counted_cents)})]},d.till_number)),e.jsxs("div",{className:`flex justify-between font-semibold ${t.projected_variance_cents===0?"text-green-600":"text-destructive"}`,children:[e.jsx("span",{children:"Projected variance"}),e.jsx("span",{children:t.projected_variance_cents==null?"—":`${t.projected_variance_cents>0?"+":""}${u(t.projected_variance_cents)}`})]}),(t.opening_per_till??[]).some(d=>!d.confirmed||d.variance_cents!==0)&&e.jsxs("div",{className:"border-t pt-0.5 mt-0.5 space-y-0.5",children:[e.jsx("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wide",children:"Opening floats"}),(t.opening_per_till??[]).map(d=>e.jsxs("div",{className:`flex justify-between ${!d.confirmed||d.variance_cents!==0?"text-destructive":"text-muted-foreground"}`,"data-testid":`working-opening-till-${t.venue}-${d.till_number}`,children:[e.jsxs("span",{className:"pl-2",children:["Till ",d.till_number,d.counted_by?` (${d.counted_by})`:""]}),e.jsx("span",{children:d.confirmed?d.variance_cents===0?u(d.counted_cents):`${u(d.counted_cents)} (${d.variance_cents>0?"+":""}${u(d.variance_cents)})`:"not confirmed"})]},d.till_number))]})]})]},t.venue))})]})})}function Ze({venue:r,weekStart:l,currentServiceDate:n,days:i,onRefresh:j}){const{toast:t}=J(),d=X(),[x,g]=v.useState(null),[_,m]=v.useState(!1),[s,h]=v.useState(l),[C,y]=v.useState(""),[N,S]=v.useState(""),[b,p]=v.useState(""),[T,f]=v.useState(null),[k,D]=v.useState(!1),{uploadFile:c,isUploading:o}=Ne({onSuccess:a=>p(a.objectPath),onError:a=>t({title:"Photo upload failed",description:a.message,variant:"destructive"})}
11),{data:$,isFetching:A}=W({queryKey:["/api/staff/till-recon/petty-cash/history",r,l],queryFn:()=>fetch(`/api/staff/till-recon/petty-cash/history?venue=${encodeURIComponent(r)}&week_start=${l}`,{credentials:"include"}).then(async a=>{if(!a.ok)throw new Error("Failed to load petty cash history");return a.json()}),enabled:k}),P=i.flatMap(a=>(a.petty_cash??[]).map(q=>({row:q,day:a.service_date}))),I=a=>a<=n,le=()=>{m(!1),g(null),y(""),S(""),p("")},Te=()=>{var a;g(null),m(!0),h(((a=i.find(q=>I(q.service_date)))==null?void 0:a.service_date)??l),y(""),S(""),p("")},De=a=>{g(a),m(!1),h(a.service_date),y((a.amount_cents/100).toFixed(2)),S(a.description),p(a.photo_url??"")},ee=O({mutationFn:()=>L(x?"PATCH":"POST",x?`/api/staff/till-recon/petty-cash/${x.id}`:"/api/staff/till-recon/petty-cash",{...x?{}:{venue:r},service_date:s,amount_cents:Math.round(Number(C)*100),description:N.trim(),photo_url:b||null}),onSuccess:async()=>{le(),await V(d,r,l),j(),t({title:x?"Receipt updated":"Receipt added"})},onError:a=>t({title:"Couldn't save receipt",description:(a==null?void 0:a.message)||String(a),variant:"destructive"})}),B=O({mutationFn:async()=>{if(T)return L("DELETE",`/api/staff/till-recon/petty-cash/${T.id}`)},onSuccess:async()=>{f(null),await V(d,r,l),j(),t({title:"Receipt deleted"})},onError:a=>t({title:"Couldn't delete receipt",description:(a==null?void 0:a.message)||String(a),variant:"destructive"})}),qe=Number.isFinite(Number(C))&&Number(C)>0,te=_||!!x,Fe=a=>{const q=a.action==="deleted"?a.before_data:a.after_data;if(a.action==="created"||a.action==="deleted")return q?[`Amount ${u(q.amount_cents)}`,`Description “${q.description}”`,`Service day ${R(q.service_date)}`]:["Receipt details unavailable"];const F=a.before_data,E=a.after_data;if(!F||!E)return["Receipt details unavailable"];const K=[];return F.amount_cents!==E.amount_cents&&K.push(`Amount ${u(F.amount_cents)} → ${u(E.amount_cents)}`),F.description!==E.description&&K.push(`Description “${F.description}” → “${E.description}”`),F.service_date!==E.service_date&&K.push(`Service day ${R(F.service_date)} → ${R(E.service_date)}`),F.photo_url!==E.photo_url&&K.push(F.photo_url?E.photo_url?"Photo replaced":"Photo removed":"Photo added"),K.length?K:["No receipt details changed"]};return e.jsxs("div",{className:"border-t pt-4 space-y-3","data-testid":"weekly-petty-cash-manager",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsxs("p",{className:"font-semibold flex items-center gap-2",children:[e.jsx(Q,{className:"w-4 h-4"})," Petty cash receipts"]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Receipts reduce the cash available to bank."})]}),!te&&e.jsx(w,{size:"sm",variant:"outline",onClick:Te,"data-testid":"button-weekly-add-receipt",children:"Add receipt"})]}),te&&e.jsxs("div",{className:"rounded-lg border bg-muted/20 p-3 space-y-3","data-testid":"weekly-receipt-form",children:[e.jsxs("div",{className:"grid gap-3 sm:grid-cols-[1fr_1fr_1.6fr]",children:[e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-muted-foreground",children:"Service day"}),e.jsx("select",{className:"flex h-10 w-full rounded-md border border-input bg-background px-3 text-sm",value:s,onChange:a=>h(a.target.value),"data-testid":"select-receipt-day",children:i.map(a=>e.jsxs("option",{value:a.service_date,disabled:!I(a.service_date),children:[R(a.service_date),I(a.service_date)?"":" · future"]},a.service_date))})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-muted-foreground",children:"Amount ($)"}),e.jsx(U,{type:"number",min:"0.01",step:"0.01",inputMode:"decimal",value:C,onChange:a=>y(a.target.value),"data-testid":"input-receipt-amount"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-muted-foreground",children:"Description"}),e.jsx(U,{value:N,onChange:a=>S(a.target.value),placeholder:"What was purchased?","data-testid":"input-receipt-description"})]})]}),e.jsxs("div",{className:"flex items-center justify-between gap-3 flex-wrap",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("label",{className:"inline-flex items-center gap-2 text-sm text-primary underline cursor-pointer",children:[e.jsx("input",{type:"file",accept:"image/*",capture:"environment",className:"hidden",onChange:async a=>{var F;const q=(F=a.target.files)==null?void 0:F[0];a.target.value="",q&&c(await _e(q,1400))},"data-testid":"input-receipt-photo"}),e.jsx(re,{className:"w-4 h-4"})," ",o?"Uploading…":b?"Replace photo":"Add receipt photo"]}),b&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("img",{src:b,alt:"Receipt",className:"w-10 h-10 rounded object-cover border"}),x&&e.jsx(w,{type:"button",variant:"ghost",size:"sm",className:"text-destructive",onClick:()=>p(""),"data-testid":"button-remove-receipt-photo",children:"Remove photo"})]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(w,{variant:"ghost",size:"sm",onClick:le,children:"Cancel"}),e.jsx(w,{size:"sm",onClick:()=>ee.mutate(),disabled:!qe||!N.trim()||o||ee.isPending||!I(s),"data-testid":"button-weekly-save-receipt",children:ee.isPending?"Saving…":x?"Save changes":"Save receipt"})]})]})]}),P.length===0&&!te&&e.jsx("p",{className:"text-sm text-muted-foreground rounded-lg border border-dashed p-4",children:"No petty cash receipts recorded for this week."}),P.length>0&&e.jsx("div",{className:"space-y-2",children:P.map(({row:a,day:q})=>e.jsxs("div",{className:"flex items-center gap-3 rounded-lg border p-2.5","data-testid":`weekly-receipt-row-${a.id}`,children:[a.photo_url?e.jsx("a",{href:a.photo_url,target:"_blank",rel:"noreferrer",children:e.jsx("img",{src:a.photo_url,alt:"Receipt",className:"w-10 h-10 rounded object-cover border"})}):e.jsx("div",{className:"w-10 h-10 rounded border bg-muted flex items-center justify-center",children:e.jsx(Q,{className:"w-4 h-4 text-muted-foreground"})}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"text-sm font-medium truncate",children:a.description}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[R(q)," · ",a.created_by]})]}),e.jsx("span",{className:"font-semibold whitespace-nowrap",children:u(a.amount_cents)}),e.jsx(w,{variant:"ghost",size:"icon",onClick:()=>De(a),"aria-label":"Edit receipt","data-testid":`button-edit-receipt-${a.id}`,children:e.jsx(ze,{className:"w-4 h-4"})}),e.jsx(w,{variant:"ghost",size:"icon",className:"text-destructive",onClick:()=>f(a),"aria-label":"Delete receipt","data-testid":`button-delete-receipt-${a.id}`,children:e.jsx(we,{className:"w-4 h-4"})})]},a.id))}),e.jsxs("div",{className:"border-t pt-3",children:[e.jsxs("button",{type:"button",className:"flex items-center gap-2 text-sm font-medium",onClick:()=>D(a=>!a),"data-testid":"button-toggle-petty-history",children:[e.jsx(Oe,{className:"w-4 h-4"})," ",k?"Hide audit history":"Inspect audit history"," ",A&&e.jsx(G,{className:"w-3 h-3 animate-spin"})]}),k&&e.jsx("div",{className:"mt-2 space-y-2","data-testid":"petty-history",children:($??[]).length===0?e.jsx("p",{className:"text-xs text-muted-foreground",children:"No changes recorded for this week."}):($??[]).map(a=>e.jsxs("div",{className:"rounded border px-3 py-2 text-xs","data-testid":`petty-history-row-${a.id}`,children:[e.jsxs("div",{className:"flex justify-between gap-2",children:[e.jsxs("span",{className:"font-medium capitalize",children:[a.action," receipt"]}),e.jsx("span",{className:"text-muted-foreground",children:Ce(a.created_at)})]}),e.jsxs("p",{className:"text-muted-foreground",children:["By ",a.actor," · ",R(a.service_date),a.previous_service_date&&a.previous_service_date!==a.service_date?` (moved from ${R(a.previous_service_date)})`:""]}),e.jsx("ul",{className:"mt-1 list-disc pl-4 space-y-0.5",children:Fe(a).map(q=>e.jsx("li",{children:q},q))})]},a.id))})]}),e.jsx(pe,{open:!!T,onOpenChange:a=>!a&&f(null),children:e.jsxs(xe,{"data-testid":"dialog-confirm-delete-receipt",children:[e.jsxs(fe,{children:[e.jsx(je,{children:"Delete this receipt?"}),e.jsxs(ge,{children:["This change is permanent, but remains visible in the immutable audit history. ",T&&`${u(T.amount_cents)} · ${T.description}`]})]}),e.jsxs(ye,{children:[e.jsx(be,{disabled:B.isPending,children:"Cancel"}),e.jsx(ve,{onClick:a=>{a.preventDefault(),B.mutate()},disabled:B.isPending,className:"bg-destructive text-destructive-foreground hover:bg-destructive/90","data-testid":"button-confirm-delete-receipt",children:B.isPending?"Deleting…":"Delete receipt"})]})]})})]})}function Qe({venue:r,weekStart:l,currentServiceDate:n,onWeekChange:i}){const j=ie(n),{data:t,isLoading:d,isFetching:x,error:g,refetch:_}=W({queryKey:["/api/staff/till-recon/weekly-banking",r,l],queryFn:()=>fetch(`/api/staff/till-recon/weekly-banking?venue=${encodeURIComponent(r)}&week_start=${l}`,{credentials:"include"}).then(async s=>{if(!s.ok){const h=await s.json().catch(()=>null);throw new Error((h==null?void 0:h.message)||"Failed to load weekly banking report")}return s.json()})}),m=s=>s.status==="complete"?"Reconciled":s.status==="square_error"?"Square unavailable":s.status==="incomplete"?`${s.tills_submitted}/${s.tills_expected} tills`:"Not reconciled";return e.jsx(M,{className:"border-yellow-400","data-testid":"card-weekly-banking",children:e.jsxs(z,{className:"p-4 space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3 flex-wrap",children:[e.jsxs("div",{children:[e.jsxs("p",{className:"font-semibold flex items-center gap-2",children:[e.jsx(ke,{className:"w-4 h-4 text-yellow-500"}),"Weekly banking — ",(t==null?void 0:t.venue_label)??"venue"]}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-0.5",children:["Monday open to Sunday close · ",de(l),"–",de(ae(l,6))]})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(w,{variant:"outline",size:"icon",onClick:()=>i(ae(l,-7)),"aria-label":"Previous week","data-testid":"button-weekly-previous",children:e.jsx(Pe,{className:"w-4 h-4"})}),e.jsx(w,{variant:"outline",size:"sm",onClick:()=>i(j),disabled:l===j,"data-testid":"button-weekly-current",children:"Current week"}),e.jsx(w,{variant:"outline",size:"icon",onClick:()=>i(ae(l,7)),disabled:l>=j,"aria-label":"Next week","data-testid":"button-weekly-next",children:e.jsx(Ee,{className:"w-4 h-4"})}),e.jsx(w,{variant:"ghost",size:"sm",onClick:()=>_(),disabled:x,"data-testid":"button-weekly-refresh",children:x?"Refreshing…":"Refresh"})]})]}),d?e.jsxs("p",{className:"text-sm text-muted-foreground flex items-center gap-2",children:[e.jsx(G,{className:"w-4 h-4 animate-spin"})," Loading weekly results…"]}):g?e.jsx("p",{className:"text-sm text-destructive",children:g.message}):t?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"rounded-lg border p-3",children:[e.jsx("p",{className:"text-xs text-muted-foreground",children:"Cash to bank"}),e.jsx("p",{className:"text-xl font-bold","data-testid":"text-weekly-bank-total",children:t.totals.banking_days_included>0?u(t.totals.bankable_cents):"—"}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[t.totals.banking_days_included,"/7 reconciled days included"]})]}),e.jsxs("div",{className:"rounded-lg border p-3",children:[e.jsx("p",{className:"text-xs text-muted-foreground",children:"Cash variance"}),e.jsx("p",{className:`text-xl font-bold ${t.totals.variance_days_included>0&&t.totals.variance_cents!==0?"text-destructive":t.totals.variance_days_included>0?"text-green-600":""}`,"data-testid":"text-weekly-variance-total",children:t.totals.variance_days_included>0?ce(t.totals.variance_cents):"—"}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[t.totals.variance_days_included,"/7 verified days included"]})]})]}),!t.totals.all_days_complete&&e.jsx("p",{className:"text-xs text-muted-foreground",children:"Weekly totals are partial. Days without a completed reconciliation are not treated as $0."}),e.jsx("div",{className:"grid gap-2 sm:grid-cols-2 lg:grid-cols-4",children:t.days.map(s=>e.jsxs("div",{className:"rounded-lg border p-3 space-y-2","data-testid":`weekly-day-${s.service_date}`,children:[e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsx("span",{className:"font-medium text-sm",children:R(s.service_date)}),e.jsx(H,{variant:s.status==="complete"?"secondary":s.status==="square_error"?"destructive":"outline",children:m(s)})]}),e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"To bank"}),e.jsx("span",{className:"font-medium",children:s.bankable_cents==null?"—":u(s.bankable_cents)})]}),e.jsxs("div",{className:`flex justify-between text-sm ${s.variance_cents==null?"text-muted-foreground":s.variance_cents===0?"text-green-600":"text-destructive"}`,children:[e.jsx("span",{children:"Variance"}),e.jsx("span",{className:"font-medium",children:s.variance_cents==null?"—":ce(s.variance_cents)})]}),s.petty_cash_cents?e.jsxs("div",{className:"flex justify-between text-xs text-muted-foreground",children:[e.jsx("span",{children:"Petty cash"}),e.jsxs("span",{children:["−",u(s.petty_cash_cents)]})]}):null,(s.float_shortfall_cents??0)>0&&e.jsxs("p",{className:"text-xs text-destructive",children:["Float top-up: ",u(s.float_shortfall_cents)]}),s.square_error&&e.jsx("p",{className:"text-xs text-destructive",children:s.square_error})]},s.service_date))}),e.jsx(Ze,{venue:r,weekStart:l,currentServiceDate:n,days:t.days,onRefresh:()=>_()})]}):null]})})}function lt(){const{isAuthenticated:r,isLoading:l}=Ae(),[n,i]=v.useState("chalkys"),[j,t]=v.useState(null),[d,x]=v.useState(!1),[g,_]=v.useState(null),{data:m}=W({queryKey:["/api/staff/till-recon/config"],enabled:r}),s=j??(m==null?void 0:m.current_service_date)??"",{data:h,isLoading:C}=W({queryKey:["/api/staff/till-recon",n,s],queryFn:()=>fetch(`/api/staff/till-recon?venue=${n}&date=${s}`,{credentials:"include"}).then(c=>{if(!c.ok)throw new Error("Failed to load till reconciliation");return c.json()}),enabled:r&&ne(s)});if(l)return null;if(!r)return e.jsx("div",{className:"min-h-screen flex items-center justify-center",children:e.jsxs("p",{className:"text-muted-foreground",children:["Please ",e.jsx(se,{href:"/staff",className:"underline",children:"log in"})," to reconcile tills."]})});const y=m==null?void 0:m.venues.find(c=>c.key===n),N=new Map(((h==null?void 0:h.tills)??[]).map(c=>[c.till_number,c])),S=new Map(((h==null?void 0:h.opening_counts)??[]).map(c=>[c.till_number,c])),b=h==null?void 0:h.reconciliation,p=g??(s?ie(s):""),T=Array.from({length:(y==null?void 0:y.tills)??0},(c,o)=>o+1),f=m&&T.every(c=>N.has(c))?T.map(c=>({tillNumber:c,plan:$e(N.get(c).denominations,m.float_cents)})):null,k=(f==null?void 0:f.reduce((c,{plan:o})=>c+o.bankTotal,0))??0,D=(f==null?void 0:f.reduce((c,{plan:o})=>c+o.shortfall,0))??0;return e.jsx("div",{className:"min-h-screen bg-background",children:e.jsxs("div",{className:"max-w-3xl mx-auto p-4 space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 flex-wrap",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(se,{href:"/staff",children:e.jsx(w,{variant:"ghost",size:"icon","data-testid":"button-back",children:e.jsx(Ue,{className:"w-5 h-5"})})}),e.jsxs("h1",{className:"text-xl font-bold flex items-center gap-2",children:[e.jsx(Z,{className:"w-5 h-5 text-yellow-500"})," Till reconciliation"]})]}),e.jsx(U,{type:"date",className:"w-auto",value:s,onChange:c=>t(c.target.value),"data-testid":"input-service-date"})]}),e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[((m==null?void 0:m.venues)??[]).map(c=>e.jsx(w,{size:"sm",variant:n===c.key?"default":"outline",onClick:()=>i(c.key),"data-testid":`tab-venue-${c.key}`,children:c.label},c.key)),e.jsxs(w,{size:"sm",variant:d?"secondary":"outline",onClick:()=>{s&&(d||_(ie(s)),x(c=>!c))},disabled:!ne(s),"data-testid":"button-weekly-banking",children:[e.jsx(ke,{className:"w-4 h-4 mr-1"}),d?"Hide weekly results":"Weekly banking report"]}),e.jsx(se,{href:"/staff/till-recon/weekly-count",children:e.jsxs(w,{size:"sm",variant:"outline","data-testid":"button-weekly-cash-count",children:[e.jsx(Z,{className:"w-4 h-4 mr-1"}),"End-of-week cash count"]})})]}),d&&p&&(m==null?void 0:m.current_service_date)&&e.jsx(Qe,{venue:n,weekStart:p,currentServiceDate:m.current_service_date,o
11nWeekChange:_}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Service day runs 3am–3am, so sales after midnight count toward the night before. Each till starts with a ",m?u(m.float_cents):"$500.00"," float. Count the cash and enter how many of each note and coin — the variance is shown once every till is submitted."]}),C?e.jsxs("p",{className:"text-sm text-muted-foreground flex items-center gap-2",children:[e.jsx(G,{className:"w-4 h-4 animate-spin"})," Loading…"]}):e.jsxs(e.Fragment,{children:[Array.from({length:(y==null?void 0:y.tills)??0},(c,o)=>o+1).map(c=>e.jsx(Ke,{venue:n,date:s,tillNumber:c,existing:N.get(c),opening:S.get(c),denominations:(m==null?void 0:m.denominations)??[],floatCents:(m==null?void 0:m.float_cents)??5e4},`${n}-${s}-${c}`)),e.jsx(We,{venue:n,date:s,rows:(h==null?void 0:h.petty_cash)??[]}),f&&e.jsx(M,{className:D===0?"border-green-500 bg-green-50/40":"border-yellow-400","data-testid":"card-nightly-safe-confirmation",children:e.jsxs(z,{className:"p-4 space-y-2",children:[e.jsx("p",{className:"font-semibold",children:"Cash to put in the safe"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Recheck this before banking the night’s cash across all tills."}),e.jsx("p",{className:"text-2xl font-bold text-green-700","data-testid":"text-nightly-safe-total",children:u(k)}),e.jsx("div",{className:"border-t pt-2 space-y-1 text-sm",children:f.map(({tillNumber:c,plan:o})=>e.jsxs("div",{className:"flex justify-between",children:[e.jsxs("span",{className:"text-muted-foreground",children:["Till ",c]}),e.jsx("span",{children:u(o.bankTotal)})]},c))}),D>0&&e.jsxs("p",{className:"text-xs text-yellow-800 font-medium","data-testid":"text-nightly-safe-shortfall",children:["The remaining till float is ",u(D)," short of $500 across the submitted tills. Top it up from the safe before trading."]})]})}),h!=null&&h.all_submitted&&b?e.jsx(M,{className:b.square_cash_available?b.variance_cents===0?"border-green-500":"border-destructive":"border-yellow-400","data-testid":"card-reconciliation",children:e.jsxs(z,{className:"p-4 space-y-2",children:[e.jsxs("p",{className:"font-semibold",children:["Reconciliation · ",h.venue_label]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Square location: ",b.square_location]}),e.jsxs("div",{className:"text-sm space-y-1",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsxs("span",{className:"text-muted-foreground",children:["Floats (",y==null?void 0:y.tills," × $500)"]}),e.jsx("span",{children:u(b.floats_cents)})]}),!b.square_cash_available&&e.jsxs("p",{className:"text-sm text-destructive","data-testid":"text-square-cash-unavailable",children:["Square cash unavailable: ",b.square_cash_message]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsxs("span",{className:"text-muted-foreground",children:["Square cash sales ",b.square_cash_available?`(${b.square_cash_payments} payments)`:""]}),e.jsx("span",{children:b.square_cash_available?u(b.square_cash_cents):"Unavailable"})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Petty cash payouts"}),e.jsxs("span",{children:["−",u(b.petty_cash_cents)]})]}),e.jsxs("div",{className:"flex justify-between font-medium",children:[e.jsx("span",{children:"Cash takings after petty cash"}),e.jsx("span",{"data-testid":"text-net-cash-takings",children:b.net_cash_takings_cents==null?"Unavailable":u(b.net_cash_takings_cents)})]}),e.jsxs("div",{className:"flex justify-between font-medium border-t pt-1",children:[e.jsx("span",{children:"Expected in tills"}),e.jsx("span",{"data-testid":"text-expected",children:b.expected_cents==null?"Unavailable":u(b.expected_cents)})]}),e.jsxs("div",{className:"flex justify-between font-medium",children:[e.jsx("span",{children:"Counted"}),e.jsx("span",{"data-testid":"text-counted",children:u(b.counted_cents)})]}),e.jsxs("div",{className:`flex justify-between font-bold ${b.variance_cents===0?"text-green-600":b.variance_cents==null?"text-muted-foreground":"text-destructive"}`,children:[e.jsx("span",{children:"Variance"}),e.jsx("span",{"data-testid":"text-variance",children:b.variance_cents==null?"Unavailable":e.jsxs(e.Fragment,{children:[b.variance_cents>0?"+":"",u(b.variance_cents)]})})]})]}),e.jsxs("div",{className:"border-t pt-2 space-y-1",children:[e.jsx("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wide",children:"Opening floats"}),Array.from({length:(y==null?void 0:y.tills)??0},(c,o)=>o+1).map(c=>{const o=S.get(c),$=o?o.counted_cents-((m==null?void 0:m.float_cents)??5e4):null;return e.jsxs("div",{className:`flex justify-between text-sm ${o?$!==0?"text-destructive":"text-muted-foreground":"text-destructive"}`,"data-testid":`recon-opening-till-${c}`,children:[e.jsxs("span",{children:["Till ",c," opening",o?` · by ${o.counted_by}`:""]}),e.jsx("span",{children:o?$===0?e.jsxs("span",{className:"text-green-600",children:[u(o.counted_cents)," ✓"]}):e.jsxs(e.Fragment,{children:[u(o.counted_cents)," ",e.jsxs("span",{className:"font-medium",children:["(",$>0?"+":"",u($)," vs float)"]})]}):"not recorded"})]},c)})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"All tills submitted. Logged-in staff can amend counts and petty cash if a correction is needed."})]})}):e.jsx("p",{className:"text-sm text-muted-foreground","data-testid":"text-awaiting-tills",children:`${(h==null?void 0:h.tills.length)??0} of ${(y==null?void 0:y.tills)??0} tills submitted — the variance appears once all tills are in.`}),e.jsx(Be,{venue:n}),e.jsx(He,{date:s})]})]})})}export{lt as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.