Skip to content

Commit 086c1cc

Browse files
main feed component
1 parent ef705a6 commit 086c1cc

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

src/components/feed/Feed.tsx

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
'use client'
2+
3+
import { useEffect, useRef, useState } from 'react'
4+
import { FetchLoading } from 'fetch-loading'
5+
import fetchFeedItems from '@/api/fetchFeedItems'
6+
import {
7+
Card,
8+
CardContent,
9+
CardDescription,
10+
CardFooter,
11+
CardHeader,
12+
CardTitle,
13+
} from '@/components/ui/card'
14+
15+
const Feed = () => {
16+
const PAGE_SIZE = 10
17+
const nextPage = useRef<number>(1)
18+
const [feedItems, setFeedItems] = useState<
19+
Array<{
20+
postId: number
21+
id: number
22+
name: string
23+
email: string
24+
body: string
25+
}>
26+
>([])
27+
const [isLoading, setIsLoading] = useState(false)
28+
29+
const loadMore = async () => {
30+
if (isLoading) return
31+
setIsLoading(true)
32+
await fetchFeedItems(nextPage, PAGE_SIZE, setFeedItems)
33+
setIsLoading(false)
34+
}
35+
36+
useEffect(() => {
37+
loadMore()
38+
}, [])
39+
40+
useEffect(() => {
41+
const handleScroll = () => {
42+
if (
43+
window.innerHeight + window.scrollY >=
44+
document.body.offsetHeight - 96
45+
) {
46+
loadMore()
47+
}
48+
}
49+
50+
window.addEventListener('scroll', handleScroll)
51+
return () => window.removeEventListener('scroll', handleScroll)
52+
}, [isLoading])
53+
54+
return (
55+
<main
56+
className="w-full flex flex-col items-center gap-4 max-w-7xl relative isolate bg-stone-300 text-stone-950 lg:rounded-lg p-3 sm:p-4 lg:p-6
57+
drop-shadow-stone-900 drop-shadow-sm"
58+
>
59+
{feedItems.length > 0 ? (
60+
<div className="grid grid-cols-[repeat(auto-fit,minmax(min(100%,448px),1fr))] grid-flow-row-dense w-full gap-3 sm:gap-4 lg:gap-6">
61+
{feedItems.map((item) => (
62+
<Card key={item.id}>
63+
<CardHeader>
64+
<CardTitle>{item.name}</CardTitle>
65+
<CardDescription>{item.email}</CardDescription>
66+
</CardHeader>
67+
<CardContent>
68+
<p>{item.body}</p>
69+
</CardContent>
70+
<CardFooter>
71+
<p>Post #{item.id}</p>
72+
</CardFooter>
73+
</Card>
74+
))}
75+
</div>
76+
) : null}
77+
78+
{isLoading && (
79+
<div className="p-2 pt-4">
80+
<FetchLoading ariaLabel="Loading more Items." />
81+
</div>
82+
)}
83+
</main>
84+
)
85+
}
86+
87+
export default Feed

0 commit comments

Comments
 (0)