Files
khata-ui/src/components/Dashboard/Dashboard.view.tsx
Vishesh 'ironeagle' Bangotra 77b60ba073 items-by-period (#2)
Reviewed-on: #2
Co-authored-by: Vishesh 'ironeagle' Bangotra <aetoskia@gmail.com>
Co-committed-by: Vishesh 'ironeagle' Bangotra <aetoskia@gmail.com>
2026-05-09 13:00:42 +00:00

140 lines
4.1 KiB
TypeScript

import * as React from "react";
import {
Box,
Container,
Grid,
Typography,
ToggleButton,
ToggleButtonGroup
} from "@mui/material";
import { useTheme, alpha } from "@mui/material/styles";
import { GroupKey } from "../../features/report";
import { DashboardProps, DashboardState } from "./Dashboard.models";
interface ViewProps extends DashboardProps {
state: DashboardState;
setState: React.Dispatch<React.SetStateAction<DashboardState>>;
toggleMode: () => void;
togglePeriodType: () => void;
setSelectedPeriodId: (id: string | null) => void;
setSelectedGroupKey: (groupKey: GroupKey | null) => void;
toggleComparison: () => void;
}
export default function DashboardView({
config,
data,
state,
setState,
toggleMode,
togglePeriodType,
toggleComparison,
setSelectedPeriodId,
setSelectedGroupKey,
}: ViewProps) {
const theme = useTheme();
const themeMode = theme.palette.mode;
const { mode, periodType, comparison, selectedPeriodId, selectedGroupKey } = state;
// Resolve colors with fallbacks
const colors = React.useMemo(() => {
const palette = config.style?.palette?.[mode];
const modeColors = palette ? palette[themeMode] : null;
if (modeColors) {
return {
primary: modeColors.primary,
light: modeColors.background || alpha(modeColors.primary, 0.1),
text: modeColors.text || (themeMode === 'light' ? theme.palette.text.primary : '#fff')
};
}
// Fallback to standard theme colors
const themeColor = mode === 'expense' ? theme.palette.error : theme.palette.success;
return {
primary: themeColor.main,
light: alpha(themeColor.main, themeMode === 'light' ? 0.08 : 0.15),
text: themeColor.main
};
}, [config.style?.palette, mode, themeMode, theme.palette]);
return (
<Container
sx={{
mt: 4,
mb: 4,
background: `linear-gradient(180deg, ${colors.light} 0%, transparent 100%)`,
borderRadius: 4,
p: 2,
transition: 'background 0.3s ease'
}}
>
<Box sx={{ display: "flex", justifyContent: "center", mb: 3 }}>
<ToggleButtonGroup
value={mode}
exclusive
onChange={toggleMode}
sx={{
borderRadius: 3,
overflow: "hidden",
"& .MuiToggleButton-root": {
px: 3,
textTransform: "none",
color: "text.secondary"
},
"&.Mui-selected": {
bgcolor: colors.primary,
color: "white",
borderColor: colors.primary
},
}}
>
<ToggleButton value="expense">Expenses</ToggleButton>
<ToggleButton value="income">Income</ToggleButton>
</ToggleButtonGroup>
</Box>
<Grid container spacing={4}>
{config.sections.map((section) => {
const Component = section.component;
return (
<Grid key={section.id} size={section.style?.size || 12 as any}>
{section.title && !section.isList && (
<Box sx={{ mb: 2 }}>
<Typography variant="h6" fontWeight={700}>
{section.title}
</Typography>
</Box>
)}
<Component
{...section.settings}
header={section.title}
summary={section.summary}
reportData={data}
title={section.title}
accentColor={colors.primary}
colorScheme={colors}
// State management
mode={mode}
periodType={periodType}
comparison={comparison}
selectedPeriodId={selectedPeriodId}
selectedGroupKey={selectedGroupKey}
togglePeriodType={togglePeriodType}
toggleComparison={toggleComparison}
setSelectedPeriodId={setSelectedPeriodId}
setSelectedGroupKey={setSelectedGroupKey}
/>
</Grid>
);
})}
</Grid>
</Container>
);
}