Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Create start of /me route
  • Loading branch information
regalijan committed Oct 23, 2023
1 parent 5607c2e commit 692ad58
Showing 1 changed file with 276 additions and 0 deletions.
276 changes: 276 additions & 0 deletions app/routes/me.tsx
@@ -0,0 +1,276 @@
import {
Button,
Container,
Divider,
Heading,
Link,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalHeader,
ModalOverlay,
Table,
TableContainer,
Tbody,
Td,
Text,
Th,
Thead,
Tr,
useDisclosure,
useToast,
} from "@chakra-ui/react";
import { type Dispatch, type SetStateAction, useEffect, useState } from "react";
import { useLoaderData } from "@remix-run/react";

export async function loader({ context }: { context: RequestContext }) {
const { current_user: currentUser } = context.data;

if (!currentUser) throw new Response(null, { status: 401 });

const d1Promises = [];

for (const itemType of ["appeals", "inactivity_notices", "reports"])
d1Promises.push(
context.env.D1.prepare(
`SELECT *
FROM ${itemType}
WHERE user = ?
ORDER BY created_at DESC;`,
)
.bind(currentUser.id)
.all(),
);

const settledPromises = await Promise.allSettled(d1Promises);

return settledPromises.filter((p) => {
if (p.status === "fulfilled") return p.value.results;

return null;
}) as any as ({ [k: string]: any }[] | null)[];
}

export default function () {
const data: ({ [k: string]: any }[] | null)[] =
useLoaderData<typeof loader>();
const timeStates: {
[k: number]: { data: string; set: Dispatch<SetStateAction<string>> };
} = {};
const toast = useToast();

for (const result of data) {
if (!result) continue;

for (const row of result) {
const [data, set] = useState(new Date(row.created_at).toUTCString());
timeStates[row.created_at] = {
data,
set,
};

useEffect(() => {
timeStates[row.created_at].set(
new Date(row.created_at).toLocaleString(),
);
}, [row.created_at]);
}
}

async function fetchItem(id: string, type: string) {
const itemResp = await fetch(`/api/me/items/${type}/${id}`);

if (!itemResp.ok) {
let error: string;

try {
error = ((await itemResp.json()) as { error: string }).error;
} catch {
error = "Unknown error";
}

toast({
description: error,
isClosable: true,
status: "error",
title: "Oops",
});

return;
}

const data: { [k: string]: any } = await itemResp.json();

switch (type) {
case "appeal":
setModalBody(
<ModalContent>
<ModalHeader>View Appeal</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Heading size="lg">Why were you banned?</Heading>
<br />
<Text>
<i>{data.ban_reason}</i>
</Text>
<br />
<Divider />
<br />
<Heading size="lg">Why should we unban you?</Heading>
<br />
<Text>
<i>{data.reason_for_unban}</i>
</Text>
<br />
<Divider />
<br />
<Heading size="lg">
What have you learned from your mistake?
</Heading>
<br />
<Text>
<i>{data.learned}</i>
</Text>
</ModalBody>
</ModalContent>,
);

break;

case "inactivity":
setModalBody(
<ModalContent>
<ModalHeader>View Inactivity Notice</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Heading size="lg">Reason for Inactivity</Heading>
<br />
<Text>
<i>{data.reason}</i>
</Text>
<br />
<Divider />
<br />
<Heading size="lg">Start Date</Heading>
<br />
<Text>
<i>{new Date(data.start).toLocaleDateString()}</i>
</Text>
<br />
<Divider />
<br />
<Heading size="lg">End Date</Heading>
<br />
<Text>
<i>{new Date(data.end).toLocaleDateString()}</i>
</Text>
</ModalBody>
</ModalContent>,
);

break;

case "report":
setModalBody(
<ModalContent>
<ModalHeader>View Report</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Heading size="lg">Username(s)</Heading>
<br />
<Text>
<i>{data.target_usernames.toString()}</i>
</Text>
<br />
<Divider />
<br />
<Heading size="lg">Description</Heading>
<br />
<Text>
<i>{data.description ?? "No description"}</i>
</Text>
<br />
<Divider />
<br />
<Heading size="lg">Media Links</Heading>
<br />
{data.resolved_attachments.map((attachment: string) => (
<Link color="#646cff" href={attachment} target="_blank">
View media here
</Link>
))}
</ModalBody>
</ModalContent>,
);

break;

default:
setModalBody(<ModalContent></ModalContent>);

break;
}
}

const { isOpen, onClose, onOpen } = useDisclosure();
const [modalBody, setModalBody] = useState(<ModalContent></ModalContent>);

function resetModal() {
onClose();
setModalBody(<ModalContent></ModalContent>);
}

return (
<Container maxW="container.lg">
<Modal isCentered isOpen={isOpen} onClose={resetModal} size="lg">
<ModalOverlay />
{modalBody}
</Modal>
<Heading mb={8}>My Data</Heading>
<br />
<br />
<Heading size="lg">Discord Appeals</Heading>
<TableContainer>
<Table variant="simple">
<Thead>
<Tr>
<Th>Date</Th>
<Th>ID</Th>
<Th>Status</Th>
<Th>View</Th>
</Tr>
</Thead>
<Tbody>
{data[0]
? data[0].map((result) => {
return (
<Tr>
<Td>{timeStates[result.created_at].data}</Td>
<Td>{result.id}</Td>
<Td>
{result.open
? "Pending"
: result.approved
? "Accepted"
: "Denied"}
</Td>
<Td>
<Button
onClick={async () =>
await fetchItem(result.id, "appeal")
}
>
View
</Button>
</Td>
</Tr>
);
})
: undefined}
</Tbody>
</Table>
</TableContainer>
</Container>
);
}

0 comments on commit 692ad58

Please sign in to comment.