mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-11 17:26:32 +02:00
feat: implement dashboard page and add loading skeletons for all dashboard modules
This commit is contained in:
1 parent
b39e010903
commit
a4debe992b
8 files changed
+158
-2
No files matched your search
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user