From 3ef71275a889a64fae09a22ad4619f8b49915952 Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Sun, 10 May 2026 19:46:32 +0530 Subject: [PATCH 1/3] added basic filtering --- src/Dashboard.tsx | 103 ++++++++++++++++++++++++--- src/features/report/report.models.ts | 9 +++ src/features/report/useReport.ts | 8 +++ 3 files changed, 111 insertions(+), 9 deletions(-) diff --git a/src/Dashboard.tsx b/src/Dashboard.tsx index 2fb1971..bd3f4d1 100644 --- a/src/Dashboard.tsx +++ b/src/Dashboard.tsx @@ -3,7 +3,11 @@ import { Box, Container, CircularProgress, - Alert + Alert, + TextField, + Paper, + Autocomplete, + Button } from "@mui/material"; import ConfigurableDashboard from "./components/Dashboard"; @@ -14,18 +18,67 @@ import { } from "./features/report"; export default function Dashboard() { + const [appliedPayees, setAppliedPayees] = React.useState([]); + const [appliedTags, setAppliedTags] = React.useState([]); + + const [payeeInput, setPayeeInput] = React.useState([]); + const [tagsInput, setTagsInput] = React.useState([]); + + const [loadedPayees, setLoadedPayees] = React.useState([]); + const [loadedTags, setLoadedTags] = React.useState([]); + const report = useReport({ periods: ["weekly", "monthly", "full"], rolling: true, include_transactions: true, group_by: ["tags"], - }) + payee: appliedPayees.length > 0 ? appliedPayees : undefined, + tags: appliedTags.length > 0 ? appliedTags : undefined, + }); + + React.useEffect(() => { + if (report.data?.data) { + setLoadedPayees(prev => { + const pSet = new Set(prev); + report.data.data.buckets.forEach((b: any) => { + Object.values(b.periods).forEach((periodArray: any) => { + periodArray?.forEach((p: any) => { + p.expenses?.transactions?.forEach((t: any) => { + if (t.payee?.name) pSet.add(t.payee.name); + }); + p.incomes?.transactions?.forEach((t: any) => { + if (t.payee?.name) pSet.add(t.payee.name); + }); + }); + }); + }); + return Array.from(pSet).sort(); + }); + + setLoadedTags(prev => { + const tSet = new Set(prev); + report.data.data.buckets.forEach((b: any) => { + Object.values(b.periods).forEach((periodArray: any) => { + periodArray?.forEach((p: any) => { + p.expenses?.transactions?.forEach((t: any) => { + t.tags?.forEach((tag: any) => tSet.add(tag.name || tag)); + }); + p.incomes?.transactions?.forEach((t: any) => { + t.tags?.forEach((tag: any) => tSet.add(tag.name || tag)); + }); + }); + }); + }); + return Array.from(tSet).sort(); + }); + } + }, [report.data?.data]); const isLoading = report.isLoading; const error = report.error; - if (isLoading) { + if (isLoading && !report.data) { return ( @@ -41,15 +94,47 @@ export default function Dashboard() { ); } - if (!report) { + if (!report.data) { return null; } - const data = prepareReport(report.data?.data); + const data = prepareReport(report.data.data); return ( - + + + setPayeeInput(val as string[])} + renderInput={(params) => } + sx={{ minWidth: 250, flex: 1 }} + /> + setTagsInput(val as string[])} + renderInput={(params) => } + sx={{ minWidth: 250, flex: 1 }} + /> + + + + ); } diff --git a/src/features/report/report.models.ts b/src/features/report/report.models.ts index d905aa5..e393fdb 100644 --- a/src/features/report/report.models.ts +++ b/src/features/report/report.models.ts @@ -86,5 +86,14 @@ export interface ReportData { ignore_self: boolean; include_transactions: boolean; + start_date?: string | null; + end_date?: string | null; + flow?: "expense" | "income" | null; + payee?: string[] | null; + account?: string[] | null; + tags?: string[] | null; + min_amount?: number | null; + max_amount?: number | null; + buckets: ReportBucket[]; } diff --git a/src/features/report/useReport.ts b/src/features/report/useReport.ts index d479d33..3c8ec74 100644 --- a/src/features/report/useReport.ts +++ b/src/features/report/useReport.ts @@ -7,6 +7,14 @@ export interface ReportParams { group_by?: ("payee" | "tags")[]; ignore_self?: boolean; include_transactions?: boolean; + start_date?: string; + end_date?: string; + flow?: "expense" | "income"; + payee?: string[]; + account?: string[]; + tags?: string[]; + min_amount?: number; + max_amount?: number; } export function useReport(params: ReportParams) { -- 2.49.1 From 3c3afffef8ca6ca20beb01f8a27563f5760c395d Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Sun, 10 May 2026 19:57:49 +0530 Subject: [PATCH 2/3] uix fixes for filtering --- src/Dashboard.tsx | 75 +++++++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/src/Dashboard.tsx b/src/Dashboard.tsx index bd3f4d1..2354645 100644 --- a/src/Dashboard.tsx +++ b/src/Dashboard.tsx @@ -101,36 +101,53 @@ export default function Dashboard() { const data = prepareReport(report.data.data); return ( - - setPayeeInput(val as string[])} - renderInput={(params) => } - sx={{ minWidth: 250, flex: 1 }} - /> - setTagsInput(val as string[])} - renderInput={(params) => } - sx={{ minWidth: 250, flex: 1 }} - /> - - + setPayeeInput(val as string[])} + renderInput={(params) => } + sx={{ minWidth: { sm: 250 }, flex: 1 }} + /> + setTagsInput(val as string[])} + renderInput={(params) => } + sx={{ minWidth: { sm: 250 }, flex: 1 }} + /> + + + Date: Sun, 10 May 2026 20:04:52 +0530 Subject: [PATCH 3/3] ui fixes for filtering --- src/Dashboard.tsx | 50 ++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/Dashboard.tsx b/src/Dashboard.tsx index 2354645..1e5cecf 100644 --- a/src/Dashboard.tsx +++ b/src/Dashboard.tsx @@ -109,31 +109,41 @@ export default function Dashboard() { display: "flex", flexDirection: { xs: "column", sm: "row" }, gap: 2, - alignItems: { xs: "stretch", sm: "center" }, + alignItems: { xs: "stretch", sm: "flex-end" }, borderRadius: 4, mb: -2 // pull up to be closer to the dashboard container below }} elevation={0} variant="outlined" > - setPayeeInput(val as string[])} - renderInput={(params) => } - sx={{ minWidth: { sm: 250 }, flex: 1 }} - /> - setTagsInput(val as string[])} - renderInput={(params) => } - sx={{ minWidth: { sm: 250 }, flex: 1 }} - /> + + + Filter by Payee + + setPayeeInput(val as string[])} + renderInput={(params) => } + sx={{ '& .MuiOutlinedInput-root': { height: 'auto', minHeight: '2.5rem', py: 0.5 } }} + /> + + + + Filter by Tags + + setTagsInput(val as string[])} + renderInput={(params) => } + sx={{ '& .MuiOutlinedInput-root': { height: 'auto', minHeight: '2.5rem', py: 0.5 } }} + /> + -- 2.49.1