feat(web): re-apply dashboard UI improvements on top of i18n

Re-applies changes from #9471 that were overwritten by the i18n PR:

- URL-based routing via react-router-dom (NavLink, Routes, BrowserRouter)
- Replace emoji icons with lucide-react in ConfigPage and SkillsPage
- Sidebar layout for ConfigPage, SkillsPage, and LogsPage
- Custom dropdown Select component (SelectOption) in CronPage
- Remove all non-functional rounded borders across the UI
- Fixed header with proper content offset

Made-with: Cursor
This commit is contained in:
Austin Pickett 2026-04-14 10:23:43 -04:00
parent 16f9d02084
commit e88aa8a58c
11 changed files with 547 additions and 489 deletions

View file

@ -11,6 +11,22 @@ import {
ChevronRight,
Settings2,
FileText,
Settings,
Bot,
Monitor,
Palette,
Users,
Brain,
Package,
Lock,
Globe,
Mic,
Volume2,
Ear,
ClipboardList,
MessageCircle,
Wrench,
FileQuestion,
} from "lucide-react";
import { api } from "@/lib/api";
import { getNestedValue, setNestedValue } from "@/lib/nested";
@ -27,24 +43,29 @@ import { useI18n } from "@/i18n";
/* Helpers */
/* ------------------------------------------------------------------ */
const CATEGORY_ICONS: Record<string, string> = {
general: "⚙️",
agent: "🤖",
terminal: "💻",
display: "🎨",
delegation: "👥",
memory: "🧠",
compression: "📦",
security: "🔒",
browser: "🌐",
voice: "🎙️",
tts: "🔊",
stt: "👂",
logging: "📋",
discord: "💬",
auxiliary: "🔧",
const CATEGORY_ICONS: Record<string, React.ComponentType<{ className?: string }>> = {
general: Settings,
agent: Bot,
terminal: Monitor,
display: Palette,
delegation: Users,
memory: Brain,
compression: Package,
security: Lock,
browser: Globe,
voice: Mic,
tts: Volume2,
stt: Ear,
logging: ClipboardList,
discord: MessageCircle,
auxiliary: Wrench,
};
function CategoryIcon({ category, className }: { category: string; className?: string }) {
const Icon = CATEGORY_ICONS[category] ?? FileQuestion;
return <Icon className={className ?? "h-4 w-4"} />;
}
/* ------------------------------------------------------------------ */
/* Component */
/* ------------------------------------------------------------------ */
@ -232,7 +253,7 @@ export default function ConfigPage() {
<div key={key}>
{showCatBadge && (
<div className="flex items-center gap-2 pt-4 pb-2 first:pt-0">
<span className="text-base">{CATEGORY_ICONS[cat] || "📄"}</span>
<CategoryIcon category={cat} className="h-4 w-4 text-muted-foreground" />
<span className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
{prettyCategoryName(cat)}
</span>
@ -268,7 +289,7 @@ export default function ConfigPage() {
<div className="flex items-center justify-between gap-4">
<div className="flex items-center gap-2">
<Settings2 className="h-4 w-4 text-muted-foreground" />
<code className="text-xs text-muted-foreground bg-muted/50 px-2 py-0.5 rounded">
<code className="text-xs text-muted-foreground bg-muted/50 px-2 py-0.5">
{t.config.configPath}
</code>
</div>
@ -381,13 +402,13 @@ export default function ConfigPage() {
setSearchQuery("");
setActiveCategory(cat);
}}
className={`group flex items-center gap-2 rounded-md px-2.5 py-1.5 text-left text-xs transition-colors cursor-pointer ${
className={`group flex items-center gap-2 px-2.5 py-1.5 text-left text-xs transition-colors cursor-pointer ${
isActive
? "bg-primary/10 text-primary font-medium"
: "text-muted-foreground hover:text-foreground hover:bg-muted/50"
}`}
>
<span className="text-sm leading-none">{CATEGORY_ICONS[cat] || "📄"}</span>
<CategoryIcon category={cat} className="h-3.5 w-3.5 shrink-0" />
<span className="flex-1 truncate">{prettyCategoryName(cat)}</span>
<span className={`text-[10px] tabular-nums ${isActive ? "text-primary/60" : "text-muted-foreground/50"}`}>
{categoryCounts[cat] || 0}
@ -434,7 +455,7 @@ export default function ConfigPage() {
<CardHeader className="py-3 px-4">
<div className="flex items-center justify-between">
<CardTitle className="text-sm flex items-center gap-2">
<span className="text-base">{CATEGORY_ICONS[activeCategory] || "📄"}</span>
<CategoryIcon category={activeCategory} className="h-4 w-4" />
{prettyCategoryName(activeCategory)}
</CardTitle>
<Badge variant="secondary" className="text-[10px]">