dashboard fixes
This commit is contained in:
@@ -1,26 +1,53 @@
|
||||
import * as React from "react";
|
||||
import { Box, Container, Grid, Typography, Avatar, CircularProgress, Alert } from "@mui/material";
|
||||
import {
|
||||
Box,
|
||||
Container,
|
||||
Grid,
|
||||
Typography,
|
||||
CircularProgress,
|
||||
Alert,
|
||||
ToggleButton,
|
||||
ToggleButtonGroup
|
||||
} from "@mui/material";
|
||||
|
||||
import LatestItemsList, { LatestItem } from "./components/LatestItemsList";
|
||||
import ProgressCard from "./components/ProgressCard";
|
||||
import HistoryChart from "./components/HistoryChart";
|
||||
import { fetchLatestExpenses, fetchAggregatedExpenses, AggregatedDashboardData } from "./utils/dashboardLoader";
|
||||
|
||||
import {
|
||||
fetchLatestExpenses,
|
||||
fetchAggregatedExpenses,
|
||||
fetchAggregatedIncome,
|
||||
AggregatedDashboardData
|
||||
} from "./utils/dashboardLoader";
|
||||
|
||||
export default function Dashboard() {
|
||||
const [latest, setLatest] = React.useState<LatestItem[]>([]);
|
||||
const [aggregated, setAggregated] = React.useState<AggregatedDashboardData | null>(null);
|
||||
const [aggregated, setAggregated] =
|
||||
React.useState<AggregatedDashboardData | null>(null);
|
||||
|
||||
const [mode, setMode] =
|
||||
React.useState<"expense" | "income">("expense");
|
||||
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
|
||||
// -------- LOAD DATA --------
|
||||
React.useEffect(() => {
|
||||
async function loadData() {
|
||||
try {
|
||||
setLoading(true);
|
||||
const [latestData, aggData] = await Promise.all([
|
||||
fetchLatestExpenses(),
|
||||
fetchAggregatedExpenses()
|
||||
]);
|
||||
|
||||
const latestData = await fetchLatestExpenses();
|
||||
|
||||
const aggData =
|
||||
mode === "expense"
|
||||
? await fetchAggregatedExpenses()
|
||||
: await fetchAggregatedIncome();
|
||||
|
||||
setLatest(latestData);
|
||||
setAggregated(aggData);
|
||||
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
setError(err.message || "Failed to load dashboard data");
|
||||
@@ -28,12 +55,14 @@ export default function Dashboard() {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
loadData();
|
||||
}, []);
|
||||
|
||||
loadData();
|
||||
}, [mode]);
|
||||
|
||||
// -------- UI STATES --------
|
||||
if (loading) {
|
||||
return (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '60vh' }}>
|
||||
<Box sx={{ display: "flex", justifyContent: "center", alignItems: "center", height: "60vh" }}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
);
|
||||
@@ -51,57 +80,38 @@ export default function Dashboard() {
|
||||
|
||||
return (
|
||||
<Container maxWidth="xl" sx={{ mt: 4, mb: 4 }}>
|
||||
{/* -------- TOGGLE -------- */}
|
||||
<Box sx={{ display: "flex", justifyContent: "center", mb: 3 }}>
|
||||
<ToggleButtonGroup
|
||||
value={mode}
|
||||
exclusive
|
||||
onChange={(_, val) => val && setMode(val)}
|
||||
>
|
||||
<ToggleButton value="expense">Expenses</ToggleButton>
|
||||
<ToggleButton value="income">Income</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
</Box>
|
||||
|
||||
<Grid container spacing={4}>
|
||||
{/* Column 1: Latest Transactions */}
|
||||
{/* Column 1 */}
|
||||
<Grid item xs={12} md={4}>
|
||||
<LatestItemsList
|
||||
title="Recent Transactions"
|
||||
items={latest}
|
||||
onViewAll={() => {}}
|
||||
<LatestItemsList
|
||||
title="Recent Transactions"
|
||||
items={latest}
|
||||
onViewAll={() => {}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
{/* Column 2: Breakdown Graph */}
|
||||
<Grid item xs={12} md={4}>
|
||||
<Box sx={{ mb: 4, display: 'flex', justifyContent: 'center', visibility: 'hidden' }}>
|
||||
<Typography variant="h6">Spacer</Typography>
|
||||
</Box>
|
||||
{/* Column 2 */}
|
||||
<Grid item xs={12} md={8}>
|
||||
<HistoryChart
|
||||
header="Expense Breakdown"
|
||||
header={`${mode === "expense" ? "Expense" : "Income"} Breakdown`}
|
||||
summary="Interactive chronological tracking"
|
||||
tabs={["Today", "Week", "Month", "Year"]}
|
||||
data={aggregated?.chartData || {}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
{/* Column 3: Top Payees Progress */}
|
||||
<Grid item xs={12} md={4}>
|
||||
<Box sx={{ mb: 4, display: 'flex', justifyContent: 'center' }}>
|
||||
<Typography variant="h6" fontWeight={700}>Top Analytics</Typography>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ mb: 4 }}>
|
||||
<ProgressCard
|
||||
header="Total Expenses"
|
||||
progressAmount={aggregated?.totalAmount || 0}
|
||||
totalAmount={aggregated?.totalAmount || 0}
|
||||
summary={`Rs ${aggregated?.totalAmount || 0}`}
|
||||
colorTheme="error" // Highlight total in red/error or use info
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Typography variant="h6" fontWeight={600} mb={2} px={1}>Top 5 Payees</Typography>
|
||||
{aggregated?.topPayees.map((payee, idx) => (
|
||||
<Box sx={{ mb: 2 }} key={payee.payeeName}>
|
||||
<ProgressCard
|
||||
header={payee.payeeName}
|
||||
progressAmount={payee.amount}
|
||||
totalAmount={aggregated?.totalAmount || 1}
|
||||
colorTheme={themes[idx % themes.length]}
|
||||
/>
|
||||
</Box>
|
||||
))}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user