compare shows +/- instead of full amounts for easier consumption
This commit is contained in:
@@ -5,8 +5,6 @@ export interface ChartDataPoint {
|
||||
id: string;
|
||||
amount: number;
|
||||
compareAmount?: number;
|
||||
count?: number;
|
||||
compareLabel?: string;
|
||||
highlighted?: boolean;
|
||||
}
|
||||
|
||||
@@ -32,12 +30,46 @@ export interface HistoryChartProps {
|
||||
setComparison: (mode: boolean) => void;
|
||||
}
|
||||
|
||||
export interface AggregatedDashboardData {
|
||||
chartData: ChartData;
|
||||
totalAmount: number;
|
||||
topPayees: Array<{ payeeName: string; amount: number }>;
|
||||
}
|
||||
const formatDisplay = (point: ChartDataPoint, tab: string) => {
|
||||
const base = point.amount;
|
||||
const cmp = point.compareAmount || 0;
|
||||
|
||||
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({
|
||||
header,
|
||||
@@ -52,9 +84,7 @@ export default function HistoryChart({
|
||||
const [activeTab, setActiveTab] = React.useState<string>(tabs[0] || "");
|
||||
|
||||
const handleTabChange = (_: React.MouseEvent<HTMLElement>, newTab: string | null) => {
|
||||
if (newTab !== null) {
|
||||
setActiveTab(newTab);
|
||||
}
|
||||
if (newTab !== null) setActiveTab(newTab);
|
||||
};
|
||||
|
||||
const activeDataKey = activeTab.toLowerCase() as keyof ChartData;
|
||||
@@ -80,24 +110,6 @@ export default function HistoryChart({
|
||||
)
|
||||
: 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 (
|
||||
<Paper
|
||||
sx={{
|
||||
@@ -119,38 +131,12 @@ export default function HistoryChart({
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
{/* Tabs */}
|
||||
<ToggleButtonGroup
|
||||
value={activeTab}
|
||||
exclusive
|
||||
onChange={handleTabChange}
|
||||
fullWidth
|
||||
sx={{
|
||||
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"
|
||||
}
|
||||
}
|
||||
}}
|
||||
sx={{ mb: 4 }}
|
||||
>
|
||||
{tabs.map((tab) => (
|
||||
<ToggleButton key={tab} value={tab}>
|
||||
@@ -159,7 +145,6 @@ export default function HistoryChart({
|
||||
))}
|
||||
</ToggleButtonGroup>
|
||||
|
||||
{/* Period Toggle */}
|
||||
<ToggleButtonGroup
|
||||
value={period}
|
||||
exclusive
|
||||
@@ -184,7 +169,6 @@ export default function HistoryChart({
|
||||
<ToggleButton value="on">Compare</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
|
||||
{/* Chart */}
|
||||
{currentData.length > 0 ? (
|
||||
<Box sx={{ display: "flex", alignItems: "flex-end", height: 220, mt: 4 }}>
|
||||
{currentData.map((point) => {
|
||||
@@ -203,29 +187,15 @@ export default function HistoryChart({
|
||||
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
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "flex-end",
|
||||
gap: comparison ? 0.5 : 0,
|
||||
height: "100%"
|
||||
height: "100%",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
{/* Compare */}
|
||||
{comparison && (
|
||||
<Box
|
||||
sx={{
|
||||
@@ -237,37 +207,43 @@ export default function HistoryChart({
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Current */}
|
||||
<Box
|
||||
sx={{
|
||||
width: 10,
|
||||
height: `${currentHeight}%`,
|
||||
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
|
||||
variant="caption"
|
||||
color="text.secondary"
|
||||
sx={{ fontSize: "0.6rem", display: "block" }}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: -18,
|
||||
left: "50%",
|
||||
transform: "translateX(-50%)",
|
||||
fontSize: "0.65rem",
|
||||
whiteSpace: "nowrap"
|
||||
}}
|
||||
>
|
||||
{point.compareLabel}
|
||||
{formatDisplay(point, activeTab.toLowerCase())}
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
<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>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user