import { createRef, MouseEventHandler, useEffect, useState } from "react"; import { TeamState, useSession } from "./Session"; import { User } from "./api"; import { useTheme } from "./ThemeProvider"; import { colourTheme, darkTheme, normalTheme, rainbowTheme } from "./themes"; import { useNavigate } from "react-router"; import { Team } from "./types"; interface ContextMenuItem { label: string; onClick: () => void; } const UserInfo = (user: User, teams: TeamState | undefined) => { return (
username:
{user?.username}
display name:
{user?.display_name}
number:
{user?.number || "-"}
email:
{user?.email || "-"}
{teams && ( <>
teams:
)}
); }; export default function Avatar() { const { user, teams, setTeams, onLogout } = useSession(); const { theme, setTheme } = useTheme(); const navigate = useNavigate(); const [contextMenu, setContextMenu] = useState<{ open: boolean; allowOpen: boolean; mouseX: number; mouseY: number; }>({ open: false, allowOpen: true, mouseX: 0, mouseY: 0 }); const contextMenuRef = createRef(); const avatarRef = createRef(); const contextMenuItems: ContextMenuItem[] = [ { label: "view Profile", onClick: handleViewProfile }, { label: "change password", onClick: () => navigate("/changepassword") }, { label: "change theme", onClick: () => { switch (theme) { case darkTheme: setTheme(colourTheme); break; case colourTheme: setTheme(rainbowTheme); break; case rainbowTheme: setTheme(normalTheme); break; case normalTheme: setTheme(darkTheme); } }, }, { label: "logout", onClick: onLogout }, ]; const handleMenuClick: MouseEventHandler = (event) => { if (!contextMenu.allowOpen) return; event.preventDefault(); setContextMenu({ open: !contextMenu.open, allowOpen: contextMenu.allowOpen, mouseX: event.clientX + 4, mouseY: event.clientY + 2, }); }; useEffect(() => { if (contextMenu.open) { document.addEventListener("click", handleCloseContextMenuOutside); } return () => { document.removeEventListener("click", handleCloseContextMenuOutside); }; }, [contextMenu.open]); const handleMenuClose = () => { setContextMenu({ ...contextMenu, open: false }); setContextMenu((prevContextMenu) => ({ ...prevContextMenu, allowOpen: false, })); setTimeout(() => { setContextMenu((prevContextMenu) => ({ ...prevContextMenu, allowOpen: true, })); }, 100); }; const handleCloseContextMenuOutside: (event: MouseEvent) => void = (ev) => { if ( !( contextMenuRef.current?.contains(ev.target as Node) || avatarRef.current?.contains(ev.target as Node) ) ) handleMenuClose(); }; const [dialog, setDialog] = useState(<>); const dialogRef = createRef(); function handleViewProfile() { if (user && teams) { dialogRef.current?.showModal(); setDialog(UserInfo(user, teams)); } } return ( <>
{ if (contextMenu.open && event.target === avatarRef.current) { handleMenuClose(); } else { handleMenuClick(event); } }} ref={avatarRef} > 👤 {user?.username}
{teams && teams?.teams.length > 1 && ( )}
{contextMenu.open && (
    {contextMenuItems.map((item, index) => (
  • { item.onClick(); handleMenuClose(); }} > {item.label}
  • ))}
)} { event.stopPropagation(); event.currentTarget.close(); }} > {dialog} ); }