207 lines
6.1 KiB
TypeScript
207 lines
6.1 KiB
TypeScript
import {
|
|
Box,
|
|
Button,
|
|
Card,
|
|
CardBody,
|
|
CardFooter,
|
|
CardHeader,
|
|
Heading,
|
|
HStack,
|
|
Radio,
|
|
RadioGroup,
|
|
Spacer,
|
|
Stack,
|
|
Text,
|
|
useToast,
|
|
} from "@chakra-ui/react";
|
|
import { useState } from "react";
|
|
|
|
export default function (props: ReportCardProps) {
|
|
const [attachmentIdx, setAttachmentIdx] = useState(0);
|
|
const [loading, setLoading] = useState(false);
|
|
const toast = useToast();
|
|
const targetMap: { [k: number]: string } = {};
|
|
const [attachmentsReady, setAttachmentReady] = useState(
|
|
!props.attachments_loading,
|
|
);
|
|
const actionMap: { [k: number]: number } = {};
|
|
|
|
for (let i = 0; i < props.target_ids.length; i++)
|
|
Object.defineProperty(targetMap, props.target_ids[i], {
|
|
value: props.target_usernames[i],
|
|
});
|
|
|
|
async function recheckAttachment() {
|
|
const attachmentCheck = await fetch("/api/uploads/status", {
|
|
body: JSON.stringify(props.attachments),
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
method: "POST",
|
|
});
|
|
|
|
setAttachmentReady(attachmentCheck.ok);
|
|
}
|
|
|
|
async function submitActions() {
|
|
setLoading(true);
|
|
const submitReq = await fetch(`/api/reports/${props.id}/action`, {
|
|
body: JSON.stringify(actionMap),
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
method: "POST",
|
|
});
|
|
|
|
if (!submitReq.ok) {
|
|
setLoading(false);
|
|
toast({
|
|
description: ((await submitReq.json()) as { error: string }).error,
|
|
status: "error",
|
|
title: "S̸̯̜̈́o̴̳̅̾̏̽m̴͔͕̈́̋ē̴̙͓̯̍̃ț̸͖̘̀h̶̛̳̝̐i̵̋͘͜ņ̷̙̤͌g̴̭̻̓̈́ ̴̘͍̦̪̆w̸̡̏̑̊é̸̠̖̹̂͜n̴̖̳̤̕t̴͚̊̊̕ ̸̛͙̺̬̎́w̴͈͑̋͊r̷̢̛o̵̱̩̍͋ͅṇ̸̝̰̮́g̵̡̢̦͕͂",
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
toast({
|
|
description: "Actions were successfully applied",
|
|
status: "success",
|
|
title: "Success",
|
|
});
|
|
setLoading(false);
|
|
location.reload();
|
|
}
|
|
|
|
return (
|
|
<Card key={props.id} w="100%">
|
|
<CardHeader>
|
|
<Heading size="lg">
|
|
Report for {props.target_usernames.toString()}
|
|
</Heading>
|
|
<Text fontSize="xs">ID(s): {props.target_ids.toString()}</Text>
|
|
</CardHeader>
|
|
<CardBody>
|
|
{attachmentsReady ? (
|
|
<div style={{ position: "relative" }}>
|
|
<video
|
|
autoPlay={true}
|
|
controls={true}
|
|
src={`/api/uploads/${props.attachments[attachmentIdx]}`}
|
|
width="100%"
|
|
/>
|
|
<HStack
|
|
pos="absolute"
|
|
top="50%"
|
|
transform="translate(5%, -50%)"
|
|
w="90%"
|
|
zIndex="1"
|
|
>
|
|
<Button
|
|
borderRadius="50%"
|
|
h="16"
|
|
onClick={() => setAttachmentIdx(attachmentIdx - 1)}
|
|
visibility={attachmentIdx > 0 ? "visible" : "hidden"}
|
|
w="16"
|
|
>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="32"
|
|
height="32"
|
|
fill="currentColor"
|
|
viewBox="0 0 16 16"
|
|
>
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M12 8a.5.5 0 0 1-.5.5H5.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5H11.5a.5.5 0 0 1 .5.5z"
|
|
/>
|
|
</svg>
|
|
</Button>
|
|
<Spacer />
|
|
<Button
|
|
borderRadius="50%"
|
|
h="16"
|
|
onClick={() => setAttachmentIdx(attachmentIdx + 1)}
|
|
visibility={
|
|
props.attachments.length > attachmentIdx + 1
|
|
? "visible"
|
|
: "hidden"
|
|
}
|
|
w="16"
|
|
>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="32"
|
|
height="32"
|
|
fill="currentColor"
|
|
viewBox="0 0 16 16"
|
|
>
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M4 8a.5.5 0 0 1 .5-.5h5.793L8.146 5.354a.5.5 0 1 1 .708-.708l3 3a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708-.708L10.293 8.5H4.5A.5.5 0 0 1 4 8z"
|
|
/>
|
|
</svg>
|
|
</Button>
|
|
</HStack>
|
|
</div>
|
|
) : (
|
|
<Text>Attachments processing...</Text>
|
|
)}
|
|
<br />
|
|
<Text my="16px">{props.description}</Text>
|
|
</CardBody>
|
|
<CardFooter>
|
|
{props.attachments_loading ? (
|
|
<Button
|
|
colorScheme="blue"
|
|
onClick={async () => await recheckAttachment()}
|
|
>
|
|
Reload Attachment
|
|
</Button>
|
|
) : (
|
|
<Stack direction="column">
|
|
{(function () {
|
|
const radioGroups = [];
|
|
for (let i = 0; i < props.target_ids.length; i++) {
|
|
radioGroups.push(
|
|
<RadioGroup
|
|
name={props.target_ids[i].toString()}
|
|
onChange={(val) => {
|
|
actionMap[props.target_ids[i]] = parseInt(val);
|
|
}}
|
|
>
|
|
<Stack direction="row">
|
|
<Text>{props.target_usernames[i]}</Text>
|
|
<Radio key={0} value="0">
|
|
Ignore
|
|
</Radio>
|
|
<Radio key={1} value="1">
|
|
Hide from Leaderboards
|
|
</Radio>
|
|
<Radio key={2} value="2">
|
|
Ban
|
|
</Radio>
|
|
</Stack>
|
|
</RadioGroup>,
|
|
);
|
|
}
|
|
|
|
return radioGroups;
|
|
})()}
|
|
<Box pt="16px">
|
|
<Button
|
|
colorScheme="blue"
|
|
onClick={async () => await submitActions()}
|
|
isLoading={loading}
|
|
loadingText="Submitting..."
|
|
>
|
|
Submit
|
|
</Button>
|
|
</Box>
|
|
</Stack>
|
|
)}
|
|
</CardFooter>
|
|
</Card>
|
|
);
|
|
}
|