feat: implement login auth for all

also show the username underneath the logo
This commit is contained in:
2025-03-06 13:29:10 +01:00
parent 99e80c8077
commit 8b092fed51
9 changed files with 252 additions and 108 deletions

99
src/Avatar.tsx Normal file
View File

@@ -0,0 +1,99 @@
import { MouseEventHandler, useEffect, useState } from "react";
import { useSession } from "./Session";
import { logout } from "./api";
interface ContextMenuItem {
label: string;
onClick: () => void;
}
export default function Avatar() {
const { user, onLogout } = useSession();
const [contextMenu, setContextMenu] = useState<{
open: boolean;
mouseX: number;
mouseY: number;
}>({ open: false, mouseX: 0, mouseY: 0 });
const contextMenuItems: ContextMenuItem[] = [
{ label: "View Profile", onClick: () => console.log("View Profile") },
{ label: "Edit Profile", onClick: () => console.log("Edit Profile") },
{ label: "Logout", onClick: onLogout },
];
const handleMenuClick: MouseEventHandler<HTMLDivElement> = (event) => {
event.preventDefault();
setContextMenu({
open: !contextMenu.open,
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 });
};
const handleCloseContextMenuOutside: MouseEventHandler<Document> = (
event
) => {
if (
!event.target ||
(!(event.target as Element).closest(".context-menu") &&
!(event.target as Element).closest(".avatar"))
) {
handleMenuClose();
}
};
return (
<div
className="avatar"
onContextMenu={handleMenuClick}
style={{ display: user ? "block" : "none" }}
onClick={handleMenuClick}
>
{user?.username}
{contextMenu.open && (
<ul
className="context-menu"
style={{
zIndex: 3,
position: "absolute",
top: contextMenu.mouseY,
left: contextMenu.mouseX,
background: "white",
border: "1px solid #ddd",
padding: 0,
margin: 0,
listStyle: "none",
}}
>
{contextMenuItems.map((item, index) => (
<li
key={index}
style={{
padding: "10px",
borderBottom: "1px solid #ddd",
cursor: "pointer",
}}
onClick={() => {
item.onClick();
handleMenuClose();
}}
>
{item.label}
</li>
))}
</ul>
)}
</div>
);
}