diff --git a/src/features/report/index.ts b/src/features/report/index.ts index f037c04..64a342d 100644 --- a/src/features/report/index.ts +++ b/src/features/report/index.ts @@ -1,3 +1,13 @@ export { useReport } from './useReport' +export type { + Transaction, + PeriodData, + PeriodGroup, + Period, + ReportData, +} from './report.models' +export { + prepareReport +} from './report.utils' diff --git a/src/features/report/report.mapper.ts b/src/features/report/report.mapper.ts deleted file mode 100644 index 33a738d..0000000 --- a/src/features/report/report.mapper.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { - AggregatedDashboardData, - ChartData, - ChartDataPoint, -} from "../../components/HistoryChart"; - -type ReportBucket = any; - -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" -): AggregatedDashboardData { - const flow = type === "expense" ? "expenses" : "incomes"; - - const chartData: ChartData = { - daily: [], - - 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, - }; -} diff --git a/src/features/report/useReport.ts b/src/features/report/useReport.ts index ad7a1e2..e7e501d 100644 --- a/src/features/report/useReport.ts +++ b/src/features/report/useReport.ts @@ -1,14 +1,18 @@ import { useResourceByName } from "../../../react-openapi"; export interface ReportParams { - period: "weekly" | "monthly" | "yearly" | "fyly"; + period: "weekly" | "monthly" | "yearly" | "fyly" | "full"; rolling?: boolean; report_date?: string; - group_by?: ("flow" | "payee" | "tags")[]; + group_by?: ("payee" | "tags")[]; ignore_self?: boolean; } export function useReport(params: ReportParams) { const { useList } = useResourceByName("reports"); + if (params.group_by) { + // @ts-ignore + params.group_by = params.group_by[0] + } return useList(params); } \ No newline at end of file