The weeb for the next gen discord boat - Wamellow
wamellow.com
bot
discord
1"use client";
2
3import type { User } from "@/common/user";
4import { userStore } from "@/common/user";
5import { webStore } from "@/common/webstore";
6import { LoginButton } from "@/components/login-button";
7import { Avatar, AvatarImage } from "@/components/ui/avatar";
8import {
9 DropdownMenu,
10 DropdownMenuContent,
11 DropdownMenuGroup,
12 DropdownMenuItem,
13 DropdownMenuLabel,
14 DropdownMenuSeparator,
15 DropdownMenuTrigger
16} from "@/components/ui/dropdown-menu";
17import { authorize } from "@/utils/authorize-user";
18import Link from "next/link";
19import { useEffect, useState } from "react";
20import { HiBookOpen, HiChevronDown, HiIdentification, HiLogout, HiSparkles, HiSupport, HiTerminal, HiViewGridAdd } from "react-icons/hi";
21
22import { Skeleton } from "./ui/skeleton";
23
24enum State {
25 Idle = 0,
26 Loading = 1,
27 Failure = 2
28}
29
30export function Header() {
31 const [state, setState] = useState<State>(State.Loading);
32 const user = userStore((s) => s);
33
34 useEffect(() => {
35 authorize({ setState })
36 .then((_user) => {
37 userStore.setState({
38 ...(_user || {}),
39 __fetched: true
40 });
41 });
42
43 webStore.setState({
44 width: window?.innerWidth
45 });
46 }, []);
47
48 if (state === State.Failure) {
49 return <LoginButton state={state} className="ml-auto" />;
50 }
51
52 if (state === State.Loading || !user) {
53 return (
54 <div className="ml-auto flex items-center py-2 px-4">
55 <Skeleton className="rounded-full mr-2 size-[30px]" />
56 <Skeleton className="rounded-xl w-20 h-5" />
57 </div>
58 );
59 }
60
61 return <Dropdown user={user} />;
62}
63
64function Dropdown({ user }: { user: User; }) {
65 return (
66 <DropdownMenu>
67 <DropdownMenuTrigger asChild>
68 <button
69 className="ml-auto truncate flex hover:bg-wamellow py-2 px-4 rounded-lg duration-200 items-center data-[state=open]:bg-wamellow outline-none"
70 >
71 <Avatar className="size-[30px] mr-2">
72 <AvatarImage
73 alt={user.username}
74 src={user.avatar ? `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}?size=96` : "/discord.webp"}
75 />
76 </Avatar>
77
78 <p className="mr-1 relative bottom-px truncate block text-primary-foreground font-medium tracking-tight">{user.globalName || user.username}</p>
79 <HiChevronDown />
80 </button>
81 </DropdownMenuTrigger>
82 <DropdownMenuContent className='w-56 scale-120 relative top-7 right-5' align="end">
83 <DropdownMenuLabel className='flex items-center gap-3'>
84 <Avatar>
85 <AvatarImage
86 alt={user.username}
87 src={user.avatar ? `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}?size=96` : "/discord.webp"}
88 />
89 </Avatar>
90 <div className='flex flex-col pb-0.5 truncate'>
91 <span className='text-popover-foreground truncate'>{user.globalName || user.username}</span>
92 <span className='text-muted-foreground text-xs truncate'>{user.email}</span>
93 </div>
94 </DropdownMenuLabel>
95 <DropdownMenuSeparator />
96 <DropdownMenuGroup>
97 <DropdownMenuItem asChild>
98 <Link href="/profile">
99 <HiViewGridAdd />
100 Dashboard
101 </Link>
102 </DropdownMenuItem>
103 <DropdownMenuItem asChild>
104 <Link href="/profile">
105 <HiIdentification />
106 Profile
107 </Link>
108 </DropdownMenuItem>
109 <DropdownMenuItem asChild>
110 <Link href={user.premium ? "/profile/billing" : "/premium"}>
111 <HiSparkles />
112 {user.premium ? "Billing" : "Premium"}
113 </Link>
114 </DropdownMenuItem>
115 </DropdownMenuGroup>
116 <DropdownMenuSeparator />
117 <DropdownMenuGroup>
118 <DropdownMenuItem asChild>
119 <Link href="/support">
120 <HiSupport />
121 Support
122 </Link>
123 </DropdownMenuItem>
124 <DropdownMenuItem asChild>
125 <Link href="/docs/index">
126 <HiBookOpen />
127 Documentation
128 </Link>
129 </DropdownMenuItem>
130 <DropdownMenuItem disabled>
131 <HiTerminal />
132 Developer API
133 </DropdownMenuItem>
134 </DropdownMenuGroup>
135 <DropdownMenuSeparator />
136 <DropdownMenuGroup>
137 <DropdownMenuItem
138 asChild
139 className="text-red-400"
140 >
141 <Link href="/login?logout=true" prefetch={false}>
142 <HiLogout />
143 Logout
144 </Link>
145 </DropdownMenuItem>
146 </DropdownMenuGroup>
147 </DropdownMenuContent>
148 </DropdownMenu>
149 );
150}