car-crushers-portal/app/routes/events-team_.events-breakdown.tsx

150 lines
3.5 KiB
TypeScript

import {
Container,
Heading,
Table,
TableCaption,
TableContainer,
Tbody,
Td,
Th,
Thead,
Tr,
} from "@chakra-ui/react";
import { useLoaderData } from "@remix-run/react";
export async function loader({ context }: { context: RequestContext }) {
const { current_user: user } = context.data;
if (!user)
throw new Response(null, {
status: 401,
});
if (![1 << 4, 1 << 12].find((p) => user.permissions & p))
throw new Response(null, {
status: 403,
});
const memberResults = await context.env.D1.prepare(
"SELECT id, name FROM et_members;",
).all();
if (!memberResults.success)
throw new Response(null, {
status: 500,
});
const data: {
[k: string]: {
fotd: number;
name: string;
};
} & {
[k: string]: {
[k: string]: number;
};
} = {};
for (const row of memberResults.results as Record<string, string>[]) {
data[row.id].fotd = 0;
data[row.id].gamenight = 0;
data[row.id].name = row.name;
data[row.id].rotw = 0;
data[row.id].qotd = 0;
}
const eventsResult = await context.env.D1.prepare(
"SELECT answered_at, created_by, day, month, performed_at, reached_minimum_player_count, type, year FROM events;",
).all();
if (!eventsResult.success)
throw new Response(null, {
status: 500,
});
for (const row of eventsResult.results) {
const creator = row.created_by as string;
const type = row.type as string;
if (!data[creator]) continue;
if (row.performed_at) data[creator][type as string] += 10;
else {
const now = new Date();
const currentYear = now.getUTCFullYear();
const currentMonth = now.getUTCMonth() + 1;
const currentDay = now.getUTCDate();
if (
(row.year as number) < currentYear ||
(currentYear === row.year && currentMonth > (row.month as number)) ||
(currentMonth === row.month &&
currentYear === row.year &&
(row.day as number) < currentDay)
)
data[creator][type] -= 5;
}
switch (row.type) {
case "gamenight":
if (row.reached_minimum_player_count) data[creator].gamenight += 10;
break;
case "rotw":
if (
(row.answered_at as number) - (row.performed_at as number) >=
86400000
)
data[creator].rotw += 10;
break;
default:
break;
}
}
return data;
}
export default function () {
const data = useLoaderData<typeof loader>();
return (
<Container maxW="container.lg">
<Heading>Points Breakdown</Heading>
<TableContainer mt="16px">
<Table variant="simple">
<TableCaption>
Total points breakdown by event type. This does not include
deductions from strikes.
</TableCaption>
<Thead>
<Tr>
<Th>Discord ID</Th>
<Th>Name</Th>
<Th>FoTD Points</Th>
<Th>Gamenight Points</Th>
<Th>QoTD Points</Th>
<Th>RoTW Points</Th>
</Tr>
</Thead>
<Tbody>
{Object.entries(data).map(([k, v]) => (
<Tr>
<Td>{k}</Td>
<Td>{v.name}</Td>
<Td>{v.fotd}</Td>
<Td>{v.gamenight}</Td>
<Td>{v.qotd}</Td>
<Td>{v.rotw}</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
</Container>
);
}