233 lines
7.2 KiB
TypeScript
233 lines
7.2 KiB
TypeScript
import {
|
|
Avatar,
|
|
Box,
|
|
Button,
|
|
Center,
|
|
CloseButton,
|
|
Container,
|
|
Drawer,
|
|
DrawerContent,
|
|
DrawerOverlay,
|
|
Flex,
|
|
HStack,
|
|
Link,
|
|
Spacer,
|
|
Text,
|
|
useDisclosure,
|
|
} from "@chakra-ui/react";
|
|
|
|
async function destroySession() {
|
|
await fetch("/api/auth/session", {
|
|
method: "DELETE",
|
|
}).catch(() => {});
|
|
|
|
location.assign("/");
|
|
}
|
|
|
|
function getAvatarUrl(userData: { [k: string]: any }): string {
|
|
const BASE = "https://cdn.discordapp.com/";
|
|
|
|
if (!userData.id || typeof window["BigInt"] === "undefined") return "";
|
|
|
|
if (!userData.avatar)
|
|
return BASE + `embed/avatars/${(BigInt(userData.id) >> 22n) % 6n}.png`;
|
|
|
|
return BASE + `avatars/${userData.id}/${userData.avatar}`;
|
|
}
|
|
|
|
export default function (props: {
|
|
avatar?: string;
|
|
discriminator?: string;
|
|
email?: string;
|
|
hide?: boolean;
|
|
id?: string;
|
|
permissions?: number;
|
|
username?: string;
|
|
}) {
|
|
let data = { ...props };
|
|
const { isOpen, onClose, onOpen } = useDisclosure();
|
|
|
|
function hasMod(): boolean {
|
|
const { permissions } = props;
|
|
|
|
if (typeof permissions === "undefined") return false;
|
|
|
|
return Boolean(
|
|
[
|
|
1 << 0,
|
|
1 << 2,
|
|
1 << 4,
|
|
1 << 5,
|
|
1 << 6,
|
|
1 << 7,
|
|
1 << 8,
|
|
1 << 9,
|
|
1 << 10,
|
|
1 << 11,
|
|
].find((int) => permissions & int)
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Box as="section" pb={{ base: "6" }}>
|
|
<Box as="nav" boxSizing="unset">
|
|
<Container display="grid" maxW="container.xl" py={{ base: "6" }}>
|
|
<Container
|
|
alignItems="center"
|
|
className="mobile-nav"
|
|
display="flex"
|
|
gridColumn="1"
|
|
gridRow="1"
|
|
justifyContent="space-between"
|
|
p="0"
|
|
w="calc(100vw - 6rem)"
|
|
>
|
|
<a href="/">
|
|
<img
|
|
src="/files/logo192.png"
|
|
alt="Car Crushers Logo"
|
|
style={{ width: "36px" }}
|
|
/>
|
|
</a>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
fill="currentColor"
|
|
viewBox="0 0 16 16"
|
|
onClick={onOpen}
|
|
>
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"
|
|
/>
|
|
</svg>
|
|
</Container>
|
|
<Flex
|
|
alignSelf="center"
|
|
className="desktop-nav"
|
|
display="flex"
|
|
gap="0.5rem"
|
|
gridColumn="1"
|
|
gridRow="1"
|
|
justifyContent="space-between"
|
|
p="0"
|
|
textAlign="center"
|
|
>
|
|
<a href="/" style={{ alignSelf: "center" }}>
|
|
<img
|
|
src="/files/logo192.png"
|
|
width="32"
|
|
alt="Car Crushers Logo"
|
|
/>
|
|
</a>
|
|
<Spacer />
|
|
<Spacer />
|
|
<Center gap="1.25rem" whiteSpace="nowrap">
|
|
<Button as="a" href="/about" variant="ghost">
|
|
About Us
|
|
</Button>
|
|
<Button as="a" href="/team" variant="ghost">
|
|
Our Team
|
|
</Button>
|
|
<Button as="a" href="/support" variant="ghost">
|
|
Support
|
|
</Button>
|
|
<Button
|
|
as="a"
|
|
display={hasMod() ? undefined : "none"}
|
|
href="/mod-queue"
|
|
variant="ghost"
|
|
>
|
|
Moderation
|
|
</Button>
|
|
</Center>
|
|
<Spacer />
|
|
<Spacer />
|
|
{data.hide ? null : data.id ? (
|
|
<HStack spacing="3">
|
|
<Avatar
|
|
display={data.id ? "flex" : "none"}
|
|
src={getAvatarUrl(data)}
|
|
/>
|
|
<Text>{data.id ? data.username : ""}</Text>
|
|
<Button
|
|
onClick={async () => await destroySession()}
|
|
size="md"
|
|
style={{ display: data.id ? "block" : "none" }}
|
|
variant="ghost"
|
|
>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="24"
|
|
height="24"
|
|
fill="currentColor"
|
|
viewBox="0 0 16 16"
|
|
>
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M10 12.5a.5.5 0 0 1-.5.5h-8a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h8a.5.5 0 0 1 .5.5v2a.5.5 0 0 0 1 0v-2A1.5 1.5 0 0 0 9.5 2h-8A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h8a1.5 1.5 0 0 0 1.5-1.5v-2a.5.5 0 0 0-1 0v2z"
|
|
/>
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M15.854 8.354a.5.5 0 0 0 0-.708l-3-3a.5.5 0 0 0-.708.708L14.293 7.5H5.5a.5.5 0 0 0 0 1h8.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3z"
|
|
/>
|
|
</svg>
|
|
</Button>
|
|
</HStack>
|
|
) : (
|
|
<Button>Log In</Button>
|
|
)}
|
|
</Flex>
|
|
</Container>
|
|
</Box>
|
|
</Box>
|
|
<Drawer isOpen={isOpen} onClose={onClose} placement="left">
|
|
<DrawerOverlay />
|
|
<DrawerContent gap="1.5vh" p="1.5vh">
|
|
<CloseButton onClick={onClose} />
|
|
<hr />
|
|
<Link href="/about">About Us</Link>
|
|
<Link href="/team">Our Team</Link>
|
|
<Link href="/support">Support</Link>
|
|
<Link href="/mod-queue" display={hasMod() ? undefined : "none"}>
|
|
Moderation
|
|
</Link>
|
|
<hr />
|
|
<Flex alignItems="center" gap="1rem">
|
|
<Link display={data.id ? "none" : ""} href="/api/auth/oauth">
|
|
Log In
|
|
</Link>
|
|
<Avatar display={data.id ? "" : "none"} src={getAvatarUrl(data)} />
|
|
<Text align="center" style={{ overflowWrap: "anywhere" }}>
|
|
{data.id ? data.username : ""}
|
|
</Text>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="24"
|
|
height="24"
|
|
fill="currentColor"
|
|
viewBox="0 0 16 16"
|
|
style={{
|
|
cursor: "pointer",
|
|
display: data.id ? "block" : "none",
|
|
}}
|
|
onClick={async () => destroySession()}
|
|
>
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M10 12.5a.5.5 0 0 1-.5.5h-8a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h8a.5.5 0 0 1 .5.5v2a.5.5 0 0 0 1 0v-2A1.5 1.5 0 0 0 9.5 2h-8A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h8a1.5 1.5 0 0 0 1.5-1.5v-2a.5.5 0 0 0-1 0v2z"
|
|
/>
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M15.854 8.354a.5.5 0 0 0 0-.708l-3-3a.5.5 0 0 0-.708.708L14.293 7.5H5.5a.5.5 0 0 0 0 1h8.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3z"
|
|
/>
|
|
</svg>
|
|
</Flex>
|
|
</DrawerContent>
|
|
</Drawer>
|
|
</>
|
|
);
|
|
}
|