Skip to content

Commit 7e95cba

Browse files
committed
Added Pagination
1 parent b8d5c53 commit 7e95cba

File tree

4 files changed

+83
-12
lines changed

4 files changed

+83
-12
lines changed

global.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// global.d.ts
2+
declare module '@heroicons/react/solid';
3+
declare module '@heroicons/react/outline';

package-lock.json

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"react-dom": "^18"
1616
},
1717
"devDependencies": {
18+
"@heroicons/react": "^2.1.5",
1819
"@types/node": "^20",
1920
"@types/react": "^18",
2021
"@types/react-dom": "^18",

src/app/page.tsx

+69-12
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,100 @@
11
// app/page.tsx
2-
32
"use client";
3+
44
import { useEffect, useState } from 'react';
5-
import { fetchTopStories, fetchItemById } from '../../utils/api';
5+
import { fetchTopStories, fetchItemById } from '../../utils/api';
66
import Link from 'next/link';
7+
import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/24/solid';
78

89
type Story = {
910
id: number;
1011
title: string;
1112
url?: string;
1213
by: string;
14+
score: number;
15+
time: number;
1316
};
1417

1518
export default function Home() {
1619
const [stories, setStories] = useState<Story[]>([]);
20+
const [currentPage, setCurrentPage] = useState(1);
21+
const [totalPages, setTotalPages] = useState(0);
22+
const storiesPerPage = 10; // Number of stories per page
1723

1824
useEffect(() => {
1925
const getStories = async () => {
2026
const storyIds = await fetchTopStories();
21-
const storiesData = await Promise.all(storyIds.map((id: number) => fetchItemById(id)));
27+
setTotalPages(Math.ceil(storyIds.length / storiesPerPage));
28+
29+
const paginatedStoryIds = storyIds.slice(
30+
(currentPage - 1) * storiesPerPage,
31+
currentPage * storiesPerPage
32+
);
33+
34+
const storiesData = await Promise.all(paginatedStoryIds.map((id: number) => fetchItemById(id)));
2235
setStories(storiesData);
2336
};
2437

2538
getStories();
26-
}, []);
39+
}, [currentPage]);
40+
41+
const handleNextPage = () => {
42+
if (currentPage < totalPages) {
43+
setCurrentPage(currentPage + 1);
44+
}
45+
};
46+
47+
const handlePrevPage = () => {
48+
if (currentPage > 1) {
49+
setCurrentPage(currentPage - 1);
50+
}
51+
};
2752

2853
return (
29-
<div className="container mx-auto p-4">
30-
<h1 className="text-3xl font-bold">Hacker News - Top Stories</h1>
31-
<ul className="mt-4">
54+
<div className="container mx-auto p-6">
55+
<h1 className="text-4xl font-bold text-center mb-6">Hacker News - Top Stories</h1>
56+
<ul className="space-y-6">
3257
{stories.map((story) => (
33-
<li key={story.id} className="mb-4">
34-
<Link href={`/story/${story.id}`} className="text-blue-600 hover:underline">
35-
{story.title}
36-
</Link>
37-
<p className="text-sm text-gray-600">by {story.by}</p>
58+
<li key={story.id} className="bg-white shadow-md p-4 rounded-lg">
59+
<div className="flex items-start justify-between">
60+
<div>
61+
<Link href={`/story/${story.id}`} className="text-lg font-semibold text-blue-600 hover:underline">
62+
{story.title}
63+
</Link>
64+
<p className="text-sm text-gray-600">by {story.by}</p>
65+
</div>
66+
<p className="text-gray-500 text-sm">
67+
{story.score} points | {new Date(story.time * 1000).toLocaleDateString()}
68+
</p>
69+
</div>
3870
</li>
3971
))}
4072
</ul>
73+
74+
{/* Pagination Controls */}
75+
<div className="flex justify-center items-center mt-6">
76+
<button
77+
className={`mr-2 p-2 rounded-md bg-gray-200 ${
78+
currentPage === 1 ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-300'
79+
}`}
80+
onClick={handlePrevPage}
81+
disabled={currentPage === 1}
82+
>
83+
<ChevronLeftIcon className="w-5 h-5 text-gray-600" />
84+
</button>
85+
<span className="text-lg font-semibold">
86+
{currentPage} / {totalPages}
87+
</span>
88+
<button
89+
className={`ml-2 p-2 rounded-md bg-gray-200 ${
90+
currentPage === totalPages ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-300'
91+
}`}
92+
onClick={handleNextPage}
93+
disabled={currentPage === totalPages}
94+
>
95+
<ChevronRightIcon className="w-5 h-5 text-gray-600" />
96+
</button>
97+
</div>
4198
</div>
4299
);
43100
}

0 commit comments

Comments
 (0)