Display global statistics
This commit is contained in:
22
moneymgr_web/src/api/StatsApi.ts
Normal file
22
moneymgr_web/src/api/StatsApi.ts
Normal 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;
|
||||
}
|
||||
}
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user