Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 3 additions & 14 deletions src/components/home/Home.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,8 @@ import { getUserInfoAPI } from "services/user/user";
import "styles/components/home/Home.scss";
import { getAuthToken } from "utils/token";
import { getUserInfo } from "utils/user";
import { RankingPreview } from "./RankingPreview";
const rankingData = [
{ username: "Player1", score: 1000 },
{ username: "Player2", score: 900 },
{ username: "Player3", score: 800 },
{ username: "Player4", score: 700 },
{ username: "Player5", score: 600 },
{ username: "Player6", score: 500 },
{ username: "Player7", score: 400 },
{ username: "Player8", score: 300 },
{ username: "Player9", score: 200 },
{ username: "Player10", score: 100 },
];
import { RankingPreview } from "components/home/RankingPreview.jsx";

const Home = () => {
const navigate = useNavigate();
const { isSignIn } = useOutletContext();
Expand Down Expand Up @@ -91,7 +80,7 @@ const Home = () => {
<div className="home-middle-container">
<InformationContainer />
<div className="preview-container">
<RankingPreview rankingData={rankingData} />
<RankingPreview />
<IntroduceCharacterPreview />
</div>
</div>
Expand Down
36 changes: 32 additions & 4 deletions src/components/home/RankingPreview.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
import { useEffect, useState } from "react";
import { getMyRankingAPI, getRankingListAPI } from "services/home/ranking";
import "styles/components/home/RankingPreview.scss";
export const RankingPreview = ({ rankingData }) => {
export const RankingPreview = () => {
const [rankingData, setRankingData] = useState([]);
const [myScore, setMyScore] = useState(null);

useEffect(() => {
const fetchRanking = async () => {
try {
// 🔹 내 랭킹 먼저 가져오기
const myRes = await getMyRankingAPI();
const me = myRes?.data || myRes;

if (me) {
setMyScore(me.exp);
}

// 🔹 전체 랭킹 가져오기
const listRes = await getRankingListAPI();
const list = listRes?.data || listRes || [];
setRankingData(list);
} catch (e) {
console.error("랭킹 프리뷰 조회 실패:", e);
}
};

fetchRanking();
}, []);
console.log(rankingData);
return (
<div className="ranking-preview-container">
<h2>랭킹 </h2>
Expand All @@ -8,10 +36,10 @@ export const RankingPreview = ({ rankingData }) => {
rankingData.slice(0, 4).map((item, index) => (
<li key={index} className="ranking-item">
<span className="user-rank-info">
{index + 1}. {item.username}
{item.rank}. {item.nickname}
</span>
<div className="dots" />
<span className="score">{item.score} 점</span>
<span className="score">{item.exp} 점</span>
</li>
))
) : (
Expand All @@ -24,7 +52,7 @@ export const RankingPreview = ({ rankingData }) => {
<div className="my-score-box">
<div className="my-score-background">
<div className="my-score-edge" />
<span className="my-score">9ssssss 점</span>
<span className="my-score">{myScore ?? 0} 점</span>
</div>
</div>
</div>
Expand Down
27 changes: 27 additions & 0 deletions src/components/home/SideRankingList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import "styles/components/home/SideRankingList.scss";

const SideRankingList = ({ title, list, highlightRank }) => {
return (
<div className="side-ranking">
<h2 className="side-title">{title}</h2>

<div className="side-list">
{list.map((item) => (
<div
key={`rank-${item.rank}-${item.nickname}`}
className={
"side-item " + (item.rank === highlightRank ? "highlight" : "")
}
>
<span className="rank">{item.rank}.</span>
<span className="name">{item.nickname}</span>
<span className="dashed-line"></span>
<span className="score">{item.exp}점</span>
</div>
))}
</div>
</div>
);
};

export default SideRankingList;
3 changes: 3 additions & 0 deletions src/constants/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,7 @@ export const SERVICE_LIST_API = process.env.REACT_APP_SERVICE_LIST_API;
export const SERVICE_MY_LIST_API = process.env.REACT_APP_SERVICE_MY_LIST_API;
export const SERVICE_QNA_API = process.env.REACT_APP_SERVICE_QNA;

export const RANKING_API = process.env.REACT_APP_RANKING_API;
export const RANkING_MY_API = process.env.REACT_APP_MY_RANKING_API;

export const AI_SERVER_IP = process.env.REACT_APP_AI_SERVER_IP;
89 changes: 89 additions & 0 deletions src/pages/home/RankingPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import SideRankingList from "components/home/SideRankingList";
import { useEffect, useState } from "react";
import { getMyRankingAPI, getRankingListAPI } from "services/home/ranking";
import "styles/pages/home/RankingPage.scss";

const RankingPage = () => {
const [rankingList, setRankingList] = useState([]);
const [myRank, setMyRank] = useState(null);
const [myScore, setMyScore] = useState(null);
const [topList, setTopList] = useState([]);
const [nearList, setNearList] = useState([]);

useEffect(() => {
const fetchRanking = async () => {
try {
// ② 내 랭킹 조회
const myRes = await getMyRankingAPI();
const me = myRes?.data || myRes;

if (!me) return;

// 전체 랭킹 조회 (7명까지)
const fullRes = await getRankingListAPI();
const list = fullRes?.data || fullRes || [];
setRankingList(list);
setTopList(list.slice(0, 7));

setMyRank(me.rank);
setMyScore(me.exp);

// 내 근처 랭킹 계산 (위 아래 3명)
const myIndex = list.findIndex((item) => item.rank === me.rank);
const start = Math.max(myIndex - 3, 0);
const end = Math.min(myIndex + 4, list.length);
setNearList(list.slice(start, end));
} catch (err) {
console.error("랭킹 조회 실패:", err);
}
};

fetchRanking();
}, []);

// 바로 위 등수와의 점수 차이
const diffScore =
myRank > 1 && rankingList.length >= myRank - 1
? rankingList[myRank - 2].exp - myScore
: 0;

return (
<div className="ranking-page-wrapper">
<div className="ranking-page">
<SideRankingList title="상위 랭킹" list={topList} />

<div className="ranking-center">
<div className="rank-label">내 등수</div>
<div className="my-rank">
<span className="rank-number">{myRank ?? "-"}</span>
<span className="rank-unit">등</span>
</div>

<div className="score-row">
<span className="score-label">내 점수</span>
<span className="dashed-line"></span>
<span className="my-score">{myScore ?? 0} 점</span>
</div>
</div>

<SideRankingList
title="내 근처 랭킹"
list={nearList}
highlightRank={myRank}
/>
</div>
<div className="bottom-banner">
{myRank === 1 ? (
<p>현재 1등입니다!</p>
) : (
<p>
<span className="banner-score">{diffScore}</span>점만 더 높으면
등수를 앞지를 수 있어요!
</p>
)}
</div>
</div>
);
};

export default RankingPage;
8 changes: 6 additions & 2 deletions src/routes/home.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import ServiceFAQPage from "pages/home/ServiceFAQPage";
import ServiceCenterDetailPage from "pages/home/ServiceCenterDetailPage";
import ServicePostPage from "pages/home/ServicePostPage";
import FAQDetailPage from "pages/home/FAQDetailPage";
import RankingPage from "pages/home/RankingPage";
const home = [
{
path: "/",
Expand All @@ -19,7 +20,10 @@ const home = [
index: true,
element: <Home />,
},

{
path: "ranking",
element: <RankingPage />,
},
{
path: "character-intro",
element: <IntroducePage />,
Expand Down Expand Up @@ -55,7 +59,7 @@ const home = [
{
path: "service-center/post",
element: <ServicePostPage />
}
},
],
},
];
Expand Down
10 changes: 10 additions & 0 deletions src/services/home/ranking.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { RANKING_API, RANkING_MY_API } from "constants/api";
import { apiInterface } from "services/axiosForm";

export const getRankingListAPI = async (params = {}) => {
return await apiInterface("get", RANKING_API, {}, params, false);
};

export const getMyRankingAPI = async () => {
return await apiInterface("get", RANkING_MY_API, {}, {}, true);
};
52 changes: 52 additions & 0 deletions src/styles/components/home/SideRankingList.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.side-ranking {
width: 302px;

.side-title {
font-size: 20px;
font-weight: 400;
margin-bottom: 35px;
}

.side-list {
display: flex;
flex-direction: column;
gap: 16.47px;
font-family: SUIT-Regular;

.side-item {
display: flex;
font-size: 21.08px;
padding-left: 5px;
padding-right: 5px;
align-items: center;

line-height: 29.65px;

&.highlight {
background: #FFDA37;
}

.rank {
padding-right: 10px;
}

.name {
padding-right: 5px;

}

.dashed-line {
flex: 1;
border-bottom: 2px dashed #D7CCCC;
}

.score {
width: 60px;
font-size: 16px;
text-align: right;
}
}
}


}
Loading