Compare commits
3 Commits
69c9fd6bef
...
692d907ca5
| Author | SHA1 | Date | |
|---|---|---|---|
| 692d907ca5 | |||
| 15c2cce263 | |||
| 3704bd0c23 |
@@ -12,8 +12,8 @@ import {
|
|||||||
import LatestItemsList, { LatestItem } from "./components/LatestItemsList";
|
import LatestItemsList, { LatestItem } from "./components/LatestItemsList";
|
||||||
import HistoryChart from "./components/HistoryChart";
|
import HistoryChart from "./components/HistoryChart";
|
||||||
import {
|
import {
|
||||||
AggregatedDashboardData,
|
AggregatedDashboardData
|
||||||
} from "./components/HistoryChart";
|
} from "./types/historyChart";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
fetchLatestTransactions,
|
fetchLatestTransactions,
|
||||||
@@ -85,6 +85,13 @@ export default function Dashboard() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const currentData = aggregated[mode];
|
const currentData = aggregated[mode];
|
||||||
|
if (!currentData) {
|
||||||
|
return (
|
||||||
|
<Box sx={{ display: "flex", justifyContent: "center", alignItems: "center", height: "60vh" }}>
|
||||||
|
<CircularProgress />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
const currentLatest = latest[mode];
|
const currentLatest = latest[mode];
|
||||||
|
|
||||||
// -------- UI STATES --------
|
// -------- UI STATES --------
|
||||||
|
|||||||
@@ -101,10 +101,10 @@ export default function Header({
|
|||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
color="inherit"
|
color="inherit"
|
||||||
onClick={() => navigate("/dashboard")}
|
onClick={() => navigate("/admin")}
|
||||||
sx={{ textTransform: "none", fontWeight: 500 }}
|
sx={{ textTransform: "none", fontWeight: 500 }}
|
||||||
>
|
>
|
||||||
Dashboard
|
Admin
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
color="inherit"
|
color="inherit"
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export default function Home() {
|
|||||||
variant="contained"
|
variant="contained"
|
||||||
size="large"
|
size="large"
|
||||||
endIcon={<ArrowForwardIcon />}
|
endIcon={<ArrowForwardIcon />}
|
||||||
onClick={() => navigate("/admin")}
|
onClick={() => navigate("/dashboard")}
|
||||||
sx={{
|
sx={{
|
||||||
px: 4,
|
px: 4,
|
||||||
py: 1.5,
|
py: 1.5,
|
||||||
|
|||||||
@@ -1,35 +1,16 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Box, Typography, ToggleButtonGroup, ToggleButton, Paper } from "@mui/material";
|
import {
|
||||||
|
Box,
|
||||||
export interface ChartDataPoint {
|
Typography,
|
||||||
id: string;
|
ToggleButtonGroup,
|
||||||
amount: number;
|
ToggleButton,
|
||||||
compareAmount?: number;
|
Paper
|
||||||
compareLabel?: string;
|
} from "@mui/material";
|
||||||
highlighted?: boolean;
|
import {
|
||||||
}
|
ChartDataPoint,
|
||||||
|
HistoryChartProps,
|
||||||
export interface ChartSeries {
|
ChartData,
|
||||||
rolling: ChartDataPoint[];
|
} from "../types/historyChart";
|
||||||
calendar: ChartDataPoint[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ChartData {
|
|
||||||
daily: ChartDataPoint[];
|
|
||||||
weekly: ChartSeries;
|
|
||||||
monthly: ChartSeries;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HistoryChartProps {
|
|
||||||
header: string;
|
|
||||||
summary?: string;
|
|
||||||
tabs: string[];
|
|
||||||
data: ChartData;
|
|
||||||
period: "rolling" | "calendar";
|
|
||||||
onPeriodChange: (mode: "rolling" | "calendar") => void;
|
|
||||||
comparison: boolean;
|
|
||||||
setComparison: (mode: boolean) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatDisplay = (
|
const formatDisplay = (
|
||||||
point: ChartDataPoint,
|
point: ChartDataPoint,
|
||||||
@@ -181,7 +162,10 @@ export default function HistoryChart({
|
|||||||
<Box sx={{ display: "flex", alignItems: "flex-end", height: 220, mt: 4 }}>
|
<Box sx={{ display: "flex", alignItems: "flex-end", height: 220, mt: 4 }}>
|
||||||
{currentData.map((point) => {
|
{currentData.map((point) => {
|
||||||
const currentHeight = (point.amount / maxAmount) * 100;
|
const currentHeight = (point.amount / maxAmount) * 100;
|
||||||
const compareHeight = ((point.compareAmount || 0) / maxAmount) * 100;
|
const compareHeight = comparison
|
||||||
|
? ((point.compareAmount || 0) / maxAmount) * 100
|
||||||
|
: 0;
|
||||||
|
const labelHeight = Math.max(currentHeight, compareHeight);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@@ -204,6 +188,22 @@ export default function HistoryChart({
|
|||||||
position: "relative"
|
position: "relative"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<Typography
|
||||||
|
variant="caption"
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
bottom: `${labelHeight}%`,
|
||||||
|
left: "50%",
|
||||||
|
transform: "translate(-50%, -6px)",
|
||||||
|
fontSize: "0.65rem",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
pointerEvents: "none"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{formatDisplay(point, activeTab.toLowerCase(), comparison)}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{/* Compare */}
|
||||||
{comparison && (
|
{comparison && (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@@ -215,29 +215,18 @@ export default function HistoryChart({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Spacer */}
|
||||||
|
<Box sx={{ width: 4 }} />
|
||||||
|
|
||||||
|
{/* Current */}
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
width: 10,
|
width: 10,
|
||||||
height: `${currentHeight}%`,
|
height: `${currentHeight}%`,
|
||||||
bgcolor: point.highlighted ? "error.main" : "primary.main",
|
bgcolor: point.highlighted ? "error.main" : "primary.main",
|
||||||
borderRadius: 2,
|
borderRadius: 2
|
||||||
position: "relative"
|
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
<Typography
|
|
||||||
variant="caption"
|
|
||||||
sx={{
|
|
||||||
position: "absolute",
|
|
||||||
top: -18,
|
|
||||||
left: "50%",
|
|
||||||
transform: "translateX(-50%)",
|
|
||||||
fontSize: "0.65rem",
|
|
||||||
whiteSpace: "nowrap"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{formatDisplay(point, activeTab.toLowerCase(), comparison)}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
36
src/types/historyChart.ts
Normal file
36
src/types/historyChart.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
export interface ChartDataPoint {
|
||||||
|
id: string;
|
||||||
|
amount: number;
|
||||||
|
compareAmount?: number;
|
||||||
|
compareLabel?: string;
|
||||||
|
highlighted?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ChartSeries {
|
||||||
|
rolling: ChartDataPoint[];
|
||||||
|
calendar: ChartDataPoint[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ChartData {
|
||||||
|
daily: ChartDataPoint[];
|
||||||
|
weekly: ChartSeries;
|
||||||
|
monthly: ChartSeries;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AggregatedDashboardData {
|
||||||
|
chartData: ChartData;
|
||||||
|
totalAmount: number;
|
||||||
|
topPayees: Array<{ payeeName: string; amount: number }>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HistoryChartProps {
|
||||||
|
header: string;
|
||||||
|
summary?: string;
|
||||||
|
tabs: string[];
|
||||||
|
data: ChartData;
|
||||||
|
period: "rolling" | "calendar";
|
||||||
|
onPeriodChange: (mode: "rolling" | "calendar") => void;
|
||||||
|
comparison: boolean;
|
||||||
|
setComparison: (mode: boolean) => void;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user