Implement skeleton loading states for dashboard and routes (P3.8)
Add skeleton loading components per specs/dashboard.md requirements: - DecisionCardSkeleton: Shimmer placeholder for status and reason - DataPanelSkeleton: Skeleton rows for 5 metrics - NutritionPanelSkeleton: Skeleton for nutrition guidance - MiniCalendarSkeleton: Placeholder grid with navigation and legend - OverrideTogglesSkeleton: 4 toggle placeholders - CycleInfoSkeleton: Cycle day and phase placeholders - DashboardSkeleton: Combined skeleton for route-level loading Add Next.js loading.tsx files for instant loading states: - src/app/loading.tsx (Dashboard) - src/app/calendar/loading.tsx - src/app/history/loading.tsx - src/app/plan/loading.tsx - src/app/settings/loading.tsx Update dashboard page to use DashboardSkeleton instead of "Loading..." text. Fix flaky garmin test with wider date tolerance for timezone variations. 29 new tests in skeletons.test.tsx (749 total tests passing). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
47
src/app/plan/loading.tsx
Normal file
47
src/app/plan/loading.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
// ABOUTME: Route-level loading state for the plan page.
|
||||
// ABOUTME: Shows skeleton placeholders during page navigation.
|
||||
|
||||
export default function Loading() {
|
||||
return (
|
||||
<div className="min-h-screen bg-zinc-50 dark:bg-black">
|
||||
<header className="border-b bg-white dark:bg-zinc-900 px-6 py-4">
|
||||
<div className="container mx-auto">
|
||||
<h1 className="text-xl font-bold">Training Plan</h1>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main className="container mx-auto p-6">
|
||||
<div className="animate-pulse space-y-6">
|
||||
{/* Current phase status */}
|
||||
<div className="rounded-lg border p-6 space-y-3">
|
||||
<div className="h-6 w-40 bg-gray-200 rounded" />
|
||||
<div className="h-4 w-64 bg-gray-200 rounded" />
|
||||
<div className="h-4 w-48 bg-gray-200 rounded" />
|
||||
</div>
|
||||
|
||||
{/* Phase cards grid */}
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{[1, 2, 3, 4, 5].map((i) => (
|
||||
<div key={i} className="rounded-lg border p-4 space-y-3">
|
||||
<div className="h-5 w-32 bg-gray-200 rounded" />
|
||||
<div className="h-4 w-full bg-gray-200 rounded" />
|
||||
<div className="h-4 w-3/4 bg-gray-200 rounded" />
|
||||
<div className="h-4 w-1/2 bg-gray-200 rounded" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Exercise reference section */}
|
||||
<div className="rounded-lg border p-6 space-y-4">
|
||||
<div className="h-6 w-48 bg-gray-200 rounded" />
|
||||
<div className="grid gap-3 md:grid-cols-2">
|
||||
{[1, 2, 3, 4, 5, 6].map((i) => (
|
||||
<div key={i} className="h-4 bg-gray-200 rounded" />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user