import { ReactNode, useEffect, useRef, useState } from "react";
import { Link, NavLink, useNavigate } from "react-router-dom";
import { useAuth } from "../context/AuthContext";
import { useNotifications } from "../context/NotificationsContext";
import { NotificationBell } from "./NotificationBell";
import { Sheet } from "./Sheet";
import {
AgentsIcon,
BellIcon,
HomeIcon,
LogOutIcon,
RequestsIcon,
SettingsIcon,
ShieldIcon,
} from "./icons";
const navItems = [
{ to: "/", label: "Dashboard", end: true },
{ to: "/requests", label: "Requests" },
{ to: "/agents", label: "Agents" },
{ to: "/settings", label: "Settings" },
];
const tabs = [
{ to: "/", label: "Home", Icon: HomeIcon, end: true },
{ to: "/requests", label: "Requests", Icon: RequestsIcon },
{ to: "/agents", label: "Agents", Icon: AgentsIcon },
{ to: "/notifications", label: "Alerts", Icon: BellIcon, badge: true },
{ to: "/settings", label: "Settings", Icon: SettingsIcon },
];
export function Layout({ children }: { children: ReactNode }) {
const { user } = useAuth();
return (
PatchPass
{/* Below md the bell is replaced by the Alerts tab. */}
{children}
{/* Keeps the last of the page clear of the fixed tab bar. */}
);
}
function BottomTabs() {
const { unreadCount } = useNotifications();
return (
);
}
function AccountMenu() {
const { user, logout } = useAuth();
const navigate = useNavigate();
const [open, setOpen] = useState(false);
const ref = useRef(null);
useEffect(() => {
if (!open) return;
const onDown = (e: MouseEvent) => {
if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);
};
document.addEventListener("mousedown", onDown);
return () => document.removeEventListener("mousedown", onDown);
}, [open]);
const signOut = async () => {
setOpen(false);
await logout();
navigate("/login");
};
const initial = user?.display_name?.[0]?.toUpperCase() ?? "?";
return (
{/* Desktop: dropdown. */}
{open && (
setOpen(false)}>
Settings
{user?.role === "ADMIN" && (
setOpen(false)} accent>
Admin
)}
)}
{/* Mobile: bottom sheet, which is reachable one-handed. */}
setOpen(false)} padded={false}>
{initial}
{user?.display_name}
@{user?.username}
}
label="Settings"
onClick={() => {
setOpen(false);
navigate("/settings");
}}
/>
{user?.role === "ADMIN" && (
}
label="Admin"
accent
onClick={() => {
setOpen(false);
navigate("/admin");
}}
/>
)}
}
label="Log out"
danger
onClick={signOut}
/>
);
}
function MenuLink({
to,
onClick,
accent,
children,
}: {
to: string;
onClick: () => void;
accent?: boolean;
children: ReactNode;
}) {
return (
{children}
);
}
function SheetRow({
icon,
label,
onClick,
accent,
danger,
}: {
icon: ReactNode;
label: string;
onClick: () => void;
accent?: boolean;
danger?: boolean;
}) {
return (
);
}