import { Box, Button, Card, CardBody, CardHeader, Container, Heading, HStack, Image, Input, Link, Stack, StackDivider, Text, } from "@chakra-ui/react"; import { type FormEvent, useState } from "react"; export async function loader({ context }: { context: RequestContext }) { const { current_user: currentUser } = context.data; if (!currentUser) throw new Response(null, { status: 401, }); if (!(currentUser.permissions & (1 << 5))) throw new Response(null, { status: 403, }); return null; } export function meta() { return [{ title: "Hammer - Car Crushers" }]; } export default function () { const [username, setUsername] = useState(""); const [uid, setUid] = useState(""); const [status, setStatus] = useState(""); const [visible, setVisible] = useState(false); const [avatarUrl, setAvatarUrl] = useState(""); const [history, setHistory] = useState([]); async function getHistory() { const username = (document.getElementById("username") as HTMLInputElement) .value; if (username.length < 4) return alert("Username is too short!"); const historyResp = await fetch(`/api/game-bans/${username}/history`); if (!historyResp.ok) return alert( `ERROR: ${((await historyResp.json()) as { error: string }).error}`, ); const history: { [k: string]: any }[] = await historyResp.json(); if (!history.length) return alert("No history for this user."); const cardList = []; for (const entry of history) { const url = entry.entity.properties.evidence.stringValue; const isUrl = () => { try { new URL(url).href; return true; } catch { return false; } }; cardList.push( <Card> <CardHeader> <Heading size="md">{new Date().toLocaleString()}</Heading> </CardHeader> <CardBody> <Stack divider={<StackDivider />} spacing="4"> <Box> <Heading size="xs">ACTION</Heading> <Text pt="2" size="sm"> {entry.entity.properties.action.stringValue} </Text> </Box> <Box> <Heading size="xs">EVIDENCE</Heading> <Text pt="2" size="sm"> {isUrl() ? ( <Link color="#646cff" href={url}> {url} </Link> ) : ( url )} </Text> </Box> </Stack> </CardBody> </Card>, ); } } return ( <Container maxW="container.md"> <Heading>User Lookup</Heading> <HStack> <Input id="username" onBeforeInput={(e) => { const { data }: { data?: string } & FormEvent<HTMLInputElement> = e; if (data?.match(/\W/)) e.preventDefault(); }} placeholder="Roblox username" /> <Button ml="8px" onClick={async () => await getHistory()}> Search </Button> </HStack> <Card maxW="sm" visibility={visible ? "visible" : "hidden"}> <CardBody> <Image mb="16" src={avatarUrl} /> <Stack divider={<StackDivider />} spacing="6"> <Box> <Heading size="xs">USERNAME</Heading> <Text pt="2" fontSize="sm"> {username} </Text> </Box> <Box> <Heading size="xs">USER ID</Heading> <Text pt="2" fontSize="sm"> {uid} </Text> </Box> <Box> <Heading size="xs">MODERATION STATUS</Heading> <Text pt="2" fontSize="sm"> {status} </Text> </Box> </Stack> </CardBody> </Card> {history} </Container> ); }