import { useRouter } from "next/navigation"; import { Sparkles } from "lucide-react"; import Image from "next/image"; import React from "react"; import type { Category, Script } from "@/lib/types"; import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; import { basePath } from "@/config/site-config"; import { fetchCategories } from "@/lib/data"; import { cn } from "@/lib/utils"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/tooltip"; import { DialogTitle } from "./ui/dialog"; import { Button } from "./ui/button"; import { Badge } from "./ui/badge"; export function formattedBadge(type: string) { switch (type) { case "vm": return VM; case "ct": return LXC; case "pve": return PVE; case "addon": return ADDON; } return null; } function getRandomScript(categories: Category[], previouslySelected: Set = new Set()): Script | null { const allScripts = categories.flatMap(cat => cat.scripts || []); if (allScripts.length === 0) return null; const availableScripts = allScripts.filter(script => !previouslySelected.has(script.slug)); if (availableScripts.length === 0) { return allScripts[Math.floor(Math.random() * allScripts.length)]; } const idx = Math.floor(Math.random() * availableScripts.length); return availableScripts[idx]; } function CommandMenu() { const [open, setOpen] = React.useState(false); const [links, setLinks] = React.useState([]); const [isLoading, setIsLoading] = React.useState(false); const [selectedScripts, setSelectedScripts] = React.useState>(new Set()); const router = useRouter(); const fetchSortedCategories = () => { setIsLoading(true); fetchCategories() .then((categories) => { setLinks(categories); setIsLoading(false); }) .catch((error) => { setIsLoading(false); console.error(error); }); }; React.useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === "k" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); fetchSortedCategories(); setOpen(open => !open); } }; document.addEventListener("keydown", handleKeyDown); return () => document.removeEventListener("keydown", handleKeyDown); }, []); const handleOpenRandomScript = async () => { if (links.length === 0) { setIsLoading(true); try { const categories = await fetchCategories(); setLinks(categories); const randomScript = getRandomScript(categories, selectedScripts); if (randomScript) { setSelectedScripts(prev => new Set([...prev, randomScript.slug])); router.push(`/scripts?id=${randomScript.slug}`); } } finally { setIsLoading(false); } } else { const randomScript = getRandomScript(links, selectedScripts); if (randomScript) { setSelectedScripts(prev => new Set([...prev, randomScript.slug])); router.push(`/scripts?id=${randomScript.slug}`); } } }; const getUniqueScriptsMap = React.useCallback(() => { const scriptMap = new Map(); for (const category of links) { for (const script of category.scripts) { if (!scriptMap.has(script.slug)) { scriptMap.set(script.slug, { script, categoryName: category.name }); } } } return scriptMap; }, [links]); const getUniqueScriptsByCategory = React.useCallback(() => { const scriptMap = getUniqueScriptsMap(); const categoryOrder = links.map(cat => cat.name); const grouped: Record = {}; for (const name of categoryOrder) { grouped[name] = []; } for (const { script, categoryName } of scriptMap.values()) { if (grouped[categoryName]) { grouped[categoryName].push(script); } else { grouped[categoryName] = [script]; } } Object.keys(grouped).forEach((cat) => { if (grouped[cat].length === 0) delete grouped[cat]; }); return grouped; }, [getUniqueScriptsMap, links]); const uniqueScriptsByCategory = getUniqueScriptsByCategory(); return ( <> { fetchSortedCategories(); setOpen(true); }} > Search scripts... ⌘ K { if (e.key === "Enter" || e.key === " ") { handleOpenRandomScript(); } }} > Open Random Script Open Random Script Search scripts {isLoading ? "Loading..." : "No scripts found."} {Object.entries(uniqueScriptsByCategory).map(([categoryName, scripts]) => ( {scripts.map(script => ( { setOpen(false); router.push(`/scripts?id=${script.slug}`); }} tabIndex={0} aria-label={`Open script ${script.name}`} onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { setOpen(false); router.push(`/scripts?id=${script.slug}`); } }} > setOpen(false)}> ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)} unoptimized width={16} height={16} alt="" className="h-5 w-5" /> {script.name} {formattedBadge(script.type)} ))} ))} > ); } export default CommandMenu;
Open Random Script