diff --git a/src/@components/@common/BestPiickleCard/index.tsx b/src/@components/@common/BestPiickleCard/index.tsx
new file mode 100644
index 00000000..7a36e9bf
--- /dev/null
+++ b/src/@components/@common/BestPiickleCard/index.tsx
@@ -0,0 +1,53 @@
+import { LocationType } from "../../../types/cardCollection";
+import { GTM_CLASS_NAME } from "../../../util/const/gtm";
+import useNavigateCardCollection, { NavigateCardCollectionBestType } from "../hooks/useNavigateCardCollection";
+import * as St from "./style";
+
+interface BestPiickleCardProps {
+ bestPiickle: {
+ _id: string;
+ tags: string[];
+ content: string;
+ };
+ idx: number;
+ canNavigate: boolean;
+ isLast?: boolean;
+}
+
+export default function BestPiickleCard(props: BestPiickleCardProps) {
+ const { bestPiickle, idx, canNavigate, isLast } = props;
+ const { content, tags } = bestPiickle;
+ const GTM_IDX_KEY = `mainBestPiickle${idx + 1}`;
+
+ const navigateCardCollection = useNavigateCardCollection(LocationType.BEST) as NavigateCardCollectionBestType;
+
+ const onClickCard = () => {
+ if (!canNavigate) return;
+ navigateCardCollection(idx);
+ };
+
+ return (
+
+ {isLast ? (
+
+
+ {tags.map((tag: string, i: number) => {
+ return {tag.slice(1)};
+ })}
+
+ {content}
+ 카드 보기
+
+ ) : (
+
+
+ 나머지 주제들도
+
+ 보고 싶다면?
+
+ 나머지 보기
+
+ )}
+
+ );
+}
diff --git a/src/@components/@common/BestPiickleCard/style.ts b/src/@components/@common/BestPiickleCard/style.ts
new file mode 100644
index 00000000..82683011
--- /dev/null
+++ b/src/@components/@common/BestPiickleCard/style.ts
@@ -0,0 +1,71 @@
+import styled from "styled-components";
+
+export const Container = styled.button``;
+
+export const BestPiickleCard = styled.div`
+ position: relative;
+
+ width: 18rem;
+ height: 10.6rem;
+
+ padding: 0.8rem 1.2rem;
+
+ border-radius: 0.4rem;
+ background: ${({ theme }) => theme.newColors.lightgreen2};
+`;
+
+export const TagsWrapper = styled.ul`
+ display: flex;
+ gap: 0.8rem;
+`;
+
+export const Tag = styled.li`
+ ${({ theme }) => theme.newFonts.caption1};
+ color: ${({ theme }) => theme.newColors.green};
+`;
+
+export const Content = styled.p`
+ margin-top: 0.4rem;
+
+ text-align: left;
+
+ white-space: normal;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+
+ ${({ theme }) => theme.newFonts.btn1}
+ color: ${({ theme }) => theme.newColors.gray900};
+`;
+
+export const PickButtonWrapper = styled.div`
+ margin-top: 1.2rem;
+
+ ${({ theme }) => theme.newFonts.btn2};
+ color: ${({ theme }) => theme.newColors.gray700};
+
+ text-align: right;
+`;
+
+export const LastCard = styled(BestPiickleCard)`
+ display: flex;
+ flex-direction: column;
+
+ padding-top: 2.1rem;
+ background: ${({ theme }) => theme.newColors.white};
+`;
+
+export const LastCardButton = styled.button`
+ margin-top: 1.2rem;
+ align-self: flex-end;
+
+ width: 6.9rem;
+ height: 2.5rem;
+
+ border-radius: 2.9rem;
+ background: ${({ theme }) => theme.newColors.green};
+
+ color: ${({ theme }) => theme.newColors.white};
+ ${({ theme }) => theme.newFonts.btn2}
+`;
diff --git a/src/@components/@common/HeadingTitleContainer/index.tsx b/src/@components/@common/HeadingTitleContainer/index.tsx
index c50146fd..696e0b98 100644
--- a/src/@components/@common/HeadingTitleContainer/index.tsx
+++ b/src/@components/@common/HeadingTitleContainer/index.tsx
@@ -1,23 +1,25 @@
-import { routePaths } from "../../../core/routes/path";
+import { RoutePaths } from "../../../core/routes/path";
import { GTM_CLASS_NAME } from "../../../util/const/gtm";
import { HeadingTitle } from "../../../util/main/headingTitles";
import { St } from "./style";
export interface HeadingTitleContainerProps {
headingTitles: HeadingTitle;
+ paddingVerticalValue?: number;
+ routePath?: RoutePaths;
}
export default function HeadingTitleContainer(props: HeadingTitleContainerProps) {
- const { headingTitles } = props;
+ const { headingTitles, paddingVerticalValue, routePath } = props;
return (
-
-
+
+
{headingTitles.title}
{headingTitles.content}
- {headingTitles && headingTitles.isMoreBtn && (
-
+ {headingTitles && routePath && (
+
더보기
)}
diff --git a/src/@components/@common/HeadingTitleContainer/style.ts b/src/@components/@common/HeadingTitleContainer/style.ts
index 393b51f5..5b8181a8 100644
--- a/src/@components/@common/HeadingTitleContainer/style.ts
+++ b/src/@components/@common/HeadingTitleContainer/style.ts
@@ -2,12 +2,13 @@ import { Link } from "react-router-dom";
import styled from "styled-components";
export const St = {
- Container: styled.header`
+ Container: styled.header<{ paddingVerticalValue: number }>`
display: flex;
align-items: center;
justify-content: space-between;
padding: 2.4rem 0;
+ padding: ${({ paddingVerticalValue }) => `${paddingVerticalValue}rem 0`};
`,
Wrapper: styled.div<{ ismore: boolean }>`
diff --git a/src/@components/@common/hooks/useScrollableContainer.ts b/src/@components/@common/hooks/useDraggingContainer.ts
similarity index 96%
rename from src/@components/@common/hooks/useScrollableContainer.ts
rename to src/@components/@common/hooks/useDraggingContainer.ts
index 1995239b..42e107ea 100644
--- a/src/@components/@common/hooks/useScrollableContainer.ts
+++ b/src/@components/@common/hooks/useDraggingContainer.ts
@@ -1,6 +1,6 @@
import { useRef, useState } from "react";
-export default function useScrollableContainer() {
+export default function useDraggingContainer() {
const containerRef = useRef(null);
const [isStartDragging, setIsStartDragging] = useState(false);
diff --git a/src/@components/BestPiicklePage/BestPiickleRank/RankItem/index.tsx b/src/@components/BestPiicklePage/BestPiickleRank/RankItem/index.tsx
new file mode 100644
index 00000000..de8ad5da
--- /dev/null
+++ b/src/@components/BestPiicklePage/BestPiickleRank/RankItem/index.tsx
@@ -0,0 +1,40 @@
+import { useState } from "react";
+
+import IcBookmarkCheck_16_20 from "../../../../asset/icon/IcBookmarkCheck_16_20";
+import { cardCollectionApi } from "../../../../core/api/cardCollection";
+import { LocationType } from "../../../../types/cardCollection";
+import useNavigateCardCollection, {
+ NavigateCardCollectionBookMarkType,
+} from "../../../@common/hooks/useNavigateCardCollection";
+import * as St from "./style";
+
+interface RankItemProps {
+ cardId: string;
+ content: string;
+ rank: number;
+}
+
+export default function RankItem(props: RankItemProps) {
+ const { cardId, content, rank } = props;
+
+ const navigateRankCollection = useNavigateCardCollection(LocationType.BEST) as NavigateCardCollectionBookMarkType;
+
+ const [isBookmarked, setIsBookmarked] = useState(true);
+ const toggleBookmark = () => {
+ setIsBookmarked((prev) => !prev);
+ //cardCollectionApi.addNDeleteBookmark(cardId);
+ };
+
+ return (
+
+
+ {rank}
+ {content}
+
+
+
+
+ navigateRankCollection(rank)} />
+
+ );
+}
diff --git a/src/@components/BestPiicklePage/BestPiickleRank/RankItem/style.ts b/src/@components/BestPiicklePage/BestPiickleRank/RankItem/style.ts
new file mode 100644
index 00000000..9b140acb
--- /dev/null
+++ b/src/@components/BestPiicklePage/BestPiickleRank/RankItem/style.ts
@@ -0,0 +1,59 @@
+import styled from "styled-components";
+
+export const RankItemContainer = styled.article`
+ position: relative;
+
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ padding: 0.8rem 1.6rem;
+
+ background-color: ${({ theme }) => theme.newColors.white};
+
+ height: 4.8rem;
+`;
+
+export const RankItemLink = styled.button`
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+
+ width: 80%;
+`;
+
+export const RankItemContent = styled.span`
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+`;
+
+export const RankItemNumber = styled.h2<{ idx: number }>`
+ ${({ theme }) => theme.newFonts.body3};
+ color: ${({ idx, theme }) => (idx <= 3 ? theme.newColors.green : theme.newColors.gray600)};
+
+ margin-right: 1.2rem;
+`;
+
+export const RankItemText = styled.p`
+ ${({ theme }) => theme.newFonts.body4};
+ color: ${({ theme }) => theme.newColors.gray900};
+
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ width: 26.4rem;
+`;
+
+export const BookmarkWrapper = styled.div`
+ width: 2.8rem;
+ height: 2.8rem;
+
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ cursor: pointer;
+`;
diff --git a/src/@components/BestPiicklePage/BestPiickleRank/index.tsx b/src/@components/BestPiicklePage/BestPiickleRank/index.tsx
new file mode 100644
index 00000000..cecaf9a0
--- /dev/null
+++ b/src/@components/BestPiicklePage/BestPiickleRank/index.tsx
@@ -0,0 +1,29 @@
+import { HeadingTitle } from "../../../util/main/headingTitles";
+import HeadingTitleContainer from "../../@common/HeadingTitleContainer";
+import RankItem from "./RankItem";
+import * as St from "./style";
+
+const rankTitles: HeadingTitle = {
+ title: "베스트 피클 랭킹",
+ content: "가장 많이 북마크한 대화주제를 확인해보세요",
+};
+
+export default function BestPiickleRank() {
+ return (
+
+ {/* todo : rankitem id 수정*/}
+
+
+
+
+
+
+
+
+
+
+ 이어서 베스트 피클 카드 보기
+
+
+ );
+}
diff --git a/src/@components/BestPiicklePage/BestPiickleRank/style.ts b/src/@components/BestPiicklePage/BestPiickleRank/style.ts
new file mode 100644
index 00000000..8af9a561
--- /dev/null
+++ b/src/@components/BestPiicklePage/BestPiickleRank/style.ts
@@ -0,0 +1,29 @@
+import styled from "styled-components";
+
+export const RankContainer = styled.section`
+ display: flex;
+ flex-direction: column;
+
+ margin-bottom: 7.2rem;
+`;
+
+export const ButtonWrapper = styled.article`
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ width: 100%;
+
+ margin-top: 1.2rem;
+`;
+
+export const ContinueButton = styled.button`
+ width: 20rem;
+ height: 3.6rem;
+ border-radius: 4.6rem;
+ background: ${({ theme }) => theme.newColors.green};
+
+ ${({ theme }) => theme.newFonts.body4};
+ color: white;
+ text-align: center;
+`;
diff --git a/src/@components/BestPiicklePage/BestPiickleRecommend/RecommendItem/index.tsx b/src/@components/BestPiicklePage/BestPiickleRecommend/RecommendItem/index.tsx
new file mode 100644
index 00000000..ec9854bf
--- /dev/null
+++ b/src/@components/BestPiicklePage/BestPiickleRecommend/RecommendItem/index.tsx
@@ -0,0 +1,36 @@
+import BestPiickleCard from "../../../@common/BestPiickleCard";
+import useDraggingContainer from "../../../@common/hooks/useDraggingContainer";
+import { useBestPiickle } from "../../../MainPage/hooks/useBestPiickle";
+import * as St from "./style";
+
+interface RecommendProps {
+ recommendType: string;
+}
+
+export default function RecommendItem(props: RecommendProps) {
+ const { recommendType } = props;
+ const { bestPiickle } = useBestPiickle();
+ const { scrollableContainerProps, isDragging } = useDraggingContainer();
+ return (
+
+ {recommendType}
+
+ {bestPiickle && (
+
+ {bestPiickle &&
+ bestPiickle.data.slice(0, 4).map((bestPiickle, idx) => {
+ return (
+
+ );
+ })}
+
+ )}
+
+ );
+}
diff --git a/src/@components/BestPiicklePage/BestPiickleRecommend/RecommendItem/style.ts b/src/@components/BestPiicklePage/BestPiickleRecommend/RecommendItem/style.ts
new file mode 100644
index 00000000..d0358227
--- /dev/null
+++ b/src/@components/BestPiicklePage/BestPiickleRecommend/RecommendItem/style.ts
@@ -0,0 +1,33 @@
+import styled from "styled-components";
+
+export const RecommemdItemContainer = styled.article`
+ display: flex;
+ flex-direction: column;
+ &:first-of-type > h2 {
+ padding-top: 0;
+ }
+`;
+
+export const RecommendType = styled.h2`
+ ${({ theme }) => theme.newFonts.body4};
+ padding: 2.4rem 1.6rem;
+`;
+
+export const SliderWrapper = styled.article`
+ display: flex;
+ overflow-x: scroll;
+
+ padding-left: 1.6rem;
+ & > button:not(:last-child) > div {
+ margin-right: 0.8rem;
+ }
+ & > button:last-child > div {
+ margin-right: 1.6rem;
+ }
+
+ -ms-overflow-style: none; /* IE and Edge */
+ scrollbar-width: none; /* Firefox */
+ &::-webkit-scrollbar {
+ display: none;
+ }
+`;
diff --git a/src/@components/BestPiicklePage/BestPiickleRecommend/index.tsx b/src/@components/BestPiicklePage/BestPiickleRecommend/index.tsx
new file mode 100644
index 00000000..fc446455
--- /dev/null
+++ b/src/@components/BestPiicklePage/BestPiickleRecommend/index.tsx
@@ -0,0 +1,25 @@
+import { HeadingTitle } from "../../../util/main/headingTitles";
+import HeadingTitleContainer from "../../@common/HeadingTitleContainer";
+import RecommendItem from "./RecommendItem";
+import * as St from "./style";
+
+const recommendTitles: HeadingTitle = {
+ title: "이런 베스트 피클은 어때요?",
+ content: "",
+};
+
+export default function BestPiickleRecommend() {
+ return (
+
+
+
+ {[
+ "💖 유저들이 가장 최근에 북마크한 대화주제",
+ "👩 여성이 북마크한 대화주제들",
+ "👱♂️ 남성이 북마크한 대화주제를 확인해보세요",
+ ].map((recommendType, idx) => (
+
+ ))}
+
+ );
+}
diff --git a/src/@components/BestPiicklePage/BestPiickleRecommend/style.ts b/src/@components/BestPiicklePage/BestPiickleRecommend/style.ts
new file mode 100644
index 00000000..ac593159
--- /dev/null
+++ b/src/@components/BestPiicklePage/BestPiickleRecommend/style.ts
@@ -0,0 +1,8 @@
+import styled from "styled-components";
+
+export const RecommendContainer = styled.section`
+ display: flex;
+ flex-direction: column;
+
+ margin-bottom: 2rem;
+`;
diff --git a/src/@components/BestPiicklePage/index.tsx b/src/@components/BestPiicklePage/index.tsx
new file mode 100644
index 00000000..eef6b368
--- /dev/null
+++ b/src/@components/BestPiicklePage/index.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+
+import Header from "../@common/Header";
+import SuspenseBoundary from "../@common/SuspenseBoundary";
+import BestPiickleRank from "./BestPiickleRank";
+import BestPiickleRecommend from "./BestPiickleRecommend";
+import St from "./style";
+
+export default function BestPiicklePage() {
+ return (
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/@components/BestPiicklePage/style.ts b/src/@components/BestPiicklePage/style.ts
new file mode 100644
index 00000000..f6668530
--- /dev/null
+++ b/src/@components/BestPiicklePage/style.ts
@@ -0,0 +1,11 @@
+import styled from "styled-components";
+
+const Root = styled.main`
+ display: flex;
+ flex-direction: column;
+`;
+
+const St = {
+ Root,
+};
+export default St;
diff --git a/src/@components/MainPage/BestPiickle/BestPiickleCard/index.tsx b/src/@components/MainPage/BestPiickle/BestPiickleCard/index.tsx
deleted file mode 100644
index ff10870e..00000000
--- a/src/@components/MainPage/BestPiickle/BestPiickleCard/index.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import { LocationType } from "../../../../types/cardCollection";
-import { GTM_CLASS_NAME } from "../../../../util/const/gtm";
-import useNavigateCardCollection, {
- NavigateCardCollectionBestType,
-} from "../../../@common/hooks/useNavigateCardCollection";
-import St from "./style";
-
-interface BestPiickleCardProps {
- bestPiickle: {
- _id: string;
- tags: string[];
- content: string;
- };
- idx: number;
- canNavigate: boolean;
-}
-
-export default function BestPiickleCard(props: BestPiickleCardProps) {
- const { bestPiickle, idx, canNavigate } = props;
- const { content, tags } = bestPiickle;
- const GTM_IDX_KEY = `mainBestPiickle${idx + 1}`;
-
- const navigateCardCollection = useNavigateCardCollection(LocationType.BEST) as NavigateCardCollectionBestType;
-
- return (
- {
- if (!canNavigate) return;
- navigateCardCollection(idx);
- }}>
-
-
- {tags.map((tag: string, i: number) => {
- return {tag.slice(1)};
- })}
-
- {content}
- 카드 보기
-
-
- );
-}
diff --git a/src/@components/MainPage/BestPiickle/BestPiickleCard/style.ts b/src/@components/MainPage/BestPiickle/BestPiickleCard/style.ts
deleted file mode 100644
index 79bc8b71..00000000
--- a/src/@components/MainPage/BestPiickle/BestPiickleCard/style.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import styled from "styled-components";
-
-const Container = styled.button``;
-
-const BestPiickleCard = styled.div`
- position: relative;
-
- width: 20rem;
- height: 13.6rem;
-
- padding: 1.2rem;
-
- border: 0.1rem solid ${({ theme }) => theme.newColors.gray300};
-`;
-
-const TagsWrapper = styled.ul`
- display: flex;
- gap: 0.8rem;
-`;
-
-const Tag = styled.li`
- ${({ theme }) => theme.newFonts.caption1};
- color: ${({ theme }) => theme.newColors.gray800};
-`;
-
-const Content = styled.p`
- width: 17rem;
- height: 4.4rem;
-
- margin-top: 0.4rem;
-
- text-align: left;
-
- // 말줄임표 설정
- white-space: normal;
- display: -webkit-box;
- -webkit-line-clamp: 2;
- -webkit-box-orient: vertical;
- overflow: hidden;
-
- ${({ theme }) => theme.newFonts.body3};
- color: ${({ theme }) => theme.newColors.gray900};
-`;
-
-const PickButtonWrapper = styled.div`
- position: absolute;
- left: -0.1rem;
- bottom: -0.1rem;
-
- width: 20rem;
- height: 3.2rem;
-
- display: flex;
- justify-content: center;
- align-items: center;
-
- ${({ theme }) => theme.newFonts.btn2};
- color: ${({ theme }) => theme.colors.white};
- background-color: ${({ theme }) => theme.newColors.gray900};
- backdrop-filter: blur(0.6rem);
-`;
-
-const St = {
- Container,
- BestPiickleCard,
- TagsWrapper,
- Tag,
- Content,
- PickButtonWrapper,
-};
-export default St;
diff --git a/src/@components/MainPage/BestPiickle/index.tsx b/src/@components/MainPage/BestPiickle/index.tsx
index 12290120..17578115 100644
--- a/src/@components/MainPage/BestPiickle/index.tsx
+++ b/src/@components/MainPage/BestPiickle/index.tsx
@@ -1,24 +1,35 @@
+import { routePaths } from "../../../core/routes/path";
import { headingTitles } from "../../../util/main/headingTitles";
+import BestPiickleCard from "../../@common/BestPiickleCard";
import HeadingTitleContainer from "../../@common/HeadingTitleContainer";
-import useScrollableContainer from "../../@common/hooks/useScrollableContainer";
+import useDraggingContainer from "../../@common/hooks/useDraggingContainer";
import { useBestPiickle } from "../hooks/useBestPiickle";
-import BestPiickleCard from "./BestPiickleCard";
import St from "./style";
export default function BestPiickle() {
const { bestPiickle } = useBestPiickle();
- const { scrollableContainerProps, isDragging } = useScrollableContainer();
+ const { scrollableContainerProps, isDragging } = useDraggingContainer();
return (
-
+
{bestPiickle && (
{bestPiickle &&
bestPiickle.data.slice(0, 5).map((bestPiickle, idx) => {
return (
-
+
);
})}
diff --git a/src/@components/MainPage/Medley/index.tsx b/src/@components/MainPage/Medley/index.tsx
index bfe12f87..74c2a4fd 100644
--- a/src/@components/MainPage/Medley/index.tsx
+++ b/src/@components/MainPage/Medley/index.tsx
@@ -1,10 +1,10 @@
-import useScrollableContainer from "../../@common/hooks/useScrollableContainer";
+import useDraggingContainer from "../../@common/hooks/useDraggingContainer";
import { useMedleyLists } from "../hooks/useMedleyLists";
import MedleyCard from "./MedleyCard";
import * as St from "./style";
export default function Medley() {
- const { scrollableContainerProps, isDragging } = useScrollableContainer();
+ const { scrollableContainerProps, isDragging } = useDraggingContainer();
const { randomMedleyLists } = useMedleyLists();
return (
diff --git a/src/@components/MainPage/MoodPiickle/index.tsx b/src/@components/MainPage/MoodPiickle/index.tsx
index 76e219d4..72aa5a17 100644
--- a/src/@components/MainPage/MoodPiickle/index.tsx
+++ b/src/@components/MainPage/MoodPiickle/index.tsx
@@ -1,3 +1,4 @@
+import { routePaths } from "../../../core/routes/path";
import { LocationType } from "../../../types/cardCollection";
import { GTM_CLASS_NAME } from "../../../util/const/gtm";
import { headingTitles } from "../../../util/main/headingTitles";
@@ -22,7 +23,11 @@ export default function MoodPiickle() {
return (
-
+
{randomCategoryLists &&
randomCategoryLists.slice(0, 4).map((moodPiickle, index) => (
diff --git a/src/@components/MainPage/PiickleMe/index.tsx b/src/@components/MainPage/PiickleMe/index.tsx
index a321d625..0710e22a 100644
--- a/src/@components/MainPage/PiickleMe/index.tsx
+++ b/src/@components/MainPage/PiickleMe/index.tsx
@@ -10,7 +10,7 @@ export default function PiickleMe() {
return (
-
+
diff --git a/src/@components/index.ts b/src/@components/index.ts
index b4502c6e..32acfaa4 100644
--- a/src/@components/index.ts
+++ b/src/@components/index.ts
@@ -1,3 +1,4 @@
+export { default as BestPiicklePage } from "./BestPiicklePage";
export { default as BookmarkPage } from "./BookmarkPage";
export { default as CardCollectionPage } from "./CardCollectionPage";
export { default as CategoryPage } from "./CategoryPage";
diff --git a/src/Router.tsx b/src/Router.tsx
index 9b687c8a..4899afbd 100644
--- a/src/Router.tsx
+++ b/src/Router.tsx
@@ -2,6 +2,7 @@ import { BrowserRouter, Route, Routes } from "react-router-dom";
import {
AgreePage,
+ BestPiicklePage,
BookmarkPage,
CardCollectionPage,
CategoryPage,
@@ -26,6 +27,7 @@ export default function Router() {
})} />
, restricted: true })} />
+ })} />
})} />