feat: implement dashboard page and add loading skeletons for all dashboard modules

This commit is contained in:
Michael committed 2026-04-03 07:12:15 +02:00
1 parent b39e010903
commit a4debe992b
8 files changed
+158 -2

No files matched your search

+30
View File
@@ -0,0 +1,30 @@
export default function AnalyticsLoading() {
return (
<div className="flex flex-col gap-6 animate-pulse">
{/* Header */}
<div className="flex items-center justify-between">
<div className="h-7 w-40 rounded-lg bg-[var(--bg-elevated)]" />
<div className="flex gap-2">
<div className="h-9 w-32 rounded-lg bg-[var(--bg-elevated)]" />
<div className="h-9 w-32 rounded-lg bg-[var(--bg-elevated)]" />
</div>
</div>
{/* Filter bar */}
<div className="h-12 rounded-xl bg-[var(--bg-elevated)] border border-[var(--border)]" />
{/* Table skeleton */}
<div className="rounded-2xl border border-[var(--border)] overflow-hidden bg-[var(--bg-elevated)]">
<div className="h-10 bg-[var(--bg-base)] border-b border-[var(--border)]" />
{Array.from({ length: 8 }).map((_, i) => (
<div key={i} className="h-10 border-b border-[var(--border)] flex items-center px-4 gap-4">
<div className="h-3 w-32 rounded bg-[var(--border)]" />
<div className="h-3 w-20 rounded bg-[var(--border)]" />
<div className="h-3 w-20 rounded bg-[var(--border)]" />
<div className="h-3 w-16 rounded bg-[var(--border)]" />
</div>
))}
</div>
</div>
);
}
+27
View File
@@ -0,0 +1,27 @@
export default function DashboardLoading() {
return (
<div className="flex flex-col gap-6 animate-pulse">
{/* Header skeleton */}
<div className="flex items-center justify-between">
<div className="h-7 w-48 rounded-lg bg-[var(--bg-elevated)]" />
<div className="h-5 w-32 rounded-lg bg-[var(--bg-elevated)]" />
</div>
{/* KPI cards row */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
{Array.from({ length: 4 }).map((_, i) => (
<div key={i} className="h-28 rounded-2xl bg-[var(--bg-elevated)] border border-[var(--border)]" />
))}
</div>
{/* Main content area */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="h-64 rounded-2xl bg-[var(--bg-elevated)] border border-[var(--border)]" />
<div className="h-64 rounded-2xl bg-[var(--bg-elevated)] border border-[var(--border)]" />
</div>
{/* Bottom tables */}
<div className="h-80 rounded-2xl bg-[var(--bg-elevated)] border border-[var(--border)]" />
</div>
);
}
+8 -1
View File
@@ -1,4 +1,11 @@
import { pgGetDashboardData, type DashboardTopItem, type DashboardSiteStats, type DashboardSiteTop10 } from "@/lib/pg-ff-client";
import { unstable_cache } from "next/cache";
const getCachedDashboardData = unstable_cache(
pgGetDashboardData,
["dashboard-data"],
{ revalidate: 600 } // 10 minutes
);
import { TrendingUp, TrendingDown, Minus, Store, Euro, Users, ShoppingCart, Award, BarChart3 } from "lucide-react";
// ---------------------------------------------------------------------------
@@ -722,7 +729,7 @@ function SectionHeader({ label, sub }: { label: string; sub?: string }) {
export default async function DashboardPage() {
let data;
try {
data = await pgGetDashboardData();
data = await getCachedDashboardData();
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
console.error("[Dashboard] pgGetDashboardData failed:", e);
+21
View File
@@ -0,0 +1,21 @@
export default function ExportsLoading() {
return (
<div className="flex flex-col gap-6 animate-pulse">
{/* Header */}
<div className="h-7 w-56 rounded-lg bg-[var(--bg-elevated)]" />
{/* Table */}
<div className="rounded-2xl border border-[var(--border)] overflow-hidden bg-[var(--bg-elevated)]">
<div className="h-10 bg-[var(--bg-base)] border-b border-[var(--border)]" />
{Array.from({ length: 8 }).map((_, i) => (
<div key={i} className="h-10 border-b border-[var(--border)] flex items-center px-4 gap-4">
<div className="h-3 w-24 rounded bg-[var(--border)]" />
<div className="h-3 w-32 rounded bg-[var(--border)]" />
<div className="h-3 w-20 rounded bg-[var(--border)]" />
<div className="h-3 w-16 rounded bg-[var(--border)]" />
</div>
))}
</div>
</div>
);
}
@@ -0,0 +1,34 @@
export default function HitParadeLoading() {
return (
<div className="flex flex-col gap-6 animate-pulse">
{/* Header */}
<div className="flex items-center justify-between">
<div className="h-7 w-44 rounded-lg bg-[var(--bg-elevated)]" />
<div className="flex gap-2">
<div className="h-9 w-28 rounded-lg bg-[var(--bg-elevated)]" />
<div className="h-9 w-28 rounded-lg bg-[var(--bg-elevated)]" />
</div>
</div>
{/* Podium / top cards */}
<div className="grid grid-cols-3 gap-4">
{Array.from({ length: 3 }).map((_, i) => (
<div key={i} className="h-32 rounded-2xl bg-[var(--bg-elevated)] border border-[var(--border)]" />
))}
</div>
{/* Rankings table */}
<div className="rounded-2xl border border-[var(--border)] overflow-hidden bg-[var(--bg-elevated)]">
<div className="h-10 bg-[var(--bg-base)] border-b border-[var(--border)]" />
{Array.from({ length: 10 }).map((_, i) => (
<div key={i} className="h-10 border-b border-[var(--border)] flex items-center px-4 gap-4">
<div className="h-3 w-6 rounded bg-[var(--border)]" />
<div className="h-3 w-40 rounded bg-[var(--border)]" />
<div className="h-3 w-24 rounded bg-[var(--border)]" />
<div className="h-3 w-16 rounded bg-[var(--border)]" />
</div>
))}
</div>
</div>
);
}
+17
View File
@@ -0,0 +1,17 @@
export default function SettingsLoading() {
return (
<div className="flex flex-col gap-6 animate-pulse max-w-2xl">
{/* Header */}
<div className="h-7 w-40 rounded-lg bg-[var(--bg-elevated)]" />
{/* Settings sections */}
{Array.from({ length: 3 }).map((_, i) => (
<div key={i} className="rounded-2xl border border-[var(--border)] overflow-hidden bg-[var(--bg-elevated)] p-6 flex flex-col gap-4">
<div className="h-5 w-36 rounded bg-[var(--border)]" />
<div className="h-10 rounded-lg bg-[var(--bg-base)]" />
<div className="h-10 rounded-lg bg-[var(--bg-base)]" />
</div>
))}
</div>
);
}
+18
View File
@@ -0,0 +1,18 @@
export default function SnapshotsLoading() {
return (
<div className="flex flex-col gap-6 animate-pulse">
{/* Header */}
<div className="flex items-center justify-between">
<div className="h-7 w-36 rounded-lg bg-[var(--bg-elevated)]" />
<div className="h-9 w-36 rounded-lg bg-[var(--bg-elevated)]" />
</div>
{/* Cards grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{Array.from({ length: 6 }).map((_, i) => (
<div key={i} className="h-36 rounded-2xl bg-[var(--bg-elevated)] border border-[var(--border)]" />
))}
</div>
</div>
);
}