131 lines
4.2 KiB
TypeScript
131 lines
4.2 KiB
TypeScript
import * as React from "react";
|
|
import { Box, Typography, ToggleButtonGroup, ToggleButton, Paper } from "@mui/material";
|
|
|
|
export interface ChartDataPoint {
|
|
id: string;
|
|
amount: number;
|
|
count?: number;
|
|
highlighted?: boolean;
|
|
}
|
|
|
|
export interface HistoryChartProps {
|
|
header: string;
|
|
summary?: string;
|
|
tabs: string[];
|
|
data: Record<string, ChartDataPoint[]>;
|
|
}
|
|
|
|
export default function HistoryChart({
|
|
header,
|
|
summary,
|
|
tabs,
|
|
data,
|
|
}: HistoryChartProps) {
|
|
const [activeTab, setActiveTab] = React.useState<string>(tabs[0] || "");
|
|
|
|
const handleTabChange = (_: React.MouseEvent<HTMLElement>, newTab: string | null) => {
|
|
if (newTab !== null) {
|
|
setActiveTab(newTab);
|
|
}
|
|
};
|
|
|
|
const activeDataKey = activeTab.toLowerCase();
|
|
const currentData = data[activeDataKey] || data[activeTab] || [];
|
|
|
|
const maxAmount = Math.max(...currentData.map((d) => d.amount), 1);
|
|
|
|
return (
|
|
<Paper sx={{ p: { xs: 2, sm: 4 }, borderRadius: 4, width: "100%", boxShadow: 'none', border: '1px solid', borderColor: 'divider' }}>
|
|
<Typography variant="h6" fontWeight={700} gutterBottom>
|
|
{header}
|
|
</Typography>
|
|
{summary && (
|
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
|
|
{summary}
|
|
</Typography>
|
|
)}
|
|
|
|
<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',
|
|
boxShadow: '0 2px 8px rgba(0,0,0,0.05)',
|
|
},
|
|
},
|
|
}}
|
|
>
|
|
{tabs.map((tab) => (
|
|
<ToggleButton key={tab} value={tab}>
|
|
{tab}
|
|
</ToggleButton>
|
|
))}
|
|
</ToggleButtonGroup>
|
|
|
|
{/* Chart Area */}
|
|
{currentData.length > 0 ? (
|
|
<Box sx={{ display: "flex", alignItems: "flex-end", height: 200, mt: 4, position: 'relative' }}>
|
|
{currentData.map((point) => {
|
|
const heightPerc = (point.amount / maxAmount) * 100;
|
|
return (
|
|
<Box
|
|
key={point.id}
|
|
sx={{
|
|
flex: 1,
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
alignItems: "center",
|
|
justifyContent: "flex-end",
|
|
height: "100%",
|
|
}}
|
|
>
|
|
<Typography variant="caption" sx={{ mb: 1, opacity: 0.7, fontSize: '0.65rem', display: { xs: 'none', sm: 'block' } }}>
|
|
{point.amount > 0 ? `Rs ${point.amount}` : ''}
|
|
</Typography>
|
|
|
|
<Box
|
|
sx={{
|
|
width: "40%",
|
|
minWidth: 12,
|
|
maxWidth: 32,
|
|
height: `${heightPerc}%`,
|
|
minHeight: "4px",
|
|
bgcolor: point.highlighted ? "error.main" : "grey.300",
|
|
borderRadius: 4,
|
|
transition: "height 0.5s cubic-bezier(0.4, 0, 0.2, 1)",
|
|
...(point.highlighted && {
|
|
boxShadow: (theme) => `0 4px 12px ${theme.palette.error.main}40`,
|
|
}),
|
|
}}
|
|
/>
|
|
|
|
<Typography variant="caption" color="text.secondary" sx={{ mt: 1, fontWeight: 500, fontSize: '0.7rem' }}>
|
|
{point.id}
|
|
</Typography>
|
|
</Box>
|
|
);
|
|
})}
|
|
</Box>
|
|
) : (
|
|
<Box sx={{ height: 200, display: "flex", alignItems: "center", justifyContent: "center" }}>
|
|
<Typography color="text.secondary">No Data Available</Typography>
|
|
</Box>
|
|
)}
|
|
</Paper>
|
|
);
|
|
}
|