From 4eca3b7124a52ad07f8e70dc5d4de7a350452a05 Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Sat, 4 Apr 2026 22:35:17 +0530 Subject: [PATCH] calcuation fixes --- src/Dashboard.tsx | 67 +++++++++++++++++++++++---------- src/utils/dashboardLoader.ts | 73 ++++++++++++++---------------------- 2 files changed, 75 insertions(+), 65 deletions(-) diff --git a/src/Dashboard.tsx b/src/Dashboard.tsx index 3604f78..d961c52 100644 --- a/src/Dashboard.tsx +++ b/src/Dashboard.tsx @@ -13,16 +13,28 @@ import LatestItemsList, { LatestItem } from "./components/LatestItemsList"; import HistoryChart from "./components/HistoryChart"; import { - fetchLatestExpenses, + fetchLatestTransactions, fetchAggregatedExpenses, fetchAggregatedIncome, AggregatedDashboardData } from "./utils/dashboardLoader"; export default function Dashboard() { - const [latest, setLatest] = React.useState([]); - const [aggregated, setAggregated] = - React.useState(null); + const [latest, setLatest] = React.useState<{ + expense: LatestItem[]; + income: LatestItem[]; + }>({ + expense: [], + income: [] + }); + + const [aggregated, setAggregated] = React.useState<{ + expense: AggregatedDashboardData | null; + income: AggregatedDashboardData | null; + }>({ + expense: null, + income: null + }); const [mode, setMode] = React.useState<"expense" | "income">("expense"); @@ -30,21 +42,33 @@ export default function Dashboard() { const [loading, setLoading] = React.useState(true); const [error, setError] = React.useState(null); - // -------- LOAD DATA -------- + // -------- LOAD ONCE -------- React.useEffect(() => { async function loadData() { try { setLoading(true); - const latestData = await fetchLatestExpenses(); + const [ + latestExpense, + latestIncome, + expenseData, + incomeData + ] = await Promise.all([ + fetchLatestTransactions("expense"), + fetchLatestTransactions("income"), + fetchAggregatedExpenses(), + fetchAggregatedIncome() + ]); - const aggData = - mode === "expense" - ? await fetchAggregatedExpenses() - : await fetchAggregatedIncome(); + setLatest({ + expense: latestExpense, + income: latestIncome + }); - setLatest(latestData); - setAggregated(aggData); + setAggregated({ + expense: expenseData, + income: incomeData + }); } catch (err: any) { console.error(err); @@ -55,7 +79,10 @@ export default function Dashboard() { } loadData(); - }, [mode]); + }, []); + + const currentData = aggregated[mode]; + const currentLatest = latest[mode]; // -------- UI STATES -------- if (loading) { @@ -89,25 +116,25 @@ export default function Dashboard() { - {/* LEFT → 1/3 (4 cols) */} + {/* LEFT → 1/3 */} {}} /> - {/* RIGHT → 2/3 (8 cols) */} + {/* RIGHT → 2/3 */} ); -} +} \ No newline at end of file diff --git a/src/utils/dashboardLoader.ts b/src/utils/dashboardLoader.ts index af67fb6..082822b 100644 --- a/src/utils/dashboardLoader.ts +++ b/src/utils/dashboardLoader.ts @@ -10,32 +10,41 @@ const DEFAULT_ICON = React.createElement(MonetizationOnIcon, { }); // ---------------- LATEST ---------------- -export async function fetchLatestExpenses(): Promise { +export async function fetchLatestTransactions( + type: "expense" | "income" +): Promise { const res = await api.get('/expenses', { - params: { limit: 10, sort: '-occurred_at' } + params: { limit: 100, sort: '-occurred_at' } }); const items = res.data?.items || res.data || []; - return items.map((exp: any, index: number) => { - const time = new Date( - exp.occurred_at || exp.created_at || Date.now() - ).getTime(); + const isValid = (amt: number) => + type === "expense" ? amt < 0 : amt > 0; - const diffDays = Math.floor( - Math.abs(Date.now() - time) / (1000 * 60 * 60 * 24) - ); + return items + .filter((item: any) => isValid(Number(item.amount) || 0)) + .slice(0, 10) + .map((exp: any, index: number) => { + const time = new Date( + exp.occurred_at || exp.created_at || Date.now() + ).getTime(); - return { - id: exp.id || index, - icon: DEFAULT_ICON, - iconBgColor: "#e8f5e9", - title: exp.payee?.name || exp.payee || "Unknown Payee", - subtitle: exp.category?.name || exp.account?.name || "Transaction", - amount: `Rs ${exp.amount || 0}`, - timeAgo: diffDays === 0 ? "Today" : `${diffDays} days ago` - }; - }); + const diffDays = Math.floor( + Math.abs(Date.now() - time) / (1000 * 60 * 60 * 24) + ); + + return { + id: exp.id || index, + icon: DEFAULT_ICON, + iconBgColor: + type === "expense" ? "#ffebee" : "#e8f5e9", + title: exp.payee?.name || exp.payee || "Unknown Payee", + subtitle: exp.category?.name || exp.account?.name || "Transaction", + amount: `Rs ${Math.abs(exp.amount || 0)}`, + timeAgo: diffDays === 0 ? "Today" : `${diffDays} days ago` + }; + }); } // ---------------- TYPES ---------------- @@ -62,12 +71,6 @@ export async function fetchAggregatedData( const normalize = (amt: number) => Math.abs(amt); - // ---------------- BUCKETS ---------------- - const todayBuckets: Record = { - "12am":0,"3am":0,"6am":0,"9am":0, - "12pm":0,"3pm":0,"6pm":0,"9pm":0 - }; - const weekBuckets: Record = { "Mon":0,"Tue":0,"Wed":0,"Thu":0, "Fri":0,"Sat":0,"Sun":0 @@ -134,25 +137,6 @@ export async function fetchAggregatedData( const payee = item.payee?.name || item.payee || "Unknown"; payeeMap[payee] = (payeeMap[payee] || 0) + amt; - // ---- TODAY - if ( - d.getDate() === now.getDate() && - d.getMonth() === now.getMonth() && - d.getFullYear() === now.getFullYear() - ) { - const hr = d.getHours(); - let label = "12am"; - if (hr >= 3 && hr < 6) label = "3am"; - else if (hr >= 6 && hr < 9) label = "6am"; - else if (hr >= 9 && hr < 12) label = "9am"; - else if (hr >= 12 && hr < 15) label = "12pm"; - else if (hr >= 15 && hr < 18) label = "3pm"; - else if (hr >= 18 && hr < 21) label = "6pm"; - else if (hr >= 21) label = "9pm"; - - todayBuckets[label] += amt; - } - // ---- WEEK if (d >= weekStart && d <= weekEnd) { const day = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][d.getDay()]; @@ -192,7 +176,6 @@ export async function fetchAggregatedData( })); const chartData = { - today: toPoints(todayBuckets), week: toPoints(weekBuckets), month: toPoints(monthBuckets), year: toPoints(yearBuckets)