127 lines
3.3 KiB
TypeScript
127 lines
3.3 KiB
TypeScript
import {
|
|
Box,
|
|
Button,
|
|
Card,
|
|
CardBody,
|
|
CardFooter,
|
|
CardHeader,
|
|
Heading,
|
|
Input,
|
|
Modal,
|
|
ModalBody,
|
|
ModalContent,
|
|
ModalFooter,
|
|
ModalHeader,
|
|
Stack,
|
|
StackDivider,
|
|
Text,
|
|
useDisclosure,
|
|
useToast,
|
|
} from "@chakra-ui/react";
|
|
import { useState } from "react";
|
|
|
|
export default function (props: GameAppealProps) {
|
|
const [loading, setLoading] = useState(false)
|
|
async function performAction(action: "accept" | "deny"): Promise<void> {
|
|
setLoading(true)
|
|
const statsReduction = parseInt(
|
|
(document.getElementById("reductPercentage") as HTMLInputElement).value,
|
|
);
|
|
|
|
const actionResponse = await fetch(`/api/game-appeals/${props.roblox_id}`, {
|
|
body: JSON.stringify({
|
|
statsReduction: isNaN(statsReduction) ? 0 : statsReduction,
|
|
}),
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
method: "POST",
|
|
});
|
|
|
|
useToast()(
|
|
actionResponse.ok
|
|
? {
|
|
duration: 5000,
|
|
status: "success",
|
|
title: `Appeal ${action === "accept" ? "accepted" : "denied"}`,
|
|
}
|
|
: {
|
|
description: `${
|
|
((await actionResponse.json()) as { error: string }).error
|
|
}`,
|
|
duration: 10000,
|
|
status: "error",
|
|
title: "An error occurred...",
|
|
},
|
|
);
|
|
|
|
setLoading(false)
|
|
}
|
|
|
|
const { isOpen, onClose, onOpen } = useDisclosure();
|
|
|
|
return (
|
|
<Card key={props.roblox_id} w="100%">
|
|
<CardHeader>
|
|
<Heading size="md">Game Ban Appeal for {props.roblox_username}</Heading>
|
|
<Text fontSize="xs">ID: {props.roblox_id}</Text>
|
|
</CardHeader>
|
|
<CardBody>
|
|
<Stack divider={<StackDivider />}>
|
|
<Box>
|
|
<Heading size="xs">Response: Explanation of Ban</Heading>
|
|
<Text>{props.whatHappened}</Text>
|
|
</Box>
|
|
<Box>
|
|
<Heading size="xs">Response: Reasoning for Unban</Heading>
|
|
<Text>{props.reasonForUnban}</Text>
|
|
</Box>
|
|
</Stack>
|
|
</CardBody>
|
|
<CardFooter pb="4px">
|
|
<Box>
|
|
<Button colorScheme="red">Deny</Button>
|
|
<Button colorScheme="blue" ml="8px">
|
|
Accept
|
|
</Button>
|
|
</Box>
|
|
</CardFooter>
|
|
<Modal isOpen={isOpen} onClose={onClose}>
|
|
<ModalContent>
|
|
<ModalHeader>
|
|
<Heading>
|
|
How much should this player's stats be reduced by?
|
|
</Heading>
|
|
</ModalHeader>
|
|
<ModalBody>
|
|
<Input
|
|
id="reductPercentage"
|
|
onBeforeInput={(e) => {
|
|
const value = (e.target as EventTarget & { value: string })
|
|
.value;
|
|
|
|
return !value.match(/\D/);
|
|
}}
|
|
placeholder="Number between 0 and 100"
|
|
/>
|
|
</ModalBody>
|
|
<ModalFooter>
|
|
<Button colorScheme="red" onClick={onClose}>
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
colorScheme="blue"
|
|
ml="8px"
|
|
onClick={async () => await performAction("accept")}
|
|
isLoading={loading}
|
|
loadingText='Submitting...'
|
|
>
|
|
Submit
|
|
</Button>
|
|
</ModalFooter>
|
|
</ModalContent>
|
|
</Modal>
|
|
</Card>
|
|
);
|
|
}
|