diff --git a/src/assets/image/backArrow.svg b/src/assets/image/backArrow.svg new file mode 100644 index 0000000..6511ecc --- /dev/null +++ b/src/assets/image/backArrow.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/image/frontArrow.svg b/src/assets/image/frontArrow.svg new file mode 100644 index 0000000..b34dde6 --- /dev/null +++ b/src/assets/image/frontArrow.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/image/info.svg b/src/assets/image/info.svg new file mode 100644 index 0000000..60542f2 --- /dev/null +++ b/src/assets/image/info.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/components/NavBar/NavBar.style.ts b/src/components/NavBar/NavBar.style.ts index d3f7b01..cd5461f 100644 --- a/src/components/NavBar/NavBar.style.ts +++ b/src/components/NavBar/NavBar.style.ts @@ -45,6 +45,7 @@ export const NavBar = styled.div` align-items: flex-start; gap: 8px; flex-shrink: 0; + border-bottom: 2px solid rgba(0, 0, 0, 0); } .nav-items a { @@ -56,8 +57,17 @@ export const NavBar = styled.div` line-height: 22px; /* 157.143% */ } - .nav-items a:hover { - color: #007bff; /* 호버 시 색상 변화 */ + .nav-item:hover { + border-bottom: 2px solid #636ae8; + } + + .active { + display: flex; + padding: 24px 23.75px 24px 17.75px; + align-items: flex-start; + gap: 8px; + flex-shrink: 0; + border-bottom: 2px solid #636ae8; } .nav-button { diff --git a/src/components/NavBar/NavBar.tsx b/src/components/NavBar/NavBar.tsx index 5d2b6fe..43e474b 100644 --- a/src/components/NavBar/NavBar.tsx +++ b/src/components/NavBar/NavBar.tsx @@ -1,4 +1,4 @@ -import { useNavigate } from "react-router-dom"; +import { useNavigate, useLocation } from "react-router-dom"; import * as S from "@/components/NavBar/NavBar.style"; import logo from "@/assets/image/logo.svg"; import doc from "@/assets/image/doc.svg"; @@ -9,6 +9,10 @@ import logout from "@/assets/image/logout.svg"; const NavBar = () => { const navigate = useNavigate(); + const location = useLocation(); + + // 특정 경로가 현재 경로와 일치하면 해당 스타일을 적용 + const isActive = (path: string) => location.pathname === path; return ( @@ -17,11 +21,17 @@ const NavBar = () => { Logo navigate("/main")} />
-
navigate("/lank")}> +
navigate("/lank")} + > Lank 랭킹 페이지
-
navigate("/fileask")}> +
navigate("/fileask")} + > Doc 문서 요청하기
diff --git a/src/pages/LankPage/LankPage.style.ts b/src/pages/LankPage/LankPage.style.ts index e69de29..7c49026 100644 --- a/src/pages/LankPage/LankPage.style.ts +++ b/src/pages/LankPage/LankPage.style.ts @@ -0,0 +1,63 @@ +import styled from "styled-components"; + +export const StyledLankPage = styled.div` + display: flex; + align-items: start; + justify-content: center; + height: 100vh; + margin: 40px 16px; + gap: 16px; +`; + +export const LankDescription = styled.div` + border-radius: 16px; + border: 1px solid #dee1e6; + background: #fff; + padding: 16px; + display: flex; + flex-direction: column; + align-items: start; + justify-content: center; + + .maintitle { + display: flex; + align-items: center; + gap: 8px; + color: #636ae8; + font-family: Inter; + font-size: 20px; + font-style: normal; + font-weight: 600; + line-height: 30px; /* 150% */ + margin-bottom: 30px; + margin-left: 16px; + } + + .subtitle { + color: #323743; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 700; + line-height: 22px; /* 157.143% */ + } + + .description { + color: #323743; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 22px; /* 157.143% */ + margin-top: 8px; + margin-left: 16px; + margin-bottom: 30px; + } +`; + +export const Lank = styled.div` + border-radius: 16px; + border: 1px solid #dee1e6; + background: #fff; + padding: 25px; +`; diff --git a/src/pages/LankPage/LankPage.tsx b/src/pages/LankPage/LankPage.tsx index a03ed39..8290841 100644 --- a/src/pages/LankPage/LankPage.tsx +++ b/src/pages/LankPage/LankPage.tsx @@ -1,5 +1,62 @@ +import NavBar from "@/components/NavBar/NavBar"; +import * as S from "@/pages/LankPage/LankPage.style"; +import info from "@/assets/image/info.svg"; +import Table from "@/pages/LankPage/LankTable"; + const LankPage = () => { - return

LankPage

; + return ( + <> + + + +
+ info + 랭킹 기준과 혜택 +
+
랭킹 등급 기준
+
+ 브론즈: 제한 없음
+ 실버: 500포인트 이상인 상위 40% 유저
+ 골드: 1000포인트 이상인 상위 10% 유저
+ 플래티넘: 1500포인트 이상인 상위 3% 유저 +
+
랭킹별 혜택
+
+ 브론즈: 없음 +
+ 실버: 30 RLUSD, 자료구매시 5% RLUSD 결제,
+        자료 요청 수수료 5% 할인 +
+ 골드: 120 RLUSD, 자료구매시 10% RLUSD 결제,
+        자료 요청 수수료 10% 할인 +
+ 플래티넘: 400 RLUSD, 자료구매시 20% RLUSD 결제,
+        자료 요청 수수료 15% 할인 +
+
포인트 획득 방식
+
+ 자료 업로드: 100 포인트 +
+ 파일 다운로드수: 10 포인트 +
+ 파일 리뷰 3.5 이상: 50 포인트 +
+ 4.5 이상인 리뷰 개수: 20 포인트 +
+ 리뷰 작성: 5 포인트 +
+ 자료 요청 응답: 50 포인트 +
+ 요청글 등록: 10 포인트 +
+
+
+ + + + + + ); }; export default LankPage; diff --git a/src/pages/LankPage/LankTable.style.ts b/src/pages/LankPage/LankTable.style.ts new file mode 100644 index 0000000..f4585dc --- /dev/null +++ b/src/pages/LankPage/LankTable.style.ts @@ -0,0 +1,97 @@ +import styled from "styled-components"; + +export const LankTable = styled.table` + border-radius: 16px; + border: 1px solid #dee1e6; + background: rgba(0, 0, 0, 0); + width: 55vw; + border-collapse: separate; + text-align: center; + + .header { + border-bottom: 1px solid #dee1e6; + background: #fafafb; + padding: 10px; + } + .td { + padding: 10px; + align-items: center; + } + .tr:nth-child(2n + 0) { + border: 0px solid #dee1e6; + background: #fafafb; + } +`; + +export const StyledLankPage = styled.div` + display: flex; + align-items: center; + flex-direction: column; + margin: 20px 16px; + gap: 16px; +`; + +export const PaginationWrapper = styled.div` + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + margin-top: 15px; +`; + +export const PageButton = styled.button<{ active: boolean }>` + padding: 8px 12px; + background-color: ${({ active }) => (active ? "#636ae8" : "#fff")}; + color: ${({ active }) => (active ? "#fff" : "#9095A1")}; + border-radius: 16px; + border: 1px solid ${({ active }) => (active ? "#636ae8" : "#dee1e6")}; + cursor: pointer; + + &:hover { + background-color: ${({ active }) => (active ? "#636ae8" : "#f0f0f0")}; + border-color: #636ae8; /* hover 시 border 색상 변경 */ + } +`; + +export const ArrowButton = styled.button` + padding: 8px; + background-color: #fff; + color: #636ae8; + border-radius: 50%; + cursor: pointer; + + &:hover { + background-color: #fff; /* 화살표 버튼에는 hover 배경색을 없애거나 투명하게 */ + } +`; + +export const Ellipsis = styled.span` + color: #636ae8; +`; + +export const StyledLankLabel = styled.div<{ rank: string }>` + display: flex; + justify-content: center; /* 수평 가운데 정렬 */ + align-items: center; /* 수직 가운데 정렬 */ + background-color: ${({ rank }) => + rank === "브론즈" + ? "#FFF5F0" + : rank === "실버" + ? "#F4F6FB" + : rank === "골드" + ? "#FEF9EE" + : "#EFFCFA"}; + color: ${({ rank }) => + rank === "브론즈" + ? "#672700" + : rank === "실버" + ? "#263F6D" + : rank === "골드" + ? "#98690C" + : "#147567"}; + border-radius: 18px; + width: 80px; + font-size: 14px; + text-align: center; /* 텍스트 가운데 정렬 */ + width: 100%; /* 셀의 너비 전체를 사용 */ +`; diff --git a/src/pages/LankPage/LankTable.tsx b/src/pages/LankPage/LankTable.tsx new file mode 100644 index 0000000..0f8528a --- /dev/null +++ b/src/pages/LankPage/LankTable.tsx @@ -0,0 +1,111 @@ +import { useState } from "react"; +import * as S from "@/pages/LankPage/LankTable.style"; +import frontArrow from "@/assets/image/frontArrow.svg"; +import backArrow from "@/assets/image/backArrow.svg"; + +interface TableData { + no: number; + name: string; + points: number; + ranking: string; +} + +const Table = () => { + // 더미 데이터 (실제로는 API로 데이터를 받으면 됩니다) + const data: TableData[] = [ + { no: 1, name: "홍길동", points: 5000, ranking: "플래티넘" }, + { no: 2, name: "홍길동", points: 5000, ranking: "플래티넘" }, + { no: 3, name: "홍길동", points: 5000, ranking: "골드" }, + { no: 4, name: "홍길동", points: 5000, ranking: "골드" }, + { no: 5, name: "홍길동", points: 5000, ranking: "실버" }, + { no: 6, name: "홍길동", points: 2000, ranking: "실버" }, + { no: 7, name: "홍길동", points: 2000, ranking: "실버" }, + { no: 8, name: "홍길동", points: 2000, ranking: "브론즈" }, + { no: 9, name: "홍길동", points: 2000, ranking: "브론즈" }, + { no: 10, name: "홍길동", points: 2000, ranking: "브론즈" }, + ]; + + const [currentPage, setCurrentPage] = useState(1); + const itemsPerPage = 10; // 한 페이지에 보여줄 아이템 수 + + // 현재 페이지에 해당하는 데이터만 필터링 + const currentData = data.slice( + (currentPage - 1) * itemsPerPage, + currentPage * itemsPerPage + ); + + // 페이지네이션 처리 + const totalPages = Math.ceil(data.length / itemsPerPage); + + // 페이지 버튼 생성 함수 + const createPageButtons = () => { + const pageButtons = []; + const range = 2; // "현재 페이지"를 기준으로 보여줄 범위 + + for ( + let i = Math.max(1, currentPage - range); + i <= Math.min(totalPages, currentPage + range); + i++ + ) { + pageButtons.push(i); + } + + return pageButtons; + }; + + return ( + + + + + + + + + + + + {currentData.map((item) => ( + + + + + + + ))} + + + {/* 페이지네이션 */} + + setCurrentPage((prev) => Math.max(prev - 1, 1))} + > + ◁ + + {createPageButtons().map((page: number) => ( + setCurrentPage(page)} + active={page === currentPage} + > + {page} + + ))} + {currentPage + 2 < totalPages && ...} + + setCurrentPage((prev) => Math.min(prev + 1, totalPages)) + } + > + ▷ + + + + ); +}; + +export default Table;
NONAME포인트랭킹
{item.no}{item.name}{item.points} + + {item.ranking} + +