diff --git a/src/components/HistoryChart.tsx b/src/components/HistoryChart.tsx index e0658e4..c46f374 100644 --- a/src/components/HistoryChart.tsx +++ b/src/components/HistoryChart.tsx @@ -30,27 +30,36 @@ export default function HistoryChart({ }; const activeDataKey = activeTab.toLowerCase(); - const currentData = data[activeDataKey] || data[activeTab] || []; + const rawData = data[activeDataKey] || data[activeTab] || []; + const currentData = [...rawData].reverse(); - const maxAmount = Math.max(...currentData.map((d) => d.amount), 1); + const maxAmount = + currentData.length > 0 + ? Math.max(...currentData.map((d) => d.amount), 1) + : 1; // ✅ Formatter (₹ + adaptive units) const formatAmount = (amount: number) => { const tab = activeTab.toLowerCase(); + if (amount === 0) return ""; + if (tab === "year") { - const lakhs = amount / 100000; - return `₹ ${lakhs.toFixed(2)} L`; + if (amount >= 100000) { + return `₹ ${(amount / 100000).toFixed(2)} L`; + } + return `₹ ${amount.toLocaleString("en-IN")}`; } if (tab === "month") { - const thousands = amount / 1000; - return `₹ ${thousands.toFixed(1)} K`; + if (amount >= 1000) { + return `₹ ${(amount / 1000).toFixed(1)} K`; + } + return `₹ ${amount.toLocaleString("en-IN")}`; } return `₹ ${amount.toLocaleString("en-IN")}`; }; - return ( @@ -100,7 +109,11 @@ export default function HistoryChart({ const heightPerc = (point.amount / maxAmount) * 100; return ( - + {point.amount > 0 ? formatAmount(point.amount) : ""} diff --git a/src/utils/dashboardLoader.ts b/src/utils/dashboardLoader.ts index 08ef56f..6e54e62 100644 --- a/src/utils/dashboardLoader.ts +++ b/src/utils/dashboardLoader.ts @@ -77,6 +77,7 @@ export interface AggregatedDashboardData { topPayees: Array<{ payeeName: string; amount: number }>; } +// ---------------- AGGREGATION ---------------- // ---------------- AGGREGATION ---------------- export async function fetchAggregatedData( type: "expense" | "income" @@ -103,7 +104,7 @@ export async function fetchAggregatedData( const weekStart = getStartOfWeek(now); const weekEnd = endOfDay(new Date(weekStart.getTime() + 6 * 86400000)); - // ---------------- MONTH (5 rolling weeks) ---------------- + // ---------------- MONTH (rolling 5 weeks, Mon–Sun aligned) ---------------- const monthBuckets: { label: string; start: Date; @@ -111,9 +112,11 @@ export async function fetchAggregatedData( amount: number; }[] = []; + const currentWeekStart = getStartOfWeek(now); + for (let i = 0; i < 5; i++) { - const end = endOfDay(new Date(now.getTime() - i * 7 * 86400000)); - const start = startOfDay(new Date(end.getTime() - 6 * 86400000)); + const start = new Date(currentWeekStart.getTime() - i * 7 * 86400000); + const end = endOfDay(new Date(start.getTime() + 6 * 86400000)); monthBuckets.push({ label: `${format(start)} - ${format(end)}`, @@ -123,7 +126,7 @@ export async function fetchAggregatedData( }); } - // ---------------- YEAR (12 months) ---------------- + // ---------------- YEAR (rolling 12 months) ---------------- const yearBuckets: { label: string; start: Date; @@ -136,10 +139,18 @@ export async function fetchAggregatedData( d.setMonth(d.getMonth() - i); const start = new Date(d.getFullYear(), d.getMonth(), 1); - const end = endOfDay(new Date(d.getFullYear(), d.getMonth() + 1, 0)); + + const end = + i === 0 + ? endOfDay(now) // current month → till now + : endOfDay(new Date(d.getFullYear(), d.getMonth() + 1, 0)); + + const label = `${d.toLocaleString("default", { + month: "short" + })}-${String(d.getFullYear()).slice(2)}`; yearBuckets.push({ - label: d.toLocaleString("default", { month: "short" }), + label, start, end, amount: 0 @@ -170,27 +181,31 @@ export async function fetchAggregatedData( } } - // MONTH - monthBuckets.forEach(b => { + // MONTH (rolling weeks) + for (const b of monthBuckets) { if (d >= b.start && d <= b.end) { b.amount += amt; } - }); + } - // YEAR - yearBuckets.forEach(b => { + // YEAR (rolling months) + for (const b of yearBuckets) { if (d >= b.start && d <= b.end) { b.amount += amt; } - }); + } } const toPoints = (b: any): ChartDataPoint[] => - Object.entries(b).map(([k, v]: any) => ({ - id: k, - amount: typeof v === "number" ? v : v.amount, - subLabel: typeof v === "number" ? undefined : v.range - })); + Array.isArray(b) + ? b.map((x) => ({ + id: x.label, + amount: x.amount + })) + : Object.entries(b).map(([k, v]: any) => ({ + id: k, + amount: v + })); const chartData = { week: toPoints(weekBuckets),