11import { useState , useEffect , useMemo } from 'react' ;
22import { courseService , type Course } from '@/services/course.service' ;
33import SearchBar from '@/components/common/SearchBar' ;
4+ import StickyFilterBar from '@/components/common/StickyFilterBar' ;
45import CreatorCard from '@/components/common/CreatorCard' ;
56import { CreatorGridSkeleton } from '@/components/common/CreatorSkeleton' ;
67import EmptyState from '@/components/common/EmptyState' ;
7-
8- // ✅ NEW IMPORTS
98import { Button } from '@/components/ui/button' ;
109import { UnavailableAction } from '@/components/ui/unavailable-action' ;
1110
11+ // Fallback demo data in case API fails
1212const DEMO_CREATORS : Course [ ] = [
1313 {
1414 id : '1' ,
@@ -20,6 +20,56 @@ const DEMO_CREATORS: Course[] = [
2020 level : 'BEGINNER' ,
2121 thumbnail : 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=400&h=400&fit=crop' ,
2222 } ,
23+ {
24+ id : '2' ,
25+ title : 'Sarah Chen' ,
26+ description : 'Solidity Developer' ,
27+ price : 0.12 ,
28+ instructorId : 'schen_dev' ,
29+ category : 'Tech' ,
30+ level : 'ADVANCED' ,
31+ thumbnail : 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=400&h=400&fit=crop' ,
32+ } ,
33+ {
34+ id : '3' ,
35+ title : 'Marcus Thorne' ,
36+ description : 'Crypto Strategist' ,
37+ price : 0.08 ,
38+ instructorId : 'mthorne' ,
39+ category : 'Finance' ,
40+ level : 'INTERMEDIATE' ,
41+ thumbnail : 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=400&h=400&fit=crop' ,
42+ } ,
43+ {
44+ id : '4' ,
45+ title : 'Elena Vance' ,
46+ description : 'UI/UX Designer' ,
47+ price : 0.04 ,
48+ instructorId : 'evance_design' ,
49+ category : 'Design' ,
50+ level : 'BEGINNER' ,
51+ thumbnail : 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=400&h=400&fit=crop' ,
52+ } ,
53+ {
54+ id : '5' ,
55+ title : 'David Kojo' ,
56+ description : 'Music Producer' ,
57+ price : 0.15 ,
58+ instructorId : 'dkojo_beats' ,
59+ category : 'Music' ,
60+ level : 'ADVANCED' ,
61+ thumbnail : 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=400&h=400&fit=crop' ,
62+ } ,
63+ {
64+ id : '6' ,
65+ title : 'Yuki Sato' ,
66+ description : 'Motion Designer' ,
67+ price : 0.07 ,
68+ instructorId : 'yuki_s' ,
69+ category : 'Design' ,
70+ level : 'INTERMEDIATE' ,
71+ thumbnail : 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=400&h=400&fit=crop' ,
72+ } ,
2373] ;
2474
2575function LandingPage ( ) {
@@ -32,8 +82,13 @@ function LandingPage() {
3282 setIsLoading ( true ) ;
3383 try {
3484 const data = await courseService . getCourses ( ) ;
35- setCreators ( data . length > 0 ? data : DEMO_CREATORS ) ;
36- } catch {
85+ if ( data && data . length > 0 ) {
86+ setCreators ( data ) ;
87+ } else {
88+ setCreators ( DEMO_CREATORS ) ;
89+ }
90+ } catch ( error ) {
91+ console . error ( 'Failed to fetch creators:' , error ) ;
3792 setCreators ( DEMO_CREATORS ) ;
3893 } finally {
3994 setTimeout ( ( ) => setIsLoading ( false ) , 800 ) ;
@@ -54,51 +109,63 @@ function LandingPage() {
54109 const handleResetSearch = ( ) => setSearchQuery ( '' ) ;
55110
56111 return (
57- < main className = "relative min-h-screen bg-black px-6 py-12" >
58- < div className = "mx-auto max-w-7xl" >
59-
60- { /* HEADER */ }
112+ < main className = "relative min-h-screen overflow-x-hidden bg-[linear-gradient(160deg,#08111f_0%,#10213b_45%,#f0b14d_160%)] px-6 py-12 md:px-12" >
113+ < div className = "absolute left-[-4rem] top-[10%] size-72 rounded-full bg-amber-300/20 blur-[100px]" />
114+ < div className = "absolute bottom-[8%] right-[-3rem] size-72 rounded-full bg-emerald-300/15 blur-[100px]" />
115+ < div className = "absolute inset-0 bg-[radial-gradient(circle_at_top,rgba(255,186,73,0.1),transparent_40%),radial-gradient(circle_at_bottom_left,rgba(74,222,128,0.08),transparent_35%)]" />
116+
117+ < div className = "relative z-10 mx-auto max-w-7xl" >
61118 < header className = "mb-16 text-center" >
62- < h1 className = "text-4xl font-bold text-white mb-6" >
119+ < img className = "mx-auto mb-8 size-10" src = "/icons/logo.svg" alt = "Access Layer logo" />
120+ < p className = "mb-3 text-sm font-bold uppercase tracking-[0.25em] text-amber-400/80" >
121+ Creator Keys Marketplace
122+ </ p >
123+ < h1 className = "mb-8 font-grotesque text-[clamp(2.5rem,8vw,5rem)] font-extrabold leading-[1.1] tracking-tight text-white" >
63124 Access Layer
64125 </ h1 >
65-
66- { /* ✅ TOOLTIP BUTTON */ }
67- < div className = "flex justify-center mb-6" >
126+ < div className = "mb-8 flex justify-center" >
68127 < UnavailableAction disabled = { true } reason = "Feature coming soon" >
69128 < Button > Buy Access</ Button >
70129 </ UnavailableAction >
71130 </ div >
131+ </ header >
72132
133+ < StickyFilterBar
134+ eyebrow = "Marketplace filters"
135+ title = "Find creators without losing your place"
136+ description = "Search by creator name or handle while you keep scrolling through the marketplace. The filter shell stays visible and compact so you can refine results without losing your place."
137+ resultCount = { filteredCreators . length }
138+ >
73139 < SearchBar
74140 value = { searchQuery }
75141 onChange = { setSearchQuery }
142+ className = "max-w-none shadow-2xl shadow-black/20"
76143 />
77- </ header >
144+ </ StickyFilterBar >
78145
79- { /* CONTENT */ }
80- < section >
146+ < section className = "mt-2" >
81147 { isLoading ? (
82- < CreatorGridSkeleton count = { 3 } />
148+ < CreatorGridSkeleton count = { 6 } />
83149 ) : filteredCreators . length > 0 ? (
84- < div className = "grid grid-cols-1 md :grid-cols-3 gap-6 " >
150+ < div className = "grid grid-cols-1 gap-8 sm :grid-cols-2 lg:grid-cols-3 " >
85151 { filteredCreators . map ( creator => (
86152 < CreatorCard key = { creator . id } creator = { creator } />
87153 ) ) }
88154 </ div >
89155 ) : (
90- < EmptyState
91- image = "/images/no-results.png"
92- title = "No creators found"
93- description = "Try a different search"
94- onReset = { handleResetSearch }
95- />
156+ < div className = "flex justify-center py-12" >
157+ < EmptyState
158+ image = "/images/no-results.png"
159+ title = "No creators found"
160+ description = { `We couldn't find any creators matching "${ searchQuery } ". Try a different name or handle.` }
161+ onReset = { handleResetSearch }
162+ />
163+ </ div >
96164 ) }
97165 </ section >
98-
99166 </ div >
100167 </ main >
101168 ) ;
102169}
103170
104- export default LandingPage ;
171+ export default LandingPage ;
0 commit comments