Some checks failed
Release / release (push) Has been cancelled
Full-stack dashboard for controlling, automating, and analyzing Artifacts MMO characters via the game's HTTP API. Backend (FastAPI): - Async Artifacts API client with rate limiting and retry - 6 automation strategies (combat, gathering, crafting, trading, task, leveling) - Automation engine with runner, manager, cooldown tracker, pathfinder - WebSocket relay (game server -> frontend) - Game data cache, character snapshots, price history, analytics - 9 API routers, 7 database tables, 3 Alembic migrations - 108 unit tests Frontend (Next.js 15 + shadcn/ui): - Live character dashboard with HP/XP bars and cooldowns - Character detail with stats, equipment, inventory, skills, manual actions - Automation management with live log streaming - Interactive canvas map with content-type coloring and zoom/pan - Bank management, Grand Exchange with price charts - Events, logs, analytics pages with Recharts - WebSocket auto-reconnect with query cache invalidation - Settings page, error boundaries, dark theme Infrastructure: - Docker Compose (dev + prod) - GitHub Actions CI/CD - Documentation (Architecture, Automation, Deployment, API)
122 lines
3.3 KiB
TypeScript
122 lines
3.3 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { usePathname } from "next/navigation";
|
|
import { useState } from "react";
|
|
import {
|
|
LayoutDashboard,
|
|
Bot,
|
|
Map,
|
|
Landmark,
|
|
ArrowLeftRight,
|
|
Zap,
|
|
ScrollText,
|
|
BarChart3,
|
|
Settings,
|
|
ChevronLeft,
|
|
ChevronRight,
|
|
Swords,
|
|
} from "lucide-react";
|
|
import { cn } from "@/lib/utils";
|
|
import { NAV_ITEMS } from "@/lib/constants";
|
|
import { Button } from "@/components/ui/button";
|
|
import {
|
|
Tooltip,
|
|
TooltipContent,
|
|
TooltipProvider,
|
|
TooltipTrigger,
|
|
} from "@/components/ui/tooltip";
|
|
|
|
const ICON_MAP: Record<string, React.ComponentType<{ className?: string }>> = {
|
|
LayoutDashboard,
|
|
Bot,
|
|
Map,
|
|
Landmark,
|
|
ArrowLeftRight,
|
|
Zap,
|
|
ScrollText,
|
|
BarChart3,
|
|
Settings,
|
|
};
|
|
|
|
export function Sidebar() {
|
|
const pathname = usePathname();
|
|
const [collapsed, setCollapsed] = useState(false);
|
|
|
|
return (
|
|
<TooltipProvider>
|
|
<aside
|
|
className={cn(
|
|
"hidden md:flex flex-col h-screen border-r border-border bg-card transition-all duration-300 shrink-0",
|
|
collapsed ? "w-[60px]" : "w-[240px]"
|
|
)}
|
|
>
|
|
{/* Logo / Title */}
|
|
<div className="flex items-center gap-2 px-4 h-14 border-b border-border shrink-0">
|
|
<Swords className="size-5 text-primary shrink-0" />
|
|
{!collapsed && (
|
|
<span className="font-semibold text-lg tracking-tight text-foreground">
|
|
Artifacts
|
|
</span>
|
|
)}
|
|
</div>
|
|
|
|
{/* Navigation */}
|
|
<nav className="flex-1 flex flex-col gap-1 p-2 overflow-y-auto">
|
|
{NAV_ITEMS.map((item) => {
|
|
const Icon = ICON_MAP[item.icon];
|
|
const isActive =
|
|
pathname === item.href || pathname.startsWith(item.href + "/");
|
|
|
|
const linkContent = (
|
|
<Link
|
|
href={item.href}
|
|
className={cn(
|
|
"flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors",
|
|
isActive
|
|
? "bg-accent text-accent-foreground"
|
|
: "text-muted-foreground hover:bg-accent/50 hover:text-foreground"
|
|
)}
|
|
>
|
|
{Icon && <Icon className="size-4 shrink-0" />}
|
|
{!collapsed && <span>{item.label}</span>}
|
|
</Link>
|
|
);
|
|
|
|
if (collapsed) {
|
|
return (
|
|
<Tooltip key={item.href}>
|
|
<TooltipTrigger asChild>{linkContent}</TooltipTrigger>
|
|
<TooltipContent side="right">
|
|
<p>{item.label}</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
);
|
|
}
|
|
|
|
return <div key={item.href}>{linkContent}</div>;
|
|
})}
|
|
</nav>
|
|
|
|
{/* Collapse toggle */}
|
|
<div className="border-t border-border p-2 shrink-0">
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={() => setCollapsed(!collapsed)}
|
|
className="w-full justify-center"
|
|
>
|
|
{collapsed ? (
|
|
<ChevronRight className="size-4" />
|
|
) : (
|
|
<>
|
|
<ChevronLeft className="size-4" />
|
|
<span>Collapse</span>
|
|
</>
|
|
)}
|
|
</Button>
|
|
</div>
|
|
</aside>
|
|
</TooltipProvider>
|
|
);
|
|
}
|