Skip to content
Permalink
7ec760efd4
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
298 lines (267 sloc) 7.77 KB
import {
Button,
Input,
Link,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Radio,
RadioGroup,
Table,
TableContainer,
Tbody,
Text,
Td,
Th,
Thead,
Tr,
VStack,
useToast,
} from "@chakra-ui/react";
import { useState } from "react";
export default function (props: { isOpen: boolean; onClose: () => void }) {
const actionMap: { [k: string]: number } = {};
const [users, setUsers] = useState([] as string[]);
const [loading, setLoading] = useState(true);
const toast = useToast();
const fileTypes: { [k: string]: string } = {
gif: "image/gif",
heic: "image/heic",
heif: "image/heif",
jfif: "image/jpeg",
jpeg: "image/jpeg",
jpg: "image/jpg",
m4v: "video/x-m4v",
mkv: "video/x-matroska",
mov: "video/mp4",
mp4: "video/mp4",
png: "image/png",
webp: "image/webp",
webm: "video/webm",
wmv: "video/x-ms-wmv",
};
function addUser(user: string) {
(document.getElementById("username") as HTMLInputElement).value = "";
const newUsers = [...users];
if (newUsers.includes(user)) return;
newUsers.push(user);
setUsers(newUsers);
}
function removeUser(user: string) {
const newUsers = [...users];
const userIdx = newUsers.indexOf(user);
if (userIdx === -1) return;
newUsers.splice(userIdx, 1);
setUsers(newUsers);
delete actionMap[user];
}
function reset() {
(document.getElementById("username") as HTMLInputElement).value = "";
(document.getElementById("evidence") as HTMLInputElement).value = "";
setUsers([]);
Object.keys(actionMap).forEach((k) => delete actionMap[k]);
props.onClose();
}
async function submit() {
setLoading(true);
const actions: number[] = [];
const usernames: string[] = [];
for (const [u, a] of Object.entries(actionMap)) {
actions.push(a);
usernames.push(u);
}
if (!usernames.length || !actions.length) return;
const files = (document.getElementById("evidence") as HTMLInputElement)
.files;
if (!files) {
setLoading(false);
return;
}
const [evidence] = files;
const submitReq = await fetch("/api/reports/submit", {
body: JSON.stringify({
actions,
bypass: true,
filename: evidence.name,
filesize: evidence.size,
usernames,
}),
headers: {
"content-type": "application/json",
},
method: "POST",
});
if (!submitReq.ok) {
setLoading(false);
toast({
description: ((await submitReq.json()) as { error: string }).error,
status: "error",
title: "Failed to submit report",
});
return;
}
const { id, upload_url }: { [k: string]: string } = await submitReq.json();
const fileUpload = await fetch(upload_url, {
body: evidence,
headers: {
"content-type":
evidence.type ||
fileTypes[
evidence.name.split(".")[evidence.name.split(".").length - 1]
],
},
method: "PUT",
});
if (!fileUpload.ok) {
setLoading(false);
await fetch("/api/reports/recall", {
body: JSON.stringify({ id }),
headers: {
"content-type": "application/json",
},
method: "POST",
});
toast({
description: "Failed to upload file",
status: "error",
title: "Error",
});
return;
}
await fetch("/api/reports/complete", {
body: JSON.stringify({ id }),
headers: {
"content-type": "application/json",
},
method: "POST",
});
toast({
description: "User moderated",
status: "success",
title: "Success",
});
setLoading(false);
}
return (
<Modal isCentered isOpen={props.isOpen} onClose={props.onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>New Game Ban</ModalHeader>
<ModalCloseButton onClick={reset} />
<ModalBody>
<Text>Username(s)</Text>
<Input id="username" mb="8px" placeholder="builderman" />
<Button
onClick={function () {
const user = (
document.getElementById("username") as HTMLInputElement
).value;
if (
!user ||
user.length < 3 ||
user.length > 20 ||
// @ts-expect-error
user.match(/_/g)?.length > 1 ||
user.match(/\W/)
) {
toast({
description: "Check the username and try again",
duration: 5000,
isClosable: true,
status: "error",
title: "Invalid Username",
});
return;
}
addUser(user);
}}
>
Add
</Button>
<br />
<br />
<TableContainer>
<Table variant="simple">
<Thead>
<Tr>
<Th>Username</Th>
<Th>Punishment</Th>
<Th>&nbsp;</Th>
</Tr>
</Thead>
<Tbody>
{users.map((user) => (
<Tr key={user}>
<Td>{user}</Td>
<Td>
<RadioGroup
onChange={(val) =>
Object.defineProperty(actionMap, user, {
value: parseInt(val),
})
}
>
<VStack>
<Radio value="0">Do Nothing</Radio>
<Radio value="1">Hide from Leaderboards</Radio>
<Radio value="2">Ban</Radio>
</VStack>
</RadioGroup>
</Td>
<Td>
<Button onClick={() => removeUser(user)} variant="ghost">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6Z" />
<path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1ZM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118ZM2.5 3h11V2h-11v1Z" />
</svg>
</Button>
</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
<br />
<br />
<Text>Evidence</Text>
<Button
mr="8px"
onClick={() => document.getElementById("evidence")?.click()}
>
Select Files
</Button>
<input id="evidence" type="file" />
</ModalBody>
</ModalContent>
<ModalFooter>
<Button onClick={reset}>Cancel</Button>
<Button
colorScheme="blue"
disabled={
!(
Object.entries(actionMap).length &&
(document.getElementById("evidence") as HTMLInputElement).files
?.length
)
}
ml="8px"
onClick={async () => await submit()}
isLoading={loading}
loadingText="Submitting..."
>
Submit
</Button>
</ModalFooter>
</Modal>
);
}