Display global statistics

This commit is contained in:
2025-05-02 10:01:22 +02:00
parent 16ef1147fe
commit 272c8ab312
8 changed files with 170 additions and 6 deletions

View File

@ -0,0 +1,22 @@
import { APIClient } from "./ApiClient";
export interface GlobalStats {
global_balance: number;
number_movements: number;
number_files: number;
total_files_size: number;
}
export class StatsApi {
/**
* Get global statistics
*/
static async GetGlobal(): Promise<GlobalStats> {
return (
await APIClient.exec({
uri: `/stats/global`,
method: "GET",
})
).data;
}
}

View File

@ -1,7 +1,103 @@
import { useAccounts } from "../hooks/AccountsListProvider";
import FunctionsIcon from "@mui/icons-material/Functions";
import RefreshIcon from "@mui/icons-material/Refresh";
import { Grid, IconButton, Paper, Tooltip, Typography } from "@mui/material";
import React from "react";
import { GlobalStats, StatsApi } from "../api/StatsApi";
import { AsyncWidget } from "../widgets/AsyncWidget";
import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer";
import ImportExportIcon from "@mui/icons-material/ImportExport";
import FolderCopyIcon from "@mui/icons-material/FolderCopy";
import ScaleIcon from "@mui/icons-material/Scale";
import { filesize } from "filesize";
import { AmountWidget } from "../widgets/AmountWidget";
export function HomeRoute(): React.ReactElement {
const accounts = useAccounts();
console.log(accounts.list.list);
return <>home authenticated todo</>;
const loadKey = React.useRef(1);
const [global, setGlobal] = React.useState<GlobalStats | undefined>();
const load = async () => {
setGlobal(await StatsApi.GetGlobal());
};
const reload = async () => {
loadKey.current += 1;
setGlobal(undefined);
};
return (
<MoneyMgrWebRouteContainer
label={"Welcome to Money Manager"}
actions={
<Tooltip title="Refresh dashboard">
<IconButton onClick={reload}>
<RefreshIcon />
</IconButton>
</Tooltip>
}
>
<AsyncWidget
ready={global !== undefined}
loadKey={loadKey.current}
load={load}
errMsg="Failed to load statistics!"
build={() => <StatsDashboard global={global!} />}
/>
</MoneyMgrWebRouteContainer>
);
}
export function StatsDashboard(p: { global: GlobalStats }): React.ReactElement {
return (
<>
<Grid container spacing={2}>
{" "}
<StatTile
title="Global balance"
value={<AmountWidget amount={p.global.global_balance} />}
icon={<FunctionsIcon />}
/>
<StatTile
title="Number of movements"
value={p.global.number_movements}
icon={<ImportExportIcon />}
/>
<StatTile
title="Number of files"
value={p.global.number_files}
icon={<FolderCopyIcon />}
/>
<StatTile
title="Total size of files"
value={filesize(p.global.total_files_size)}
icon={<ScaleIcon />}
/>
</Grid>
</>
);
}
export function StatTile(p: {
title: string;
value: number | string | React.ReactElement;
icon: React.ReactElement;
}): React.ReactElement {
return (
<Grid size={4}>
<Paper elevation={5} style={{ padding: "10px" }}>
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
}}
>
{p.icon}
<Typography variant="h5" style={{ flex: 1 }}>
{p.title}
</Typography>
{p.value}
</div>
</Paper>
</Grid>
);
}