"use client";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { Command } from "cmdk";
import { useTheme } from "next-themes";
import {
LayoutDashboard,
Mic2,
ListMusic,
BarChart3,
CreditCard,
Users,
KeyRound,
Settings,
Plus,
Moon,
Sun,
Search,
} from "lucide-react";
interface PaletteRoute {
label: string;
href: string;
icon: React.ComponentType<{ className?: string }>;
keywords?: string[];
}
const ROUTES: PaletteRoute[] = [
{ label: "Dashboard", href: "/dashboard", icon: LayoutDashboard, keywords: ["home"] },
{ label: "Episodes", href: "/episodes", icon: Mic2, keywords: ["library", "podcasts"] },
{ label: "Series", href: "/series", icon: ListMusic, keywords: ["season"] },
{ label: "Usage", href: "/usage", icon: BarChart3, keywords: ["limits", "quota"] },
{ label: "Billing", href: "/billing", icon: CreditCard, keywords: ["plan", "upgrade", "subscription"] },
{ label: "Team", href: "/team", icon: Users, keywords: ["members", "workspace", "branding"] },
{ label: "API keys", href: "/api-keys", icon: KeyRound, keywords: ["developer", "token"] },
{ label: "Settings", href: "/settings", icon: Settings, keywords: ["account", "profile"] },
];
/**
* Global ⌘K / Ctrl-K command palette. Provides "New episode", jump-to-route
* navigation, and a theme toggle. Mounted once in the app layout.
*/
export function CommandPalette() {
const router = useRouter();
const { resolvedTheme, setTheme } = useTheme();
const [open, setOpen] = useState(false);
useEffect(() => {
function onKey(e: KeyboardEvent) {
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
e.preventDefault();
setOpen((o) => !o);
}
}
document.addEventListener("keydown", onKey);
return () => document.removeEventListener("keydown", onKey);
}, []);
function run(action: () => void) {
setOpen(false);
action();
}
const isDark = resolvedTheme === "dark";
return (
No results found.
run(() => router.push("/episodes/new"))}
/>
run(() => setTheme(isDark ? "light" : "dark"))}
/>
{ROUTES.map((r) => (
run(() => router.push(r.href))}
/>
))}
);
}
function PaletteItem({
label,
keywords,
icon: Icon,
onSelect,
}: {
label: string;
keywords?: string[];
icon: React.ComponentType<{ className?: string }>;
onSelect: () => void;
}) {
return (
{label}
);
}