2023-10-19 16:49:09 -04:00

232 lines
5.9 KiB
TypeScript

import {
Alert,
AlertDescription,
AlertIcon,
AlertTitle,
Box,
Button,
Container,
Flex,
Heading,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Spacer,
Text,
Textarea,
useDisclosure,
useToast,
} from "@chakra-ui/react";
import { useLoaderData } from "@remix-run/react";
import { useState } from "react";
import Success from "../../components/Success.js";
export async function loader({ context }: { context: RequestContext }) {
if (!context.data.current_user)
throw new Response(null, {
status: 401,
});
const { current_user: currentUser } = context.data;
const dataKV = context.env.DATA;
const disabled = await dataKV.get("appeal_disabled");
return {
can_appeal:
!Boolean(disabled) &&
!Boolean(await dataKV.get(`blockedappeal_${currentUser.id}`)) &&
!Boolean(
(
await dataKV.list({
prefix: `appeal_${currentUser.id}`,
})
).keys.find((appeal) => (appeal.metadata as { [k: string]: any }).open)
),
can_toggle:
currentUser.permissions & (1 << 0) || currentUser.permissions & (1 << 11),
disabled: Boolean(disabled),
};
}
export default function () {
const pageProps = useLoaderData<typeof loader>();
const { isOpen, onClose, onOpen } = useDisclosure();
const [showSuccess, setShowSuccess] = useState(false);
const toast = useToast();
async function submit() {
const learned = (document.getElementById("learned") as HTMLInputElement)
.value;
const whyBanned = (document.getElementById("whyBanned") as HTMLInputElement)
.value;
const whyUnban = (document.getElementById("whyUnban") as HTMLInputElement)
.value;
const submitReq = await fetch("/api/appeals/submit", {
body: JSON.stringify({
learned,
whyBanned,
whyUnban,
}),
headers: {
"content-type": "application/json",
},
method: "POST",
}).catch(() => {});
if (!submitReq)
return toast({
description: "Please check your internet and try again",
duration: 10000,
isClosable: true,
status: "error",
title: "Request Failed",
});
if (!submitReq.ok)
return toast({
description: ((await submitReq.json()) as { error: string }).error,
duration: 10000,
isClosable: true,
status: "error",
title: "Error",
});
setShowSuccess(true);
}
async function toggle(active: boolean) {
const toggleReq = await fetch("/api/appeals/toggle", {
body: JSON.stringify({ active }),
headers: {
"content-type": "application/json",
},
method: "POST",
});
if (!toggleReq.ok)
return toast({
description: ((await toggleReq.json()) as { error: string }).error,
duration: 10000,
isClosable: true,
status: "error",
title: "Error",
});
toast({
description: `The appeals form is now ${active ? "opened" : "closed"}.`,
isClosable: true,
status: "success",
title: `Appeals ${active ? "enabled" : "disabled"}`,
});
onClose();
await new Promise((p) => setTimeout(p, 5000));
}
return showSuccess ? (
<Success
heading="Appeal Submitted"
message="You will receive an email when we reach a decision."
/>
) : (
<Container maxW="container.md" pt="4vh" textAlign="start">
<Alert
borderRadius="8px"
display={pageProps.disabled ? "flex" : "none"}
mb="16px"
status="error"
>
<AlertIcon />
<Box>
<AlertTitle>Appeals Closed</AlertTitle>
<AlertDescription>
We are currently not accepting appeals.
</AlertDescription>
</Box>
</Alert>
<Flex>
<Spacer />
<Button display={pageProps.can_toggle ? "" : "none"} onClick={onOpen}>
{pageProps.disabled ? "Enable" : "Disable"} Appeals
</Button>
</Flex>
<br />
<Modal isCentered isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Toggle appeals?</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Text>
Are you sure you want to{" "}
{pageProps.disabled ? "enable" : "disable"} appeals?
</Text>
</ModalBody>
<ModalFooter style={{ gap: "8px" }}>
<Button onClick={onClose} variant="ghost">
No
</Button>
<Button
onClick={async () => await toggle(pageProps.disabled)}
variant="danger"
>
Yes
</Button>
</ModalFooter>
</ModalContent>
</Modal>
<Heading size="xl">Discord Appeals</Heading>
<br />
<Text fontSize="md">
This is for Discord bans only! See the support page if you were banned
from the game.
</Text>
<br />
<br />
<Heading size="md">Why were you banned?</Heading>
<br />
<Textarea
disabled={!pageProps.can_appeal}
id="whyBanned"
maxLength={500}
placeholder="Your response"
/>
<br />
<br />
<br />
<Heading size="md">Why should we unban you?</Heading>
<br />
<Textarea
disabled={!pageProps.can_appeal}
id="whyUnban"
maxLength={2000}
placeholder="Your response"
/>
<br />
<br />
<br />
<Heading size="md">What have you learned from your mistake?</Heading>
<br />
<Textarea
disabled={!pageProps.can_appeal}
id="learned"
maxLength={2000}
placeholder="Your response"
/>
<br />
<br />
<Button
disabled={pageProps.can_appeal}
onClick={async () => await submit()}
>
Submit
</Button>
</Container>
);
}