All checks were successful
Deploy to Netlify / Deploy to Netlify (push) Successful in 1m39s
125 lines
4 KiB
TypeScript
125 lines
4 KiB
TypeScript
import { useState } from "react";
|
|
import { Avatar, AvatarFallback } from "~/components/ui/avatar";
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuGroup,
|
|
DropdownMenuItem,
|
|
DropdownMenuLabel,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
} from "~/components/ui/dropdown-menu";
|
|
import {
|
|
ChevronDown,
|
|
LineChartIcon,
|
|
LogOut,
|
|
Moon,
|
|
Settings,
|
|
Sun,
|
|
} from "lucide-react";
|
|
// TODO: THEME
|
|
// import { useTheme } from "~/components/ui/theme-provider";
|
|
import { useNavigate } from "react-router";
|
|
import { logout, type User } from "~/lib/api";
|
|
|
|
export default function UserDropdown({ user }: { user: User }) {
|
|
// TODO: const { theme, setTheme } = useTheme();
|
|
const [theme, setTheme] = useState("light");
|
|
const [open, setOpen] = useState(false);
|
|
const navigate = useNavigate();
|
|
|
|
const handleLogout = async () => {
|
|
try {
|
|
await logout();
|
|
navigate("/login", { replace: true });
|
|
} catch (error) {
|
|
console.error("Logout failed:", error);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<DropdownMenu open={open} onOpenChange={setOpen}>
|
|
<DropdownMenuTrigger asChild>
|
|
<button
|
|
className={
|
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive h-9 px-4 py-2 has-[>svg]:px-3 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 flex items-center gap-2 px-2"
|
|
}
|
|
>
|
|
<Avatar className="h-10 w-10">
|
|
<AvatarFallback>{getAvatar(user.fullName)}</AvatarFallback>
|
|
</Avatar>
|
|
<span className="hidden md:inline-block font-medium">
|
|
{user.fullName}
|
|
</span>
|
|
<ChevronDown className="h-4 w-4 text-muted-foreground" />
|
|
</button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end" className="w-56">
|
|
<DropdownMenuLabel>
|
|
<div className="flex flex-col space-y-1">
|
|
<p className="text-sm font-medium leading-none">
|
|
{user.fullName}
|
|
</p>
|
|
<p className="text-xs leading-none text-muted-foreground">
|
|
{user.className}
|
|
</p>
|
|
</div>
|
|
</DropdownMenuLabel>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuGroup>
|
|
<DropdownMenuItem
|
|
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
|
|
>
|
|
{theme === "dark" ? (
|
|
<>
|
|
<Sun className="mr-2 h-4 w-4" />
|
|
<span>Mode clair</span>
|
|
</>
|
|
) : (
|
|
<>
|
|
<Moon className="mr-2 h-4 w-4" />
|
|
<span>Mode sombre</span>
|
|
</>
|
|
)}
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
navigate("/settings");
|
|
}}>
|
|
<Settings className="mr-2 h-4 w-4" />
|
|
<span>
|
|
Paramètres
|
|
</span>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem onClick={(e) => {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
navigate("/progress");
|
|
}}>
|
|
<LineChartIcon className="mr-2 h-4 w-4" />
|
|
<span
|
|
|
|
>
|
|
Progression
|
|
</span>
|
|
</DropdownMenuItem>
|
|
</DropdownMenuGroup>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem onClick={handleLogout}>
|
|
<LogOut className="mr-2 h-4 w-4" />
|
|
<span >Se déconnecter</span>
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
);
|
|
}
|
|
|
|
const getAvatar = (name: string) => {
|
|
return name
|
|
.split(" ")
|
|
.map((word) => word.charAt(0))
|
|
.join("")
|
|
.toUpperCase();
|
|
};
|