-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathpage.tsx
More file actions
145 lines (129 loc) · 4.88 KB
/
page.tsx
File metadata and controls
145 lines (129 loc) · 4.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
"use client"
import { useEffect, useState, useCallback } from "react"
import { useRouter, useSearchParams } from "next/navigation"
import { getPaginatedPosts } from "@/lib/blog"
import BlogCard from "@/components/blog-card"
import Pagination from "@/components/pagination"
import Link from "next/link"
import Footer from "@/components/footer"
import ThemeToggle from "@/components/theme-toggle"
interface BlogPost {
slug: string
title: string
author: string
date: string
image: string
excerpt: string
featured: boolean
}
interface PaginatedData {
posts: BlogPost[]
totalPages: number
hasNextPage: boolean
hasPrevPage: boolean
}
export default function HomePage() {
const router = useRouter()
const searchParams = useSearchParams()
const [paginatedData, setPaginatedData] = useState<PaginatedData | null>(null)
const [loading, setLoading] = useState(true)
const [currentPage, setCurrentPage] = useState(1)
// Get current page from URL
const getPageFromUrl = useCallback(() => {
const pageParam = searchParams.get("page")
if (!pageParam) return 1
const page = Number.parseInt(pageParam, 10)
return isNaN(page) || page < 1 ? 1 : page
}, [searchParams])
// Update current page when URL changes
useEffect(() => {
const urlPage = getPageFromUrl()
if (urlPage !== currentPage) {
setCurrentPage(urlPage)
}
}, [searchParams, getPageFromUrl, currentPage])
// Load posts when current page changes
useEffect(() => {
function loadPosts() {
setLoading(true)
try {
const data = getPaginatedPosts(currentPage, 12)
setPaginatedData(data)
} catch (error) {
console.error("Error loading posts:", error)
} finally {
setLoading(false)
}
}
loadPosts()
}, [currentPage])
const handlePageChange = useCallback(
(page: number) => {
if (page < 1) page = 1
setCurrentPage(page)
router.push(`/?page=${page}`, { scroll: false })
},
[router],
)
if (loading) {
return (
<div className="min-h-screen bg-gradient-to-br from-green-50 via-yellow-50 to-[#FFC517]/10 dark:from-slate-950 dark:via-emerald-950 dark:to-slate-900 transition-colors flex items-center justify-center">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-[#228B22] dark:border-amber-300 mx-auto mb-4"></div>
<p className="text-gray-600 dark:text-gray-300">Loading articles...</p>
</div>
</div>
)
}
if (!paginatedData) {
return (
<div className="min-h-screen bg-gradient-to-br from-green-50 via-yellow-50 to-[#FFC517]/10 dark:from-slate-950 dark:via-emerald-950 dark:to-slate-900 transition-colors flex items-center justify-center">
<div className="text-center">
<p className="text-gray-600 dark:text-gray-300">Failed to load articles.</p>
</div>
</div>
)
}
const { posts, totalPages, hasNextPage, hasPrevPage } = paginatedData
return (
<div className="min-h-screen bg-gradient-to-br from-green-50 via-yellow-50 to-[#FFC517]/10 dark:from-slate-950 dark:via-emerald-950 dark:to-slate-900 transition-colors">
{/* Header */}
<header className="border-b border-[#228B22]/10 dark:border-white/10 bg-white/90 dark:bg-slate-900/80 backdrop-blur-sm sticky top-0 z-50 shadow-sm transition-colors">
<div className="max-w-6xl mx-auto px-4 py-6 flex justify-between items-center">
<div>
<h1 className="text-5xl font-bold font-playfair bg-gradient-to-r from-[#228B22] via-[#5A981A] via-[#91A511] via-[#ADAC0D] via-[#E4B905] to-[#FFBF00] bg-clip-text text-transparent drop-shadow-sm leading-tight pb-2">
Stable Viewpoints
</h1>
<p className="text-gray-600 dark:text-gray-300 mt-2 text-lg">Independent Articles about Stability</p>
</div>
<div className="flex items-center gap-4">
<ThemeToggle />
<Link
href="/submit"
className="inline-flex items-center gap-2 bg-gradient-to-r from-[#228B22] to-[#91A511] hover:from-[#3E921E] hover:to-[#ADAC0D] text-white px-6 py-3 font-semibold transition-all duration-300 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5"
>
Submit an Article
</Link>
</div>
</div>
</header>
{/* Main Content */}
<main className="max-w-6xl mx-auto px-4 py-12">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{posts.map((post) => (
<BlogCard key={post.slug} post={post} />
))}
</div>
{/* Pagination */}
<Pagination
currentPage={currentPage}
totalPages={totalPages}
hasNextPage={hasNextPage}
hasPrevPage={hasPrevPage}
onPageChange={handlePageChange}
/>
</main>
<Footer />
</div>
)
}