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 })} /> + })} /> })} />