import { Box, Button, Card, CardBody, CardFooter, CardHeader, Heading, ListItem, Stack, StackDivider, Text, UnorderedList, useToast, } from "@chakra-ui/react"; import { useState } from "react"; export default function ( props: InactivityNoticeProps & { port?: MessagePort }, ) { const toast = useToast(); const [loading, setLoading] = useState(false); async function makeDecision(accepted: boolean) { setLoading(true); const decisionReq = await fetch(`/api/inactivity/${props.id}`, { body: JSON.stringify({ accepted }), headers: { "content-type": "application/json", }, method: "POST", }); if (!decisionReq.ok) { setLoading(false); toast({ description: ((await decisionReq.json()) as { error: string }).error, isClosable: true, status: "error", title: "Oops", }); return; } toast({ description: `Inactivity notice ${accepted ? "accepted" : "denied"}.`, isClosable: true, status: "success", title: "Success", }); setLoading(false); } const Approved = () => ( <svg fill="currentColor" height="16" viewBox="0 0 16 16" width="16"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z" /> </svg> ); const Denied = () => ( <svg fill="currentColor" height="16" viewBox="0 0 16 16" width="16"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z" /> </svg> ); const Pending = () => ( <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" > <path d="M2.5 15a.5.5 0 1 1 0-1h1v-1a4.5 4.5 0 0 1 2.557-4.06c.29-.139.443-.377.443-.59v-.7c0-.213-.154-.451-.443-.59A4.5 4.5 0 0 1 3.5 3V2h-1a.5.5 0 0 1 0-1h11a.5.5 0 0 1 0 1h-1v1a4.5 4.5 0 0 1-2.557 4.06c-.29.139-.443.377-.443.59v.7c0 .213.154.451.443.59A4.5 4.5 0 0 1 12.5 13v1h1a.5.5 0 0 1 0 1zm2-13v1c0 .537.12 1.045.337 1.5h6.326c.216-.455.337-.963.337-1.5V2zm3 6.35c0 .701-.478 1.236-1.011 1.492A3.5 3.5 0 0 0 4.5 13s.866-1.299 3-1.48zm1 0v3.17c2.134.181 3 1.48 3 1.48a3.5 3.5 0 0 0-1.989-3.158C8.978 9.586 8.5 9.052 8.5 8.351z" /> </svg> ); return ( <Card w="100%"> <CardHeader> <Heading size="md">Inactivity Notice for {props.user.username}</Heading> <Text fontSize="xs">ID: {props.user.id}</Text> </CardHeader> <CardBody> <Stack divider={<StackDivider />}> <Box> <Heading size="xs">Reason for Inactivity</Heading> <Text>{props.reason}</Text> </Box> <Box> <Heading size="xs">Start Date</Heading> <Text>{new Date(props.start).toLocaleDateString()}</Text> </Box> <Box> <Heading size="xs">End Date</Heading> <Text>{new Date(props.end).toLocaleDateString()}</Text> </Box> {typeof props.hiatus === "boolean" ? ( <Box> <Heading size="xs">Notice Type</Heading> <Text> {props.hiatus ? "Hiatus/Inactivity" : "Activity Decrease"} </Text> </Box> ) : null} <Box> <Heading size="xs">Decisions</Heading> <UnorderedList> {props.departments.map((d) => { const dept = d as "ET" | "DM" | "FM" | "WM"; return ( <ListItem> <Stack alignItems="center" direction="row"> <Text>{d}: </Text> {typeof props.decisions[dept] === "boolean" ? ( props.decisions[dept] ? ( <Approved /> ) : ( <Denied /> ) ) : ( <Pending /> )} </Stack> </ListItem> ); })} </UnorderedList> </Box> </Stack> </CardBody> <CardFooter display={ props.departments.length !== Object.values( props.decisions as { [k: string]: boolean; }, ).length ? undefined : "none" } pb="4px" > <Box> <Button colorScheme="red" onClick={async () => await makeDecision(false)} isLoading={loading} loadingText="Processing..." > Deny </Button> <Button colorScheme="blue" ml="8px" onClick={async () => await makeDecision(true)} isLoading={loading} loadingText="Processing..." > Accept </Button> </Box> </CardFooter> </Card> ); }