compare shows +/- instead of full amounts for easier consumption
This commit is contained in:
@@ -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,37 +207,43 @@ 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>
|
||||||
|
|
||||||
<Typography
|
|
||||||
variant="caption"
|
|
||||||
color="text.secondary"
|
|
||||||
sx={{ fontSize: "0.7rem", display: "block" }}
|
|
||||||
>
|
|
||||||
{point.id}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<Typography
|
||||||
|
variant="caption"
|
||||||
|
color="text.secondary"
|
||||||
|
sx={{
|
||||||
|
mt: 1,
|
||||||
|
fontSize: "0.7rem",
|
||||||
|
textAlign: "center",
|
||||||
|
lineHeight: 1.2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{formatLabel(point.id, activeDataKey)}
|
||||||
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
Reference in New Issue
Block a user