comparison

This commit is contained in:
2026-04-06 18:39:19 +05:30
parent f320f6ff31
commit e6c7778c08
3 changed files with 194 additions and 80 deletions

View File

@@ -32,6 +32,9 @@ const getStartOfWeek = (d: Date) => {
return startOfDay(date);
};
const shiftDate = (d: Date, days: number) =>
new Date(d.getTime() + days * 86400000);
// ---------------- LATEST ----------------
export async function fetchLatestTransactions(
type: "expense" | "income"
@@ -106,13 +109,20 @@ export async function fetchAggregatedData(
const normalize = (amt: number) => Math.abs(amt);
// ---------------- DAILY ----------------
const dailyBuckets: Record<string, number> = {
Mon: 0, Tue: 0, Wed: 0, Thu: 0,
Fri: 0, Sat: 0, Sun: 0
const dailyBuckets: Record<string, any> = {
Mon: { amount: 0, compare: 0 },
Tue: { amount: 0, compare: 0 },
Wed: { amount: 0, compare: 0 },
Thu: { amount: 0, compare: 0 },
Fri: { amount: 0, compare: 0 },
Sat: { amount: 0, compare: 0 },
Sun: { amount: 0, compare: 0 }
};
const weekStart = getStartOfWeek(now);
const weekEnd = endOfDay(new Date(weekStart.getTime() + 6 * 86400000));
const prevWeekStart = shiftDate(weekStart, -7);
const prevWeekEnd = shiftDate(weekEnd, -7);
// ---------------- WEEKLY ----------------
const weeklyRolling: any[] = [];
@@ -120,7 +130,7 @@ export async function fetchAggregatedData(
const currentWeekStart = getStartOfWeek(now);
// rolling (last 5 weeks, oldest → newest)
// rolling (last 5 weeks)
for (let i = 4; i >= 0; i--) {
const start = new Date(currentWeekStart.getTime() - i * 7 * 86400000);
const end = endOfDay(new Date(start.getTime() + 6 * 86400000));
@@ -129,11 +139,14 @@ export async function fetchAggregatedData(
label: `${format(start)} - ${format(end)}`,
start,
end,
amount: 0
amount: 0,
compare: 0,
prevStart: shiftDate(start, -7),
prevEnd: shiftDate(end, -7)
});
}
// calendar (full weeks covering current month)
// calendar weeks
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0);
@@ -151,7 +164,10 @@ export async function fetchAggregatedData(
label: `${format(start)} - ${format(end)}`,
start,
end,
amount: 0
amount: 0,
compare: 0,
prevStart: shiftDate(start, -7),
prevEnd: shiftDate(end, -7)
});
}
@@ -159,7 +175,7 @@ export async function fetchAggregatedData(
const monthlyRolling: any[] = [];
const monthlyCalendar: any[] = [];
// rolling (last 12 months, oldest → newest)
// rolling (last 12 months)
for (let i = 11; i >= 0; i--) {
const d = new Date(now);
d.setMonth(d.getMonth() - i);
@@ -170,24 +186,44 @@ export async function fetchAggregatedData(
? endOfDay(now)
: endOfDay(new Date(d.getFullYear(), d.getMonth() + 1, 0));
const prevStart = new Date(start);
prevStart.setMonth(prevStart.getMonth() - 1);
const prevEnd = new Date(end);
prevEnd.setMonth(prevEnd.getMonth() - 1);
monthlyRolling.push({
label: `${d.toLocaleString("default", { month: "short" })}-${String(d.getFullYear()).slice(2)}`,
label: `${d.toLocaleString("default", { month: "short" })}-${String(
d.getFullYear()
).slice(2)}`,
start,
end,
amount: 0
amount: 0,
compare: 0,
prevStart,
prevEnd
});
}
// calendar (full year Jan → Dec)
// calendar (JanDec)
for (let i = 0; i < 12; i++) {
const start = new Date(now.getFullYear(), i, 1);
const end = endOfDay(new Date(now.getFullYear(), i + 1, 0));
const prevStart = new Date(start);
prevStart.setFullYear(prevStart.getFullYear() - 1);
const prevEnd = new Date(end);
prevEnd.setFullYear(prevEnd.getFullYear() - 1);
monthlyCalendar.push({
label: `${start.toLocaleString("default", { month: "short" })}-${String(start.getFullYear()).slice(2)}`,
label: `${start.toLocaleString("default", { month: "short" })}-${String(
start.getFullYear()
).slice(2)}`,
start,
end,
amount: 0
amount: 0,
compare: 0,
prevStart,
prevEnd
});
}
@@ -210,38 +246,51 @@ export async function fetchAggregatedData(
// DAILY
if (d >= weekStart && d <= weekEnd) {
const day = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][d.getDay()];
if (dailyBuckets[day] !== undefined) {
dailyBuckets[day] += amt;
if (dailyBuckets[day]) {
dailyBuckets[day].amount += amt;
}
}
if (d >= prevWeekStart && d <= prevWeekEnd) {
const day = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][d.getDay()];
if (dailyBuckets[day]) {
dailyBuckets[day].compare += amt;
}
}
// WEEKLY
for (const b of weeklyRolling) {
if (d >= b.start && d <= b.end) b.amount += amt;
if (d >= b.prevStart && d <= b.prevEnd) b.compare += amt;
}
for (const b of weeklyCalendar) {
if (d >= b.start && d <= b.end) b.amount += amt;
if (d >= b.prevStart && d <= b.prevEnd) b.compare += amt;
}
// MONTHLY
for (const b of monthlyRolling) {
if (d >= b.start && d <= b.end) b.amount += amt;
if (d >= b.prevStart && d <= b.prevEnd) b.compare += amt;
}
for (const b of monthlyCalendar) {
if (d >= b.start && d <= b.end) b.amount += amt;
if (d >= b.prevStart && d <= b.prevEnd) b.compare += amt;
}
}
const toPoints = (arr: any[]): ChartDataPoint[] =>
arr.map((x) => ({
id: x.label,
amount: x.amount
amount: x.amount,
compareAmount: x.compare
}));
const chartData: ChartData = {
daily: Object.entries(dailyBuckets).map(([k, v]) => ({
daily: Object.entries(dailyBuckets).map(([k, v]: any) => ({
id: k,
amount: v
amount: v.amount,
compareAmount: v.compare
})),
weekly: {
rolling: toPoints(weeklyRolling),
@@ -253,7 +302,7 @@ export async function fetchAggregatedData(
}
};
// highlight max (per visible set default to rolling)
// highlight max (current only)
Object.values(chartData).forEach((group: any) => {
const arr = Array.isArray(group) ? group : group.rolling;
if (!arr?.length) return;