Dashboard.view.tsx to handle rendering and Dashboard.tsx to handle state

This commit is contained in:
2026-05-19 18:51:59 +05:30
parent 7dd685ae49
commit 2a12e33e22
4 changed files with 151 additions and 93 deletions

View File

@@ -10,8 +10,14 @@ import {
Button
} from "@mui/material";
import ConfigurableDashboard from "./components/Dashboard";
import { DashboardState } from "./components/Dashboard";
import DashboardView from "./components/Dashboard";
import {
DashboardState,
DashboardStateSetters,
DashboardFlow,
} from "./components/Dashboard";
import { configuration } from "./dashboard-config";
import {
useReport,
@@ -19,7 +25,13 @@ import {
} from "./features/report";
export default function Dashboard() {
const [flow, setFlow] = React.useState<"outflows" | "inflows">("outflows");
const [state, setState] = React.useState<DashboardState>({
flow: "outflows",
periodType: "rolling",
selectedPeriodId: null,
selectedGroupKey: null,
comparison: false,
});
const [appliedPayees, setAppliedPayees] = React.useState<string[]>([]);
const [appliedTags, setAppliedTags] = React.useState<string[]>([]);
@@ -32,7 +44,7 @@ export default function Dashboard() {
const report = useReport({
periods: ["daily", "weekly", "monthly", "all"],
flow: flow,
flow: state.flow,
payee: appliedPayees.length > 0 ? appliedPayees : undefined,
tags: appliedTags.length > 0 ? appliedTags : undefined,
});
@@ -69,14 +81,124 @@ export default function Dashboard() {
}
}, [report.data?.data]);
const toggleFlow =
React.useCallback(() => {
setState((prev) => ({
...prev,
flow:
prev.flow ===
"outflows"
? "inflows"
: "outflows",
selectedGroupKey:
null,
selectedPeriodId:
null,
}));
}, []);
const setFlow =
React.useCallback(
(
flow: DashboardFlow
) => {
setState((prev) => ({
...prev,
flow,
selectedGroupKey:
null,
selectedPeriodId:
null,
}));
},
[]
);
const togglePeriodType =
React.useCallback(() => {
setState((prev) => ({
...prev,
periodType:
prev.periodType ===
"rolling"
? "calendar"
: "rolling",
}));
}, []);
const toggleComparison =
React.useCallback(() => {
setState((prev) => ({
...prev,
comparison:
!prev.comparison,
}));
}, []);
const setSelectedPeriodId =
React.useCallback(
(
selectedPeriodId: DashboardState["selectedPeriodId"]
) => {
setState((prev) => ({
...prev,
selectedPeriodId,
}));
},
[]
);
const setSelectedGroupKey =
React.useCallback(
(
selectedGroupKey: DashboardState["selectedGroupKey"]
) => {
setState((prev) => ({
...prev,
selectedGroupKey,
}));
},
[]
);
const stateSetters: DashboardStateSetters =
React.useMemo(
() => ({
toggleFlow,
setFlow,
togglePeriodType,
toggleComparison,
setSelectedPeriodId,
setSelectedGroupKey,
}),
[
toggleFlow,
setFlow,
togglePeriodType,
toggleComparison,
setSelectedPeriodId,
setSelectedGroupKey,
]
);
const isLoading = report.isLoading;
const error = report.error;
/** Callback for the ConfigurableDashboard's flow toggle */
const handleFlowChange = React.useCallback((newState: DashboardState) => {
setFlow(newState.flow);
}, []);
if (isLoading && !report.data) {
return (
<Box sx={{ display: "flex", justifyContent: "center", alignItems: "center", height: "60vh" }}>
@@ -143,8 +265,8 @@ export default function Dashboard() {
sx={{ '& .MuiOutlinedInput-root': { height: 'auto', minHeight: '2.5rem', py: 0.5 } }}
/>
</Box>
<Button
variant="contained"
<Button
variant="contained"
size="large"
onClick={() => {
setAppliedPayees(payeeInput);
@@ -157,11 +279,12 @@ export default function Dashboard() {
</Button>
</Paper>
</Container>
<ConfigurableDashboard
<DashboardView
config={configuration}
data={data}
state={state}
stateSetters={stateSetters}
isFetching={report.isFetching}
onFlowChange={handleFlowChange}
/>
</Box>
);

View File

@@ -50,11 +50,12 @@ export interface DashboardConfig {
};
}
export interface DashboardProps {
export interface DashboardViewProps {
config: DashboardConfig;
data: ReportData;
state: DashboardState;
stateSetters: DashboardStateSetters;
isFetching: boolean;
onFlowChange?: (state: DashboardState) => void;
}

View File

@@ -8,88 +8,22 @@ import {
Button
} from "@mui/material";
import { useTheme, alpha } from "@mui/material/styles";
import { DashboardProps, DashboardState, DashboardStateSetters, DashboardFlow } from "./Dashboard.models";
import { DashboardViewProps } from "./Dashboard.models";
export default function Dashboard({
export default function DashboardView({
config,
data,
state,
stateSetters,
isFetching,
onFlowChange,
}: DashboardProps) {
}: DashboardViewProps) {
const theme = useTheme();
const themeMode = theme.palette.mode;
const [state, setState] = React.useState<DashboardState>({
flow: "outflows",
periodType: "rolling",
selectedPeriodId: null,
selectedGroupKey: null,
comparison: false,
});
const toggleFlow = () => {
setState(prev => {
const nextFlow: DashboardFlow = prev.flow === "outflows" ? "inflows" : "outflows";
const nextState: DashboardState = {
...prev,
flow: nextFlow,
selectedGroupKey: null,
selectedPeriodId: null,
};
onFlowChange?.(nextState);
return nextState;
});
};
const handleFlowChange = (
_event: React.MouseEvent<HTMLElement>,
newFlow: DashboardFlow | null
) => {
if (newFlow !== null && newFlow !== state.flow) {
setState(prev => {
const nextState: DashboardState = {
...prev,
flow: newFlow,
selectedGroupKey: null,
selectedPeriodId: null,
};
onFlowChange?.(nextState);
return nextState;
});
}
};
const togglePeriodType = () => {
setState(prev => ({
...prev,
periodType: prev.periodType === "rolling" ? "calendar" : "rolling",
}));
};
const toggleComparison = () => {
setState(prev => ({
...prev,
comparison: !prev.comparison,
}));
};
const setSelectedPeriodId = (selectedPeriodId: typeof state.selectedPeriodId) => {
setState(prev => ({ ...prev, selectedPeriodId }));
};
const setSelectedGroupKey = (groupKey: typeof state.selectedGroupKey) => {
setState(prev => ({ ...prev, selectedGroupKey: groupKey }));
};
const stateSetters: DashboardStateSetters = {
togglePeriodType,
toggleComparison,
toggleFlow,
setSelectedPeriodId,
setSelectedGroupKey,
};
const { flow, selectedGroupKey } = state;
const {
flow,
selectedGroupKey,
} = state;
const colors = React.useMemo(() => {
const palette = config.style.palette[flow];
@@ -145,7 +79,7 @@ export default function Dashboard({
<ToggleButtonGroup
value={flow}
exclusive
onChange={handleFlowChange}
onChange={stateSetters.toggleFlow}
sx={{
borderRadius: 3,
overflow: "hidden",
@@ -169,7 +103,7 @@ export default function Dashboard({
<Button
size="small"
sx={{ mt: 1, textTransform: "none" }}
onClick={() => setSelectedGroupKey(null)}
onClick={() => stateSetters.setSelectedGroupKey(null)}
>
Clear Drill-down
</Button>

View File

@@ -1,2 +1,2 @@
export { default } from "./Dashboard";
export { default } from "./Dashboard.view";
export * from "./Dashboard.models";