Files
ds-pages/pages/statistic.tsx
2023-03-16 15:32:14 +00:00

159 lines
3.9 KiB
TypeScript

import { Button, Container, createStyles, Group, rem, Text, Title } from "@mantine/core";
import { IconArrowBack } from "@tabler/icons";
import { GetServerSidePropsResult } from "next";
import { useRouter } from "next/router";
import { MINIO_ACCESS_KEY, MINIO_ENABLED, MINIO_ENDPOINT, MINIO_SECRET_KEY } from "../lib/config";
import { prismaClient } from "../lib/db";
import { minIO } from "../lib/minio";
function humanFileSize(bytes: number, si = false, dp = 1) {
const thresh = si ? 1000 : 1024;
if (Math.abs(bytes) < thresh) {
return bytes + " B";
}
const units = si
? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
: ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
let u = -1;
const r = 10 ** dp;
do {
bytes /= thresh;
++u;
} while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
return bytes.toFixed(dp) + " " + units[u];
}
const useStyles = createStyles((theme) => ({
root: {
display: "flex",
backgroundImage: `linear-gradient(-60deg, ${theme.colors[theme.primaryColor][4]} 0%, ${
theme.colors[theme.primaryColor][7]
} 100%)`,
padding: `calc(${theme.spacing.xl} * 1.5)`,
borderRadius: theme.radius.md,
[theme.fn.smallerThan("sm")]: {
flexDirection: "column",
},
},
title: {
color: theme.white,
textTransform: "uppercase",
fontWeight: 700,
fontSize: theme.fontSizes.sm,
},
count: {
color: theme.white,
fontSize: rem(32),
lineHeight: 1,
fontWeight: 700,
marginBottom: theme.spacing.md,
fontFamily: `Greycliff CF, ${theme.fontFamily}`,
},
description: {
color: theme.colors[theme.primaryColor][0],
fontSize: theme.fontSizes.sm,
marginTop: rem(5),
},
stat: {
flex: 1,
"& + &": {
paddingLeft: theme.spacing.xl,
marginLeft: theme.spacing.xl,
borderLeft: `${rem(1)} solid ${theme.colors[theme.primaryColor][3]}`,
[theme.fn.smallerThan("sm")]: {
paddingLeft: 0,
marginLeft: 0,
borderLeft: 0,
paddingTop: theme.spacing.xl,
marginTop: theme.spacing.xl,
borderTop: `${rem(1)} solid ${theme.colors[theme.primaryColor][3]}`,
},
},
},
}));
interface StatsGroupProps {
data: { title: string; stats: string; description?: string }[];
}
export default function StatisticPage({ data }: StatsGroupProps) {
const { classes } = useStyles();
const router = useRouter();
const stats = data.map((stat) => (
<div key={stat.title} className={classes.stat}>
<Text className={classes.count}>{stat.stats}</Text>
<Text className={classes.title}>{stat.title}</Text>
<Text className={classes.description}>{stat.description}</Text>
</div>
));
return (
<Container my="2rem">
<Title>Statistic</Title>
<Group position="apart" mb="1rem">
<div></div>
<Button variant="subtle" onClick={() => router.back()} rightIcon={<IconArrowBack />}>
Back
</Button>
</Group>
<div className={classes.root}>{stats}</div>
</Container>
);
}
export async function getServerSideProps(): Promise<GetServerSidePropsResult<StatsGroupProps>> {
const [total, { time }] = await Promise.all([
prismaClient.paragraph.count(),
prismaClient.paragraph.findFirstOrThrow({
orderBy: {
time: "desc",
},
select: {
time: true,
},
}),
]);
const data = [
{
title: "Paragraphs",
stats: total.toString(),
},
{
title: "Last Update",
stats: time?.toLocaleDateString() ?? "N/A",
},
];
if (MINIO_ENABLED) {
await minIO.login(MINIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY);
const info = await minIO.bucketInfo();
data.push({
title: "Images",
stats: info.objects.toString(),
});
data.push({
title: "Images Size",
stats: humanFileSize(info.size),
});
}
return {
props: {
data,
},
};
}