import { Box, Button, Card, CardBody, CardFooter, CardHeader, Heading, ListItem, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, ModalOverlay, NumberDecrementStepper, NumberIncrementStepper, NumberInput, NumberInputField, NumberInputStepper, Stack, StackDivider, Text, UnorderedList, useDisclosure, useToast, VStack, } from "@chakra-ui/react"; import { useState } from "react"; export default function (props: GameAppealProps & { port?: MessagePort }) { const [loading, setLoading] = useState(false); const [percentage, setPercentage] = useState(0); const { isOpen, onClose, onOpen } = useDisclosure(); const toast = useToast(); async function performAction(action: "accept" | "deny"): Promise<void> { setLoading(true); const actionResponse = await fetch( `/api/game-appeals/${props.id}/${action}`, { body: JSON.stringify({ statsReduction: isNaN(percentage) ? 0 : percentage, }), headers: { "content-type": "application/json", }, method: "POST", }, ); toast( 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); onClose(); props.port?.postMessage(`gma_${props.id}`); } return ( <Card id={`gma_${props.roblox_id}${props.created_at}`} 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.what_happened}</Text> </Box> <Box> <Heading size="xs">Response: Reasoning for Unban</Heading> <Text>{props.reason_for_unban}</Text> </Box> </Stack> </CardBody> <CardFooter pb="4px"> <Box> <Button colorScheme="red" onClick={async () => await performAction("deny")} > Deny </Button> <Button colorScheme="blue" ml="8px" onClick={onOpen}> Accept </Button> </Box> </CardFooter> <Modal isOpen={isOpen} onClose={onClose}> <ModalOverlay /> <ModalContent> <ModalHeader> <Heading size="sm"> How much should this player's stats be reduced by? </Heading> </ModalHeader> <ModalBody> <VStack spacing={4}> <NumberInput max={10} min={-10} onChange={(_, n) => setPercentage(n)} precision={0} w="100%" > <NumberInputField /> <NumberInputStepper> <NumberIncrementStepper /> <NumberDecrementStepper /> </NumberInputStepper> </NumberInput> <Text alignSelf="start">Stat multiplication factors:</Text> <UnorderedList alignSelf="start"> <ListItem> Money: {Math.min(0.1 * percentage, 1).toFixed(2)} </ListItem> <ListItem> Parts: {Math.min(0.6 * percentage, 1).toFixed(2)} </ListItem> <ListItem> Derby Wins: {Math.min(0.6 * percentage, 1).toFixed(2)} </ListItem> </UnorderedList> </VStack> </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> ); }