car-crushers-portal/components/NewInfractionModal.tsx

170 lines
4.3 KiB
TypeScript

import {
Button,
Input,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Select,
Text,
useToast
} from "@chakra-ui/react";
import { useState } from "react";
export default function(props: { isOpen: boolean; onClose: () => void }) {
const [loading, setLoading] = useState(false);
const [punishment, setPunishment] = useState("");
const [user, setUser] = useState("");
const toast = useToast();
function pasteHandler(e: ClipboardEvent) {
if (!props.isOpen) return;
const evidenceElement = document.getElementById(
"evidence"
) as HTMLInputElement;
if (!evidenceElement.files && e.clipboardData?.files) {
evidenceElement.files = e.clipboardData.files;
return;
}
if (!evidenceElement.files || !e.clipboardData?.files.length) return;
if (typeof window["DataTransfer"] === "undefined")
return alert("Your browser is too old to paste images in.");
const dataTransfer = new DataTransfer();
for (const file of evidenceElement.files) dataTransfer.items.add(file);
dataTransfer.items.add(e.clipboardData.files[0]);
evidenceElement.files = dataTransfer.files;
}
addEventListener("paste", pasteHandler);
function reset() {
removeEventListener("paste", pasteHandler);
(
document.getElementById("punishment") as unknown as HTMLSelectElement
).selectedIndex = -1;
(document.getElementById("user") as HTMLInputElement).value = "";
(document.getElementById("evidence") as HTMLInputElement).files = null;
props.onClose();
}
async function submit() {
setLoading(true);
const form = new FormData();
const { files } = document.getElementById("evidence") as HTMLInputElement;
form.append("user", user);
form.append("punishment", punishment);
if (files) {
for (let i = 0; i < files.length; i++)
form.append(`file${i}`, files[i], files[i].name);
}
const postReq = await fetch("/api/infractions/new", {
body: form,
method: "POST"
});
if (postReq.ok) {
setLoading(false);
toast({
description: "Infraction created",
duration: 5000,
isClosable: true,
status: "success",
title: "Success"
});
props.onClose();
return;
}
setLoading(false);
toast({
description: `Failed to create infraction (${
((await postReq.json()) as { error: string }).error
})`,
duration: 5000,
isClosable: true,
status: "error",
title: "Error"
});
}
return (
<Modal
closeOnEsc={false}
closeOnOverlayClick={false}
isCentered
isOpen={props.isOpen}
onClose={props.onClose}
>
<ModalOverlay />
<ModalContent>
<ModalHeader>New Infraction</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Text>User ID</Text>
<Input
id="user"
placeholder="1234567890987654321"
onChange={(e) => setUser(e.target.value)}
/>
<br />
<br />
<Text>Punishment</Text>
<Select
id="punishment"
onChange={(t) => setPunishment(t.target.value)}
placeholder="Select punishment"
>
<option value="verbal">Verbal Warning</option>
<option value="warn">Warning</option>
<option value="mute">Mute</option>
<option value="ban_temp">Temporary Ban</option>
<option value="ban_perm">Permanent Ban</option>
<option value="ban_unappealable">Unappealable Permanent Ban</option>
</Select>
<br />
<br />
<Text>Evidence</Text>
<Button
as="label"
// @ts-expect-error
for="evidence"
mr="8px"
>
Select Files
</Button>
<input id="evidence" multiple type="file" />
</ModalBody>
<ModalFooter>
<Button onClick={reset}>Cancel</Button>
<Button
colorScheme="blue"
ml="8px"
onClick={async () => await submit()}
isLoading={loading}
loadingText="Submitting..."
>
Submit
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
}