compare shows +/- instead of full amounts for easier consumption

This commit is contained in:
2026-04-07 11:06:24 +05:30
parent 6602d29299
commit b587f8aeb6

View File

@@ -5,8 +5,6 @@ export interface ChartDataPoint {
id: string; id: string;
amount: number; amount: number;
compareAmount?: number; compareAmount?: number;
count?: number;
compareLabel?: string;
highlighted?: boolean; highlighted?: boolean;
} }
@@ -32,12 +30,46 @@ export interface HistoryChartProps {
setComparison: (mode: boolean) => void; setComparison: (mode: boolean) => void;
} }
export interface AggregatedDashboardData { const formatDisplay = (point: ChartDataPoint, tab: string) => {
chartData: ChartData; const base = point.amount;
totalAmount: number; const cmp = point.compareAmount || 0;
topPayees: Array<{ payeeName: string; amount: number }>;
const diff = base - cmp;
const sign = diff >= 0 ? "+" : "-";
const absDiff = Math.abs(diff);
const formatShort = (val: number) => {
if (tab === "monthly") {
if (val >= 100000) return `${(val / 100000).toFixed(2)}L`;
}
if (tab === "weekly") {
if (val >= 1000) return `${(val / 1000).toFixed(1)}K`;
}
return val.toLocaleString("en-IN");
};
if (!cmp) return `${formatShort(base)}`;
return `${formatShort(base)} (${sign}${formatShort(absDiff)})`;
};
const formatLabel = (label: string, type: string) => {
if (type === "monthly") return label;
if (type === "weekly") {
const parts = label.split(" - ");
if (parts.length === 2) {
const [start, end] = parts;
const startDay = start.split(" ")[0];
const endParts = end.split(" ");
const endDay = endParts[0];
const month = endParts[1];
return `${startDay}${endDay} ${month}`;
}
} }
return label;
};
export default function HistoryChart({ export default function HistoryChart({
header, header,
@@ -52,9 +84,7 @@ export default function HistoryChart({
const [activeTab, setActiveTab] = React.useState<string>(tabs[0] || ""); const [activeTab, setActiveTab] = React.useState<string>(tabs[0] || "");
const handleTabChange = (_: React.MouseEvent<HTMLElement>, newTab: string | null) => { const handleTabChange = (_: React.MouseEvent<HTMLElement>, newTab: string | null) => {
if (newTab !== null) { if (newTab !== null) setActiveTab(newTab);
setActiveTab(newTab);
}
}; };
const activeDataKey = activeTab.toLowerCase() as keyof ChartData; const activeDataKey = activeTab.toLowerCase() as keyof ChartData;
@@ -80,24 +110,6 @@ export default function HistoryChart({
) )
: 1; : 1;
const formatAmount = (amount: number) => {
const tab = activeTab.toLowerCase();
if (amount === 0) return "";
if (tab === "monthly") {
if (amount >= 100000) return `${(amount / 100000).toFixed(2)} L`;
return `${amount.toLocaleString("en-IN")}`;
}
if (tab === "weekly") {
if (amount >= 1000) return `${(amount / 1000).toFixed(1)} K`;
return `${amount.toLocaleString("en-IN")}`;
}
return `${amount.toLocaleString("en-IN")}`;
};
return ( return (
<Paper <Paper
sx={{ sx={{
@@ -119,38 +131,12 @@ export default function HistoryChart({
</Typography> </Typography>
)} )}
{/* Tabs */}
<ToggleButtonGroup <ToggleButtonGroup
value={activeTab} value={activeTab}
exclusive exclusive
onChange={handleTabChange} onChange={handleTabChange}
fullWidth fullWidth
sx={{ sx={{ mb: 4 }}
mb: 4,
bgcolor: (theme) =>
theme.palette.mode === "dark"
? "rgba(255,255,255,0.05)"
: "rgba(0,0,0,0.02)",
borderRadius: 8,
p: 0.5,
"& .MuiToggleButton-root": {
border: "none",
borderRadius: 8,
textTransform: "capitalize",
fontWeight: 600,
color: "text.secondary",
"&.Mui-selected": {
bgcolor: (theme) =>
theme.palette.mode === "dark"
? "primary.dark"
: "primary.light",
color: (theme) =>
theme.palette.mode === "dark"
? "primary.contrastText"
: "primary.main"
}
}
}}
> >
{tabs.map((tab) => ( {tabs.map((tab) => (
<ToggleButton key={tab} value={tab}> <ToggleButton key={tab} value={tab}>
@@ -159,7 +145,6 @@ export default function HistoryChart({
))} ))}
</ToggleButtonGroup> </ToggleButtonGroup>
{/* Period Toggle */}
<ToggleButtonGroup <ToggleButtonGroup
value={period} value={period}
exclusive exclusive
@@ -184,7 +169,6 @@ export default function HistoryChart({
<ToggleButton value="on">Compare</ToggleButton> <ToggleButton value="on">Compare</ToggleButton>
</ToggleButtonGroup> </ToggleButtonGroup>
{/* Chart */}
{currentData.length > 0 ? ( {currentData.length > 0 ? (
<Box sx={{ display: "flex", alignItems: "flex-end", height: 220, mt: 4 }}> <Box sx={{ display: "flex", alignItems: "flex-end", height: 220, mt: 4 }}>
{currentData.map((point) => { {currentData.map((point) => {
@@ -203,29 +187,15 @@ export default function HistoryChart({
height: "100%" height: "100%"
}} }}
> >
{/* Values */}
<Box sx={{ mb: 1, textAlign: "center" }}>
{comparison && point.compareAmount ? (
<Typography variant="caption" sx={{ fontSize: "0.6rem", color: "text.secondary" }}>
{formatAmount(point.compareAmount)}
</Typography>
) : null}
<Typography variant="caption" sx={{ fontSize: "0.65rem" }}>
{formatAmount(point.amount)}
</Typography>
</Box>
{/* Bars */}
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "flex-end", alignItems: "flex-end",
gap: comparison ? 0.5 : 0, gap: comparison ? 0.5 : 0,
height: "100%" height: "100%",
position: "relative"
}} }}
> >
{/* Compare */}
{comparison && ( {comparison && (
<Box <Box
sx={{ sx={{
@@ -237,38 +207,44 @@ export default function HistoryChart({
/> />
)} )}
{/* Current */}
<Box <Box
sx={{ sx={{
width: 10, width: 10,
height: `${currentHeight}%`, height: `${currentHeight}%`,
bgcolor: point.highlighted ? "error.main" : "primary.main", bgcolor: point.highlighted ? "error.main" : "primary.main",
borderRadius: 2 borderRadius: 2,
position: "relative"
}} }}
/> >
</Box>
{/* Label */}
<Box sx={{ mt: 1, textAlign: "center" }}>
{comparison && point.compareLabel && (
<Typography <Typography
variant="caption" variant="caption"
color="text.secondary" sx={{
sx={{ fontSize: "0.6rem", display: "block" }} position: "absolute",
top: -18,
left: "50%",
transform: "translateX(-50%)",
fontSize: "0.65rem",
whiteSpace: "nowrap"
}}
> >
{point.compareLabel} {formatDisplay(point, activeTab.toLowerCase())}
</Typography> </Typography>
)} </Box>
</Box>
<Typography <Typography
variant="caption" variant="caption"
color="text.secondary" color="text.secondary"
sx={{ fontSize: "0.7rem", display: "block" }} sx={{
mt: 1,
fontSize: "0.7rem",
textAlign: "center",
lineHeight: 1.2
}}
> >
{point.id} {formatLabel(point.id, activeDataKey)}
</Typography> </Typography>
</Box> </Box>
</Box>
); );
})} })}
</Box> </Box>