11import { Suspense } from 'react' ;
22import { notFound } from 'next/navigation' ;
3- import Image from 'next/image' ;
4- import Link from 'next/link' ;
53import { Header } from '@/components/header' ;
64import { Footer } from '@/components/footer' ;
7- import { ProjectCard } from '@/components/project-card' ;
8- import { RichTextContent } from '@/components/ui/rich-text' ;
95import { CreatorProfileSkeleton } from '@/components/ui/skeleton-group' ;
10- import { creators } from '@/lib/creators-data' ;
6+ import { CardSkeleton , TextSkeleton } from '@/components/skeletons/card-skeleton' ;
7+ import { CreatorHeroSection , CreatorCtaSection } from '@/components/streaming/creator-hero-section' ;
8+ import { CreatorBioSection } from '@/components/streaming/creator-bio-section' ;
9+ import { CreatorProjectsSection } from '@/components/streaming/creator-projects-section' ;
10+ import { fetchCreatorCore } from '@/lib/streaming/chunk-data' ;
1111
12- // Simulate async data fetch (replace with real DB/API call)
13- async function getCreator ( id : string ) {
14- // Artificial delay to demonstrate streaming
15- await new Promise ( ( r ) => setTimeout ( r , 0 ) ) ;
16- return creators . find ( ( c ) => c . id === id ) ?? null ;
17- }
18-
19- async function CreatorProfile ( { id } : { id : string } ) {
20- const creator = await getCreator ( id ) ;
12+ async function CreatorProfileShell ( { id } : { id : string } ) {
13+ const creator = await fetchCreatorCore ( id ) ;
2114 if ( ! creator ) notFound ( ) ;
2215
2316 return (
2417 < >
25- { /* Cover */ }
26- < div className = "relative h-48 sm:h-64 w-full bg-muted overflow-hidden" >
27- < Image
28- src = { creator . coverImage }
29- alt = { `${ creator . name } cover` }
30- fill
31- className = "object-cover"
32- priority
33- />
34- </ div >
35-
36- < div className = "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-24" >
37- { /* Avatar + name */ }
38- < div className = "flex flex-col sm:flex-row sm:items-end gap-4 -mt-12 mb-8" >
39- < div className = "relative w-24 h-24 rounded-full overflow-hidden border-4 border-background bg-muted shrink-0" >
40- < Image src = { creator . avatar } alt = { creator . name } fill className = "object-cover" />
41- </ div >
42- < div className = "pb-1" >
43- < h1 className = "text-2xl sm:text-3xl font-bold text-foreground" > { creator . name } </ h1 >
44- < p className = "text-muted-foreground" > { creator . title } · { creator . discipline } </ p >
45- </ div >
46- < div className = "sm:ml-auto flex gap-3 pb-1" >
47- < a href = { creator . linkedIn } target = "_blank" rel = "noopener noreferrer"
48- className = "text-sm px-4 py-2 rounded-md border border-border hover:bg-muted transition-colors" >
49- LinkedIn
50- </ a >
51- < a href = { creator . twitter } target = "_blank" rel = "noopener noreferrer"
52- className = "text-sm px-4 py-2 rounded-md border border-border hover:bg-muted transition-colors" >
53- Twitter
54- </ a >
18+ < Suspense fallback = {
19+ < div className = "animate-pulse" >
20+ < div className = "h-48 sm:h-64 bg-muted w-full" />
21+ < div className = "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8" >
22+ < div className = "flex items-end gap-4 -mt-12 mb-6" >
23+ < div className = "w-24 h-24 rounded-full bg-muted border-4 border-background" />
24+ < div className = "h-7 bg-muted rounded w-48" />
25+ </ div >
5526 </ div >
5627 </ div >
28+ } >
29+ < CreatorHeroSection id = { id } />
30+ </ Suspense >
5731
58- { /* Tagline */ }
59- < p className = "text-lg italic text-muted-foreground mb-4" > “{ creator . tagline } ”</ p >
60-
61- { /* Bio — supports rich HTML if stored, falls back to plain text */ }
62- < div className = "mb-8 max-w-3xl" >
63- { creator . bio . startsWith ( '<' ) ? (
64- < RichTextContent html = { creator . bio } />
65- ) : (
66- < p className = "text-foreground leading-relaxed" > { creator . bio } </ p >
67- ) }
68- </ div >
69-
70- { /* Skills */ }
71- < div className = "flex flex-wrap gap-2 mb-12" >
72- { creator . skills . map ( ( skill ) => (
73- < span key = { skill } className = "px-3 py-1 text-sm bg-muted rounded-full text-foreground" >
74- { skill }
75- </ span >
76- ) ) }
77- </ div >
32+ < div className = "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-24" >
33+ < Suspense fallback = { < div className = "mb-8" > < TextSkeleton lines = { 4 } /> </ div > } >
34+ < CreatorBioSection id = { id } />
35+ </ Suspense >
7836
79- { /* Projects — wrapped in its own Suspense for granular streaming */ }
8037 < section >
8138 < h2 className = "text-xl font-semibold text-foreground mb-6" > Projects</ h2 >
8239 < Suspense fallback = {
8340 < div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6" >
84- { Array . from ( { length : 3 } ) . map ( ( _ , i ) => (
85- < div key = { i } className = "bg-card border border-border rounded-lg overflow-hidden animate-pulse" >
86- < div className = "aspect-video bg-muted" />
87- < div className = "p-4 space-y-2" >
88- < div className = "h-5 bg-muted rounded w-3/4" />
89- < div className = "h-4 bg-muted rounded w-full" />
90- </ div >
91- </ div >
92- ) ) }
41+ { Array . from ( { length : 3 } ) . map ( ( _ , i ) => < CardSkeleton key = { i } /> ) }
9342 </ div >
9443 } >
95- { creator . projects . length > 0 ? (
96- < div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6" >
97- { creator . projects . map ( ( project ) => (
98- < ProjectCard key = { project . id } project = { project } />
99- ) ) }
100- </ div >
101- ) : (
102- < p className = "text-muted-foreground" > No projects yet.</ p >
103- ) }
44+ < CreatorProjectsSection id = { id } />
10445 </ Suspense >
10546 </ section >
10647
107- { /* CTA */ }
108- < div className = "mt-16 text-center border border-border rounded-xl p-10 bg-muted/30" >
109- < h3 className = "text-2xl font-bold text-foreground mb-3" > Work with { creator . name } </ h3 >
110- < p className = "text-muted-foreground mb-6" > Reach out directly to discuss your project.</ p >
111- < a href = { creator . linkedIn } target = "_blank" rel = "noopener noreferrer"
112- className = "inline-flex items-center justify-center px-6 py-3 bg-primary text-primary-foreground rounded-lg font-semibold hover:bg-primary/90 transition-colors" >
113- Get In Touch
114- </ a >
115- </ div >
48+ < Suspense fallback = { < div className = "mt-16 h-40 bg-muted rounded-xl animate-pulse" /> } >
49+ < CreatorCtaSection id = { id } />
50+ </ Suspense >
11651 </ div >
11752 </ >
11853 ) ;
@@ -126,7 +61,7 @@ export default async function CreatorPage({ params }: { params: Promise<{ id: st
12661 < Header />
12762 < main className = "flex-grow" >
12863 < Suspense fallback = { < CreatorProfileSkeleton /> } >
129- < CreatorProfile id = { id } />
64+ < CreatorProfileShell id = { id } />
13065 </ Suspense >
13166 </ main >
13267 < Footer />
0 commit comments