Skip to content

Commit fa6e559

Browse files
committed
랭킹 페이지 추가
1 parent 5c69c47 commit fa6e559

File tree

3 files changed

+97
-7
lines changed

3 files changed

+97
-7
lines changed

src/app/(main)/ranking/page.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import type {Metadata} from "next";
2+
import {Header} from "@/app/components/main-layout/header";
3+
import {RakingList} from "@/app/components/main-layout/raking/raking-list";
4+
import {getRaking} from "@/app/lib/raking";
25

36
export const metadata: Metadata = {
47
title: "랭킹",
58
description: "비비노 평점 랭킹을 기반으로한 랭킹입니다",
6-
//준비중일때는 색인 안되게 하기
7-
robots: {
8-
index: false,
9-
}
109
};
1110

1211

13-
export default function Page() {
12+
export default async function Page() {
13+
const initialRaking = await getRaking()
1414
return (
15-
<div className={"min-h-96 md:container md:mx-auto"}>
16-
<p className={"text-lg"}>준비 중 입니다.</p>
15+
<div className={"mt-4 flex flex-col gap-4 px-4 md:container md:mx-auto"}>
16+
<Header>랭킹</Header>
17+
<RakingList initialRaking={initialRaking}/>
1718
</div>
1819
)
1920
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
'use client'
2+
3+
import {useEffect, useState} from "react";
4+
import {useInView} from "react-intersection-observer";
5+
import {Wine} from "@/app/types/wine";
6+
import {Alert, List, Spinner} from "flowbite-react";
7+
import Link from "next/link";
8+
import {WineListItemSummaryInformation} from "@/app/components/main-layout/wine-list-item-summary-information";
9+
import {getRaking} from "@/app/lib/raking";
10+
11+
export function RakingList({initialRaking}: {initialRaking: Wine[]}) {
12+
const [raking, setRaking] = useState(initialRaking);
13+
const [page, setPage] = useState(2);
14+
const [isMoreRaking, setIsMoreRaking] = useState<boolean>(true);
15+
const {ref, inView} = useInView();
16+
17+
async function loadMoreRakingResults() {
18+
const moreSearchResult = await getRaking(page);
19+
setRaking(prevResults => [...prevResults, ...moreSearchResult]);
20+
if (moreSearchResult.length <= 0) {
21+
setIsMoreRaking(false);
22+
}
23+
}
24+
25+
useEffect(() => {
26+
if (inView) {
27+
// noinspection JSIgnoredPromiseFromCall
28+
loadMoreRakingResults();
29+
setPage(prevPage => prevPage + 1);
30+
}
31+
// eslint-disable-next-line react-hooks/exhaustive-deps
32+
}, [inView]);
33+
34+
const searchResultItem = raking.map((item, index) => (
35+
<List.Item key={item.id} className={"" + (
36+
(index === 0) ? "gold-number" : (index === 1 ? "sliver-number" : ((index === 2) && "bronze-number")))}>
37+
<Link href={"/wine/" + item.id}
38+
className={"inline-block py-3"}>
39+
<div className={"inline-flex flex-col"}>
40+
<div className={"hover:underline"}>
41+
{item.name}
42+
</div>
43+
<WineListItemSummaryInformation item={item} />
44+
</div>
45+
</Link>
46+
</List.Item>
47+
));
48+
49+
return (
50+
<>
51+
<Alert color="info">
52+
와인 이름이 중복된 경우에는 와이너리, 산도 등이 달라 실제로는 다른 와인이니 착오 없으시길 바랍니다. 비비노 평점과 리뷰 개수는 현재의 수치와 다를 수 있습니다.
53+
</Alert>
54+
<List ordered className="divide-y space-y-0 divide-gray-200 dark:divide-gray-700 text-black items-center bold-list-numbers">
55+
{searchResultItem}
56+
{isMoreRaking && (
57+
<li ref={ref} className={"py-3 block text-center"}>
58+
<Spinner size="xl" color={"rose"} />
59+
</li>
60+
)}
61+
</List>
62+
</>
63+
);
64+
}

src/app/lib/raking.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use server'
2+
3+
import {Wine} from "@/app/types/wine";
4+
import {notFound} from "next/navigation";
5+
6+
export async function getRaking(page?: number): Promise<Wine[]> {
7+
let url = 'http://localhost:8000/ranking'
8+
9+
if (page !== undefined) {
10+
url += '?page=' + page
11+
}
12+
13+
const res = await fetch(url, {
14+
cache: 'no-store',
15+
})
16+
17+
if (!res.ok) {
18+
if (res.status >= 500)
19+
throw new Error('ops!')
20+
21+
notFound()
22+
}
23+
24+
return res.json()
25+
}

0 commit comments

Comments
 (0)