import * as React from "react"; import MonetizationOnIcon from "@mui/icons-material/MonetizationOn"; import { LatestItem } from "../../components/LatestItems"; import { ChartData, ChartDataPoint, } from "../../components/HistoryChart"; const DEFAULT_ICON = React.createElement(MonetizationOnIcon, { sx: { color: "#388e3c" } }); type ReportBucket = any; export function mapToLatestItems( items: any[], type: "expense" | "income" ): LatestItem[] { const isValid = (amt: number) => type === "expense" ? amt < 0 : amt > 0; return items .filter((item: any) => isValid(Number(item.amount) || 0)) .slice(0, 5) .map((exp: any, index: number) => { const time = new Date(exp.occurred_at).getTime(); 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, subtitle: exp.account.name, amount: `Rs ${Math.abs(exp.amount || 0)}`, timeAgo: diffDays === 0 ? "Today" : `${diffDays} days ago` }; }); } const sumBucket = (bucket: ReportBucket, flow: "expenses" | "incomes") => bucket.groups.reduce( (acc: number, g: any) => acc + (g?.[flow]?.sum || 0), 0 ); const toLabel = (start: string, end: string, type: "weekly" | "monthly") => { const s = new Date(start); const e = new Date(end); if (type === "monthly") { return s.toLocaleString("default", { month: "short" }); } return `${s.getDate()}–${e.getDate()} ${e.toLocaleString("default", { month: "short", })}`; }; const getWeekOfMonth = (date: Date) => { const firstDay = new Date(date.getFullYear(), date.getMonth(), 1); return Math.ceil((date.getDate() + firstDay.getDay()) / 7); }; const findCompareBucket = ( current: ReportBucket, buckets: ReportBucket[], type: "weekly" | "monthly" ): ReportBucket | undefined => { const start = new Date(current.start); if (type === "monthly") { const targetYear = start.getFullYear() - 1; const targetMonth = start.getMonth(); return buckets.find(b => { const d = new Date(b.start); return ( d.getFullYear() === targetYear && d.getMonth() === targetMonth ); }); } if (type === "weekly") { const weekIndex = getWeekOfMonth(start); // you must define this const target = new Date(start); target.setMonth(target.getMonth() - 1); return buckets.find(b => { const d = new Date(b.start); return ( d.getFullYear() === target.getFullYear() && d.getMonth() === target.getMonth() && getWeekOfMonth(d) === weekIndex ); }); } return undefined; }; const toPoints = ( buckets: ReportBucket[], type: "weekly" | "monthly", flow: "expenses" | "incomes" ): ChartDataPoint[] => { return buckets.map((b) => { const amount = sumBucket(b, flow); const prev = findCompareBucket(b, buckets, type); return { id: toLabel(b.start, b.end, type), amount, compare: prev ? { id: toLabel(prev.start, prev.end, type), amount: sumBucket(prev, flow), } : undefined, }; }); }; export function mapReportToDashboard( weekly: ReportBucket[], monthly: ReportBucket[], payeeBuckets: ReportBucket[], type: "expense" | "income" ) { const flow = type === "expense" ? "expenses" : "incomes"; const chartData: ChartData = { weekly: { rolling: toPoints(weekly, "weekly", flow), calendar: toPoints(weekly, "weekly", flow), }, monthly: { rolling: toPoints(monthly, "monthly", flow), calendar: toPoints(monthly, "monthly", flow), }, }; const totalAmount = weekly.reduce( (acc, b) => acc + sumBucket(b, flow), 0 ); const payeeMap: Record = {}; const sourceForPayees = (payeeBuckets && payeeBuckets.length > 0) ? payeeBuckets : weekly; for (const b of sourceForPayees) { for (const g of b.groups) { const key = g.group_key || "Unknown"; const amt = g?.[flow]?.sum || 0; payeeMap[key] = (payeeMap[key] || 0) + amt; } } const topPayees = Object.entries(payeeMap) // .filter(([name]) => name !== "Unknown") .map(([payeeName, amount]) => ({ payeeName, amount })) .sort((a, b) => b.amount - a.amount) .slice(0, 5); return { chartData, totalAmount, topPayees, }; }