mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-08-29 05:05:38 -04:00
Replace fully client-side dashboard and title detail pages with server component orchestrators that fetch data directly via service functions, eliminating extra network round-trips through API routes. Each section streams independently through its own Suspense boundary. - Extract getUserStats(), getTitleWithChildren(), getRecommendationsForTitle() into service layer; update getNewAvailableFeed() to include tmdbId/voteAverage - Split dashboard into server sections (stats, continue watching, library, recommendations) with client children for animations - Split title page into server hero + client interaction provider with shared context for optimistic mutations across actions and seasons - Add generateMetadata with OG tags, server-side TMDB ID resolution via redirect(), loading.tsx and not-found.tsx for both pages - Add per-section skeleton components, fix ContinueWatchingSkeleton dimensions - Remove 6 unused API routes (feed/*, titles/[id] GET, titles/[id]/recommendations) - Remove components/stats-summary.tsx, add lib/types/title.ts for shared types Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
41 lines
1.4 KiB
TypeScript
41 lines
1.4 KiB
TypeScript
import { headers } from "next/headers";
|
|
import { Suspense } from "react";
|
|
import {
|
|
ContinueWatchingSectionSkeleton,
|
|
StatsSectionSkeleton,
|
|
TitleGridSectionSkeleton,
|
|
} from "@/components/skeletons";
|
|
import { auth } from "@/lib/auth/server";
|
|
import { ContinueWatchingSection } from "./_components/continue-watching-section";
|
|
import { LibrarySection } from "./_components/library-section";
|
|
import { RecommendationsSection } from "./_components/recommendations-section";
|
|
import { StatsSection } from "./_components/stats-section";
|
|
import { WelcomeHeader } from "./_components/welcome-header";
|
|
|
|
export default async function DashboardPage() {
|
|
const session = await auth.api.getSession({ headers: await headers() });
|
|
if (!session) return null;
|
|
|
|
return (
|
|
<div className="space-y-10">
|
|
<WelcomeHeader name={session.user.name} />
|
|
|
|
<Suspense fallback={<StatsSectionSkeleton />}>
|
|
<StatsSection userId={session.user.id} />
|
|
</Suspense>
|
|
|
|
<Suspense fallback={<ContinueWatchingSectionSkeleton />}>
|
|
<ContinueWatchingSection userId={session.user.id} />
|
|
</Suspense>
|
|
|
|
<Suspense fallback={<TitleGridSectionSkeleton />}>
|
|
<LibrarySection userId={session.user.id} />
|
|
</Suspense>
|
|
|
|
<Suspense fallback={<TitleGridSectionSkeleton />}>
|
|
<RecommendationsSection userId={session.user.id} />
|
|
</Suspense>
|
|
</div>
|
|
);
|
|
}
|