From 3a8a641b823c683bba7a68640059e626e798a578 Mon Sep 17 00:00:00 2001 From: joojjang Date: Wed, 2 Oct 2024 23:52:42 +0900 Subject: [PATCH 01/20] =?UTF-8?q?refactor(challenge-record):=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=EB=90=98=EB=8A=94=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/challenge-record/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/challenge-record/index.tsx b/src/pages/challenge-record/index.tsx index 9643f4d..369dbc3 100644 --- a/src/pages/challenge-record/index.tsx +++ b/src/pages/challenge-record/index.tsx @@ -13,7 +13,7 @@ import styled from '@emotion/styled'; const ChallengeRecord = () => { // ?id=:id&category=:category&title=:title const [searchParams] = useSearchParams(); - const challengeId = searchParams.get('id') || ''; + const challengeId = Number(searchParams.get('id')) || 0; const challengeCategory = searchParams.get('category') || ''; const challengeTitle = searchParams.get('title') || ''; @@ -25,11 +25,11 @@ const ChallengeRecord = () => { const tabsList = [ { label: '인증 기록', - panel: , + panel: , }, { label: '인증하기', - panel: , + panel: , }, ]; From 89230f1f94a5746bbdb3b90ff1a377404e3de6f1 Mon Sep 17 00:00:00 2001 From: joojjang Date: Thu, 3 Oct 2024 00:02:08 +0900 Subject: [PATCH 02/20] =?UTF-8?q?fix(verification):=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=20=EB=93=B1=EB=A1=9D=20=EC=84=B1=EA=B3=B5=20=EC=8B=9C=20?= =?UTF-8?q?=ED=8F=BC=20=EB=82=B4=EC=9A=A9=20=EC=B4=88=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/challenge-record/verification/index.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/challenge-record/verification/index.tsx b/src/pages/challenge-record/verification/index.tsx index 56bd084..3beacdc 100644 --- a/src/pages/challenge-record/verification/index.tsx +++ b/src/pages/challenge-record/verification/index.tsx @@ -76,6 +76,10 @@ const Verification = ({ challengeId }: VerificationProps) => { postVerification(challengeId, content, image) .then(() => { alert('챌린지 인증이 등록되었습니다!'); + + // 폼 내용 초기화 + setContent(''); + setImage(null); handleSelectedTab(0); // 인증 기록 탭으로 이동 }) .catch((error) => { From 53bdf4164a1aa21137f6b9fb9cb3ff1cbcde37fa Mon Sep 17 00:00:00 2001 From: joojjang Date: Thu, 3 Oct 2024 00:13:00 +0900 Subject: [PATCH 03/20] =?UTF-8?q?feat(verification):=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=20=EB=93=B1=EB=A1=9D=20=EC=84=B1=EA=B3=B5=20=EC=8B=9C=20?= =?UTF-8?q?=ED=83=AD=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 부모 컴포넌트의 setActiveTab을 인증하기 탭(Verification)에 prop으로 전달 --- src/pages/challenge-record/index.tsx | 4 +++- src/pages/challenge-record/verification/index.tsx | 15 +++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/pages/challenge-record/index.tsx b/src/pages/challenge-record/index.tsx index 369dbc3..4dd5c84 100644 --- a/src/pages/challenge-record/index.tsx +++ b/src/pages/challenge-record/index.tsx @@ -29,7 +29,9 @@ const ChallengeRecord = () => { }, { label: '인증하기', - panel: , + panel: ( + + ), }, ]; diff --git a/src/pages/challenge-record/verification/index.tsx b/src/pages/challenge-record/verification/index.tsx index 3beacdc..3754c40 100644 --- a/src/pages/challenge-record/verification/index.tsx +++ b/src/pages/challenge-record/verification/index.tsx @@ -11,9 +11,12 @@ import styled from '@emotion/styled'; const MIN_CONTENT_LENGTH = 20; -type VerificationProps = { challengeId: number }; +type VerificationProps = { + challengeId: number; + setActiveTab: (value: number) => void; +}; -const Verification = ({ challengeId }: VerificationProps) => { +const Verification = ({ challengeId, setActiveTab }: VerificationProps) => { const fileInput = useRef(null); const [content, setContent] = useState(''); const [isContentValid, setIsContentValid] = useState(true); @@ -80,7 +83,8 @@ const Verification = ({ challengeId }: VerificationProps) => { // 폼 내용 초기화 setContent(''); setImage(null); - handleSelectedTab(0); // 인증 기록 탭으로 이동 + // 인증 기록 탭으로 이동 + setActiveTab(0); }) .catch((error) => { // API에서 받은 오류 객체일 경우 @@ -94,11 +98,6 @@ const Verification = ({ challengeId }: VerificationProps) => { } }; - const handleSelectedTab = (value: number) => { - // setActiveTab(value as 0 | 1); - sessionStorage.setItem('activeTab', String(value)); - }; - return ( <> From 6dae59a6c7bf9503182a24a268b28a03036efa82 Mon Sep 17 00:00:00 2001 From: joojjang Date: Thu, 3 Oct 2024 00:15:58 +0900 Subject: [PATCH 04/20] =?UTF-8?q?fix(verification):=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=20=EB=93=B1=EB=A1=9D=20=EC=99=84=EB=A3=8C=20=EC=8B=9C=20?= =?UTF-8?q?=EC=83=88=EB=A1=9C=EA=B3=A0=EC=B9=A8=ED=95=98=EC=97=AC=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=83=88=EB=A1=9C=20=ED=8E=98?= =?UTF-8?q?=EC=B9=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/challenge-record/verification/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/challenge-record/verification/index.tsx b/src/pages/challenge-record/verification/index.tsx index 3754c40..dffbeab 100644 --- a/src/pages/challenge-record/verification/index.tsx +++ b/src/pages/challenge-record/verification/index.tsx @@ -83,8 +83,9 @@ const Verification = ({ challengeId, setActiveTab }: VerificationProps) => { // 폼 내용 초기화 setContent(''); setImage(null); - // 인증 기록 탭으로 이동 + // 인증 기록 탭으로 변경 및 새로고침하여 데이터 새로 페칭 setActiveTab(0); + window.location.reload(); }) .catch((error) => { // API에서 받은 오류 객체일 경우 From ea2f74b04edd8423920833d55caeabb3f67bb497 Mon Sep 17 00:00:00 2001 From: joojjang Date: Thu, 3 Oct 2024 01:16:06 +0900 Subject: [PATCH 05/20] =?UTF-8?q?feat(tooltip):=20=EA=B3=B5=ED=86=B5?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20tooltip=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84,=20=EA=B8=B0=EB=A1=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EC=8A=A4=ED=83=AC=ED=94=84=20=EC=9C=84=EC=97=90=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/StampActive.svg | 27 ---- src/assets/StampInactive.svg | 10 -- .../common/form/textarea/tooltip/index.tsx | 148 ++++++++++++++++++ src/pages/challenge-record/records/index.tsx | 27 ++-- 4 files changed, 166 insertions(+), 46 deletions(-) delete mode 100644 src/assets/StampActive.svg delete mode 100644 src/assets/StampInactive.svg create mode 100644 src/components/common/form/textarea/tooltip/index.tsx diff --git a/src/assets/StampActive.svg b/src/assets/StampActive.svg deleted file mode 100644 index 4495033..0000000 --- a/src/assets/StampActive.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/assets/StampInactive.svg b/src/assets/StampInactive.svg deleted file mode 100644 index ba46a34..0000000 --- a/src/assets/StampInactive.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/components/common/form/textarea/tooltip/index.tsx b/src/components/common/form/textarea/tooltip/index.tsx new file mode 100644 index 0000000..cff16bd --- /dev/null +++ b/src/components/common/form/textarea/tooltip/index.tsx @@ -0,0 +1,148 @@ +import { useState } from 'react'; +import { IoCloseOutline } from 'react-icons/io5'; + +import styled from '@emotion/styled'; + +interface TooltipProps { + content: string; + children: React.ReactNode; + direction?: 'top' | 'right' | 'bottom' | 'left'; +} + +const Tooltip = ({ content, children, direction = 'top' }: TooltipProps) => { + const [isVisible, setIsVisible] = useState(true); + + const handleClose = () => { + setIsVisible(false); + }; + + return ( + + {children} + {isVisible && ( + + {content} + + + + + )} + + ); +}; + +export default Tooltip; + +// 스타일 정의 + +const TOOLTIP_COLOR = `var(--color-green-03)`; + +const TooltipWrapper = styled.div` + position: relative; + display: inline-block; +`; + +const TooltipBox = styled.div<{ direction: string }>` + position: absolute; + padding: 3px 6px; + border-radius: 4px; + background-color: ${TOOLTIP_COLOR}; + color: var(--color-white); + font-size: 12px; + font-weight: 500; + white-space: nowrap; + z-index: 10; + display: flex; + align-items: center; + + ${({ direction }) => + direction === 'top' && + ` + bottom: 100%; + left: 50%; + transform: translateX(-50%); + margin-bottom: 8px; + `} + + ${({ direction }) => + direction === 'right' && + ` + top: 50%; + left: 100%; + transform: translateY(-50%); + margin-left: 8px; + `} + + ${({ direction }) => + direction === 'bottom' && + ` + top: 100%; + left: 50%; + transform: translateX(-50%); + margin-top: 8px; + `} + + ${({ direction }) => + direction === 'left' && + ` + top: 50%; + right: 100%; + transform: translateY(-50%); + margin-right: 8px; + `} + + // 꼬리 부분 + ::after { + content: ''; + position: absolute; + border-style: solid; + + ${({ direction }) => + direction === 'top' && + ` + top: 100%; + left: 50%; + transform: translateX(-50%); + border-width: 8px 6px 0 6px; + border-color: ${TOOLTIP_COLOR} transparent transparent transparent; + `} + + ${({ direction }) => + direction === 'right' && + ` + top: 50%; + left: 0; + transform: translateY(-50%); + border-width: 8px 6px 6px 0; + border-color: transparent ${TOOLTIP_COLOR} transparent transparent; + `} + + ${({ direction }) => + direction === 'bottom' && + ` + bottom: 100%; + left: 50%; + transform: translateX(-50%); + border-width: 0 6px 8px 6px; + border-color: transparent transparent ${TOOLTIP_COLOR} transparent; + `} + + ${({ direction }) => + direction === 'left' && + ` + top: 50%; + right: 0; + transform: translateY(-50%); + border-width: 6px 0 8px 6px; + border-color: transparent transparent transparent ${TOOLTIP_COLOR}; + `} + } +`; + +const CloseButton = styled.button` + background: transparent; + border: none; + color: var(--color-white); + cursor: pointer; + margin-left: 6px; +`; diff --git a/src/pages/challenge-record/records/index.tsx b/src/pages/challenge-record/records/index.tsx index 01ee353..3ff5612 100644 --- a/src/pages/challenge-record/records/index.tsx +++ b/src/pages/challenge-record/records/index.tsx @@ -12,6 +12,7 @@ import { ChallengeRecordData, ChallengeRecordDetailData, } from '@/apis/challenge-record/challenge.record.response'; +import Tooltip from '@/components/common/form/textarea/tooltip'; import { formatDate } from '@/utils/formatters'; import { Text } from '@chakra-ui/react'; import styled from '@emotion/styled'; @@ -118,15 +119,23 @@ const Records = ({ challengeId }: RecordsProps) => { - {recordIdList.map((recordId, index) => ( - { - handleStampClick(recordId); - }} - /> - ))} + {recordIdList.map((recordId, index) => + // 첫 번째 스탬프가 채워져있을 때 툴팁 표시 + index === 0 && recordId !== -1 ? ( + + handleStampClick(recordId)} + /> + + ) : ( + handleStampClick(recordId)} + /> + ) + )} )} From 0cebfd80a82e072b24c4c6ad673868f89a1d6e3d Mon Sep 17 00:00:00 2001 From: joojjang Date: Thu, 3 Oct 2024 01:17:08 +0900 Subject: [PATCH 06/20] =?UTF-8?q?design(verification):=20=EC=82=AC?= =?UTF-8?q?=EC=A7=84=20=EC=82=AD=EC=A0=9C=20=EC=95=84=EC=9D=B4=EC=BD=98=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/challenge-record/verification/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/challenge-record/verification/index.tsx b/src/pages/challenge-record/verification/index.tsx index dffbeab..81c8617 100644 --- a/src/pages/challenge-record/verification/index.tsx +++ b/src/pages/challenge-record/verification/index.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'react'; -import { MdDeleteForever } from 'react-icons/md'; +import { IoClose } from 'react-icons/io5'; // import { useParams } from 'react-router-dom'; import Caution from '../components/caution'; @@ -113,7 +113,7 @@ const Verification = ({ challengeId, setActiveTab }: VerificationProps) => { - + )} From 98756003442c30932f918ea80d9c9246b79d26e3 Mon Sep 17 00:00:00 2001 From: joojjang Date: Thu, 3 Oct 2024 01:18:59 +0900 Subject: [PATCH 07/20] =?UTF-8?q?feat(tooltip):=20=ED=83=80=EC=9E=84=20?= =?UTF-8?q?=EC=95=84=EC=9B=83=20=ED=9B=84=20=EC=9E=90=EB=8F=99=20=EB=8B=AB?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/form/textarea/tooltip/index.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/common/form/textarea/tooltip/index.tsx b/src/components/common/form/textarea/tooltip/index.tsx index cff16bd..ecd13ad 100644 --- a/src/components/common/form/textarea/tooltip/index.tsx +++ b/src/components/common/form/textarea/tooltip/index.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { IoCloseOutline } from 'react-icons/io5'; import styled from '@emotion/styled'; @@ -12,6 +12,15 @@ interface TooltipProps { const Tooltip = ({ content, children, direction = 'top' }: TooltipProps) => { const [isVisible, setIsVisible] = useState(true); + // 툴팁 자동 닫기 + useEffect(() => { + const timer = setTimeout(() => { + setIsVisible(false); + }, 5000); + + return () => clearTimeout(timer); // 컴포넌트 언마운트 시 타이머 정리 + }, []); + const handleClose = () => { setIsVisible(false); }; From 08d22c523a91166b4d3f6fa4f9d98cf3e444d839 Mon Sep 17 00:00:00 2001 From: joojjang Date: Thu, 3 Oct 2024 01:43:58 +0900 Subject: [PATCH 08/20] =?UTF-8?q?refactor(empty-state):=20=EA=B3=B5?= =?UTF-8?q?=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A1=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/empty-state/index.tsx | 28 +++++++++++++++++++ .../ranking-section/index.tsx | 18 ++++++------ .../ranking-section/styles.ts | 6 ---- .../challenge-detail/review-section/index.tsx | 18 ++++++------ 4 files changed, 46 insertions(+), 24 deletions(-) create mode 100644 src/components/common/empty-state/index.tsx diff --git a/src/components/common/empty-state/index.tsx b/src/components/common/empty-state/index.tsx new file mode 100644 index 0000000..cb4d9b2 --- /dev/null +++ b/src/components/common/empty-state/index.tsx @@ -0,0 +1,28 @@ +import { forwardRef } from 'react'; + +import styled from '@emotion/styled'; + +interface EmptyStateProps { + children: React.ReactNode; // children의 타입 정의 +} + +// ref를 전달하기 위해 forwardRef 사용 +const EmptyState = forwardRef( + ({ children }, ref) => { + return {children}; + } +); + +EmptyState.displayName = 'EmptyState'; + +export default EmptyState; + +// 스타일 정의 +const Wrapper = styled.div` + font-size: var(--font-size-md); + + .highlight { + font-weight: 600; + color: var(--color-green-03); + } +`; diff --git a/src/pages/challenge-detail/ranking-section/index.tsx b/src/pages/challenge-detail/ranking-section/index.tsx index f98adea..0146f21 100644 --- a/src/pages/challenge-detail/ranking-section/index.tsx +++ b/src/pages/challenge-detail/ranking-section/index.tsx @@ -5,6 +5,7 @@ import { RankingItem } from '../components/ranking-item/'; import * as S from './styles'; import { getChallengeRanking } from '@/apis/challenge-detail/challenge.ranking.api'; import { type ChallengeRankingData } from '@/apis/challenge-detail/challenge.ranking.response'; +import EmptyState from '@/components/common/empty-state'; import * as Base from '@/styles/baseStyles'; type RankingSectionProps = { @@ -67,16 +68,15 @@ export const RankingSection = ({ id }: RankingSectionProps) => { ) : ( // 랭킹 없을 때 - - 아직 챌린지를 성공한 유저가 없습니다.
- 챌린지에 참여해{' '} - - 첫 번째 완료자 - - 가 되어보세요! -
+ + + 아직 챌린지를 성공한 유저가 없습니다.
+ 챌린지에 참여해 첫 번째 완료자가 + 되어보세요! +
+
)} - {isFetching ? '로딩 중...' : ' '} + {isFetching ? '로딩 중...' : ' '} ); }; diff --git a/src/pages/challenge-detail/ranking-section/styles.ts b/src/pages/challenge-detail/ranking-section/styles.ts index 8f719bb..17cb971 100644 --- a/src/pages/challenge-detail/ranking-section/styles.ts +++ b/src/pages/challenge-detail/ranking-section/styles.ts @@ -1,11 +1,5 @@ import styled from '@emotion/styled'; -export const Text = styled.span<{ fontWeight?: string; color?: string }>` - font-size: var(--font-size-md); - font-weight: ${(props) => props.fontWeight || null}; - color: ${(props) => props.color || null}; -`; - export const Wrapper = styled.div` padding: 16px 16px; display: flex; diff --git a/src/pages/challenge-detail/review-section/index.tsx b/src/pages/challenge-detail/review-section/index.tsx index f1ca71d..d5f6edb 100644 --- a/src/pages/challenge-detail/review-section/index.tsx +++ b/src/pages/challenge-detail/review-section/index.tsx @@ -5,6 +5,7 @@ import { useNavigate } from 'react-router-dom'; import * as S from './styles'; import { getReview, getChallegeAvgScore } from '@/apis/review/review.api'; import { type ReviewData } from '@/apis/review/review.response'; +import EmptyState from '@/components/common/empty-state'; import { StarRating } from '@/components/common/star-rating'; import ReviewItem from '@/pages/review/components/review-item'; import { RouterPath } from '@/routes/path'; @@ -91,15 +92,14 @@ export const ReviewSection = ({ id, category, title }: ReviewSectionProps) => { ) : ( // 리뷰 없을 때 - - 아직 리뷰가 없습니다. -
- 챌린지를 완료하고{' '} - - 첫 번째 리뷰어 - - 가 되어보세요! -
+ + + 아직 리뷰가 없습니다. +
+ 챌린지를 완료하고 첫 번째 리뷰어 + 가 되어보세요! +
+
)} ); From 4e7ab44faf1d0a30bf7d2edaf153d17531192018 Mon Sep 17 00:00:00 2001 From: joojjang Date: Thu, 3 Oct 2024 01:44:49 +0900 Subject: [PATCH 09/20] =?UTF-8?q?remove(empty-state):=20=EC=A3=BC=EC=84=9D?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/empty-state/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/common/empty-state/index.tsx b/src/components/common/empty-state/index.tsx index cb4d9b2..647090d 100644 --- a/src/components/common/empty-state/index.tsx +++ b/src/components/common/empty-state/index.tsx @@ -3,7 +3,7 @@ import { forwardRef } from 'react'; import styled from '@emotion/styled'; interface EmptyStateProps { - children: React.ReactNode; // children의 타입 정의 + children: React.ReactNode; } // ref를 전달하기 위해 forwardRef 사용 From 0fbebf551eb7af76c3d0837a07e9f9bbd99e3d41 Mon Sep 17 00:00:00 2001 From: joojjang Date: Thu, 3 Oct 2024 02:35:44 +0900 Subject: [PATCH 10/20] =?UTF-8?q?feat(verification):=20=EC=B1=8C=EB=A6=B0?= =?UTF-8?q?=EC=A7=80=20=EC=99=84=EB=A3=8C=20=EC=8B=9C,=20=EC=B0=B8?= =?UTF-8?q?=EC=97=AC=20=EA=B8=B0=EA=B0=84=20=EC=A2=85=EB=A3=8C=20=EC=8B=9C?= =?UTF-8?q?=20empty=20state=20=EB=A0=8C=EB=8D=94=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/empty-state/index.tsx | 5 + src/pages/challenge-record/index.tsx | 23 ++++- src/pages/challenge-record/records/index.tsx | 15 ++- .../challenge-record/verification/index.tsx | 93 ++++++++++++------- 4 files changed, 101 insertions(+), 35 deletions(-) diff --git a/src/components/common/empty-state/index.tsx b/src/components/common/empty-state/index.tsx index 647090d..2d6e5e9 100644 --- a/src/components/common/empty-state/index.tsx +++ b/src/components/common/empty-state/index.tsx @@ -19,6 +19,11 @@ export default EmptyState; // 스타일 정의 const Wrapper = styled.div` + display: flex; + justify-content: center; + align-items: center; + flex: 1; + padding: 0 16px; font-size: var(--font-size-md); .highlight { diff --git a/src/pages/challenge-record/index.tsx b/src/pages/challenge-record/index.tsx index 4dd5c84..eac55d7 100644 --- a/src/pages/challenge-record/index.tsx +++ b/src/pages/challenge-record/index.tsx @@ -22,15 +22,34 @@ const ChallengeRecord = () => { const savedTab = sessionStorage.getItem('activeTab'); return savedTab ? Number(savedTab) : 0; }); + + // Records -> Verification으로 비동기 데이터 전달 + const [successCount, setSuccessCount] = useState(0); + const [totalCount, setTotalCount] = useState(0); + const [endDate, setEndDate] = useState(''); + const tabsList = [ { label: '인증 기록', - panel: , + panel: ( + + ), }, { label: '인증하기', panel: ( - + ), }, ]; diff --git a/src/pages/challenge-record/records/index.tsx b/src/pages/challenge-record/records/index.tsx index 3ff5612..80b0025 100644 --- a/src/pages/challenge-record/records/index.tsx +++ b/src/pages/challenge-record/records/index.tsx @@ -17,9 +17,18 @@ import { formatDate } from '@/utils/formatters'; import { Text } from '@chakra-ui/react'; import styled from '@emotion/styled'; -type RecordsProps = { challengeId: number }; +type RecordsProps = { + challengeId: number; + setSuccessCount: (count: number) => void; + setTotalCount: (count: number) => void; + setEndDate: (date: string) => void; +}; -const Records = ({ challengeId }: RecordsProps) => { +const Records = ({ + challengeId, + setSuccessCount, + setTotalCount, +}: RecordsProps) => { const [data, setData] = useState(); // api 응답 데이터 전체 const [recordIdList, setRecordIdList] = useState([]); const [recordDetails, setRecordDetails] = @@ -41,6 +50,8 @@ const Records = ({ challengeId }: RecordsProps) => { .then((res) => { setData(res); fillRecordList(res.totalCount, res.recordIds); + setSuccessCount(res.successCount); + setTotalCount(res.totalCount); }) .catch((error) => { console.error('Error fetching records:', error); diff --git a/src/pages/challenge-record/verification/index.tsx b/src/pages/challenge-record/verification/index.tsx index 81c8617..2a2b46e 100644 --- a/src/pages/challenge-record/verification/index.tsx +++ b/src/pages/challenge-record/verification/index.tsx @@ -5,8 +5,9 @@ import { IoClose } from 'react-icons/io5'; import Caution from '../components/caution'; import { postVerification } from '@/apis/challenge-record/challenge.record.api'; import CTA, { CTAContainer } from '@/components/common/cta'; +import EmptyState from '@/components/common/empty-state'; import Textarea from '@/components/common/form/textarea'; -import { Image } from '@chakra-ui/react'; +import { Box, Image } from '@chakra-ui/react'; import styled from '@emotion/styled'; const MIN_CONTENT_LENGTH = 20; @@ -14,14 +15,25 @@ const MIN_CONTENT_LENGTH = 20; type VerificationProps = { challengeId: number; setActiveTab: (value: number) => void; + successCount: number; + totalCount: number; + endDate: string; }; -const Verification = ({ challengeId, setActiveTab }: VerificationProps) => { +const Verification = ({ + challengeId, + setActiveTab, + successCount, + totalCount, + endDate, +}: VerificationProps) => { const fileInput = useRef(null); const [content, setContent] = useState(''); const [isContentValid, setIsContentValid] = useState(true); const [image, setImage] = useState(null); const [isUploadDisabled, setIsUploadDisabled] = useState(true); + const endDateInDate = new Date(endDate); + const todayDate = new Date(); // 폼 유효성 검사 -> 버튼 상태 관리 useEffect(() => { @@ -102,35 +114,55 @@ const Verification = ({ challengeId, setActiveTab }: VerificationProps) => { return ( <> -