Basic user stats in the accounts page (#1158)

Closes #747
Blocked by #1156 #1166

Very simplistic, not much styling
This commit is contained in:
AbdBarho
2023-02-07 00:10:35 +01:00
committed by GitHub
parent cf4c8e70ce
commit 0ef36e81be
4 changed files with 108 additions and 8 deletions
+16 -1
View File
@@ -1,18 +1,33 @@
{
"accepted": "↪ Accepted",
"accepted_prompts": "Accepted prompts",
"daily": "Daily",
"day": "Day",
"good_rankings": "Good rankings",
"label": "Labels",
"labels_full": "Labels (full)",
"labels_simple": "Labels (simple)",
"last_updated_at": "Last updated at: {{val, datetime}}",
"leaderboard": "Leaderboard",
"month": "Month",
"monthly": "Monthly",
"next": "Next",
"overall": "Overall",
"previous": "Previous",
"prompt": "Prompts",
"rank": "Rank",
"rankings": "Rankings",
"replies_assistant": "Replies as Assistant",
"replies_prompter": "Replies as Prompter",
"reply": "Replies",
"reply_ranked_1": "Replies ranked first",
"score": "Score",
"top_5_contributors_today": "Top 5 Contributors Today",
"total": "Total",
"user": "User",
"view_all": "View all",
"weekly": "Weekly"
"week": "Week",
"weekly": "Weekly",
"your_account": "Your account",
"your_stats": "Your statistics"
}
+5
View File
@@ -307,4 +307,9 @@ export class OasstApiClient {
const backendUser = await this.post<BackendUser>(`/api/v1/frontend_users/`, user);
await this.put<void>(`/api/v1/users/${backendUser.user_id}?tos_acceptance=true`);
}
async fetch_user_stats(user: BackendUserCore) {
const backendUser = await this.get<BackendUser>(`/api/v1/frontend_users/${user.auth_method}/${user.id}`);
return this.get(`/api/v1/users/${backendUser.user_id}/stats`);
}
}
+75 -7
View File
@@ -1,18 +1,27 @@
import { Divider, Flex, Grid, Icon, Text } from "@chakra-ui/react";
import { Box, Divider, Flex, Grid, Icon, Text } from "@chakra-ui/react";
import Head from "next/head";
import Link from "next/link";
import { useSession } from "next-auth/react";
import React from "react";
export { getDefaultStaticProps as getStaticProps } from "src/lib/default_static_props";
import { Pencil } from "lucide-react";
import { useTranslation } from "react-i18next";
import { SurveyCard } from "src/components/Survey/SurveyCard";
import { get } from "src/lib/api";
import { getTypeSafei18nKey } from "src/lib/i18n";
import { LeaderboardEntity, LeaderboardTimeFrame } from "src/types/Leaderboard";
import uswSWRImmutable from "swr/immutable";
export default function Account() {
const { t } = useTranslation("leaderboard");
const { data: session } = useSession();
const { data } = uswSWRImmutable<{ [time in LeaderboardTimeFrame]: LeaderboardEntity }>("/api/user_stats", get);
if (!session) {
return;
}
console.log(data);
return (
<>
<Head>
@@ -23,11 +32,9 @@ export default function Account() {
/>
</Head>
<main className="oa-basic-theme p-6">
<Flex m="auto" className="max-w-7xl" alignContent="center">
<Flex direction="column" m="auto" className="max-w-7xl" alignContent="center" gap={4}>
<SurveyCard className="w-full">
<Text as="b" display="block" fontSize="2xl" py={2}>
Your Account
</Text>
<Title>{t("your_account")}</Title>
<Divider />
<Grid gridTemplateColumns="repeat(2, max-content)" alignItems="center" gap={6} py={4}>
<Text as="b">Username</Text>
@@ -40,10 +47,71 @@ export default function Account() {
<Text as="b">Email</Text>
<Text>{session.user.email ?? "(No Email)"}</Text>
</Grid>
<p></p>
</SurveyCard>
<SurveyCard>
<Title>{t("your_stats")}</Title>
{[
LeaderboardTimeFrame.total,
LeaderboardTimeFrame.day,
LeaderboardTimeFrame.week,
LeaderboardTimeFrame.month,
].map((key) => {
const values = data[key];
if (!values) {
return null;
}
return (
<Box key={key} py={4}>
<Title>{t(getTypeSafei18nKey(key))}</Title>
<Flex w="full" wrap="wrap" alignItems="flex-start" gap={4}>
<TableColumn>
<Entry title={t("score")} value={values.leader_score} />
<Entry title={t("rank")} value={values.rank} />
<Entry title={t("prompt")} value={values.prompts} />
<Entry title={t("accepted_prompts")} value={values.accepted_prompts} />
</TableColumn>
<TableColumn>
<Entry title={t("replies_assistant")} value={values.replies_assistant} />
<Entry title={t("accepted")} value={values.accepted_replies_assistant} />
<Entry title={t("replies_prompter")} value={values.replies_prompter} />
<Entry title={t("accepted")} value={values.accepted_replies_prompter} />
</TableColumn>
<TableColumn>
<Entry title={t("labels_full")} value={values.labels_full} />
<Entry title={t("labels_simple")} value={values.labels_simple} />
<Entry title={t("rankings")} value={values.rankings_total} />
<Entry title={t("reply_ranked_1")} value={values.reply_ranked_1} />
</TableColumn>
</Flex>
</Box>
);
})}
</SurveyCard>
</Flex>
</main>
</>
);
}
const Title = ({ children }) => (
<Text as="b" display="block" fontSize="2xl" py={2}>
{children}
</Text>
);
const TableColumn = ({ children }) => {
return (
<Grid gridTemplateColumns="1fr max-content" mx={8} w="60" gap={2}>
{children}
</Grid>
);
};
const Entry = ({ title, value }) => {
return (
<>
<span className="text-start">{title}</span>
<span className="text-end">{value}</span>
</>
);
};
+12
View File
@@ -0,0 +1,12 @@
import { withoutRole } from "src/lib/auth";
import { createApiClientFromUser } from "src/lib/oasst_client_factory";
import { getBackendUserCore } from "src/lib/users";
const handler = withoutRole("banned", async (req, res, token) => {
const user = await getBackendUserCore(token.sub);
const oasstApiClient = createApiClientFromUser(user);
const stats = await oasstApiClient.fetch_user_stats(user);
res.status(200).json(stats);
});
export default handler;