From 90cf37a193706430b2ba83af921cbed00010f596 Mon Sep 17 00:00:00 2001 From: inyoung Date: Thu, 18 Apr 2024 22:55:17 +0900 Subject: [PATCH] =?UTF-8?q?Feat:=20=EC=B0=9C=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20api=20=EC=97=B0=EB=8F=99=20?= =?UTF-8?q?=EB=B0=8F=20=EB=AC=B4=ED=95=9C=EC=8A=A4=ED=81=AC=EB=A1=A4=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C=20#228?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/get.ts | 5 + .../SavedCounselorCard.tsx | 6 +- .../SavedOpenConsultCard.tsx | 111 +++++++++ .../SavedOpenConsultResults.tsx | 28 +++ src/pages/Buyer/BuyerConsult.tsx | 2 + src/pages/Buyer/BuyerSavedCounselor.tsx | 210 +++++++++++++----- 6 files changed, 309 insertions(+), 53 deletions(-) create mode 100644 src/components/Buyer/BuyerSavedCounselor.tsx/SavedOpenConsultCard.tsx create mode 100644 src/components/Buyer/BuyerSavedCounselor.tsx/SavedOpenConsultResults.tsx diff --git a/src/api/get.ts b/src/api/get.ts index c8fb34ee..8e5f0829 100644 --- a/src/api/get.ts +++ b/src/api/get.ts @@ -178,3 +178,8 @@ export const getCustomerIsWriter = async (postId: any) => export const getOpenConsultDraft = async (postId: any) => await getInstance(`/posts/drafts/${postId}`); + +// Post Scrap Controller + +export const getPostScraps = async (params: any) => + getInstance(`/postScraps`, params); diff --git a/src/components/Buyer/BuyerSavedCounselor.tsx/SavedCounselorCard.tsx b/src/components/Buyer/BuyerSavedCounselor.tsx/SavedCounselorCard.tsx index c3c7e528..0e0f0754 100644 --- a/src/components/Buyer/BuyerSavedCounselor.tsx/SavedCounselorCard.tsx +++ b/src/components/Buyer/BuyerSavedCounselor.tsx/SavedCounselorCard.tsx @@ -83,8 +83,10 @@ export const SavedCounselorCard = ({ }} > - {tagList.map((value: any) => { - return ; + {tagList.map((value: any, index) => { + return ( + + ); })} {introduction} diff --git a/src/components/Buyer/BuyerSavedCounselor.tsx/SavedOpenConsultCard.tsx b/src/components/Buyer/BuyerSavedCounselor.tsx/SavedOpenConsultCard.tsx new file mode 100644 index 00000000..a8f2803a --- /dev/null +++ b/src/components/Buyer/BuyerSavedCounselor.tsx/SavedOpenConsultCard.tsx @@ -0,0 +1,111 @@ +import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'; +import styled from 'styled-components'; +import { Green, Grey1, Grey2, Grey3, Grey6 } from 'styles/color'; +import { Body1, Caption1, Caption2 } from 'styles/font'; +import { LoadingSpinner } from 'utils/LoadingSpinner'; +import { ReactComponent as LockIcon } from 'assets/icons/icon-lock.svg'; +import { ReactComponent as HeartIcon } from 'assets/icons/icon-heart2.svg'; +import { ReactComponent as HeartEmptyIcon } from 'assets/icons/icon-heart3.svg'; +import { ReactComponent as SaveIcon } from 'assets/icons/icon-save2.svg'; +import { ReactComponent as SaveEmptyIcon } from 'assets/icons/icon-save3.svg'; +import { ReactComponent as CommentIcon } from 'assets/icons/icon-comment.svg'; +import { ReactComponent as CheckIcon } from 'assets/icons/icon-check2.svg'; +import { ReactComponent as WriteIcon } from 'assets/icons/icon-write.svg'; +import { Space } from 'components/Common/Space'; +import { BackDrop } from 'components/Common/BackDrop'; +import { openConsultApiObject } from 'pages/Buyer/BuyerConsult'; +import { useNavigate } from 'react-router-dom'; +import useIntersectionObserver from 'hooks/useIntersectionObserver'; +interface SavedCounselorCardProps { + item: openConsultApiObject; +} +function SavedOpenConsultCard({ item }: SavedCounselorCardProps) { + const navigate = useNavigate(); + return ( + { + navigate(`/open-consult/${item.postId}`); + }} + > +
+ {item.title} +
+ +
{item.content}
+
+ + + {item.totalLike} + + + + {item.totalScrap} + + + + {item.totalComment} + +
+ {item.updatedAt} +
+ ); +} + +const Wrapper = styled.div` + width: 89%; + height: 14rem; + cursor: pointer; + position: relative; + background-color: ${Grey6}; + padding: 1.6rem; + box-sizing: border-box; + border-radius: 1.2rem; + .row1 { + width: calc(100% - 5rem); + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 1; + max-height: 5rem; + overflow: hidden; + } + .row2 { + display: -webkit-box; + max-height: 4.7rem; + -webkit-box-orient: vertical; + overflow: hidden; + align-self: flex-end; + margin-bottom: 0.4rem; + -webkit-line-clamp: 2; + color: ${Grey1}; + height: 4.6rem; + text-overflow: ellipsis; + font-family: Pretendard; + font-size: 1.4rem; + font-style: normal; + font-weight: 400; + line-height: 155%; + } + .row3 { + display: flex; + gap: 1.2rem; + } +`; +const HeartResizeIcon = styled(HeartIcon)` + width: 2rem; + height: 2rem; +`; +const IconItem = styled.div` + display: flex; + align-items: center; + gap: 0.5rem; +`; +const TimeLeft = styled.div` + font-size: 1.2rem; + font-weight: 400; + color: ${Grey2}; + position: absolute; + bottom: 1.8rem; + right: 1.6rem; +`; + +export default SavedOpenConsultCard; diff --git a/src/components/Buyer/BuyerSavedCounselor.tsx/SavedOpenConsultResults.tsx b/src/components/Buyer/BuyerSavedCounselor.tsx/SavedOpenConsultResults.tsx new file mode 100644 index 00000000..a506d482 --- /dev/null +++ b/src/components/Buyer/BuyerSavedCounselor.tsx/SavedOpenConsultResults.tsx @@ -0,0 +1,28 @@ +import { openConsultApiObject } from 'pages/Buyer/BuyerConsult'; +import React from 'react'; +import styled from 'styled-components'; +import SavedOpenConsultCard from './SavedOpenConsultCard'; + +interface SavedOpenConsultResultsProps { + openConsultList: openConsultApiObject[]; +} +function SavedOpenConsultResults({ + openConsultList, +}: SavedOpenConsultResultsProps) { + return ( + + {openConsultList.map((card) => ( + + ))} + + ); +} + +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 1.2rem; + align-items: center; + width: 100%; +`; +export default SavedOpenConsultResults; diff --git a/src/pages/Buyer/BuyerConsult.tsx b/src/pages/Buyer/BuyerConsult.tsx index 36b784fd..643654e6 100644 --- a/src/pages/Buyer/BuyerConsult.tsx +++ b/src/pages/Buyer/BuyerConsult.tsx @@ -30,6 +30,7 @@ export interface consultApiObject { } export interface openConsultApiObject { postId: number; + postScrapId: number; title: string; content: string; isPublic: boolean; @@ -39,6 +40,7 @@ export interface openConsultApiObject { publishedAt: string; isChosen: boolean; isScrapped: boolean; + scrappedAt: string; totalScrap: number; totalComment: number; updatedAt: string; diff --git a/src/pages/Buyer/BuyerSavedCounselor.tsx b/src/pages/Buyer/BuyerSavedCounselor.tsx index bf801232..d08fa37d 100644 --- a/src/pages/Buyer/BuyerSavedCounselor.tsx +++ b/src/pages/Buyer/BuyerSavedCounselor.tsx @@ -11,11 +11,18 @@ import { ReactComponent as Empty } from 'assets/icons/graphic-noting.svg'; import styled from 'styled-components'; import useIntersectionObserver from 'hooks/useIntersectionObserver'; import Divider2 from 'components/Common/Divider2'; +import { openConsultApiObject } from './BuyerConsult'; +import { getPostScraps } from 'api/get'; +import SavedOpenConsultResults from 'components/Buyer/BuyerSavedCounselor.tsx/SavedOpenConsultResults'; +import { LoadingSpinner } from 'utils/LoadingSpinner'; // TODO: 찜한 마인더 없을 시 페이지 추후 백 연동 시 구현 export const BuyerSavedCounselor = () => { const navigate = useNavigate(); const [isInitialLoading, setIsInitialLoading] = useState(true); const [wishlistData, setWishlistData] = useState([]); + const [openConsultData, setOpenConsultData] = useState< + openConsultApiObject[] + >([]); const [isLastElem, setIsLastElem] = useState(false); const [tabState, setTabState] = useState(1); const preventRef = useRef(true); @@ -27,10 +34,18 @@ export const BuyerSavedCounselor = () => { preventRef.current ) { preventRef.current = false; - await fetchWishlistData( - wishlistData[wishlistData.length - 1].wishlistId, - wishlistData[wishlistData.length - 1].updatedAt, - ); + if (tabState === 1) { + await fetchWishlistData( + wishlistData[wishlistData.length - 1].wishlistId, + wishlistData[wishlistData.length - 1].updatedAt, + ); + } else if (tabState === 2) { + await fetchOpenConsultData( + openConsultData[openConsultData.length - 1].postScrapId, + openConsultData[openConsultData.length - 1].scrappedAt, + ); + } + preventRef.current = true; } }; @@ -46,12 +61,12 @@ export const BuyerSavedCounselor = () => { wishlistId: lastId, updatedAt: lastUpdateAt, }; - try { const res: any = await postWishLists(body); if (res.status === 200) { if (res.data.length !== 0) { if (lastId === 0) { + setIsInitialLoading(true); setWishlistData(res.data); } else { const updatedReviews = [...wishlistData, ...res.data]; @@ -71,9 +86,44 @@ export const BuyerSavedCounselor = () => { } } }; + const fetchOpenConsultData = async (lastId: number, lastUpdateAt: string) => { + try { + const params = { + postScrapId: lastId, + scrappedAt: lastUpdateAt, + }; + const res: any = await getPostScraps({ params }); + if (res.status === 200) { + if (res.data.length !== 0) { + if (lastId === 0) { + setIsInitialLoading(true); + setOpenConsultData(res.data); + } else { + const updatedOpenConsultList = [...openConsultData, ...res.data]; + setOpenConsultData(updatedOpenConsultList); + } + } else { + setIsLastElem(true); + } + } else if (res.response.status !== 401) { + // navigate('/mypage'); + } + } catch (err) { + alert(err); + } finally { + if (lastId === 0) { + setIsInitialLoading(false); + } + } + }; useLayoutEffect(() => { - fetchWishlistData(0, ''); - }, []); + setIsInitialLoading(true); + if (tabState === 1) { + fetchWishlistData(0, ''); + } else if (tabState === 2) { + fetchOpenConsultData(0, new Date().toISOString().slice(0, 19)); + } + }, [tabState]); if (isInitialLoading) { return ( <> @@ -86,53 +136,111 @@ export const BuyerSavedCounselor = () => { 찜 목록 +
+ +
); } else { - if (wishlistData.length !== 0) { - return ( - <> - - { - navigate('/mypage'); - }} - /> - 찜 목록 - - - -
- - {!isLastElem ? ( -
- ) : ( -
- )} -
- - ); - } else { - return ( - <> - - { - navigate('/mypage'); - }} - /> - 찜 목록 - - - - - 아직 후기가 없어요. - - - ); + if (tabState === 1) { + if (wishlistData.length !== 0) { + return ( + <> + + { + navigate('/mypage'); + }} + /> + 찜 목록 + + + +
+ + {!isLastElem ? ( +
+ ) : ( +
+ )} +
+ + ); + } else { + return ( + <> + + { + navigate('/mypage'); + }} + /> + 찜 목록 + + + + + 아직 후기가 없어요. + + + ); + } + } else if (tabState === 2) { + if (openConsultData.length !== 0) { + return ( + <> + + { + navigate('/mypage'); + }} + /> + 찜 목록 + + + +
+ + {!isLastElem ? ( +
+ ) : ( +
+ )} +
+ + ); + } else { + return ( + <> + + { + navigate('/mypage'); + }} + /> + 찜 목록 + + + + + 아직 저장한 일대다상담이 없어요. + + + ); + } } } };