This commit is contained in:
Marcelo
2026-04-26 16:31:04 +00:00
parent 66c89f9bf4
commit 7e0fe5c2e1
28 changed files with 5310 additions and 2741 deletions

View File

@@ -0,0 +1,30 @@
/**
* Shared markup for loading states (used by `loading.tsx` and explicit `<Suspense>` in pages)
* so the recap UI always shows the same skeleton while server data is pending.
*/
export function RecapGridPageSkeleton() {
return (
<div className="p-4 sm:p-6">
<div className="mb-4 h-24 animate-pulse rounded-2xl border border-white/10 bg-black/40" />
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3">
{Array.from({ length: 6 }).map((_, index) => (
<div key={index} className="h-[220px] animate-pulse rounded-2xl border border-white/10 bg-white/5" />
))}
</div>
</div>
);
}
export function RecapDetailPageSkeleton() {
return (
<div className="p-4 sm:p-6">
<div className="h-16 animate-pulse rounded-2xl border border-white/10 bg-black/40" />
<div className="mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-4">
{Array.from({ length: 4 }).map((_, index) => (
<div key={index} className="h-24 animate-pulse rounded-2xl border border-white/10 bg-black/30" />
))}
</div>
<div className="mt-4 h-48 animate-pulse rounded-2xl border border-white/10 bg-black/30" />
</div>
);
}

View File

@@ -1,13 +1,5 @@
import { RecapDetailPageSkeleton } from "../RecapPageSkeletons";
export default function LoadingRecapDetail() {
return (
<div className="p-4 sm:p-6">
<div className="h-16 animate-pulse rounded-2xl border border-white/10 bg-black/40" />
<div className="mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-4">
{Array.from({ length: 4 }).map((_, index) => (
<div key={index} className="h-24 animate-pulse rounded-2xl border border-white/10 bg-black/30" />
))}
</div>
<div className="mt-4 h-48 animate-pulse rounded-2xl border border-white/10 bg-black/30" />
</div>
);
return <RecapDetailPageSkeleton />;
}

View File

@@ -1,9 +1,11 @@
import { Suspense } from "react";
import { notFound, redirect } from "next/navigation";
import { requireSession } from "@/lib/auth/requireSession";
import { getRecapMachineDetailCached, parseRecapDetailRangeInput } from "@/lib/recap/redesign";
import { RecapDetailPageSkeleton } from "../RecapPageSkeletons";
import RecapDetailClient from "./RecapDetailClient";
export default async function RecapMachineDetailPage({
async function RecapDetailData({
params,
searchParams,
}: {
@@ -33,3 +35,17 @@ export default async function RecapMachineDetailPage({
/>
);
}
export default function RecapMachineDetailPage({
params,
searchParams,
}: {
params: Promise<{ machineId: string }>;
searchParams?: Promise<Record<string, string | string[] | undefined>>;
}) {
return (
<Suspense fallback={<RecapDetailPageSkeleton />}>
<RecapDetailData params={params} searchParams={searchParams} />
</Suspense>
);
}

View File

@@ -1,12 +1,5 @@
import { RecapGridPageSkeleton } from "./RecapPageSkeletons";
export default function LoadingRecapGrid() {
return (
<div className="p-4 sm:p-6">
<div className="mb-4 h-24 animate-pulse rounded-2xl border border-white/10 bg-black/40" />
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3">
{Array.from({ length: 6 }).map((_, index) => (
<div key={index} className="h-[220px] animate-pulse rounded-2xl border border-white/10 bg-white/5" />
))}
</div>
</div>
);
return <RecapGridPageSkeleton />;
}

View File

@@ -1,9 +1,11 @@
import { Suspense } from "react";
import { redirect } from "next/navigation";
import { requireSession } from "@/lib/auth/requireSession";
import { getRecapSummaryCached } from "@/lib/recap/redesign";
import RecapGridClient from "./RecapGridClient";
import { RecapGridPageSkeleton } from "./RecapPageSkeletons";
export default async function RecapPage() {
async function RecapGridData() {
const session = await requireSession();
if (!session) redirect("/login?next=/recap");
@@ -14,3 +16,11 @@ export default async function RecapPage() {
return <RecapGridClient initialData={initialData} />;
}
export default function RecapPage() {
return (
<Suspense fallback={<RecapGridPageSkeleton />}>
<RecapGridData />
</Suspense>
);
}