Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions apps/web/app/(pages)/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Card } from "@/components/shared/card";

export default function PagesLoading() {
return (
<div className="space-y-6">
<Card className="overflow-hidden rounded-[24px] p-0">
<div className="animate-pulse space-y-4 px-6 py-7 lg:px-8 lg:py-8">
<div className="h-4 w-28 rounded-full bg-[rgba(255,255,255,0.08)]" />
<div className="h-12 max-w-3xl rounded-[18px] bg-[rgba(255,255,255,0.08)]" />
<div className="h-5 max-w-2xl rounded-full bg-[rgba(255,255,255,0.06)]" />
<div className="flex flex-wrap gap-3">
<div className="h-9 w-28 rounded-[18px] bg-[rgba(255,255,255,0.06)]" />
<div className="h-9 w-24 rounded-[18px] bg-[rgba(255,255,255,0.06)]" />
<div className="h-9 w-32 rounded-[18px] bg-[rgba(255,255,255,0.06)]" />
</div>
</div>
</Card>

<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
{Array.from({ length: 4 }).map((_, index) => (
<Card
key={index}
className="animate-pulse rounded-[20px] bg-[color:var(--bg-muted)] p-5"
>
<div className="h-4 w-24 rounded-full bg-[rgba(255,255,255,0.08)]" />
<div className="mt-4 h-8 w-20 rounded-[14px] bg-[rgba(255,255,255,0.12)]" />
<div className="mt-4 h-4 w-36 rounded-full bg-[rgba(255,255,255,0.06)]" />
</Card>
))}
</div>

<div className="grid gap-6 xl:grid-cols-2">
{Array.from({ length: 2 }).map((_, index) => (
<Card
key={index}
className="animate-pulse rounded-[24px] bg-[color:var(--bg-muted)] p-5"
>
<div className="h-4 w-28 rounded-full bg-[rgba(255,255,255,0.08)]" />
<div className="mt-4 space-y-3">
<div className="h-16 rounded-[18px] bg-[rgba(255,255,255,0.06)]" />
<div className="h-16 rounded-[18px] bg-[rgba(255,255,255,0.06)]" />
<div className="h-16 rounded-[18px] bg-[rgba(255,255,255,0.06)]" />
</div>
</Card>
))}
</div>
</div>
);
}
3 changes: 3 additions & 0 deletions apps/web/components/layout/app-shell.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Link from "next/link";
import { Activity, Database, Gauge, LayoutGrid, ShieldAlert, Sparkles } from "lucide-react";
import { cn } from "@/components/shared/cn";
import { RoutePrefetch } from "@/components/layout/route-prefetch";

const navItems = [
{ href: "/dashboard", label: "대시보드", icon: LayoutGrid },
Expand All @@ -14,6 +15,7 @@ const navItems = [
export function AppShell({ children }: { children: React.ReactNode }) {
return (
<div className="page-shell">
<RoutePrefetch />
<div className="mx-auto grid min-h-[calc(100vh-28px)] max-w-[1480px] gap-4 xl:grid-cols-[280px_minmax(0,1fr)]">
<aside className="glass gold-shadow flex flex-col justify-between rounded-[24px] border border-[color:var(--border)] px-5 py-5">
<div className="space-y-8">
Expand Down Expand Up @@ -44,6 +46,7 @@ export function AppShell({ children }: { children: React.ReactNode }) {
<Link
key={item.href}
href={item.href}
prefetch
className={cn(
"ui-pill flex items-center gap-3 px-4 py-3 text-[14px] font-medium transition",
"bg-[rgba(255,255,255,0.02)] text-[color:var(--text-muted)] hover:bg-[rgba(255,255,255,0.06)] hover:text-white"
Expand Down
25 changes: 25 additions & 0 deletions apps/web/components/layout/route-prefetch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"use client";

import { useEffect } from "react";
import { useRouter } from "next/navigation";

const ROUTES_TO_PREFETCH = [
"/dashboard",
"/events",
"/themes",
"/replay",
"/evaluation",
"/admin"
];

export function RoutePrefetch() {
const router = useRouter();

useEffect(() => {
ROUTES_TO_PREFETCH.forEach((route) => {
router.prefetch(route);
});
}, [router]);

return null;
}