Wrap next/link in a shared Link component that ships prefetch=false by default, so no route is ever prefetched (viewport or hover) anymore, and drop the DNS prefetch hint. Removes hidden background requests that were the source of intermittent issues.
78 lines
2.3 KiB
TypeScript
78 lines
2.3 KiB
TypeScript
"use client";
|
|
|
|
import {
|
|
BadgeCheck,
|
|
Cat,
|
|
ClipboardCheck,
|
|
Copy,
|
|
Dumbbell,
|
|
Image as ImageIcon,
|
|
type LucideIcon,
|
|
Puzzle,
|
|
RefreshCw,
|
|
Shirt,
|
|
Upload,
|
|
Wrench,
|
|
} from "lucide-react";
|
|
import { usePathname } from "next/navigation";
|
|
import Link from "@/components/link";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
const TABS: { href: string; label: string; icon: LucideIcon }[] = [
|
|
{ href: "/admin/studio/furni", label: "Furni", icon: Puzzle },
|
|
{ href: "/admin/studio/upload", label: "Upload", icon: Upload },
|
|
{ href: "/admin/studio/badges", label: "Badges", icon: BadgeCheck },
|
|
{ href: "/admin/studio/clothing", label: "Clothing", icon: Shirt },
|
|
{ href: "/admin/studio/effects", label: "Effects", icon: Dumbbell },
|
|
{ href: "/admin/studio/pets", label: "Pets", icon: Cat },
|
|
{ href: "/admin/studio/clone", label: "Clone", icon: Copy },
|
|
{ href: "/admin/studio/sync", label: "Sync", icon: RefreshCw },
|
|
{
|
|
href: "/admin/studio/repair-icons",
|
|
label: "Repair Icons",
|
|
icon: ImageIcon,
|
|
},
|
|
{ href: "/admin/studio/audit", label: "Audit", icon: ClipboardCheck },
|
|
{
|
|
href: "/admin/studio/maintenance",
|
|
label: "Catalogus onderhoud",
|
|
icon: Wrench,
|
|
},
|
|
];
|
|
|
|
export default function StudioLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode;
|
|
}) {
|
|
const pathname = usePathname() ?? "";
|
|
return (
|
|
<div
|
|
className="flex h-[calc(100dvh-7rem)] min-h-[520px] flex-col overflow-hidden rounded-xl border border-[var(--admin-border)]"
|
|
style={{ backgroundColor: "var(--admin-canvas)" }}
|
|
>
|
|
<div className="flex shrink-0 items-center gap-1 overflow-x-auto border-b border-[var(--admin-border)] bg-[var(--admin-surface)] px-2 py-1.5">
|
|
{TABS.map(({ href, label, icon: Icon }) => {
|
|
const active = pathname === href || pathname.startsWith(`${href}/`);
|
|
return (
|
|
<Link
|
|
key={href}
|
|
href={href}
|
|
className={cn(
|
|
"flex shrink-0 items-center gap-1.5 rounded-md px-2.5 py-1.5 text-xs font-medium transition-colors",
|
|
active
|
|
? "bg-[var(--admin-accent)] text-[var(--admin-accent-foreground)]"
|
|
: "text-[var(--admin-text-muted)] hover:bg-[var(--admin-accent)]/10 hover:text-[var(--admin-text)]",
|
|
)}
|
|
>
|
|
<Icon size={13} />
|
|
{label}
|
|
</Link>
|
|
);
|
|
})}
|
|
</div>
|
|
<div className="min-h-0 flex-1 overflow-auto">{children}</div>
|
|
</div>
|
|
);
|
|
}
|