160 lines
3.6 KiB
TypeScript
160 lines
3.6 KiB
TypeScript
import {
|
|
Button,
|
|
HStack,
|
|
Input,
|
|
Link,
|
|
Modal,
|
|
ModalBody,
|
|
ModalCloseButton,
|
|
ModalContent,
|
|
ModalHeader,
|
|
ModalOverlay,
|
|
Table,
|
|
TableContainer,
|
|
Tbody,
|
|
Td,
|
|
Th,
|
|
Thead,
|
|
Tr,
|
|
useToast,
|
|
} from "@chakra-ui/react";
|
|
import { useEffect, useState } from "react";
|
|
|
|
export default function (props: { isOpen: boolean; onClose: () => void }) {
|
|
const [mods, setMods] = useState([]);
|
|
const [userToAdd, setUserToAdd] = useState("");
|
|
const toast = useToast();
|
|
|
|
useEffect(() => {
|
|
if (!props.isOpen) return;
|
|
|
|
(async function () {
|
|
const gmeResp = await fetch("/api/gme/list");
|
|
|
|
if (!gmeResp.ok) {
|
|
toast({
|
|
description: "Failed to load GME data",
|
|
status: "error",
|
|
title: "Oops",
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
setMods(await gmeResp.json());
|
|
})();
|
|
}, [props.isOpen]);
|
|
|
|
async function addUser(user: string) {
|
|
if (!user || !user.match(/^\d{17,19}$/)) {
|
|
toast({
|
|
description: "Please check your input and try again",
|
|
status: "error",
|
|
title: "Invalid user",
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
const addResp = await fetch("/api/gme/add", {
|
|
body: JSON.stringify({ user }),
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
method: "POST",
|
|
});
|
|
|
|
if (!addResp.ok) {
|
|
toast({
|
|
description: ((await addResp.json()) as { error: string }).error,
|
|
status: "error",
|
|
title: "Oops",
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
toast({
|
|
description: `User ${user} added`,
|
|
status: "success",
|
|
title: "Success",
|
|
});
|
|
|
|
props.onClose();
|
|
}
|
|
|
|
async function removeUser(user: string) {
|
|
const removeResp = await fetch("/api/gme/remove", {
|
|
body: JSON.stringify({ user }),
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
method: "POST",
|
|
});
|
|
|
|
if (!removeResp.ok) {
|
|
toast({
|
|
description: ((await removeResp.json()) as { error: string }).error,
|
|
status: "error",
|
|
title: "Oops",
|
|
});
|
|
} else {
|
|
toast({
|
|
description: `User ${user} removed`,
|
|
status: "success",
|
|
title: "Success",
|
|
});
|
|
|
|
setMods(mods.filter((mod: any) => mod.user !== user));
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Modal isCentered isOpen={props.isOpen} onClose={props.onClose}>
|
|
<ModalOverlay />
|
|
<ModalContent>
|
|
<ModalHeader>Game Moderators</ModalHeader>
|
|
<ModalCloseButton />
|
|
<ModalBody>
|
|
<TableContainer>
|
|
<Table variant="simple">
|
|
<Thead>
|
|
<Tr>
|
|
<Th>User</Th>
|
|
<Th>Added At</Th>
|
|
<Th>Added By</Th>
|
|
<Th>Remove</Th>
|
|
</Tr>
|
|
</Thead>
|
|
<Tbody>
|
|
{mods.map((mod: any) => (
|
|
<Tr>
|
|
<Td>{mod.user}</Td>
|
|
<Td>{new Date(mod.metadata.time).toLocaleString()}</Td>
|
|
<Td>{mod.metadata.user}</Td>
|
|
<Td>
|
|
<Link onClick={async () => await removeUser(mod.user)}>
|
|
Remove
|
|
</Link>
|
|
</Td>
|
|
</Tr>
|
|
))}
|
|
</Tbody>
|
|
</Table>
|
|
</TableContainer>
|
|
<HStack mt="8px">
|
|
<Input
|
|
maxLength={19}
|
|
onChange={(e) => setUserToAdd(e.target.value)}
|
|
placeholder="1234567890987654321"
|
|
/>
|
|
<Button ml="8px" onClick={async () => await addUser(userToAdd)}>
|
|
Add
|
|
</Button>
|
|
</HStack>
|
|
</ModalBody>
|
|
</ModalContent>
|
|
</Modal>
|
|
);
|
|
}
|