52 lines
1.8 KiB
TypeScript
52 lines
1.8 KiB
TypeScript
import { LogOut } from "lucide-react";
|
|
import { useNavigate } from "react-router-dom";
|
|
|
|
import { useLogout, useMe } from "../hooks/auth";
|
|
import { useMyStats } from "../hooks/stats";
|
|
import { Avatar } from "./Avatar";
|
|
|
|
/** Боковое меню, выезжающее из правого края. Сверху — кликабельная плашка аккаунта
|
|
* (краткая сводка → /account), ниже — выход. Открытием управляет AppShell. */
|
|
export function SideMenu({ open, onClose }: { open: boolean; onClose: () => void }) {
|
|
const { data: me } = useMe();
|
|
const { data: stats } = useMyStats();
|
|
const logout = useLogout();
|
|
const navigate = useNavigate();
|
|
|
|
const goAccount = () => {
|
|
onClose();
|
|
navigate("/account");
|
|
};
|
|
|
|
const doLogout = async () => {
|
|
onClose();
|
|
await logout.mutateAsync().catch(() => {});
|
|
navigate("/login", { replace: true });
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<div className={"drawer-overlay" + (open ? " open" : "")} onClick={onClose} />
|
|
<aside className={"side-menu" + (open ? " open" : "")} aria-hidden={!open}>
|
|
{me && (
|
|
<button className="side-account" onClick={goAccount}>
|
|
<Avatar url={me.avatar_url} nickname={me.nickname} size={48} />
|
|
<span className="side-account-info">
|
|
<b>{me.nickname}</b>
|
|
<span className="muted small">
|
|
игр {stats?.overall.games ?? 0} · побед {stats?.overall.wins ?? 0}
|
|
</span>
|
|
</span>
|
|
</button>
|
|
)}
|
|
|
|
<div className="side-menu-items">
|
|
<button className="side-menu-item danger" onClick={doLogout}>
|
|
<LogOut size={18} /> Выйти
|
|
</button>
|
|
</div>
|
|
</aside>
|
|
</>
|
|
);
|
|
}
|