"use client"; import * as React from "react"; import { useRouter } from "next/navigation"; import { toast } from "sonner"; import { User } from "lucide-react"; import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, } from "@/components/ui/command"; import { navigationCommands, type NavigationCommand } from "./commands/navigation"; import { actionCommands, type ActionCommand } from "./commands/actions"; import { CommandPaletteContext, type ContextualCommand, } from "./CommandPaletteContext"; import { markAllNotificationsRead } from "@/app/(frontend)/notifications/actions"; import { autoArrangeLocker } from "@/app/(frontend)/locker/actions"; interface CommandPaletteProps { userRoles: string[]; hasIntelligence: boolean; hasLogistics: boolean; username?: string; } export function CommandPalette({ userRoles, hasIntelligence, hasLogistics, username, }: CommandPaletteProps) { const router = useRouter(); const [open, setOpen] = React.useState(false); const [loading, setLoading] = React.useState(null); const contextualCommands = React.useContext(CommandPaletteContext)?.commands ?? []; React.useEffect(() => { const down = (e: KeyboardEvent) => { if ((e.key === "k" && (e.metaKey || e.ctrlKey)) || e.key === "/") { if ( (e.target instanceof HTMLElement && e.target.isContentEditable) || e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement || e.target instanceof HTMLSelectElement ) { return; } e.preventDefault(); setOpen((prev) => !prev); } }; document.addEventListener("keydown", down); return () => document.removeEventListener("keydown", down); }, []); const runCommand = React.useCallback((command: () => unknown) => { setOpen(false); command(); }, []); const handleCallback = React.useCallback( async (actionKey: string) => { setLoading(actionKey); try { switch (actionKey) { case "markAllRead": { const result = await markAllNotificationsRead(); if (result.success) { toast.success("All notifications marked as read"); } else { toast.error(result.error ?? "Failed to mark notifications"); } break; } case "autoArrangeLocker": { const result = await autoArrangeLocker(); if (result.success) { toast.success("Locker arranged"); } else { toast.error(result.error ?? "Failed to arrange locker"); } break; } case "refreshPage": { router.refresh(); toast.success("Page refreshed"); break; } case "logout": { await fetch("/api/users/logout", { method: "POST" }); window.location.href = "/login"; break; } } } finally { setLoading(null); } }, [router], ); const filteredNavCommands = React.useMemo(() => { const base = navigationCommands.filter((cmd) => { if ( cmd.roles && !cmd.roles.some((r) => userRoles.includes(r) || userRoles.includes("developer")) ) { return false; } if (cmd.requires === "intelligence" && !hasIntelligence && !userRoles.includes("developer")) { return false; } if (cmd.requires === "logistics" && !hasLogistics && !userRoles.includes("developer")) { return false; } return true; }); if (username) { return [ { id: "nav:my-profile", label: "My Profile", icon: User, href: `/profile/${username}`, keywords: ["awards", "rank", "progression", "service record"], }, ...base, ]; } return base; }, [userRoles, hasIntelligence, hasLogistics, username]); const filteredActionCommands = React.useMemo(() => { return actionCommands.filter((cmd) => { if ( cmd.roles && !cmd.roles.some((r) => userRoles.includes(r) || userRoles.includes("developer")) ) { return false; } if (cmd.requires === "intelligence" && !hasIntelligence && !userRoles.includes("developer")) { return false; } if (cmd.requires === "logistics" && !hasLogistics && !userRoles.includes("developer")) { return false; } return true; }); }, [userRoles, hasIntelligence, hasLogistics]); const groupedContextual = React.useMemo(() => { const groups = new Map(); for (const cmd of contextualCommands) { const existing = groups.get(cmd.group) ?? []; existing.push(cmd); groups.set(cmd.group, existing); } return groups; }, [contextualCommands]); return (

No results found.

Try searching for "dashboard", "locker", or "notifications"

{filteredNavCommands.map((cmd) => ( runCommand(() => router.push(cmd.href))} > {cmd.label} {cmd.shortcut && {cmd.shortcut}} ))} {filteredActionCommands.map((cmd) => ( { if (cmd.actionType === "navigate" && cmd.href) { const href = cmd.href; runCommand(() => router.push(href)); } else if (cmd.actionType === "callback" && cmd.actionKey) { const key = cmd.actionKey; runCommand(() => handleCallback(key)); } }} > {cmd.label} ))} {groupedContextual.size > 0 && ( <> {Array.from(groupedContextual.entries()).map(([group, cmds]) => ( {cmds.map((cmd) => ( runCommand(cmd.onSelect)} > {cmd.icon && } {cmd.label} {cmd.shortcut && {cmd.shortcut}} ))} ))} )}
↑↓ navigate ↵ select esc close
⌘K to toggle
); }