From d01a0b445668978975e42c01a81e4bc7a61b31ed Mon Sep 17 00:00:00 2001 From: leekyuho Date: Sat, 23 Mar 2024 00:02:18 +0900 Subject: [PATCH 01/16] feat: insert new chat at top on consult tab (#178) --- src/components/Buyer/BuyerConsult/BuyerChatSection.tsx | 4 ++-- src/components/Seller/SellerConsult/SellerChatList.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Buyer/BuyerConsult/BuyerChatSection.tsx b/src/components/Buyer/BuyerConsult/BuyerChatSection.tsx index 3b6aa79d..3ccdf2ca 100644 --- a/src/components/Buyer/BuyerConsult/BuyerChatSection.tsx +++ b/src/components/Buyer/BuyerConsult/BuyerChatSection.tsx @@ -106,11 +106,11 @@ export const BuyerChatSection = ({ consultId: null, }; //add roomIds for unsubscribe - roomIdsRef.current.push(notification.chatId); + roomIdsRef.current.unshift(notification.chatId); cardDataRef.current = [ - ...cardDataRef.current, addedChatRoomItem, + ...cardDataRef.current, ]; setCardData(cardDataRef.current); diff --git a/src/components/Seller/SellerConsult/SellerChatList.tsx b/src/components/Seller/SellerConsult/SellerChatList.tsx index 6d2ebe4b..55550cc1 100644 --- a/src/components/Seller/SellerConsult/SellerChatList.tsx +++ b/src/components/Seller/SellerConsult/SellerChatList.tsx @@ -117,11 +117,11 @@ function SellerChatList({ consultId: null, }; //add roomIds for unsubscribe - roomIdsRef.current.push(notification.chatId); + roomIdsRef.current.unshift(notification.chatId); cardDataRef.current = [ - ...cardDataRef.current, addedChatRoomItem, + ...cardDataRef.current, ]; setConsultInfo(cardDataRef.current); From 25dec3dccafc17f98d9faf326459c0cb45c8dc06 Mon Sep 17 00:00:00 2001 From: leekyuho Date: Sat, 23 Mar 2024 16:22:32 +0900 Subject: [PATCH 02/16] feat: add patch logout (#182) --- src/api/patch.ts | 3 +++ src/pages/Buyer/BuyerLogout.tsx | 32 ++++++++++++++++++++++++++----- src/pages/Seller/SellerLogout.tsx | 30 ++++++++++++++++++++++++++--- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/api/patch.ts b/src/api/patch.ts index 1010c3ec..00349065 100644 --- a/src/api/patch.ts +++ b/src/api/patch.ts @@ -27,6 +27,9 @@ export const patchAuthFindId = async (body: any) => //비밀번호 찾기 export const patchAuthFindPassword = async (body: any) => await patchPublicInstance('/auth/find-password', body); +//로그아웃 +export const patchAuthSignOut = async (body: any) => + await patchInstance('/auth/signOut', body); //Counselor Controller //카테고리/들준마 상담사 리스트 반환 diff --git a/src/pages/Buyer/BuyerLogout.tsx b/src/pages/Buyer/BuyerLogout.tsx index 03342342..7d605d1c 100644 --- a/src/pages/Buyer/BuyerLogout.tsx +++ b/src/pages/Buyer/BuyerLogout.tsx @@ -1,3 +1,4 @@ +import { patchAuthSignOut } from 'api/patch'; import { BackIcon, HeaderWrapper } from 'components/Buyer/Common/Header'; import { Button } from 'components/Common/Button'; import { useNavigate } from 'react-router-dom'; @@ -8,6 +9,29 @@ import { Characters } from 'utils/Characters'; export const BuyerLogout = () => { const navigate = useNavigate(); + + const patchSingOut = async ( + accessTokenValue: string | null, + refreshTokenValue: string | null, + ) => { + if (accessTokenValue === null) { + return; + } + + try { + const body = { + accessToken: accessTokenValue, + refreshToken: refreshTokenValue, + }; + await patchAuthSignOut(body); + localStorage.removeItem('accessToken'); + localStorage.removeItem('refreshToken'); + navigate('/mypage'); + } catch (e) { + console.log(e); + } + }; + return ( @@ -39,11 +63,9 @@ export const BuyerLogout = () => { backgroundColor={LightGreen} color={Green} onClick={() => { - localStorage.removeItem('accessToken'); - localStorage.removeItem('refreshToken'); - // removeCookie('accessToken'); - // removeCookie('refreshToken'); - navigate('/mypage'); + const accessTokenValue = localStorage.getItem('accessToken'); + const refreshTokenValue = localStorage.getItem('refreshToken'); + patchSingOut(accessTokenValue, refreshTokenValue); }} /> diff --git a/src/pages/Seller/SellerLogout.tsx b/src/pages/Seller/SellerLogout.tsx index e83ec448..1334d433 100644 --- a/src/pages/Seller/SellerLogout.tsx +++ b/src/pages/Seller/SellerLogout.tsx @@ -1,3 +1,4 @@ +import { patchAuthSignOut } from 'api/patch'; import { BackIcon, HeaderWrapper } from 'components/Buyer/Common/Header'; import { Button } from 'components/Common/Button'; import { useNavigate } from 'react-router-dom'; @@ -8,6 +9,29 @@ import { Characters } from 'utils/Characters'; export const SellerLogout = () => { const navigate = useNavigate(); + + const patchSingOut = async ( + accessTokenValue: string | null, + refreshTokenValue: string | null, + ) => { + if (accessTokenValue === null) { + return; + } + + try { + const body = { + accessToken: accessTokenValue, + refreshToken: refreshTokenValue, + }; + await patchAuthSignOut(body); + localStorage.removeItem('accessToken'); + localStorage.removeItem('refreshToken'); + navigate('/mypage'); + } catch (e) { + console.log(e); + } + }; + return ( @@ -39,9 +63,9 @@ export const SellerLogout = () => { backgroundColor={LightGreen} color={Green} onClick={() => { - localStorage.removeItem('accessToken'); - localStorage.removeItem('refreshToken'); - navigate('/minder/mypage'); + const accessTokenValue = localStorage.getItem('accessToken'); + const refreshTokenValue = localStorage.getItem('refreshToken'); + patchSingOut(accessTokenValue, refreshTokenValue); }} /> From 9bd9859c7ecb316fdc63150aefe6906cc7180e60 Mon Sep 17 00:00:00 2001 From: leekyuho Date: Sat, 23 Mar 2024 16:28:19 +0900 Subject: [PATCH 03/16] feat: disconnect when logout (#182) --- src/pages/Buyer/BuyerLogout.tsx | 4 ++++ src/pages/Seller/SellerLogout.tsx | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/pages/Buyer/BuyerLogout.tsx b/src/pages/Buyer/BuyerLogout.tsx index 7d605d1c..f82de29c 100644 --- a/src/pages/Buyer/BuyerLogout.tsx +++ b/src/pages/Buyer/BuyerLogout.tsx @@ -1,6 +1,7 @@ import { patchAuthSignOut } from 'api/patch'; import { BackIcon, HeaderWrapper } from 'components/Buyer/Common/Header'; import { Button } from 'components/Common/Button'; +import { useStompContext } from 'contexts/StompContext'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; import { Green, Grey1, LightGreen } from 'styles/color'; @@ -10,6 +11,8 @@ import { Characters } from 'utils/Characters'; export const BuyerLogout = () => { const navigate = useNavigate(); + const { stompClient } = useStompContext(); + const patchSingOut = async ( accessTokenValue: string | null, refreshTokenValue: string | null, @@ -26,6 +29,7 @@ export const BuyerLogout = () => { await patchAuthSignOut(body); localStorage.removeItem('accessToken'); localStorage.removeItem('refreshToken'); + stompClient.current?.disconnect(); navigate('/mypage'); } catch (e) { console.log(e); diff --git a/src/pages/Seller/SellerLogout.tsx b/src/pages/Seller/SellerLogout.tsx index 1334d433..956b4d1e 100644 --- a/src/pages/Seller/SellerLogout.tsx +++ b/src/pages/Seller/SellerLogout.tsx @@ -1,6 +1,7 @@ import { patchAuthSignOut } from 'api/patch'; import { BackIcon, HeaderWrapper } from 'components/Buyer/Common/Header'; import { Button } from 'components/Common/Button'; +import { useStompContext } from 'contexts/StompContext'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; import { Green, Grey1, LightGreen } from 'styles/color'; @@ -10,6 +11,8 @@ import { Characters } from 'utils/Characters'; export const SellerLogout = () => { const navigate = useNavigate(); + const { stompClient } = useStompContext(); + const patchSingOut = async ( accessTokenValue: string | null, refreshTokenValue: string | null, @@ -26,6 +29,7 @@ export const SellerLogout = () => { await patchAuthSignOut(body); localStorage.removeItem('accessToken'); localStorage.removeItem('refreshToken'); + stompClient.current?.disconnect(); navigate('/mypage'); } catch (e) { console.log(e); From 897b035b45436e2f98b8351ae7bd1a063cd018ee Mon Sep 17 00:00:00 2001 From: leekyuho Date: Sat, 23 Mar 2024 18:08:55 +0900 Subject: [PATCH 04/16] feat: apply type initial value by query string (#155) --- .../Buyer/BuyerConsult/BuyerChatSection.tsx | 5 +- src/contexts/StompContext.tsx | 4 +- src/hooks/.gitkeep | 0 src/hooks/useConsultParams.ts | 52 +++++++++++++++++++ src/pages/Buyer/BuyerChat.tsx | 2 +- src/pages/Buyer/BuyerConsult.tsx | 36 ++++++------- 6 files changed, 75 insertions(+), 24 deletions(-) delete mode 100644 src/hooks/.gitkeep create mode 100644 src/hooks/useConsultParams.ts diff --git a/src/components/Buyer/BuyerConsult/BuyerChatSection.tsx b/src/components/Buyer/BuyerConsult/BuyerChatSection.tsx index 3ccdf2ca..7df3e4f8 100644 --- a/src/components/Buyer/BuyerConsult/BuyerChatSection.tsx +++ b/src/components/Buyer/BuyerConsult/BuyerChatSection.tsx @@ -29,7 +29,7 @@ export const BuyerChatSection = ({ * https://stackoverflow.com/questions/73896315/rxjs-subscribe-callback-doesnt-have-access-to-current-react-state-functional-c */ const cardDataRef = useRef([]); - const { stompClient } = useStompContext(); + const { stompClient, isConnected } = useStompContext(); //채팅 readId, 가장 최근 unread message, 정렬 업데이트 const updateChatData = ( chatId: number, @@ -148,6 +148,7 @@ export const BuyerChatSection = ({ sendConnectRequest(); return () => { + console.log('unmount'); if (roomIdsRef.current) { roomIdsRef.current.forEach((value) => { stompClient.current?.unsubscribe( @@ -161,7 +162,7 @@ export const BuyerChatSection = ({ ); } }; - }, [stompClient]); + }, [stompClient, isConnected]); useLayoutEffect(() => { const fetchData = async () => { diff --git a/src/contexts/StompContext.tsx b/src/contexts/StompContext.tsx index 86a55aad..f166c684 100644 --- a/src/contexts/StompContext.tsx +++ b/src/contexts/StompContext.tsx @@ -94,10 +94,12 @@ export const StompProvider: React.FC<{ children: ReactNode }> = ({ useEffect(() => { connectChat(); - // 컴포넌트 언마운트 시 연결 해제 + // Provider 언마운트 시 연결 해제 return () => { + console.log('pre unmount'); if (stompClient.current) { stompClient.current.disconnect(); + setIsConnected(false); console.log('WebSocket disconnected'); } }; diff --git a/src/hooks/.gitkeep b/src/hooks/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/hooks/useConsultParams.ts b/src/hooks/useConsultParams.ts new file mode 100644 index 00000000..df5e76c7 --- /dev/null +++ b/src/hooks/useConsultParams.ts @@ -0,0 +1,52 @@ +// import { useStompContext } from 'contexts/StompContext'; +import { useEffect, useState } from 'react'; +import { useSearchParams } from 'react-router-dom'; +import { Green, Grey1 } from 'styles/color'; + +// The setSearchParams function works like navigate, but only for the search portion of the URL. Also note that the second arg to setSearchParams is the same type as the second arg to navigate. +// https://reactrouter.com/en/main/hooks/use-search-params + +export const useConsultParams = () => { + /** initialize type value */ + const [searchParams, setSearchParams] = useSearchParams(); + const typeParam = searchParams.get('type'); + const sortParam = searchParams.get('sort'); + const initialIsLetter = typeParam === 'chat' ? false : true; + const initialSortType = sortParam === 'unread' ? 1 : 0; + /** is current tag is Letter or not */ + const [isLetter, setIsLetter] = useState(initialIsLetter); + /** sortType by number 0 : 최신순 1: 읽지 않은 순 */ + const [sortType, setSortType] = useState(initialSortType); + + const handleLetterClick = () => { + setIsLetter(true); + searchParams.set('type', 'letter'); + setSearchParams(searchParams); + }; + + const handleChatClick = () => { + setIsLetter(false); + searchParams.set('type', 'chat'); + setSearchParams(searchParams); + }; + + /** set values from query string in first mount */ + // useEffect(() => { + // if (consultParam === 'letter' || consultParam === null) { + // } else if (consultParam === 'chat') { + // } else { + // searchParams.delete('type'); + // setSearchParams(searchParams); + // } + // }, []); + + return { + isLetter, + sortType, + setSortType, + handleLetterClick, + handleChatClick, + searchParams, + setSearchParams, + }; +}; diff --git a/src/pages/Buyer/BuyerChat.tsx b/src/pages/Buyer/BuyerChat.tsx index 565bedfb..d47982e4 100644 --- a/src/pages/Buyer/BuyerChat.tsx +++ b/src/pages/Buyer/BuyerChat.tsx @@ -448,7 +448,7 @@ export const BuyerChat = () => { { - navigate('/consult'); + navigate(-1); }} /> {counselorInfo?.nickname} diff --git a/src/pages/Buyer/BuyerConsult.tsx b/src/pages/Buyer/BuyerConsult.tsx index dd898d3d..c8ea5d1d 100644 --- a/src/pages/Buyer/BuyerConsult.tsx +++ b/src/pages/Buyer/BuyerConsult.tsx @@ -13,6 +13,7 @@ import { ReactComponent as NonCheckIcon } from 'assets/icons/icon-complete-non-c import { ConsultModal } from 'components/Buyer/BuyerConsult/ConsultModal'; import { BuyerChatSection } from 'components/Buyer/BuyerConsult/BuyerChatSection'; import { BuyerLetterSection } from 'components/Buyer/BuyerConsult/BuyerLetterSection'; +import { useConsultParams } from 'hooks/useConsultParams'; export interface consultApiObject { consultStyle: string; @@ -29,13 +30,22 @@ export interface consultApiObject { export const BuyerConsult = () => { const navigate = useNavigate(); + const sortList = ['최근순', '읽지않은순']; - const [isLetter, setIsLetter] = useState(true); //편지 채팅 여부 + const { + isLetter, + sortType, + setSortType, + handleLetterClick, + handleChatClick, + } = useConsultParams(); + + // const [isLetter, setIsLetter] = useState(true); //편지 채팅 여부 const [letterColor, setLetterColor] = useState(Green); const [chattingColor, setChattingColor] = useState(Grey1); const [isChecked, setIsChecked] = useState(false); //완료 제외 체크 여부 - const [sortType, setSortType] = useState(0); //0 : 최신순 1:읽지 않은 순 + // const [sortType, setSortType] = useState(0); //0 : 최신순 1:읽지 않은 순 const [isModalOpen, setIsModalOpen] = useRecoilState( isConsultModalOpenState, ); // Modal 여부(recoil) @@ -54,25 +64,11 @@ export const BuyerConsult = () => {
- { - setIsLetter(true); - setLetterColor(Green); - setChattingColor(Grey1); - }} - > - 편지 + + 편지 - { - setIsLetter(false); - setLetterColor(Grey1); - setChattingColor(Green); - }} - > - 채팅 + + 채팅
Date: Sat, 23 Mar 2024 18:28:35 +0900 Subject: [PATCH 05/16] feat: apply query string in buyer consult sortType (#155) --- .../Buyer/BuyerConsult/ConsultModal.tsx | 18 +++++++++++++++--- src/contexts/StompContext.tsx | 1 - src/pages/Buyer/BuyerConsult.tsx | 11 ++++++++--- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/components/Buyer/BuyerConsult/ConsultModal.tsx b/src/components/Buyer/BuyerConsult/ConsultModal.tsx index 13277ace..9b94b0ba 100644 --- a/src/components/Buyer/BuyerConsult/ConsultModal.tsx +++ b/src/components/Buyer/BuyerConsult/ConsultModal.tsx @@ -1,18 +1,26 @@ import { ReactComponent as CheckIcon } from 'assets/icons/icon-modal-check.svg'; -import { SetStateAction, useEffect, useState } from 'react'; -import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; +import { SetStateAction, useState } from 'react'; +import { useRecoilState, useSetRecoilState } from 'recoil'; import styled, { keyframes } from 'styled-components'; import { Green, Grey1, Grey6 } from 'styles/color'; import { Body1 } from 'styles/font'; import { isConsultModalOpenState, scrollLockState } from 'utils/atom'; import { ReactComponent as Bar } from 'assets/icons/icon-modal-bar.svg'; +import { SetURLSearchParams } from 'react-router-dom'; interface SortModalProps { sortType: number; setSortType: React.Dispatch>; + searchParams: URLSearchParams; + setSearchParams: SetURLSearchParams; } //최근순 읽지않은순 modal -export const ConsultModal = ({ sortType, setSortType }: SortModalProps) => { +export const ConsultModal = ({ + sortType, + setSortType, + searchParams, + setSearchParams, +}: SortModalProps) => { //modal 여부 const [isModalOpen, setIsModalOpen] = useRecoilState(isConsultModalOpenState); //여기서 unmount 시 sortType 바꾸고 새로 request @@ -34,6 +42,8 @@ export const ConsultModal = ({ sortType, setSortType }: SortModalProps) => { className="row" onClick={() => { setSortType(0); + searchParams.set('sort', 'latest'); + setSearchParams(searchParams); setIsModalOpen(false); setScrollLock(false); }} @@ -51,6 +61,8 @@ export const ConsultModal = ({ sortType, setSortType }: SortModalProps) => { className="row" onClick={() => { setSortType(1); + searchParams.set('sort', 'unread'); + setSearchParams(searchParams); setIsModalOpen(false); setScrollLock(false); }} diff --git a/src/contexts/StompContext.tsx b/src/contexts/StompContext.tsx index f166c684..66fc0a3c 100644 --- a/src/contexts/StompContext.tsx +++ b/src/contexts/StompContext.tsx @@ -96,7 +96,6 @@ export const StompProvider: React.FC<{ children: ReactNode }> = ({ connectChat(); // Provider 언마운트 시 연결 해제 return () => { - console.log('pre unmount'); if (stompClient.current) { stompClient.current.disconnect(); setIsConnected(false); diff --git a/src/pages/Buyer/BuyerConsult.tsx b/src/pages/Buyer/BuyerConsult.tsx index c8ea5d1d..61d704b8 100644 --- a/src/pages/Buyer/BuyerConsult.tsx +++ b/src/pages/Buyer/BuyerConsult.tsx @@ -39,11 +39,11 @@ export const BuyerConsult = () => { setSortType, handleLetterClick, handleChatClick, + searchParams, + setSearchParams, } = useConsultParams(); // const [isLetter, setIsLetter] = useState(true); //편지 채팅 여부 - const [letterColor, setLetterColor] = useState(Green); - const [chattingColor, setChattingColor] = useState(Grey1); const [isChecked, setIsChecked] = useState(false); //완료 제외 체크 여부 // const [sortType, setSortType] = useState(0); //0 : 최신순 1:읽지 않은 순 const [isModalOpen, setIsModalOpen] = useRecoilState( @@ -106,7 +106,12 @@ export const BuyerConsult = () => { setIsModalOpen(false); }} /> - + ) : null} From fad3201e5d0fee7ca7933cc62020e053d1854462 Mon Sep 17 00:00:00 2001 From: leekyuho Date: Sat, 23 Mar 2024 18:35:33 +0900 Subject: [PATCH 06/16] feat: apply query string in buyer consult isChecked (#155) --- src/hooks/useConsultParams.ts | 17 +++++++---------- src/pages/Buyer/BuyerConsult.tsx | 6 +++++- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/hooks/useConsultParams.ts b/src/hooks/useConsultParams.ts index df5e76c7..cadbec62 100644 --- a/src/hooks/useConsultParams.ts +++ b/src/hooks/useConsultParams.ts @@ -11,12 +11,17 @@ export const useConsultParams = () => { const [searchParams, setSearchParams] = useSearchParams(); const typeParam = searchParams.get('type'); const sortParam = searchParams.get('sort'); + const checkParam = searchParams.get('check'); + // if there is any query string, set letter, unread, checked const initialIsLetter = typeParam === 'chat' ? false : true; const initialSortType = sortParam === 'unread' ? 1 : 0; + const initialIsChecked = checkParam === 'false' ? false : true; /** is current tag is Letter or not */ const [isLetter, setIsLetter] = useState(initialIsLetter); /** sortType by number 0 : 최신순 1: 읽지 않은 순 */ const [sortType, setSortType] = useState(initialSortType); + /** 완료 제외 체크 여부 */ + const [isChecked, setIsChecked] = useState(initialIsChecked); const handleLetterClick = () => { setIsLetter(true); @@ -30,16 +35,6 @@ export const useConsultParams = () => { setSearchParams(searchParams); }; - /** set values from query string in first mount */ - // useEffect(() => { - // if (consultParam === 'letter' || consultParam === null) { - // } else if (consultParam === 'chat') { - // } else { - // searchParams.delete('type'); - // setSearchParams(searchParams); - // } - // }, []); - return { isLetter, sortType, @@ -48,5 +43,7 @@ export const useConsultParams = () => { handleChatClick, searchParams, setSearchParams, + isChecked, + setIsChecked, }; }; diff --git a/src/pages/Buyer/BuyerConsult.tsx b/src/pages/Buyer/BuyerConsult.tsx index 61d704b8..b0b26bce 100644 --- a/src/pages/Buyer/BuyerConsult.tsx +++ b/src/pages/Buyer/BuyerConsult.tsx @@ -41,10 +41,12 @@ export const BuyerConsult = () => { handleChatClick, searchParams, setSearchParams, + isChecked, + setIsChecked, } = useConsultParams(); // const [isLetter, setIsLetter] = useState(true); //편지 채팅 여부 - const [isChecked, setIsChecked] = useState(false); //완료 제외 체크 여부 + // const [isChecked, setIsChecked] = useState(false); //완료 제외 체크 여부 // const [sortType, setSortType] = useState(0); //0 : 최신순 1:읽지 않은 순 const [isModalOpen, setIsModalOpen] = useRecoilState( isConsultModalOpenState, @@ -88,6 +90,8 @@ export const BuyerConsult = () => { style={{ cursor: 'pointer' }} onClick={() => { setIsChecked(!isChecked); + searchParams.set('check', String(!isChecked)); + setSearchParams(searchParams); }} > {isChecked ? : } From b8aeb1df0a04e006cfab7f96baa0928e5da6e8a8 Mon Sep 17 00:00:00 2001 From: leekyuho Date: Sat, 23 Mar 2024 18:41:44 +0900 Subject: [PATCH 07/16] feat: apply isLetter query string in seller consult (#155) --- .../Seller/SellerConsult/SellerChatList.tsx | 4 +-- .../SellerConsult/SellerConsultSection.tsx | 31 ++++++++++--------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/components/Seller/SellerConsult/SellerChatList.tsx b/src/components/Seller/SellerConsult/SellerChatList.tsx index 55550cc1..8dd1d586 100644 --- a/src/components/Seller/SellerConsult/SellerChatList.tsx +++ b/src/components/Seller/SellerConsult/SellerChatList.tsx @@ -41,7 +41,7 @@ function SellerChatList({ * https://stackoverflow.com/questions/73896315/rxjs-subscribe-callback-doesnt-have-access-to-current-react-state-functional-c */ const cardDataRef = useRef([]); - const { stompClient } = useStompContext(); + const { stompClient, isConnected } = useStompContext(); //채팅 readId, 가장 최근 unread message, 정렬 업데이트 const updateChatData = ( chatId: number, @@ -172,7 +172,7 @@ function SellerChatList({ ); } }; - }, [stompClient]); + }, [stompClient, isConnected]); const fetchChatData = useCallback(async () => { setIsLoading(true); diff --git a/src/components/Seller/SellerConsult/SellerConsultSection.tsx b/src/components/Seller/SellerConsult/SellerConsultSection.tsx index 949a2358..1740fc8a 100644 --- a/src/components/Seller/SellerConsult/SellerConsultSection.tsx +++ b/src/components/Seller/SellerConsult/SellerConsultSection.tsx @@ -9,13 +9,26 @@ import { useSetRecoilState } from 'recoil'; import { isConsultModalOpenState } from 'utils/atom'; import SellerLetterList from './SellerLetterList'; import SellerChatList from './SellerChatList'; +import { useConsultParams } from 'hooks/useConsultParams'; interface ConsultTypeProps { isActive: boolean; } export const SellerConsultSection = () => { + const { + isLetter, + // sortType, + // setSortType, + handleLetterClick, + handleChatClick, + // searchParams, + // setSearchParams, + // isChecked, + // setIsChecked, + } = useConsultParams(); + // 편지 탭과 채팅 탭 - const [isLetterActive, setIsLetterActive] = useState(true); + // const [isLetter, setIsLetter] = useState(true); // 완료된 상담 제외, 포함 const [isIncludeCompleteConsult, setIsIncludeCompleteConsult] = useState(false); @@ -27,20 +40,10 @@ export const SellerConsultSection = () => { <>
- { - setIsLetterActive(true); - }} - > + 편지 - { - setIsLetterActive(false); - }} - > + 채팅 {
- {isLetterActive ? ( + {isLetter ? ( Date: Sat, 23 Mar 2024 18:51:29 +0900 Subject: [PATCH 08/16] feat: apply query string in seller consult sortType (#155) --- .../Seller/Common/OngoingCounsultBox.tsx | 2 +- .../Seller/SellerConsult/SellerChatList.tsx | 13 +++++++++++-- .../SellerConsult/SellerConsultSection.tsx | 16 ++++++++-------- .../Seller/SellerConsult/SellerLetterList.tsx | 13 +++++++++++-- src/pages/Buyer/BuyerConsult.tsx | 3 --- 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/components/Seller/Common/OngoingCounsultBox.tsx b/src/components/Seller/Common/OngoingCounsultBox.tsx index b9ee8240..92f9da51 100644 --- a/src/components/Seller/Common/OngoingCounsultBox.tsx +++ b/src/components/Seller/Common/OngoingCounsultBox.tsx @@ -27,7 +27,7 @@ interface OngoingCounsultBoxProps { counselorprofileStatus: number | undefined; onClick?: () => void; reviewCompleted?: boolean; - isChat: boolean; + isChat?: boolean; } function OngoingCounsultBox({ categoryStatus, diff --git a/src/components/Seller/SellerConsult/SellerChatList.tsx b/src/components/Seller/SellerConsult/SellerChatList.tsx index 8dd1d586..af4c8dea 100644 --- a/src/components/Seller/SellerConsult/SellerChatList.tsx +++ b/src/components/Seller/SellerConsult/SellerChatList.tsx @@ -1,7 +1,7 @@ import { getChatsMinder } from 'api/get'; import { ConsultModal } from 'components/Buyer/BuyerConsult/ConsultModal'; import React, { useCallback, useEffect, useRef, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { SetURLSearchParams, useNavigate } from 'react-router-dom'; import { useRecoilState, useSetRecoilState } from 'recoil'; import styled from 'styled-components'; import { isConsultModalOpenState, scrollLockState } from 'utils/atom'; @@ -19,12 +19,16 @@ interface SellerConsultProps { sortType: number; setSortType: React.Dispatch>; isIncludeCompleteConsult: boolean; + searchParams: URLSearchParams; + setSearchParams: SetURLSearchParams; } function SellerChatList({ sortType, isIncludeCompleteConsult, setSortType, + searchParams, + setSearchParams, }: SellerConsultProps) { const [consultInfo, setConsultInfo] = useState([]); const [isLoading, setIsLoading] = useState(true); @@ -250,7 +254,12 @@ function SellerChatList({ setScrollLock(false); }} /> - + ) : null} diff --git a/src/components/Seller/SellerConsult/SellerConsultSection.tsx b/src/components/Seller/SellerConsult/SellerConsultSection.tsx index 1740fc8a..3d70b3b8 100644 --- a/src/components/Seller/SellerConsult/SellerConsultSection.tsx +++ b/src/components/Seller/SellerConsult/SellerConsultSection.tsx @@ -17,23 +17,19 @@ interface ConsultTypeProps { export const SellerConsultSection = () => { const { isLetter, - // sortType, - // setSortType, + sortType, + setSortType, handleLetterClick, handleChatClick, - // searchParams, - // setSearchParams, + searchParams, + setSearchParams, // isChecked, // setIsChecked, } = useConsultParams(); - // 편지 탭과 채팅 탭 - // const [isLetter, setIsLetter] = useState(true); // 완료된 상담 제외, 포함 const [isIncludeCompleteConsult, setIsIncludeCompleteConsult] = useState(false); - // 최근순, 읽지 않은 순 - const [sortType, setSortType] = useState(0); // 모달 열지 말지 const setIsModalOpen = useSetRecoilState(isConsultModalOpenState); return ( @@ -76,12 +72,16 @@ export const SellerConsultSection = () => { ) : ( )} diff --git a/src/components/Seller/SellerConsult/SellerLetterList.tsx b/src/components/Seller/SellerConsult/SellerLetterList.tsx index 76ba1379..86aeb6a3 100644 --- a/src/components/Seller/SellerConsult/SellerLetterList.tsx +++ b/src/components/Seller/SellerConsult/SellerLetterList.tsx @@ -1,7 +1,7 @@ import { getConselorLetters } from 'api/get'; import { ConsultModal } from 'components/Buyer/BuyerConsult/ConsultModal'; import React, { useCallback, useEffect, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { SetURLSearchParams, useNavigate } from 'react-router-dom'; import { useRecoilState, useSetRecoilState } from 'recoil'; import styled from 'styled-components'; import { isConsultModalOpenState, scrollLockState } from 'utils/atom'; @@ -15,12 +15,16 @@ interface SellerConsultProps { sortType: number; setSortType: React.Dispatch>; isIncludeCompleteConsult: boolean; + searchParams: URLSearchParams; + setSearchParams: SetURLSearchParams; } function SellerLetterList({ sortType, isIncludeCompleteConsult, setSortType, + searchParams, + setSearchParams, }: SellerConsultProps) { const [consultInfo, setConsultInfo] = useState([]); const [isLoading, setIsLoading] = useState(true); @@ -106,7 +110,12 @@ function SellerLetterList({ setScrollLock(false); }} /> - + ) : null} diff --git a/src/pages/Buyer/BuyerConsult.tsx b/src/pages/Buyer/BuyerConsult.tsx index b0b26bce..83bf8d16 100644 --- a/src/pages/Buyer/BuyerConsult.tsx +++ b/src/pages/Buyer/BuyerConsult.tsx @@ -45,9 +45,6 @@ export const BuyerConsult = () => { setIsChecked, } = useConsultParams(); - // const [isLetter, setIsLetter] = useState(true); //편지 채팅 여부 - // const [isChecked, setIsChecked] = useState(false); //완료 제외 체크 여부 - // const [sortType, setSortType] = useState(0); //0 : 최신순 1:읽지 않은 순 const [isModalOpen, setIsModalOpen] = useRecoilState( isConsultModalOpenState, ); // Modal 여부(recoil) From dd82d0aebabdae4e2c5e6b84dfbb41922779525a Mon Sep 17 00:00:00 2001 From: leekyuho Date: Sat, 23 Mar 2024 18:52:47 +0900 Subject: [PATCH 09/16] fix: change unread text and OngoingBox component props error (#155) --- src/components/Seller/SellerConsult/SellerConsultSection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Seller/SellerConsult/SellerConsultSection.tsx b/src/components/Seller/SellerConsult/SellerConsultSection.tsx index 3d70b3b8..035e00f4 100644 --- a/src/components/Seller/SellerConsult/SellerConsultSection.tsx +++ b/src/components/Seller/SellerConsult/SellerConsultSection.tsx @@ -48,7 +48,7 @@ export const SellerConsultSection = () => { }} > - {sortType === 0 ? '최근순' : '읽지 않은 순'} + {sortType === 0 ? '최근순' : '읽지않은순'} From 9b098e32f09ff266ad7457ffa5d41d8e5ee7c366 Mon Sep 17 00:00:00 2001 From: leekyuho Date: Sat, 23 Mar 2024 19:08:48 +0900 Subject: [PATCH 10/16] feat: apply query string in seller consult isChecked (#155) --- .../Seller/SellerConsult/SellerChatList.tsx | 8 ++++---- .../SellerConsult/SellerConsultSection.tsx | 17 ++++++++--------- .../Seller/SellerConsult/SellerLetterList.tsx | 11 ++++++----- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/components/Seller/SellerConsult/SellerChatList.tsx b/src/components/Seller/SellerConsult/SellerChatList.tsx index af4c8dea..cbc9601f 100644 --- a/src/components/Seller/SellerConsult/SellerChatList.tsx +++ b/src/components/Seller/SellerConsult/SellerChatList.tsx @@ -18,14 +18,14 @@ import { ConsultInfoItem, ConsultInfoList } from 'utils/type'; interface SellerConsultProps { sortType: number; setSortType: React.Dispatch>; - isIncludeCompleteConsult: boolean; + isChecked: boolean; searchParams: URLSearchParams; setSearchParams: SetURLSearchParams; } function SellerChatList({ sortType, - isIncludeCompleteConsult, + isChecked, setSortType, searchParams, setSearchParams, @@ -181,7 +181,7 @@ function SellerChatList({ const fetchChatData = useCallback(async () => { setIsLoading(true); const params = { - filter: !isIncludeCompleteConsult, + filter: isChecked, sortType: sortType === 0 ? 'latest' : 'unread', }; @@ -203,7 +203,7 @@ function SellerChatList({ } finally { setIsLoading(false); } - }, [isIncludeCompleteConsult, navigate, setIsLoading, sortType]); + }, [isChecked, navigate, setIsLoading, sortType]); useEffect(() => { fetchChatData(); diff --git a/src/components/Seller/SellerConsult/SellerConsultSection.tsx b/src/components/Seller/SellerConsult/SellerConsultSection.tsx index 035e00f4..75bf7718 100644 --- a/src/components/Seller/SellerConsult/SellerConsultSection.tsx +++ b/src/components/Seller/SellerConsult/SellerConsultSection.tsx @@ -23,13 +23,10 @@ export const SellerConsultSection = () => { handleChatClick, searchParams, setSearchParams, - // isChecked, - // setIsChecked, + isChecked, + setIsChecked, } = useConsultParams(); - // 완료된 상담 제외, 포함 - const [isIncludeCompleteConsult, setIsIncludeCompleteConsult] = - useState(false); // 모달 열지 말지 const setIsModalOpen = useSetRecoilState(isConsultModalOpenState); return ( @@ -57,13 +54,15 @@ export const SellerConsultSection = () => {
{ - setIsIncludeCompleteConsult(!isIncludeCompleteConsult); + setIsChecked(!isChecked); + searchParams.set('check', String(!isChecked)); + setSearchParams(searchParams); }} style={{ cursor: 'pointer', }} > - + 종료/취소된 상담 제외
@@ -74,7 +73,7 @@ export const SellerConsultSection = () => { setSortType={setSortType} searchParams={searchParams} setSearchParams={setSearchParams} - isIncludeCompleteConsult={isIncludeCompleteConsult} + isChecked={isChecked} /> ) : ( { setSortType={setSortType} searchParams={searchParams} setSearchParams={setSearchParams} - isIncludeCompleteConsult={isIncludeCompleteConsult} + isChecked={isChecked} /> )} diff --git a/src/components/Seller/SellerConsult/SellerLetterList.tsx b/src/components/Seller/SellerConsult/SellerLetterList.tsx index 86aeb6a3..11a0661d 100644 --- a/src/components/Seller/SellerConsult/SellerLetterList.tsx +++ b/src/components/Seller/SellerConsult/SellerLetterList.tsx @@ -14,14 +14,14 @@ import { LoadingSpinner } from 'utils/LoadingSpinner'; interface SellerConsultProps { sortType: number; setSortType: React.Dispatch>; - isIncludeCompleteConsult: boolean; + isChecked: boolean; searchParams: URLSearchParams; setSearchParams: SetURLSearchParams; } function SellerLetterList({ sortType, - isIncludeCompleteConsult, + isChecked, setSortType, searchParams, setSearchParams, @@ -36,16 +36,17 @@ function SellerLetterList({ const fetchLetterData = useCallback(async () => { setIsLoading(true); const params = { - filter: !isIncludeCompleteConsult, + filter: isChecked, sortType: sortType === 0 ? 'latest' : 'unread', }; let res: any; try { res = await getConselorLetters({ params }); + console.log(res.data); if (res.status === 200) { const data: ConsultInfoList = res.data; setConsultInfo(data); - } else if (res?.response?.status === 403) { + } else if (res.response.status === 403) { // 판매 정보를 등록하지 않았을 경우 alert('판매 정보를 등록해주세요.'); navigate('/minder/mypage/viewProfile'); @@ -57,7 +58,7 @@ function SellerLetterList({ } finally { setIsLoading(false); } - }, [isIncludeCompleteConsult, navigate, setIsLoading, sortType]); + }, [isChecked, navigate, setIsLoading, sortType]); useEffect(() => { fetchLetterData(); }, [fetchLetterData]); From f092a34aaf6418350e1c581131c8a7eb120ccffa Mon Sep 17 00:00:00 2001 From: leekyuho Date: Sat, 23 Mar 2024 19:22:54 +0900 Subject: [PATCH 11/16] fix: modify wrong naming in seller letter list info (#155) --- .../Seller/SellerConsult/SellerLetterList.tsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/Seller/SellerConsult/SellerLetterList.tsx b/src/components/Seller/SellerConsult/SellerLetterList.tsx index 11a0661d..b2b3cd90 100644 --- a/src/components/Seller/SellerConsult/SellerLetterList.tsx +++ b/src/components/Seller/SellerConsult/SellerLetterList.tsx @@ -6,7 +6,7 @@ import { useRecoilState, useSetRecoilState } from 'recoil'; import styled from 'styled-components'; import { isConsultModalOpenState, scrollLockState } from 'utils/atom'; import { consultStyleToCharNum } from 'utils/convertStringToCharNum'; -import { ConsultInfoList } from 'utils/type'; +import { ConsultInfoItem, ConsultInfoList } from 'utils/type'; import OngoingCounsultBox from '../Common/OngoingCounsultBox'; import { ReactComponent as NoConsultGraphicIcon } from 'assets/icons/graphic-no-calculation.svg'; import { LoadingSpinner } from 'utils/LoadingSpinner'; @@ -82,23 +82,23 @@ function SellerLetterList({ 아직 진행한 상담이 없어요 ) : ( - consultInfo?.map((item: any) => ( + consultInfo.map((item: ConsultInfoItem) => ( { - navigate(`/minder/letter/${item?.id}`); + navigate(`/minder/letter/${item.id}`); }} /> )) From ce272def22b72521307b063ac3c81f6085645875 Mon Sep 17 00:00:00 2001 From: leekyuho Date: Sat, 23 Mar 2024 19:30:58 +0900 Subject: [PATCH 12/16] chore: delete unusing imports (#155) --- .../SellerConsult/SellerConsultSection.tsx | 1 - .../Seller/SellerConsult/SellerLetterList.tsx | 2 +- src/hooks/useConsultParams.ts | 4 +--- src/pages/Buyer/BuyerChat.tsx | 2 +- src/pages/Buyer/BuyerConsult.tsx | 1 - src/pages/Buyer/BuyerPwChange.tsx | 4 ++-- src/pages/Seller/SellerChatTemp.tsx | 19 ++++--------------- 7 files changed, 9 insertions(+), 24 deletions(-) diff --git a/src/components/Seller/SellerConsult/SellerConsultSection.tsx b/src/components/Seller/SellerConsult/SellerConsultSection.tsx index 75bf7718..46bc8787 100644 --- a/src/components/Seller/SellerConsult/SellerConsultSection.tsx +++ b/src/components/Seller/SellerConsult/SellerConsultSection.tsx @@ -4,7 +4,6 @@ import { ReactComponent as CircleCheckIcon } from 'assets/icons/circle-check.svg import { Button2 } from 'styles/font'; import styled from 'styled-components'; -import { useState } from 'react'; import { useSetRecoilState } from 'recoil'; import { isConsultModalOpenState } from 'utils/atom'; import SellerLetterList from './SellerLetterList'; diff --git a/src/components/Seller/SellerConsult/SellerLetterList.tsx b/src/components/Seller/SellerConsult/SellerLetterList.tsx index b2b3cd90..15120dfa 100644 --- a/src/components/Seller/SellerConsult/SellerLetterList.tsx +++ b/src/components/Seller/SellerConsult/SellerLetterList.tsx @@ -90,7 +90,7 @@ function SellerLetterList({ content={ item.status === '질문 대기' ? '셰어의 질문이 도착할 때까지 조금만 기다려주세요! ' - : item?.latestMessageContent + : item.latestMessageContent } key={item.id} counselorprofileStatus={consultStyleToCharNum( diff --git a/src/hooks/useConsultParams.ts b/src/hooks/useConsultParams.ts index cadbec62..aabadfe6 100644 --- a/src/hooks/useConsultParams.ts +++ b/src/hooks/useConsultParams.ts @@ -1,7 +1,5 @@ -// import { useStompContext } from 'contexts/StompContext'; -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import { useSearchParams } from 'react-router-dom'; -import { Green, Grey1 } from 'styles/color'; // The setSearchParams function works like navigate, but only for the search portion of the URL. Also note that the second arg to setSearchParams is the same type as the second arg to navigate. // https://reactrouter.com/en/main/hooks/use-search-params diff --git a/src/pages/Buyer/BuyerChat.tsx b/src/pages/Buyer/BuyerChat.tsx index d47982e4..c7737b35 100644 --- a/src/pages/Buyer/BuyerChat.tsx +++ b/src/pages/Buyer/BuyerChat.tsx @@ -53,7 +53,7 @@ export const BuyerChat = () => { null, ); const [isLastElem, setIsLastElem] = useState(false); - const [startRequestActive, setStartRequestActive] = useState(true); + //useRefs const inputRef = useRef(null); //input ref 높이 초기화를 위함 const hiddenInputRef = useRef(null); diff --git a/src/pages/Buyer/BuyerConsult.tsx b/src/pages/Buyer/BuyerConsult.tsx index 83bf8d16..b7106737 100644 --- a/src/pages/Buyer/BuyerConsult.tsx +++ b/src/pages/Buyer/BuyerConsult.tsx @@ -1,6 +1,5 @@ import { Header } from 'components/Common/Header'; import { TabA1 } from 'components/Common/TabA1'; -import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useRecoilState, useSetRecoilState } from 'recoil'; import styled from 'styled-components'; diff --git a/src/pages/Buyer/BuyerPwChange.tsx b/src/pages/Buyer/BuyerPwChange.tsx index 2e9b2764..54b8ff29 100644 --- a/src/pages/Buyer/BuyerPwChange.tsx +++ b/src/pages/Buyer/BuyerPwChange.tsx @@ -62,7 +62,7 @@ export const BuyerPwChange = () => { } else { setValid(false); } - }, [pw.isValid, newPw.isValid, newPwCheck.isValid]); + }, [pw.isValid, newPw.isValid, newPwCheck.isValid, newPw.typeValid]); useEffect(() => { // 첫 마운트 시에는 error 색상 안되게 처리 @@ -108,7 +108,7 @@ export const BuyerPwChange = () => { setCorrectState('invalid'); newPwCheck.setIsValid(false); } - }, [newPw.value, newPwCheck.value]); + }, [newPw, newPw.value, newPwCheck, newPwCheck.value, pw]); return ( diff --git a/src/pages/Seller/SellerChatTemp.tsx b/src/pages/Seller/SellerChatTemp.tsx index 151e12d2..62eccdfb 100644 --- a/src/pages/Seller/SellerChatTemp.tsx +++ b/src/pages/Seller/SellerChatTemp.tsx @@ -53,7 +53,7 @@ export const SellerChatTemp = () => { const { stompClient } = useStompContext(); const preventRef = useRef(false); // observer 중복방지, 첫 mount 시 message 가져온 후 true로 전환 - const preventScrollRef = useRef(true); // message 변경 시 모바일에서 오버 스크롤로 인해 여러번 불리는 오류 발생, scrollintoview 완료 전까지 observe 막기 + const isLastElem = useRef(false); //마지막 채팅인지 확인 const lastRef = useRef(null); // 마지막 채팅 box ref const newMessageRef = useRef(true); // 새로운 메세지인지 이전 메세지 fetch인지 @@ -300,17 +300,9 @@ export const SellerChatTemp = () => { !isLastElem.current && !isInitialLoading && preventRef.current - // &&preventScrollRef.current ) { preventRef.current = false; - // preventScrollRef.current = false; - // console.log(`관측: ${messages[0].messageId}`); await getChatMessages(messages[0].messageId); - // console.log('fetch 완료'); - // setTimeout(() => { - // preventRef.current = true; - // }, 100); - // console.log(`관측: ${messages[0].messageId}`); preventRef.current = true; } }; @@ -369,9 +361,6 @@ export const SellerChatTemp = () => { block: 'start', // 페이지 하단으로 스크롤하도록 지정합니다. }); } - // console.log('스크롤 완료'); - //scrollIntoView 완료 후 다시 관측가능 - // preventScrollRef.current = true; }, [messages]); //상담 start request 관련 처리 useEffect(() => { @@ -397,7 +386,7 @@ export const SellerChatTemp = () => { }, 1000); return () => clearInterval(timer); - }, [time]); + }, [chatStatus, time]); if (isInitialLoading) { return ( @@ -405,7 +394,7 @@ export const SellerChatTemp = () => { { - navigate('/minder/consult'); + navigate(-1); }} /> @@ -418,7 +407,7 @@ export const SellerChatTemp = () => { { - navigate('/minder/consult'); + navigate(-1); }} /> {opponentName} From 6262f590ec64f32ef357ec4f300a6a38f37a75e6 Mon Sep 17 00:00:00 2001 From: Lee Kyuho <64120854+leekyuho114@users.noreply.github.com> Date: Sat, 23 Mar 2024 19:57:51 +0900 Subject: [PATCH 13/16] docs: edit pr template --- .github/pull_request_Template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_Template.md b/.github/pull_request_Template.md index 21e9c73e..ab623fed 100644 --- a/.github/pull_request_Template.md +++ b/.github/pull_request_Template.md @@ -7,7 +7,7 @@
-## Describtion +## Description
PR 내용을 작성해주세요. From 899b357da9f5bcb1cbda13456f3c4abd9fb7069c Mon Sep 17 00:00:00 2001 From: inyoung Date: Sat, 23 Mar 2024 20:37:57 +0900 Subject: [PATCH 14/16] =?UTF-8?q?Feat:=20=EB=A7=88=EC=9D=B8=EB=8D=94=20?= =?UTF-8?q?=EA=B3=B5=EA=B0=9C=EC=83=81=EB=8B=B4=20=ED=83=AD=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20Markup=20=EC=A7=84=ED=96=89=EC=A4=91=20#18?= =?UTF-8?q?0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/icons/icon-heart3.svg | 3 + src/assets/icons/icon-save3.svg | 5 + src/components/Common/TabA1.tsx | 2 +- .../SellerConsult/SellerOpenConsultList.tsx | 5 +- .../SellerOpenConsult/MainQuestionSection.tsx | 111 ++++++++++++++++++ .../SellerOpenConsult/OpenConsultHeader.tsx | 43 +++++++ src/pages/Seller/SellerOpenConsult.tsx | 14 ++- 7 files changed, 176 insertions(+), 7 deletions(-) create mode 100644 src/assets/icons/icon-heart3.svg create mode 100644 src/assets/icons/icon-save3.svg create mode 100644 src/components/Seller/SellerOpenConsult/MainQuestionSection.tsx create mode 100644 src/components/Seller/SellerOpenConsult/OpenConsultHeader.tsx diff --git a/src/assets/icons/icon-heart3.svg b/src/assets/icons/icon-heart3.svg new file mode 100644 index 00000000..0332bcd3 --- /dev/null +++ b/src/assets/icons/icon-heart3.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/icon-save3.svg b/src/assets/icons/icon-save3.svg new file mode 100644 index 00000000..16fe64b9 --- /dev/null +++ b/src/assets/icons/icon-save3.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/Common/TabA1.tsx b/src/components/Common/TabA1.tsx index e4218ad1..579673e6 100644 --- a/src/components/Common/TabA1.tsx +++ b/src/components/Common/TabA1.tsx @@ -71,7 +71,7 @@ export const TabA1 = ({ isBuyer, initState }: TabA1Props) => { if (isBuyer) { navigate('/open-consult'); } else { - navigate('/minder/consult'); + navigate('/minder/open-consult'); } }} > diff --git a/src/components/Seller/SellerConsult/SellerOpenConsultList.tsx b/src/components/Seller/SellerConsult/SellerOpenConsultList.tsx index ba6fd518..10d1063c 100644 --- a/src/components/Seller/SellerConsult/SellerOpenConsultList.tsx +++ b/src/components/Seller/SellerConsult/SellerOpenConsultList.tsx @@ -4,7 +4,9 @@ import { Green, Grey1, Grey2, Grey3, Grey6, Red, White } from 'styles/color'; import { Body1, Caption1, Caption2 } from 'styles/font'; import { ReactComponent as LockIcon } from 'assets/icons/icon-lock.svg'; import { ReactComponent as HeartIcon } from 'assets/icons/icon-heart2.svg'; -import { ReactComponent as SaveIcon } from 'assets/icons/icon-save2.svg'; +import { ReactComponent as HeartEmptyIcon } from 'assets/icons/icon-heart3.svg'; +import { ReactComponent as SaveIcon } from 'assets/icons/icon-save1.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 { Space } from 'components/Common/Space'; @@ -68,7 +70,6 @@ function SellerOpenConsultList() { 28
- 셰어 Pick diff --git a/src/components/Seller/SellerOpenConsult/MainQuestionSection.tsx b/src/components/Seller/SellerOpenConsult/MainQuestionSection.tsx new file mode 100644 index 00000000..bfb26528 --- /dev/null +++ b/src/components/Seller/SellerOpenConsult/MainQuestionSection.tsx @@ -0,0 +1,111 @@ +import React from 'react'; +import styled from 'styled-components'; +import { Grey1, Grey2, Grey3, Grey6 } from 'styles/color'; +import { ReactComponent as LockIcon } from 'assets/icons/icon-lock.svg'; +import { ReactComponent as HeartIcon } from 'assets/icons/icon-heart1.svg'; +import { ReactComponent as SaveIcon } from 'assets/icons/icon-save2.svg'; +import { ReactComponent as HeartEmptyIcon } from 'assets/icons/icon-heart3.svg'; +import { ReactComponent as CommentIcon } from 'assets/icons/icon-comment.svg'; +import { ReactComponent as SaveEmptyIcon } from 'assets/icons/icon-save3.svg'; +import { ReactComponent as CheckIcon } from 'assets/icons/icon-check2.svg'; +import { Body1, Caption1, Caption2 } from 'styles/font'; +import { Space } from 'components/Common/Space'; +function MainQuestionSection() { + return ( + + +
+ 이거 권태기 증상 맞나요? + + + 비공개 + +
+ +
+ 요즘따라 여자친구가 먼저 만나자고 이야기도 안 하고 만나면 피곤하다고만 + 해요. 스킨십도 하려고 하지 않고 인생이 재미가 없다네요.. 그런데 + 여자친구가 다른 남자 인스타 피드에는 좋아요를 눌러요... 이거 + 여자친구가 권태기가 맞는 걸까요? 맞다면 어떻게 이야기를 꺼내면 + 좋을까요? 너무 힘듭니다.. +
+ +
+ 2024.12.13 + + 연애갈등 +
+ +
+ + + + 11 + + + + 0 + + +
+ ); +} +const MainQuestionWrapper = styled.section` + display: flex; + padding: 1.2rem 2rem; + flex-direction: column; + gap: 1.2rem; + border-bottom: 1px solid ${Grey6}; +`; + +const MainQuestionText = styled.div` + width: 100%; + position: relative; + background-color: ${Grey6}; + padding: 1.6rem; + box-sizing: border-box; + border-radius: 1.2rem; + .row2 { + align-self: flex-end; + margin-bottom: 0.4rem; + color: ${Grey1}; + font-family: Pretendard; + font-size: 1.4rem; + font-style: normal; + font-weight: 400; + line-height: 155%; + } + .row3 { + display: flex; + gap: 0.8rem; + align-items: center; + } +`; +const PrivateSign = styled.div` + display: flex; + position: absolute; + top: 1.95rem; + right: 1.6rem; +`; +const Circle = styled.div` + width: 0.2rem; + height: 0.2rem; + border-radius: 100%; + background-color: ${Grey3}; +`; + +const ButtonList = styled.div` + display: flex; + gap: 1.2rem; +`; + +const ButtonItem = styled.div` + border-radius: 0.8rem; + background: ${Grey6}; + display: flex; + padding: 0.6rem 1.2rem 0.6rem 0.6rem; + align-items: center; + gap: 0.4rem; +`; + +export default MainQuestionSection; diff --git a/src/components/Seller/SellerOpenConsult/OpenConsultHeader.tsx b/src/components/Seller/SellerOpenConsult/OpenConsultHeader.tsx new file mode 100644 index 00000000..cc3c1468 --- /dev/null +++ b/src/components/Seller/SellerOpenConsult/OpenConsultHeader.tsx @@ -0,0 +1,43 @@ +import React from 'react'; +import styled from 'styled-components'; +import { White } from 'styles/color'; +import { ReactComponent as LeftArrowIcon } from 'assets/icons/left-arrow.svg'; +import { ReactComponent as OptionIcon } from 'assets/icons/icon-option.svg'; +import { Heading } from 'styles/font'; +import { useNavigate } from 'react-router-dom'; + +function OpenConsultHeader() { + const navigate = useNavigate(); + return ( + + { + navigate('/minder'); + }} + /> + 공개상담 + + ); +} + +const OpenConsultHeaderWrapper = styled.div` + display: flex; + align-items: center; + height: 5.2rem; + box-sizing: border-box; + padding: 1.2rem 2rem; + background-color: ${White}; + justify-content: center; + position: sticky; + border-bottom: 1px solid rgba(242, 241, 248, 0.95); + top: 0; +`; + +const LeftArrow = styled(LeftArrowIcon)` + cursor: pointer; + position: absolute; + top: 1.2rem; + left: 2rem; +`; + +export default OpenConsultHeader; diff --git a/src/pages/Seller/SellerOpenConsult.tsx b/src/pages/Seller/SellerOpenConsult.tsx index 667532df..2b3af7f1 100644 --- a/src/pages/Seller/SellerOpenConsult.tsx +++ b/src/pages/Seller/SellerOpenConsult.tsx @@ -1,9 +1,15 @@ -import React from 'react' +import MainQuestionSection from 'components/Seller/SellerOpenConsult/MainQuestionSection'; +import MainQuestion from 'components/Seller/SellerOpenConsult/MainQuestionSection'; +import OpenConsultHeader from 'components/Seller/SellerOpenConsult/OpenConsultHeader'; +import React from 'react'; function SellerOpenConsult() { return ( -
SellerOpenConsult
- ) + <> + + + + ); } -export default SellerOpenConsult \ No newline at end of file +export default SellerOpenConsult; From 4124be0938871d34ab6c38772f4d7400ccd4a811 Mon Sep 17 00:00:00 2001 From: inyoung Date: Sun, 24 Mar 2024 14:31:04 +0900 Subject: [PATCH 15/16] =?UTF-8?q?Feat:=20=EC=B5=9C=EA=B7=BC=20=EC=88=9C,?= =?UTF-8?q?=20=EC=9D=BD=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EC=88=9C=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=AC=20=EA=B3=B5=EA=B0=9C=EC=83=81=EB=8B=B4=20?= =?UTF-8?q?=ED=83=AD=EC=97=90=EC=84=9C=20=EA=B5=AC=ED=98=84=20#180?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SellerConsult/SellerConsultSection.tsx | 15 ++++--- .../SellerConsult/SellerOpenConsultList.tsx | 42 ++++++++++++++++++- src/hooks/useConsultParams.ts | 6 +-- src/pages/Buyer/BuyerConsult.tsx | 8 ++-- 4 files changed, 58 insertions(+), 13 deletions(-) diff --git a/src/components/Seller/SellerConsult/SellerConsultSection.tsx b/src/components/Seller/SellerConsult/SellerConsultSection.tsx index 012bdb62..6d726f2b 100644 --- a/src/components/Seller/SellerConsult/SellerConsultSection.tsx +++ b/src/components/Seller/SellerConsult/SellerConsultSection.tsx @@ -23,7 +23,7 @@ export const SellerConsultSection = () => { setSortType, handleLetterClick, handleChatClick, - handleOpenChatClick, + handleOpenConsultClick, searchParams, setSearchParams, isChecked, @@ -50,8 +50,8 @@ export const SellerConsultSection = () => { 공개상담 @@ -66,7 +66,7 @@ export const SellerConsultSection = () => { - {!(consultType === 'open-chat') && ( + {!(consultType === 'open-consult') && (
{ isChecked={isChecked} /> ) : ( - + )} ); diff --git a/src/components/Seller/SellerConsult/SellerOpenConsultList.tsx b/src/components/Seller/SellerConsult/SellerOpenConsultList.tsx index 10d1063c..d4929c8c 100644 --- a/src/components/Seller/SellerConsult/SellerOpenConsultList.tsx +++ b/src/components/Seller/SellerConsult/SellerOpenConsultList.tsx @@ -11,8 +11,31 @@ import { ReactComponent as CommentIcon } from 'assets/icons/icon-comment.svg'; import { ReactComponent as CheckIcon } from 'assets/icons/icon-check2.svg'; import { Space } from 'components/Common/Space'; import { LoadingSpinner } from 'utils/LoadingSpinner'; -function SellerOpenConsultList() { +import { SetURLSearchParams } from 'react-router-dom'; +import { isConsultModalOpenState, scrollLockState } from 'utils/atom'; +import { useRecoilState, useSetRecoilState } from 'recoil'; +import { BackDrop } from 'components/Common/BackDrop'; +import { ConsultModal } from 'components/Buyer/BuyerConsult/ConsultModal'; + +interface SellerConsultOpenProps { + sortType: number; + setSortType: React.Dispatch>; + searchParams: URLSearchParams; + setSearchParams: SetURLSearchParams; +} + +function SellerOpenConsultList({ + sortType, + setSortType, + searchParams, + setSearchParams, +}: SellerConsultOpenProps) { const [isLoading, setIsLoading] = useState(false); + const [isModalOpen, setIsModalOpen] = useRecoilState( + isConsultModalOpenState, + ); + const setScrollLock = useSetRecoilState(scrollLockState); + const fetchOpenConsultData = async () => {}; return ( <> @@ -77,6 +100,23 @@ function SellerOpenConsultList() { )} + + {isModalOpen ? ( + <> + { + setIsModalOpen(false); + setScrollLock(false); + }} + /> + + + ) : null} ); } diff --git a/src/hooks/useConsultParams.ts b/src/hooks/useConsultParams.ts index 36b63fbe..3c69a047 100644 --- a/src/hooks/useConsultParams.ts +++ b/src/hooks/useConsultParams.ts @@ -33,8 +33,8 @@ export const useConsultParams = () => { setSearchParams(searchParams); }; - const handleOpenChatClick = () => { - setConsultType('open-chat'); + const handleOpenConsultClick = () => { + setConsultType('open-consult'); searchParams.set('type', 'open-consult'); setSearchParams(searchParams); }; @@ -44,7 +44,7 @@ export const useConsultParams = () => { sortType, setSortType, handleLetterClick, - handleOpenChatClick, + handleOpenConsultClick, handleChatClick, searchParams, setSearchParams, diff --git a/src/pages/Buyer/BuyerConsult.tsx b/src/pages/Buyer/BuyerConsult.tsx index af19cca0..f3742045 100644 --- a/src/pages/Buyer/BuyerConsult.tsx +++ b/src/pages/Buyer/BuyerConsult.tsx @@ -37,7 +37,7 @@ export const BuyerConsult = () => { sortType, setSortType, handleLetterClick, - handleOpenChatClick, + handleOpenConsultClick, handleChatClick, searchParams, setSearchParams, @@ -80,10 +80,10 @@ export const BuyerConsult = () => { - + 공개상담 From 292179cff614e754a8f0b09cfbfc1db31699bef3 Mon Sep 17 00:00:00 2001 From: inyoung Date: Sun, 24 Mar 2024 16:19:05 +0900 Subject: [PATCH 16/16] =?UTF-8?q?Feat:=20=EB=A7=88=EC=9D=B8=EB=8D=94=20?= =?UTF-8?q?=EA=B3=B5=EA=B0=9C=EC=83=81=EB=8B=B4=20=ED=83=AD=20=EB=A7=88?= =?UTF-8?q?=ED=81=AC=EC=97=85=20=EC=99=84=EB=A3=8C=20#180?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SellerOpenConsult/BottomSection.tsx | 118 ++++++++++++++ .../SellerOpenConsult/CommentListSection.tsx | 146 ++++++++++++++++++ .../Seller/SellerOpenConsult/IsSendPopup.tsx | 96 ++++++++++++ .../SellerOpenConsult/MainQuestionSection.tsx | 38 ++++- src/components/Seller/SellerOpenConsult/S= | 1 + src/pages/Seller/SellerOpenConsult.tsx | 16 ++ src/utils/atom.ts | 5 + 7 files changed, 417 insertions(+), 3 deletions(-) create mode 100644 src/components/Seller/SellerOpenConsult/BottomSection.tsx create mode 100644 src/components/Seller/SellerOpenConsult/CommentListSection.tsx create mode 100644 src/components/Seller/SellerOpenConsult/IsSendPopup.tsx create mode 100644 src/components/Seller/SellerOpenConsult/S= diff --git a/src/components/Seller/SellerOpenConsult/BottomSection.tsx b/src/components/Seller/SellerOpenConsult/BottomSection.tsx new file mode 100644 index 00000000..a0a21681 --- /dev/null +++ b/src/components/Seller/SellerOpenConsult/BottomSection.tsx @@ -0,0 +1,118 @@ +import { Button } from 'components/Common/Button'; +import React, { useState } from 'react'; +import reactTextareaAutosize from 'react-textarea-autosize'; +import styled from 'styled-components'; +import { ReactComponent as SendIcon } from 'assets/icons/icon-send.svg'; +import { Green, Grey3, Grey6, LightGreen, White } from 'styles/color'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { isSendPopupOpenState } from 'utils/atom'; + +function BottomSection() { + const [isReplying, setIsReplying] = useState(false); + const [text, setText] = useState(''); + const setIsSendPopupOpen = useSetRecoilState(isSendPopupOpenState); + return ( + + {isReplying ? ( +
+ { + setText(e.target.value); + }} + rows={1} + maxRows={4} + /> + 0 ? Green : Grey3} + onClick={() => { + // sendMessage(); + setIsSendPopupOpen(true); + }} + /> +
+ ) : ( +
+
+ )} +
+ ); +} + +const BottomSectionWrapper = styled.section` + display: flex; + flex-direction: column; + align-items: center; + box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.25); + background-color: white; + text-align: center; + gap: 0.6rem; + padding-top: 0.8rem; + padding-bottom: 1.6rem; + background-color: ${White}; + position: fixed; + bottom: 0; + width: 100%; + .buttons { + display: flex; + justify-content: center; + gap: 0.7rem; + width: calc(100% - 4rem); + } + .message-input { + display: flex; + width: calc(100% - 4rem); + align-items: center; + gap: 0.8rem; + } + @media (max-width: 767px) { + width: calc(100%); + } + @media (min-width: 768px) { + width: calc(375px); + } +`; + +const MessageTextArea = styled(reactTextareaAutosize)` + width: 100%; + padding: 1.2rem 1.5rem; + outline: none; + border: none; + resize: none; + border-radius: 1.2rem; + background-color: ${Grey6}; + font-family: Pretendard; + font-size: 1.6rem; + font-style: normal; + font-weight: 400; + line-height: 110%; /* 1.76rem */ + &:focus { + border: none; + outline: none; + } +`; +const SendIconSVG = styled(SendIcon)` + cursor: pointer; + align-self: flex-end; + padding-bottom: 0.7rem; +`; + +export default BottomSection; diff --git a/src/components/Seller/SellerOpenConsult/CommentListSection.tsx b/src/components/Seller/SellerOpenConsult/CommentListSection.tsx new file mode 100644 index 00000000..7557db64 --- /dev/null +++ b/src/components/Seller/SellerOpenConsult/CommentListSection.tsx @@ -0,0 +1,146 @@ +import { lightGreen } from '@mui/material/colors'; +import { light } from '@mui/material/styles/createPalette'; +import React from 'react'; +import styled from 'styled-components'; +import { + Green, + Grey1, + Grey2, + Grey3, + Grey6, + LightGreen, + LightRed, +} from 'styles/color'; +import { Body1, Body3, Body4, Caption1, Caption2 } from 'styles/font'; +import { ReactComponent as HeartIcon } from 'assets/icons/icon-heart1.svg'; +import { ReactComponent as HeartEmptyIcon } from 'assets/icons/icon-heart3.svg'; +import { ReactComponent as SettingIcon } from 'assets/icons/icon-option.svg'; +import { Characters } from 'utils/Characters'; +import { Space } from 'components/Common/Space'; + +function CommentListSection() { + return ( + + + + 아직 답장한 마인더가 없어요! 가장 먼저 답장해보세요. + + + {/* 댓글 리스트 , 최대 5개까지*/} + +
+ + 연애상담마스터 + + 11:23 + +
+ + + 권태기 증상이 맞는 것 같네요. 속상하시겠지만, 대화를 통해 충분히 + 극복하실 수 있어요. 어쩌구 저쩌구. + + + + 28 + +
+ +
+ + 연애상담마스터 + + 11:23 + +
+ + + 권태기 증상이 맞는 것 같네요. 속상하시겠지만, 대화를 통해 충분히 + 극복하실 수 있어요. 어쩌구 저쩌구. + + + + 28 + +
{' '} + +
+ + 연애상담마스터 + + 11:23 + +
+ + + 권태기 증상이 맞는 것 같네요. 속상하시겠지만, 대화를 통해 충분히 + 극복하실 수 있어요. 어쩌구 저쩌구. + + + + 28 + +
+ +
+ ); +} + +const CommentListSectionWrapper = styled.section` + padding: 1.2rem 2rem; + display: flex; + flex-direction: column; + gap: 0.6rem; +`; + +const CommentGuide = styled.div<{ $isGreen: boolean }>` + height: 3.1rem; + background-color: ${(props) => (props.$isGreen ? LightGreen : LightRed)}; + display: flex; + justify-content: center; + align-items: center; + border-radius: 0.8rem; +`; + +const CommentCard = styled.div` + display: flex; + position: relative; + border-radius: 1.2rem; + box-sizing: border-box; + padding: 1.2rem 1.6rem; + flex-direction: column; + align-items: flex-start; + background-color: ${Grey6}; + gap: 1rem; + .flex1 { + display: flex; + width: 100%; + gap: 0.8rem; + height: 3.3rem; + align-items: center; + } +`; + +const LikeButton = styled.div` + display: flex; + border-radius: 0.8rem; + background-color: white; + padding: 0.4rem 0.8rem 0.4rem 0.4rem; + align-items: center; + gap: 0.4rem; +`; + +const Circle = styled.div` + width: 0.2rem; + height: 0.2rem; + border-radius: 100%; + background-color: ${Grey3}; +`; + +const SettingButton = styled(SettingIcon)` + position: absolute; + top: 2.65rem; + right: 2rem; +`; + +export default CommentListSection; diff --git a/src/components/Seller/SellerOpenConsult/IsSendPopup.tsx b/src/components/Seller/SellerOpenConsult/IsSendPopup.tsx new file mode 100644 index 00000000..557127c0 --- /dev/null +++ b/src/components/Seller/SellerOpenConsult/IsSendPopup.tsx @@ -0,0 +1,96 @@ +import React from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useSetRecoilState } from 'recoil'; +import styled from 'styled-components'; +import { Green, Grey4, LightGreen, White } from 'styles/color'; +import { Body1, Body3 } from 'styles/font'; +import { isSendPopupOpenState } from 'utils/atom'; + +function IsSendPopup() { + const navigate = useNavigate(); + const setIsSendPopupOpen = useSetRecoilState(isSendPopupOpenState); + const handleSendContent = () => {}; + return ( + + + 설정을 저장하지 않고 나가시겠습니까? + 저장하지 않으면 작성한 설정이 초기화됩니다. + + { + setIsSendPopupOpen(false); + }} + > + 아니오 + + + + + + ); +} +const IsSendModalBox = styled.div` + width: 100%; + height: 15rem; + z-index: 9999; + display: flex; + justify-content: center; + position: absolute; + top: 22.3rem; + @media (max-width: 767px) { + width: 100vw; + } + @media (min-width: 768px) { + width: 37.5rem; + } +`; + +const ModalBox = styled.div` + background: ${White}; + padding: 2rem; + border-radius: 1.2rem; + box-sizing: border-box; + padding: 1.6rem; + display: flex; + flex-direction: column; + align-items: center; + box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.1); + text-align: center; +`; + +const ButtonWrapper = styled.div` + margin-top: 2rem; + display: flex; + gap: 0.7rem; + font-size: 1.6rem; + font-weight: 600; +`; + +const NoButton = styled.div` + display: flex; + width: 14.8rem; + height: 5.2rem; + cursor: pointer; + border-radius: 0.8rem; + padding: 1.7rem 0rem 1.5rem 0rem; + justify-content: center; + align-items: center; + color: ${Green}; + background-color: ${LightGreen}; + box-sizing: border-box; +`; + +const YesButton = styled.div` + display: flex; + width: 14.8rem; + height: 5.2rem; + border-radius: 0.8rem; + padding: 1.7rem 0rem 1.5rem 0rem; + cursor: pointer; + justify-content: center; + align-items: center; + color: ${White}; + background-color: ${Green}; + box-sizing: border-box; +`; +export default IsSendPopup; diff --git a/src/components/Seller/SellerOpenConsult/MainQuestionSection.tsx b/src/components/Seller/SellerOpenConsult/MainQuestionSection.tsx index bfb26528..c8089dbc 100644 --- a/src/components/Seller/SellerOpenConsult/MainQuestionSection.tsx +++ b/src/components/Seller/SellerOpenConsult/MainQuestionSection.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import styled from 'styled-components'; import { Grey1, Grey2, Grey3, Grey6 } from 'styles/color'; import { ReactComponent as LockIcon } from 'assets/icons/icon-lock.svg'; @@ -11,6 +11,8 @@ import { ReactComponent as CheckIcon } from 'assets/icons/icon-check2.svg'; import { Body1, Caption1, Caption2 } from 'styles/font'; import { Space } from 'components/Common/Space'; function MainQuestionSection() { + const [isSave, setIsSave] = useState(false); + const [isLike, setIsLike] = useState(false); return ( @@ -39,11 +41,37 @@ function MainQuestionSection() { - + {isLike ? ( + { + setIsLike(false); + }} + /> + ) : ( + { + setIsLike(true); + }} + /> + )} + 11 - + {isSave ? ( + { + setIsSave(false); + }} + /> + ) : ( + { + setIsSave(true); + }} + /> + )} + 0 @@ -108,4 +136,8 @@ const ButtonItem = styled.div` gap: 0.4rem; `; +const SaveResizeIcon = styled(SaveIcon)` + width: 2rem; + height: 2rem; +`; export default MainQuestionSection; diff --git a/src/components/Seller/SellerOpenConsult/S= b/src/components/Seller/SellerOpenConsult/S= new file mode 100644 index 00000000..991aa1a5 --- /dev/null +++ b/src/components/Seller/SellerOpenConsult/S= @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/pages/Seller/SellerOpenConsult.tsx b/src/pages/Seller/SellerOpenConsult.tsx index 2b3af7f1..51c50494 100644 --- a/src/pages/Seller/SellerOpenConsult.tsx +++ b/src/pages/Seller/SellerOpenConsult.tsx @@ -1,13 +1,29 @@ +import { BackDrop } from 'components/Common/BackDrop'; +import BottomSection from 'components/Seller/SellerOpenConsult/BottomSection'; +import CommentListSection from 'components/Seller/SellerOpenConsult/CommentListSection'; +import IsSendPopup from 'components/Seller/SellerOpenConsult/IsSendPopup'; import MainQuestionSection from 'components/Seller/SellerOpenConsult/MainQuestionSection'; import MainQuestion from 'components/Seller/SellerOpenConsult/MainQuestionSection'; import OpenConsultHeader from 'components/Seller/SellerOpenConsult/OpenConsultHeader'; import React from 'react'; +import { useRecoilValue } from 'recoil'; +import { isSendPopupOpenState } from 'utils/atom'; function SellerOpenConsult() { + const isSendPopupOpen = useRecoilValue(isSendPopupOpenState); + return ( <> + + + {isSendPopupOpen && ( + <> + + + + )} ); } diff --git a/src/utils/atom.ts b/src/utils/atom.ts index e44c0f1f..af6bc515 100644 --- a/src/utils/atom.ts +++ b/src/utils/atom.ts @@ -44,6 +44,11 @@ export const isOutPopupOpenState = atom({ default: false, }); +export const isSendPopupOpenState = atom({ + key: 'isOutPopupOpenState', + default: false, +}); + export const isSuccessUpdateState = atom({ key: 'isSuccessUpdateState', default: false,