import { useContext, useEffect, useRef, useState, type KeyboardEvent } from 'react'; import { ChevronDown, LogOut, UserRound } from 'lucide-react'; import { logout } from './api'; import { AuthContext } from './AuthGate'; import { canLeaveCurrentScreen } from './navigationGuard'; // TopBar sign-out control (#295). Shows the authenticated username and a Sign out action: it consults the // unsaved-changes guard first (so a dirty draft isn't lost), POSTs `/api/v1/auth/logout` (the client adds the // required X-CSRF header), and on 204 flips the boot gate back to the login screen via AuthContext.signOut. export function UserMenu() { const { username, signOut } = useContext(AuthContext); const [open, setOpen] = useState(false); const [signingOut, setSigningOut] = useState(false); const menuRef = useRef(null); useEffect(() => { if (open) { menuRef.current?.focus(); } }, [open]); const onMenuKeyDown = (event: KeyboardEvent) => { if (event.key === 'Escape') { setOpen(false); } }; const onSignOut = () => { if (signingOut || !canLeaveCurrentScreen()) { return; } setSigningOut(true); logout() .then(() => { setOpen(false); signOut(); }) .catch(() => { // A failed logout leaves the session intact; drop the busy state so the user can retry. setSigningOut(false); }); }; const label = username ?? 'Account'; return (
{open && ( <>
)} ); }