191 lines
5.3 KiB
JavaScript
191 lines
5.3 KiB
JavaScript
import React, { lazy, Suspense } from 'react'
|
|
import { createRoot } from 'react-dom/client'
|
|
|
|
// Above-fold — eager
|
|
import HomeHero from './HomeHero'
|
|
|
|
// Below-fold — lazy-loaded to keep initial bundle small
|
|
const HomeWelcomeRow = lazy(() => import('./HomeWelcomeRow'))
|
|
const HomeFromFollowing = lazy(() => import('./HomeFromFollowing'))
|
|
const HomeTrendingForYou = lazy(() => import('./HomeTrendingForYou'))
|
|
const HomeBecauseYouLike = lazy(() => import('./HomeBecauseYouLike'))
|
|
const HomeSuggestedCreators = lazy(() => import('./HomeSuggestedCreators'))
|
|
const HomeTrending = lazy(() => import('./HomeTrending'))
|
|
const HomeRising = lazy(() => import('./HomeRising'))
|
|
const HomeFresh = lazy(() => import('./HomeFresh'))
|
|
const HomeCategories = lazy(() => import('./HomeCategories'))
|
|
const HomeTags = lazy(() => import('./HomeTags'))
|
|
const HomeCreators = lazy(() => import('./HomeCreators'))
|
|
const HomeNews = lazy(() => import('./HomeNews'))
|
|
const HomeCTA = lazy(() => import('./HomeCTA'))
|
|
|
|
function SectionFallback() {
|
|
return (
|
|
<div className="mt-14 h-48 animate-pulse rounded-xl bg-nova-800 mx-4 sm:mx-6 lg:mx-8" />
|
|
)
|
|
}
|
|
|
|
function GuestHomePage(props) {
|
|
const { hero, rising, trending, fresh, tags, creators, news } = props
|
|
|
|
return (
|
|
<>
|
|
{/* 1. Hero */}
|
|
<HomeHero artwork={hero} isLoggedIn={false} />
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeRising items={rising} />
|
|
</Suspense>
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeTrending items={trending} />
|
|
</Suspense>
|
|
|
|
{/* 3. Fresh Uploads */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeFresh items={fresh} />
|
|
</Suspense>
|
|
|
|
{/* 4. Explore Categories */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeCategories />
|
|
</Suspense>
|
|
|
|
{/* 5. Popular Tags */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeTags tags={tags} />
|
|
</Suspense>
|
|
|
|
{/* 6. Top Creators */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeCreators creators={creators} />
|
|
</Suspense>
|
|
|
|
{/* 7. News */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeNews items={news} />
|
|
</Suspense>
|
|
|
|
{/* 8. CTA Upload */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeCTA isLoggedIn={false} />
|
|
</Suspense>
|
|
</>
|
|
)
|
|
}
|
|
|
|
function AuthHomePage(props) {
|
|
const {
|
|
user_data,
|
|
hero,
|
|
from_following,
|
|
rising,
|
|
trending,
|
|
fresh,
|
|
by_tags,
|
|
by_categories,
|
|
suggested_creators,
|
|
tags,
|
|
creators,
|
|
news,
|
|
preferences,
|
|
} = props
|
|
|
|
return (
|
|
<>
|
|
{/* 1. Hero — flush to top */}
|
|
<HomeHero artwork={hero} isLoggedIn />
|
|
|
|
{/* P0. Welcome/status row — below hero so featured image sits at 0px */}
|
|
<Suspense fallback={null}>
|
|
<HomeWelcomeRow user_data={user_data} />
|
|
</Suspense>
|
|
|
|
{/* P2. From Creators You Follow */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeFromFollowing items={from_following} />
|
|
</Suspense>
|
|
|
|
{/* P3. Trending For You (by_tags = Meilisearch tag overlap sorted by trending) */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeTrendingForYou items={by_tags} preferences={preferences} />
|
|
</Suspense>
|
|
|
|
{/* Rising Now */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeRising items={rising} />
|
|
</Suspense>
|
|
|
|
{/* 2. Global Trending Now */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeTrending items={trending} />
|
|
</Suspense>
|
|
|
|
{/* P4. Because You Like {top tag} — uses by_categories for variety */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeBecauseYouLike items={by_categories} preferences={preferences} />
|
|
</Suspense>
|
|
|
|
{/* 3. Fresh Uploads */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeFresh items={fresh} />
|
|
</Suspense>
|
|
|
|
{/* 4. Explore Categories */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeCategories />
|
|
</Suspense>
|
|
|
|
{/* P5. Suggested Creators */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeSuggestedCreators creators={suggested_creators} />
|
|
</Suspense>
|
|
|
|
{/* 5. Popular Tags */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeTags tags={tags} />
|
|
</Suspense>
|
|
|
|
{/* 6. Top Creators */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeCreators creators={creators} />
|
|
</Suspense>
|
|
|
|
{/* 7. News */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeNews items={news} />
|
|
</Suspense>
|
|
|
|
{/* 8. CTA Upload */}
|
|
<Suspense fallback={<SectionFallback />}>
|
|
<HomeCTA isLoggedIn />
|
|
</Suspense>
|
|
</>
|
|
)
|
|
}
|
|
|
|
function HomePage(props) {
|
|
return (
|
|
<div className="pb-24">
|
|
{props.is_logged_in
|
|
? <AuthHomePage {...props} />
|
|
: <GuestHomePage {...props} />
|
|
}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
// Auto-mount when the Blade view provides #homepage-root
|
|
const mountEl = document.getElementById('homepage-root')
|
|
if (mountEl) {
|
|
let props = {}
|
|
try {
|
|
const propsEl = document.getElementById('homepage-props')
|
|
props = propsEl ? JSON.parse(propsEl.textContent || '{}') : {}
|
|
} catch {
|
|
props = {}
|
|
}
|
|
|
|
createRoot(mountEl).render(<HomePage {...props} />)
|
|
}
|
|
|
|
export default HomePage
|