2025-06-11 09:35:10 +00:00
|
|
|
import { createSignal, Show, Switch, Match } from "solid-js";
|
2024-10-30 22:38:29 +00:00
|
|
|
import { useStore } from "@nanostores/solid";
|
|
|
|
|
import { TbUser } from "solid-icons/tb";
|
|
|
|
|
import { type User } from "trailbase";
|
|
|
|
|
|
|
|
|
|
import { urlSafeBase64ToUuid } from "@/lib/utils";
|
|
|
|
|
import { client, $user } from "@/lib/fetch";
|
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
|
import {
|
|
|
|
|
Dialog,
|
|
|
|
|
DialogContent,
|
|
|
|
|
DialogFooter,
|
|
|
|
|
DialogHeader,
|
|
|
|
|
DialogTitle,
|
|
|
|
|
} from "@/components/ui/dialog";
|
2024-11-03 13:01:17 +00:00
|
|
|
import { navBarIconSize, navBarIconStyle } from "@/components/NavBar";
|
2024-10-30 22:38:29 +00:00
|
|
|
|
2025-06-07 11:00:18 +00:00
|
|
|
function avatarUrl(user: User): string {
|
|
|
|
|
return import.meta.env.DEV
|
|
|
|
|
? `http://localhost:4000/api/auth/v1/avatar/${user.id}`
|
|
|
|
|
: `/api/auth/v1/avatar/${user.id}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Avatar(props: { user: User | undefined; size: number }) {
|
|
|
|
|
return (
|
2025-06-11 09:35:10 +00:00
|
|
|
<Switch>
|
|
|
|
|
<Match when={props.user === undefined}>
|
|
|
|
|
<TbUser size={props.size} color="#0073aa" />
|
|
|
|
|
</Match>
|
|
|
|
|
|
|
|
|
|
<Match when={props.user !== undefined}>
|
|
|
|
|
<object
|
|
|
|
|
class="rounded-full bg-transparent"
|
|
|
|
|
type="image/png"
|
|
|
|
|
data={avatarUrl(props.user!)}
|
|
|
|
|
width={props.size}
|
|
|
|
|
height={props.size}
|
|
|
|
|
aria-label="Avatar image"
|
|
|
|
|
>
|
|
|
|
|
{/* Fallback */}
|
|
|
|
|
<TbUser size={props.size} color="#0073aa" />
|
|
|
|
|
</object>
|
|
|
|
|
</Match>
|
|
|
|
|
</Switch>
|
2025-06-07 11:00:18 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-30 22:38:29 +00:00
|
|
|
function Profile(props: { user: User }) {
|
|
|
|
|
return (
|
2025-06-07 11:00:18 +00:00
|
|
|
<div class="flex gap-4">
|
|
|
|
|
<div class="flex items-center">
|
|
|
|
|
<Avatar user={props.user} size={60} />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="flex flex-col gap-2">
|
2025-08-04 20:38:24 +00:00
|
|
|
<div>Email: {props.user.email}</div>
|
2024-10-30 22:38:29 +00:00
|
|
|
|
2025-06-07 11:00:18 +00:00
|
|
|
<div>id: {urlSafeBase64ToUuid(props.user.id)}</div>
|
2024-10-30 22:38:29 +00:00
|
|
|
|
2025-06-07 11:00:18 +00:00
|
|
|
{import.meta.env.DEV && <div>id b64: {props.user.id}</div>}
|
|
|
|
|
</div>
|
2024-10-30 22:38:29 +00:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function AuthButton() {
|
|
|
|
|
const [open, setOpen] = createSignal(false);
|
|
|
|
|
const user = useStore($user);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Dialog open={open()} onOpenChange={setOpen}>
|
2024-11-03 13:01:17 +00:00
|
|
|
<button class={navBarIconStyle} onClick={() => setOpen(true)}>
|
2025-06-07 11:00:18 +00:00
|
|
|
<Avatar user={user()} size={navBarIconSize} />
|
2024-10-30 22:38:29 +00:00
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<DialogContent class="sm:max-w-[425px]">
|
|
|
|
|
<DialogHeader>
|
|
|
|
|
<DialogTitle>Current User</DialogTitle>
|
|
|
|
|
</DialogHeader>
|
|
|
|
|
|
|
|
|
|
<Show when={user()}>
|
|
|
|
|
<Profile user={user()!} />
|
|
|
|
|
</Show>
|
|
|
|
|
|
|
|
|
|
<DialogFooter>
|
|
|
|
|
<Button
|
|
|
|
|
type="Logout"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
client.logout();
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
Logout
|
|
|
|
|
</Button>
|
|
|
|
|
</DialogFooter>
|
|
|
|
|
</DialogContent>
|
|
|
|
|
</Dialog>
|
|
|
|
|
);
|
|
|
|
|
}
|