reading reportData instead of customized data. self massaging data for needed format

This commit is contained in:
2026-05-07 15:04:28 +05:30
parent 4b046c15a5
commit df5cf9fbb6
5 changed files with 189 additions and 134 deletions

View File

@@ -1,45 +1,179 @@
import * as React from "react";
import { ChartDataPoint, HistoryChartProps, ChartData } from "./HistoryChart.models";
import { HistoryChartProps, ChartDataPoint } from "./HistoryChart.models";
import HistoryChartView from "./HistoryChart.view";
import { ReportPeriod } from "../../features/report";
type DecoratedPeriod = ReportPeriod & {
id: string;
label: string;
};
const TAB_TO_KEY: Record<string, "weekly" | "monthly" | "yearly" | "fyly"> = {
Weekly: "weekly",
Monthly: "monthly",
Yearly: "yearly",
FYLY: "fyly"
};
function getAmount(p: ReportPeriod, mode: "expense" | "income") {
return mode === "expense" ? p.expenses.sum : p.incomes.sum;
}
function mergeMetric(a: any, b: any) {
const sum = a.sum + b.sum;
const count = a.count + b.count;
return {
...a,
sum,
count,
average: count > 0 ? sum / count : 0,
transactions: a.transactions || b.transactions
? [
...(a.transactions || []),
...(b.transactions || [])
]
: undefined
};
}
function mergeBuckets(
buckets: any[],
key: "weekly" | "monthly" | "yearly" | "fyly"
): DecoratedPeriod[] {
const map = new Map<string, DecoratedPeriod>();
for (const bucket of buckets) {
const periods = (bucket.periods[key] || []) as DecoratedPeriod[];
for (const p of periods) {
const existing = map.get(p.id);
if (!existing) {
map.set(p.id, {
...p,
expenses: { ...p.expenses },
incomes: { ...p.incomes }
});
} else {
map.set(p.id, {
...existing,
expenses: mergeMetric(existing.expenses, p.expenses),
incomes: mergeMetric(existing.incomes, p.incomes)
});
}
}
}
return Array.from(map.values()).sort(
(a, b) => new Date(a.start).getTime() - new Date(b.start).getTime()
);
}
function buildChartData(
reportData: HistoryChartProps["reportData"],
key: "weekly" | "monthly" | "yearly" | "fyly",
mode: "expense" | "income",
comparison: boolean
): ChartDataPoint[] {
const merged = mergeBuckets(reportData.buckets, key);
console.log("Merged periods:", merged);
let points: ChartDataPoint[] = merged.map((p) => ({
id: p.id,
label: p.label,
amount: getAmount(p, mode)
}));
if (comparison) {
points = points.map((p, i) => ({
...p,
compare:
i > 0
? {
id: points[i - 1].id,
label: points[i - 1].label,
amount: points[i - 1].amount
}
: undefined
}));
}
return points;
}
export default function HistoryChart(props: HistoryChartProps) {
const { tabs, data, mode, periodType, comparison } = props;
const {
tabs,
reportData,
mode,
periodType,
comparison,
selectedPeriodId,
setSelectedPeriodId
} = props;
const [activeTab, setActiveTab] = React.useState<string>(tabs[0] || "");
const [startIndex, setStartIndex] = React.useState(0);
const activeDataKey = activeTab.toLowerCase() as keyof ChartData;
const activeDataKey = TAB_TO_KEY[activeTab];
let rawData: ChartDataPoint[] = [];
const section = data[activeDataKey];
rawData = section?.[periodType] || [];
const currentData = rawData;
const currentData = React.useMemo(() => {
return buildChartData(reportData, activeDataKey, mode, comparison);
}, [reportData, activeDataKey, mode, comparison]);
const maxAmount =
currentData.length > 0
? Math.max(
...currentData.flatMap((d) =>
comparison ? [d.amount, d.compare?.amount ?? 0] : [d.amount]
comparison
? [d.amount, ...(d.compare ? [d.compare.amount] : [])]
: [d.amount]
),
1
)
: 1;
const visibleCountMap = { daily: 7, weekly: 6, monthly: 4 };
// const visibleCountMap = { daily: 7, weekly: 6, monthly: 4, yearly: 4, fyly: 4, full: 4 };
const visibleCount = visibleCountMap[activeDataKey];
const visibleCountMap = {
weekly: 6,
monthly: 4,
yearly: 4,
fyly: 4
};
const visibleCount = visibleCountMap[activeDataKey] ?? 4;
const total = currentData.length;
const clampedStartIndex = Math.min(startIndex, Math.max(total - visibleCount, 0));
const clampedStartIndex = Math.min(
startIndex,
Math.max(total - visibleCount, 0)
);
React.useEffect(() => {
if (startIndex !== clampedStartIndex) {
setStartIndex(clampedStartIndex);
}
}, [startIndex, clampedStartIndex]);
const visibleData = currentData.slice(
clampedStartIndex,
clampedStartIndex + visibleCount
);
React.useEffect(() => {
setSelectedPeriodId(null);
}, [activeTab, periodType]);
React.useEffect(() => {
if (
selectedPeriodId &&
!visibleData.some((p) => p.id === selectedPeriodId)
) {
setSelectedPeriodId(null);
}
}, [visibleData, selectedPeriodId]);
return (
<HistoryChartView
{...props}
@@ -49,7 +183,7 @@ export default function HistoryChart(props: HistoryChartProps) {
visibleData={visibleData}
maxAmount={maxAmount}
visibleCount={visibleCount}
startIndex={startIndex}
startIndex={clampedStartIndex}
setStartIndex={setStartIndex}
activeDataKey={activeDataKey}
/>