2026-01-06 16:35:15 +01:00

130 lines
3.9 KiB
TypeScript

import Head from 'next/head'
import type { Article } from '@/types/nostr'
import { ArticleFiltersComponent, type ArticleFilters } from '@/components/ArticleFilters'
import { CategoryTabs } from '@/components/CategoryTabs'
import { SearchBar } from '@/components/SearchBar'
import { ArticlesList } from '@/components/ArticlesList'
import { AuthorsList } from '@/components/AuthorsList'
import { PageHeader } from '@/components/PageHeader'
import { Footer } from '@/components/Footer'
import type { Dispatch, SetStateAction } from 'react'
import { t } from '@/lib/i18n'
interface HomeViewProps {
searchQuery: string
setSearchQuery: Dispatch<SetStateAction<string>>
selectedCategory: ArticleFilters['category']
setSelectedCategory: Dispatch<SetStateAction<ArticleFilters['category']>>
filters: ArticleFilters
setFilters: Dispatch<SetStateAction<ArticleFilters>>
articles: Article[]
allArticles: Article[]
authors: Article[]
allAuthors: Article[]
loading: boolean
error: string | null
onUnlock: (article: Article) => void
unlockedArticles: Set<string>
}
function HomeHead(): React.ReactElement {
return (
<Head>
<title>zapwall.fr</title>
<meta
name="description"
content="Plateforme de publication d'articles scientifiques et de science-fiction avec sponsoring et rémunération des avis"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
</Head>
)
}
function ArticlesHero({
searchQuery,
setSearchQuery,
selectedCategory,
setSelectedCategory,
}: Pick<HomeViewProps, 'searchQuery' | 'setSearchQuery' | 'selectedCategory' | 'setSelectedCategory'>): React.ReactElement {
return (
<div className="mb-8">
<CategoryTabs selectedCategory={selectedCategory} onCategoryChange={setSelectedCategory} />
<div className="mb-4">
<SearchBar value={searchQuery} onChange={setSearchQuery} />
</div>
</div>
)
}
function HomeContent({
searchQuery,
setSearchQuery,
selectedCategory,
setSelectedCategory,
filters,
setFilters,
articles,
allArticles,
authors,
allAuthors,
loading,
error,
onUnlock,
unlockedArticles,
}: HomeViewProps): React.ReactElement {
const shouldShowFilters = !loading && allArticles.length > 0
const shouldShowAuthors = selectedCategory !== null && selectedCategory !== 'all'
// At startup, we don't know yet if we're loading articles or authors
// Use a generic loading message until we have content
const isInitialLoad = loading && allArticles.length === 0 && allAuthors.length === 0
const articlesListProps = {
articles,
allArticles,
loading: loading && !isInitialLoad, // Don't show loading if it's the initial generic state
error,
onUnlock,
unlockedArticles
}
const authorsListProps = { authors, allAuthors, loading: loading && !isInitialLoad, error }
return (
<div className="w-full px-4 py-8">
<ArticlesHero
searchQuery={searchQuery}
setSearchQuery={setSearchQuery}
selectedCategory={selectedCategory}
setSelectedCategory={setSelectedCategory}
/>
{shouldShowFilters && !shouldShowAuthors && (
<ArticleFiltersComponent filters={filters} onFiltersChange={setFilters} articles={allArticles} />
)}
{isInitialLoad ? (
<div className="text-center py-12">
<p className="text-cyber-accent/70">{t('common.loading')}</p>
</div>
) : shouldShowAuthors ? (
<AuthorsList {...authorsListProps} />
) : (
<ArticlesList {...articlesListProps} />
)}
</div>
)
}
export function HomeView(props: HomeViewProps): React.ReactElement {
return (
<>
<HomeHead />
<main className="min-h-screen bg-cyber-darker">
<PageHeader />
<HomeContent {...props} />
<Footer />
</main>
</>
)
}