state controlled by Dashboard.models.ts
This commit is contained in:
@@ -11,9 +11,7 @@ import { configuration } from "./dashboard-config";
|
|||||||
import { useDashboardData } from "./features/dashboard";
|
import { useDashboardData } from "./features/dashboard";
|
||||||
|
|
||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
const [mode, setMode] = React.useState<"expense" | "income">("expense");
|
const { data, isLoading, error } = useDashboardData();
|
||||||
const [selectedPeriodId, setSelectedPeriodId] = React.useState<string | null>(null);
|
|
||||||
const { data, isLoading, error } = useDashboardData(mode);
|
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
@@ -39,9 +37,6 @@ export default function Dashboard() {
|
|||||||
<ConfigurableDashboard
|
<ConfigurableDashboard
|
||||||
config={configuration}
|
config={configuration}
|
||||||
data={data}
|
data={data}
|
||||||
onModeChange={(newMode) => setMode(newMode)}
|
|
||||||
selectedPeriodId={selectedPeriodId}
|
|
||||||
onSelectPeriodId={(newPeriodId) => setSelectedPeriodId(newPeriodId)}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ import * as React from "react";
|
|||||||
|
|
||||||
export type DashboardMode = "expense" | "income";
|
export type DashboardMode = "expense" | "income";
|
||||||
export type DashboardPeriodType = "rolling" | "calendar";
|
export type DashboardPeriodType = "rolling" | "calendar";
|
||||||
|
export type DashboardSelectedPeriodId = string | null;
|
||||||
|
|
||||||
export interface DashboardState {
|
export interface DashboardState {
|
||||||
mode: DashboardMode;
|
mode: DashboardMode;
|
||||||
periodType: DashboardPeriodType;
|
periodType: DashboardPeriodType;
|
||||||
|
selectedPeriodId: DashboardSelectedPeriodId;
|
||||||
comparison: boolean;
|
comparison: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,8 +45,8 @@ export interface DashboardConfig {
|
|||||||
|
|
||||||
export interface DashboardProps {
|
export interface DashboardProps {
|
||||||
config: DashboardConfig;
|
config: DashboardConfig;
|
||||||
data: any; // Aggregated data from features
|
data: any;
|
||||||
onModeChange?: (mode: DashboardMode) => void;
|
toggleMode: () => void;
|
||||||
selectedPeriodId: string | null;
|
togglePeriodType: () => void;
|
||||||
onSelectPeriodId: (id: string | null) => void;
|
setSelectedPeriodId: (id: string | null) => void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,36 @@ export default function Dashboard(props: DashboardProps) {
|
|||||||
const [state, setState] = React.useState<DashboardState>({
|
const [state, setState] = React.useState<DashboardState>({
|
||||||
mode: "expense",
|
mode: "expense",
|
||||||
periodType: "rolling",
|
periodType: "rolling",
|
||||||
|
selectedPeriodId: null,
|
||||||
comparison: false,
|
comparison: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const toggleMode = () => {
|
||||||
|
setState(prev => ({
|
||||||
|
...prev,
|
||||||
|
mode: prev.mode === "expense" ? "income" : "expense",
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const togglePeriodType = () => {
|
||||||
|
setState(prev => ({
|
||||||
|
...prev,
|
||||||
|
periodType: prev.periodType === "rolling" ? "calendar" : "rolling",
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const setSelectedPeriodId = (selectedPeriodId: typeof state.selectedPeriodId) => {
|
||||||
|
setState(prev => ({ ...prev, selectedPeriodId }));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardView
|
<DashboardView
|
||||||
{...props}
|
{...props}
|
||||||
state={state}
|
state={state}
|
||||||
setState={setState}
|
setState={setState}
|
||||||
|
toggleMode={toggleMode}
|
||||||
|
togglePeriodType={togglePeriodType}
|
||||||
|
setSelectedPeriodId={setSelectedPeriodId}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,15 @@ interface ViewProps extends DashboardProps {
|
|||||||
export default function DashboardView({
|
export default function DashboardView({
|
||||||
config,
|
config,
|
||||||
data,
|
data,
|
||||||
latest,
|
|
||||||
state,
|
state,
|
||||||
setState,
|
setState,
|
||||||
onModeChange,
|
toggleMode,
|
||||||
selectedPeriodId,
|
togglePeriodType,
|
||||||
onSelectPeriodId,
|
setSelectedPeriodId,
|
||||||
}: ViewProps) {
|
}: ViewProps) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const themeMode = theme.palette.mode;
|
const themeMode = theme.palette.mode;
|
||||||
const { mode, periodType, comparison } = state;
|
const { mode, periodType, selectedPeriodId, comparison } = state;
|
||||||
|
|
||||||
// Resolve colors with fallbacks
|
// Resolve colors with fallbacks
|
||||||
const colors = React.useMemo(() => {
|
const colors = React.useMemo(() => {
|
||||||
@@ -51,13 +50,6 @@ export default function DashboardView({
|
|||||||
};
|
};
|
||||||
}, [config.style?.palette, mode, themeMode, theme.palette]);
|
}, [config.style?.palette, mode, themeMode, theme.palette]);
|
||||||
|
|
||||||
const handleModeChange = (_: any, newMode: any) => {
|
|
||||||
if (newMode && onModeChange) {
|
|
||||||
onModeChange(newMode);
|
|
||||||
setState(prev => ({ ...prev, mode: newMode }));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
sx={{
|
sx={{
|
||||||
@@ -73,7 +65,7 @@ export default function DashboardView({
|
|||||||
<ToggleButtonGroup
|
<ToggleButtonGroup
|
||||||
value={mode}
|
value={mode}
|
||||||
exclusive
|
exclusive
|
||||||
onChange={handleModeChange}
|
onChange={toggleMode}
|
||||||
sx={{
|
sx={{
|
||||||
borderRadius: 3,
|
borderRadius: 3,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
@@ -137,7 +129,6 @@ export default function DashboardView({
|
|||||||
header={section.title}
|
header={section.title}
|
||||||
summary={section.summary}
|
summary={section.summary}
|
||||||
data={section.dataKey ? data[section.dataKey] : data.chartData}
|
data={section.dataKey ? data[section.dataKey] : data.chartData}
|
||||||
items={section.dataKey === 'latest' ? latest : (data[section.dataKey || ''] || [])}
|
|
||||||
title={section.title}
|
title={section.title}
|
||||||
accentColor={colors.primary}
|
accentColor={colors.primary}
|
||||||
colorScheme={colors}
|
colorScheme={colors}
|
||||||
@@ -146,7 +137,7 @@ export default function DashboardView({
|
|||||||
comparison={comparison}
|
comparison={comparison}
|
||||||
setComparison={(c: any) => setState(prev => ({ ...prev, comparison: c }))}
|
setComparison={(c: any) => setState(prev => ({ ...prev, comparison: c }))}
|
||||||
selectedPeriodId={selectedPeriodId}
|
selectedPeriodId={selectedPeriodId}
|
||||||
onSelectPeriodId={onSelectPeriodId}
|
onSelectPeriodId={setSelectedPeriodId}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useReport } from "../report";
|
import { useReport } from "../report";
|
||||||
import { mapReportToDashboard } from "./dashboard.mapper";
|
import { mapReportToDashboard } from "./dashboard.mapper";
|
||||||
|
|
||||||
export function useDashboardData(type: "expense" | "income") {
|
export function useDashboardData() {
|
||||||
// Fetch reports for aggregation
|
// Fetch reports for aggregation
|
||||||
const weeklyReport = useReport({ period: "weekly", rolling: true });
|
const weeklyReport = useReport({ period: "weekly", rolling: true });
|
||||||
const monthlyReport = useReport({ period: "monthly", rolling: true });
|
const monthlyReport = useReport({ period: "monthly", rolling: true });
|
||||||
@@ -17,15 +17,24 @@ export function useDashboardData(type: "expense" | "income") {
|
|||||||
monthlyReport.error ||
|
monthlyReport.error ||
|
||||||
payeeReport.error;
|
payeeReport.error;
|
||||||
|
|
||||||
const aggregatedData =
|
const aggregatedData = {
|
||||||
weeklyReport.data?.data && monthlyReport.data?.data && payeeReport.data?.data
|
expense: weeklyReport.data?.data && monthlyReport.data?.data && payeeReport.data?.data
|
||||||
? mapReportToDashboard(
|
? mapReportToDashboard(
|
||||||
(weeklyReport.data.data as any).buckets,
|
(weeklyReport.data.data as any).buckets,
|
||||||
(monthlyReport.data.data as any).buckets,
|
(monthlyReport.data.data as any).buckets,
|
||||||
(payeeReport.data.data as any).buckets,
|
(payeeReport.data.data as any).buckets,
|
||||||
type
|
"expense"
|
||||||
)
|
)
|
||||||
: null;
|
: null,
|
||||||
|
income: weeklyReport.data?.data && monthlyReport.data?.data && payeeReport.data?.data
|
||||||
|
? mapReportToDashboard(
|
||||||
|
(weeklyReport.data.data as any).buckets,
|
||||||
|
(monthlyReport.data.data as any).buckets,
|
||||||
|
(payeeReport.data.data as any).buckets,
|
||||||
|
"income"
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: aggregatedData,
|
data: aggregatedData,
|
||||||
|
|||||||
Reference in New Issue
Block a user