PageSourceSearch

https://rx-zenith-ui.lovable.app/assets/Expenses-BrPSGUVS.js

js rx-zenith-ui.lovable.app collected 2026-10-03 03:43:51 UTC 15,317 bytes, 1 lines download raw bytes

1import{j as e,ap as te,a as se,q as ae,m as re,a_ as G,J as ne,ah as oe,aV as z,z as de,bm as le,X as ie,c6 as ce}from"./vendor-ui-C55-z5ML.js";import{r as a,i as xe}from"./vendor-react-BeyMlh3v.js";import{Q as me,Y as d,u as ue,ao as pe,aM as he,aN as ge}from"./index-bxsxYkA5.js";import{f as fe}from"./guestData-DdWi4Bqs.js";import{I as j}from"./input-DbmUiQSQ.js";import{L as y}from"./label-CvNWhCk0.js";import{S as L,a as P,b as R,c as D,d as S}from"./select-6xYtApt-.js";import{c as je}from"./aiHelpers-CCmpuN40.js";import{i as ye,a as be,b as Ne,c as ve}from"./isToday-QZcRFUVb.js";import{R as q,P as we,b as Ce,d as Se,T as B,L as ke,C as Ee,X as Ae,Y as Me,f as Te}from"./vendor-charts-CLYneQfg.js";import{f as J}from"./format-B8o24CUr.js";import{p as Ie}from"./parseISO-DPuZTSDx.js";import"./vendor-export-CJuGTaQd.js";import"./vendor-supabase-C07NOBum.js";import"./subDays-Bn8mKwRf.js";import"./toDate-qOSwr3PX.js";import"./en-US-D2RVN5UN.js";import"./index-sF1Hg77J.js";import"./index-DUaBbbom.js";import"./aiSuite-B0StHzAh.js";import"./constructNow-gm1t92Ki.js";import"./startOfDay-DFv_10u4.js";function Le({period:i,total:m,currency:b="PKR",categories:c,trend:x}){const{getAIConfig:N}=me(),[r,p]=a.useState(!1),[u,k]=a.useState(""),h=async()=>{const v=N();if(!v){d.error("AI not configured");return}if(!c.length){d.error("No expense data for this period");return}p(!0);try{const l=await je(v,{period:i,total:m,currency:b,categories:c,trend:x});k(l)}catch(l){d.error(l?.message||"AI request failed")}finally{p(!1)}};return e.jsxs("div",{className:"relative overflow-hidden rounded-2xl border border-primary/20 bg-gradient-to-r from-primary/5 via-card to-secondary/5 p-4 sm:p-5",children:[e.jsx("div",{className:"absolute top-0 right-0 w-32 h-32 bg-primary/8 rounded-full blur-2xl"}),e.jsxs("div",{className:"relative flex items-start gap-3",children:[e.jsx("div",{className:"w-9 h-9 rounded-xl bg-primary/15 flex items-center justify-center flex-shrink-0",children:e.jsx(te,{className:"w-4.5 h-4.5 text-primary"})}),e.jsxs("div",{className:"flex-1 min-w-0 space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 flex-wrap",children:[e.jsx("h3",{className:"text-sm font-bold text-foreground",children:"AI Expense Insight"}),e.jsxs("button",{type:"button",onClick:h,disabled:r,className:"inline-flex items-center gap-1.5 text-xs font-semibold text-primary hover:text-primary/80 disabled:opacity-50",children:[r?e.jsx(se,{className:"w-3.5 h-3.5 animate-spin"}):e.jsx(ae,{className:"w-3.5 h-3.5"}),u?"Refresh":"Analyze"]})]}),u?e.jsx("p",{className:"text-sm text-foreground/90 whitespace-pre-wrap leading-relaxed",children:u}):e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Click Analyze for a quick AI breakdown of spending patterns & savings tips for the ",i," period."]})]})]})]})}const Pe=["Rent","Utilities","Salaries","Transport","Maintenance","Other"],Re=["Cash","Bank Transfer","Cheque","Online"],W=["hsl(var(--primary))","hsl(var(--destructive))","hsl(var(--warning))","#06b6d4","#8b5cf6","#f97316"],X="phc_expense_categories",De=()=>{try{const i=localStorage.getItem(X);if(i){const m=JSON.parse(i);if(Array.isArray(m)&&m.length)return m}}catch{}return Pe},Oe=i=>{try{localStorage.setItem(X,JSON.stringify(i))}catch{}},Ke=[{key:"list",label:"List Expenses"},{key:"add",label:"Add Expense"},{key:"categories",label:"Expense Categories"}],ot=()=>{const{isGuest:i}=ue(),[m,b]=xe(),c=m.get("tab")||"list",[x,N]=a.useState([]),[r,p]=a.useState(De),[u,k]=a.useState(""),[h,v]=a.useState("All"),[l,H]=a.useState("month"),[n,g]=a.useState({category:r[0]||"Other",amount:"",date:J(new Date,"yyyy-MM-dd"),description:"",paymentMethod:"Cash"}),[O,K]=a.useState(""),[F,E]=a.useState(null),[_,w]=a.useState("");a.useEffect(()=>{if(i){N(fe());return}return pe(N)},[i]),a.useEffect(()=>{Oe(r)},[r]);const f=a.useMemo(()=>x.filter(t=>{try{const s=Ie(t.date);return l==="today"?ye(s):l==="week"?be(s):l==="month"?Ne(s):ve(s)}catch{return!0}}),[x,l]),U=a.useMemo(()=>f.reduce((t,s)=>t+s.amount,0),[f]),C=a.useMemo(()=>{const t={};return f.forEach(s=>
1{t[s.category]=(t[s.category]||0)+s.amount}),Object.entries(t).map(([s,o])=>({name:s,value:o}))},[f]),A=a.useMemo(()=>{const t={};return x.forEach(s=>{const o=s.date?.substring(0,7)||"Unknown";t[o]=(t[o]||0)+s.amount}),Object.entries(t).sort().slice(-6).map(([s,o])=>({month:s,total:o}))},[x]),V=a.useMemo(()=>f.filter(t=>{const s=t.description.toLowerCase().includes(u.toLowerCase()),o=h==="All"||t.category===h;return s&&o}),[f,u,h]),M=a.useMemo(()=>{const t={};return x.forEach(s=>{t[s.category]=(t[s.category]||0)+1}),t},[x]),Q=async()=>{if(!n.amount||!n.description){d.error("Fill amount and description");return}await ge({category:n.category,amount:Number(n.amount),date:n.date,description:n.description,paymentMethod:n.paymentMethod}),d.success("Expense added"),g({category:r[0]||"Other",amount:"",date:J(new Date,"yyyy-MM-dd"),description:"",paymentMethod:"Cash"}),b({tab:"list"})},Y=()=>{const t=O.trim();if(t){if(r.some(s=>s.toLowerCase()===t.toLowerCase())){d.error("Category already exists");return}p([...r,t]),K(""),d.success("Category added")}},$=t=>{const s=_.trim();if(!s)return;if(r.some((I,ee)=>ee!==t&&I.toLowerCase()===s.toLowerCase())){d.error("Duplicate name");return}const o=[...r];o[t]=s,p(o),E(null),w(""),d.success("Category updated")},Z=t=>{const s=r[t];if(M[s]){d.error(`Used by ${M[s]} expense(s)`);return}p(r.filter((o,I)=>I!==t)),d.success("Category removed")},T=t=>b({tab:t});return e.jsxs(re.div,{initial:{opacity:0,y:16},animate:{opacity:1,y:0},className:"space-y-6 max-w-[1600px]",children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-xl sm:text-2xl font-bold font-display text-foreground",children:"Expense Management"}),e.jsx("p",{className:"text-sm text-muted-foreground mt-0.5",children:"Track and manage operational expenses"})]}),c==="list"&&e.jsxs("button",{onClick:()=>T("add"),className:"flex items-center gap-2 bg-primary text-primary-foreground px-4 py-2.5 rounded-xl text-sm font-medium hover:opacity-90 transition-opacity",children:[e.jsx(G,{className:"w-4 h-4"})," Add Expense"]})]}),e.jsx("div",{className:"flex bg-muted rounded-xl p-1 gap-1 w-fit",children:Ke.map(t=>e.jsx("button",{onClick:()=>T(t.key),className:`px-4 py-1.5 rounded-lg text-xs font-medium transition-colors ${c===t.key?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"}`,children:t.label},t.key))}),c==="list"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-4",children:[e.jsx("div",{className:"flex bg-muted rounded-xl p-1 gap-1",children:["today","week","month","year"].map(t=>e.jsx("button",{onClick:()=>H(t),className:`px-4 py-1.5 rounded-lg text-xs font-medium transition-colors ${l===t?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"}`,children:t.charAt(0).toUpperCase()+t.slice(1)},t))}),e.jsxs("div",{className:"glass-card-solid px-5 py-3 flex items-center gap-3",children:[e.jsx(ne,{className:"w-5 h-5 text-destructive"}),e.jsxs("div",{children:[e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Total (",l,")"]}),e.jsxs("p",{className:"text-xl font-bold text-foreground",children:["PKR ",U.toLocaleString()]})]})]})]}),e.jsx(Le,{period:l,total:U,currency:"PKR",categories:C.map(t=>({name:t.name,amount:t.value})),trend:A.map(t=>({month:t.month,amount:t.total}))}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"glass-card-solid p-5",children:[e.jsx("h3",{className:"text-sm font-semibold text-foreground mb-4",children:"Category Breakdown"}),C.length>0?e.jsx(q,{width:"100%",height:220,children:e.jsxs(we,{children:[e.jsx(Ce,{data:C,cx:"50%",cy:"50%",innerRadius:50,outerRadius:80,dataKey:"value",label:({name:t,percent:s})=>`${t} ${(s*100).toFixed(0)}%`,children:C.map((t,s)=>e.jsx(Se,{fill:W[s%W.length]},s))}),e.jsx(B,{formatter:t=>`PKR ${t.toLocaleString()}`})]})}):e.jsx("p",{className:"text-sm text-muted-foreground text-center py-10",children:"No data for this period"})]}),e.jsxs("div",{className:"glass-card-solid p-5",children:[e.jsx("h3",{className:"text-sm font-semibold text-foreground mb-4",children:"Monthly Trend"}),A.length>0?e.jsx(q,{width:"100%",height:220,children:e.jsxs(ke,{data:A,children:[e.jsx(Ee,{strokeDasharray:"3 3",className:"opacity-30"}),e.jsx(Ae,{dataKey:"month",tick:{fontSize:11}}),e.jsx(Me,{tick:{fontSize:11}}),e.jsx(B,{formatter:t=>
1`PKR ${t.toLocaleString()}`}),e.jsx(Te,{type:"monotone",dataKey:"total",stroke:"hsl(var(--destructive))",strokeWidth:2,dot:{r:4}})]})}):e.jsx("p",{className:"text-sm text-muted-foreground text-center py-10",children:"No trend data"})]})]}),e.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[e.jsxs("div",{className:"relative flex-1 min-w-[200px]",children:[e.jsx(oe,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground"}),e.jsx(j,{placeholder:"Search expenses...",value:u,onChange:t=>k(t.target.value),className:"pl-10"})]}),e.jsxs(L,{value:h,onValueChange:v,children:[e.jsx(P,{className:"w-[140px]",children:e.jsx(R,{})}),e.jsxs(D,{children:[e.jsx(S,{value:"All",children:"All Categories"}),r.map(t=>e.jsx(S,{value:t,children:t},t))]})]})]}),e.jsx("div",{className:"glass-card-solid overflow-x-auto",children:e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{children:e.jsx("tr",{className:"border-b border-border",children:["Date","Category","Description","Amount","Payment","Actions"].map(t=>e.jsx("th",{className:"text-left px-5 py-3 text-xs font-semibold text-muted-foreground uppercase tracking-wider",children:t},t))})}),e.jsx("tbody",{children:V.length===0?e.jsx("tr",{children:e.jsx("td",{colSpan:6,className:"px-5 py-8 text-center text-sm text-muted-foreground",children:"No expenses found"})}):V.map(t=>e.jsxs("tr",{className:"border-b border-border last:border-0 hover:bg-muted/30 transition-colors",children:[e.jsx("td",{className:"px-5 py-3.5 text-sm text-muted-foreground",children:t.date}),e.jsx("td",{className:"px-5 py-3.5",children:e.jsx("span",{className:"text-xs font-medium px-2.5 py-1 rounded-full bg-primary/10 text-primary",children:t.category})}),e.jsx("td",{className:"px-5 py-3.5 text-sm text-foreground",children:t.description}),e.jsxs("td",{className:"px-5 py-3.5 text-sm font-medium text-destructive",children:["PKR ",t.amount.toLocaleString()]}),e.jsx("td",{className:"px-5 py-3.5 text-sm text-muted-foreground",children:t.paymentMethod}),e.jsx("td",{className:"px-5 py-3.5",children:e.jsx("button",{onClick:()=>{t.id&&(he(t.id),d.success("Deleted"))},className:"p-1.5 hover:bg-destructive/10 rounded-lg",children:e.jsx(z,{className:"w-4 h-4 text-destructive"})})})]},t.id))})]})})]}),c==="add"&&e.jsxs("div",{className:"glass-card-solid p-6 max-w-2xl",children:[e.jsx("h2",{className:"text-lg font-semibold text-foreground mb-1",children:"Add New Expense"}),e.jsx("p",{className:"text-xs text-muted-foreground mb-5",children:"Record a new operational expense entry"}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx(y,{children:"Category"}),e.jsxs(L,{value:n.category,onValueChange:t=>g({...n,category:t}),children:[e.jsx(P,{children:e.jsx(R,{})}),e.jsx(D,{children:r.map(t=>e.jsx(S,{value:t,children:t},t))})]})]}),e.jsxs("div",{children:[e.jsx(y,{children:"Amount (PKR)"}),e.jsx(j,{type:"number",value:n.amount,onChange:t=>g({...n,amount:t.target.value}),placeholder:"Enter amount"})]}),e.jsxs("div",{children:[e.jsx(y,{children:"Date"}),e.jsx(j,{type:"date",value:n.date,onChange:t=>g({...n,date:t.target.value})})]}),e.jsxs("div",{children:[e.jsx(y,{children:"Payment Method"}),e.jsxs(L,{value:n.paymentMethod,onValueChange:t=>g({...n,paymentMethod:t}),children:[e.jsx(P,{children:e.jsx(R,{})}),e.jsx(D,{children:Re.map(t=>e.jsx(S,{value:t,children:t},t))})]})]}),e.jsxs("div",{className:"sm:col-span-2",children:[e.jsx(y,{children:"Description"}),e.jsx(j,{value:n.description,onChange:t=>g({...n,description:t.target.value}),placeholder:"What was this expense for?"})]})]}),e.jsxs("div",{className:"flex gap-2 mt-6",children:[e.jsx("button",{onClick:Q,className:"flex-1 bg-primary text-primary-foreground py-2.5 rounded-xl text-sm font-medium hover:opacity-90",children:"Save Expense"}),e.jsx("button",{onClick:()=>T("list"),className:"px-5 py-2.5 rounded-xl text-sm font-medium border border-border text-muted-foreground hover:bg-muted",children:"Cancel"})]})]}),c==="categories"&&e.jsxs("div",{className:"space-y-4 max-w-3xl",children:[e.jsxs("div",{className:"glass-card-solid p-5",children:[e.jsxs("h2",{className:"text-sm font-semibold text-foreground mb-3 flex items-center gap-2",children:[e.jsx(de,{className:"w-4 h-4 text-primary"})," Add New Category"]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(j,{value:O,onChange:t=>K(t.target.value),onKeyDown:t=>t.key==="Enter"&&Y(),placeholder:"e.g. Marketing, Insurance..."}),e.jsxs("button",{onClick:Y,className:"px-4 py-2 rounded-xl bg-primary text-primary-foreground text-sm font-medium hover:opacity-90 flex items-center gap-1.5",children:[e.jsx(G,{className:"w-4 h-4"})," Add"]})]})]}),e.jsx("div",{className:"glass-card-solid overflow-hidden",children:e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-border",children:[e.jsx("th",{className:"text-left px-5 py-3 text-xs font-semibold text-muted-foreground uppercase tracking-wider",children:"Category"}),e.jsx("th",{className:"text-left px-5 py-3 text-xs font-semibold text-muted-foreground uppercase tracking-wider",children:"Used in"}),e.jsx("th",{className:"text-right px-5 py-3 text-xs font-semibold text-muted-foreground uppercase tracking-wider",children:"Actions"})]})}),e.jsxs("tbody",{children:[r.map((t,s)=>e.jsxs("tr",{className:"border-b border-border last:border-0 hover:bg-muted/30",children:[e.jsx("td",{className:"px-5 py-3",children:F===s?e.jsx(j,{value:_,onCh
1ange:o=>w(o.target.value),onKeyDown:o=>o.key==="Enter"&&$(s),autoFocus:!0}):e.jsx("span",{className:"text-sm font-medium text-foreground",children:t})}),e.jsxs("td",{className:"px-5 py-3 text-sm text-muted-foreground",children:[M[t]||0," expense(s)"]}),e.jsx("td",{className:"px-5 py-3",children:e.jsx("div",{className:"flex justify-end gap-1",children:F===s?e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>$(s),className:"p-1.5 hover:bg-primary/10 rounded-lg",children:e.jsx(le,{className:"w-4 h-4 text-primary"})}),e.jsx("button",{onClick:()=>{E(null),w("")},className:"p-1.5 hover:bg-muted rounded-lg",children:e.jsx(ie,{className:"w-4 h-4 text-muted-foreground"})})]}):e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>{E(s),w(t)},className:"p-1.5 hover:bg-primary/10 rounded-lg",children:e.jsx(ce,{className:"w-4 h-4 text-primary"})}),e.jsx("button",{onClick:()=>Z(s),className:"p-1.5 hover:bg-destructive/10 rounded-lg",children:e.jsx(z,{className:"w-4 h-4 text-destructive"})})]})})})]},t)),r.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:3,className:"px-5 py-8 text-center text-sm text-muted-foreground",children:"No categories. Add one above."})})]})]})})]})]})};export{ot 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.