blob: 3811c4a289aa6e058b58369ef41856b6298107c1 [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
"use client";
import { LogOut, Settings } from "lucide-react";
import Link from "next/link";
import { useSession } from "next-auth/react";
import { useSignOut } from "@/shared/auth/useSignOut";
import { Avatar, AvatarFallback } from "@/shared/ui/avatar";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/shared/ui/dropdown-menu";
export function UserPill() {
const { data: session, status } = useSession();
const { signOut, isPending } = useSignOut();
const loading = status === "loading";
const user = session?.user;
const name = user?.name ?? user?.email ?? "Signed out";
const email = user?.email ?? "no session";
const initial = (user?.email ?? name).slice(0, 1).toUpperCase();
return (
<div className="flex items-center gap-3">
<div className="flex flex-col items-end leading-tight">
<span className="text-sm font-semibold text-foreground">{loading ? "..." : name}</span>
<span className="text-xs text-muted-foreground">{email}</span>
</div>
<DropdownMenu>
<DropdownMenuTrigger
render={(props) => (
<button
{...props}
type="button"
aria-label="Account menu"
className="rounded-full outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
>
<Avatar className="h-10 w-10 border-2 border-brand">
<AvatarFallback>{initial}</AvatarFallback>
</Avatar>
</button>
)}
/>
<DropdownMenuContent align="end" className="w-64">
<div className="px-2 py-1.5">
<div className="truncate text-sm font-semibold text-foreground">{name}</div>
<div className="truncate text-xs text-muted-foreground">{email}</div>
</div>
<DropdownMenuSeparator />
<DropdownMenuItem
render={(props) => (
<Link {...props} href="/settings">
<Settings className="mr-2 h-4 w-4" />
Settings
</Link>
)}
/>
<DropdownMenuSeparator />
<DropdownMenuItem
variant="destructive"
disabled={isPending}
onClick={() => void signOut()}
>
<LogOut className="mr-2 h-4 w-4" />
{isPending ? "Signing out…" : "Sign out"}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
);
}