From 6b72d98cc98eeaddd6b4d239a3663480c5abcbe2 Mon Sep 17 00:00:00 2001 From: Yeonseo-Jo Date: Sun, 20 Oct 2024 22:06:02 +0900 Subject: [PATCH] =?UTF-8?q?fix=20:=20validate=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=82=B4=EB=B6=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/stepLayout/AddGuideFirstKr.tsx | 16 +++- .../stepLayout/AddGuideSecondKr.tsx | 22 ++++- src/AddOkr/components/stepLayout/AddKr.tsx | 16 +++- .../components/stepLayout/ObjContent.tsx | 8 +- .../components/stepLayout/ObjPeriod.tsx | 14 +++- .../components/stepLayout/ObjTitleCateg.tsx | 8 +- src/AddOkr/index.tsx | 80 ++++--------------- src/AddOkr/types/KrInfoTypes.ts | 1 + src/AddOkr/types/ObjectInfoTypes.ts | 1 + 9 files changed, 92 insertions(+), 74 deletions(-) diff --git a/src/AddOkr/components/stepLayout/AddGuideFirstKr.tsx b/src/AddOkr/components/stepLayout/AddGuideFirstKr.tsx index f33c50d1..b60f1b13 100644 --- a/src/AddOkr/components/stepLayout/AddGuideFirstKr.tsx +++ b/src/AddOkr/components/stepLayout/AddGuideFirstKr.tsx @@ -1,6 +1,6 @@ import { css } from '@emotion/react'; import styled from '@emotion/styled'; -import React from 'react'; +import React, { useEffect } from 'react'; import { AddOkrCardWrapper } from '../../styles/KeyResultCardStyle'; import { IAddKrFlowProps } from '../../types/KrInfoTypes'; @@ -16,11 +16,25 @@ const AddGuideFirstKr = ({ handleClickCloseBtn, krListInfo, setKrListInfo, + onValidateNextStep, }: IAddKrFlowProps) => { const { objTitle } = objInfo; const plusCardLength = Array.from({ length: MAX_KR_LENGTH - 1 }, (_, i) => i + 1); + useEffect(() => { + const isValid = + krListInfo.filter((kr) => { + return clickedCard.includes(kr.krIdx); + }).length === + krListInfo.filter((kr) => { + const { krTitle, krStartAt, krExpireAt } = kr; + return krTitle && krStartAt && krExpireAt; + }).length; + + onValidateNextStep(isValid); + }, [krListInfo, clickedCard]); + return (
diff --git a/src/AddOkr/components/stepLayout/AddGuideSecondKr.tsx b/src/AddOkr/components/stepLayout/AddGuideSecondKr.tsx index 9e45f43e..13dbade6 100644 --- a/src/AddOkr/components/stepLayout/AddGuideSecondKr.tsx +++ b/src/AddOkr/components/stepLayout/AddGuideSecondKr.tsx @@ -1,14 +1,34 @@ import { css } from '@emotion/react'; import styled from '@emotion/styled'; +import { useEffect } from 'react'; import { AddOkrCardWrapper, EmptyKeyResultCard } from '../../styles/KeyResultCardStyle'; import { IAddKrFlowProps } from '../../types/KrInfoTypes'; import GuideSecondKeyResultCard from '../addKr/GuideSecondKeyResultCard'; -const AddGuideSecondKr = ({ objInfo, clickedCard, krListInfo, setKrListInfo }: IAddKrFlowProps) => { +const AddGuideSecondKr = ({ + objInfo, + clickedCard, + krListInfo, + setKrListInfo, + onValidateNextStep, +}: IAddKrFlowProps) => { const { objTitle } = objInfo; const secondKrList = [0, 1, 2]; + useEffect(() => { + const isValid = + krListInfo.filter((kr) => { + return clickedCard.includes(kr.krIdx); + }).length === + krListInfo.filter((kr) => { + const { krTarget, krMetric } = kr; + return krTarget && krMetric; + }).length; + + onValidateNextStep(isValid); + }, [krListInfo, clickedCard]); + return (
diff --git a/src/AddOkr/components/stepLayout/AddKr.tsx b/src/AddOkr/components/stepLayout/AddKr.tsx index e5ca11df..a0833562 100644 --- a/src/AddOkr/components/stepLayout/AddKr.tsx +++ b/src/AddOkr/components/stepLayout/AddKr.tsx @@ -1,5 +1,5 @@ import styled from '@emotion/styled'; -import React from 'react'; +import React, { useEffect } from 'react'; import { AddOkrCardWrapper } from '../../styles/KeyResultCardStyle'; import { IAddKrFlowProps } from '../../types/KrInfoTypes'; @@ -15,9 +15,23 @@ const AddKr = ({ handleClickCloseBtn, krListInfo, setKrListInfo, + onValidateNextStep, }: IAddKrFlowProps) => { const { objTitle } = objInfo; + useEffect(() => { + const isValid = + krListInfo.filter((kr) => { + return clickedCard.includes(kr.krIdx); + }).length === + krListInfo.filter((kr) => { + const { krTitle, krTarget, krMetric, krStartAt, krExpireAt } = kr; + return krTitle && krTarget && krMetric && krStartAt && krExpireAt; + }).length; + + onValidateNextStep(isValid); + }, [krListInfo, clickedCard]); + const renderKrCards = () => { const plusCardLength = Array.from({ length: MAX_KR_LENGTH - 1 }, (_, i) => i + 1); return ( diff --git a/src/AddOkr/components/stepLayout/ObjContent.tsx b/src/AddOkr/components/stepLayout/ObjContent.tsx index 63a78f19..d7d4aac3 100644 --- a/src/AddOkr/components/stepLayout/ObjContent.tsx +++ b/src/AddOkr/components/stepLayout/ObjContent.tsx @@ -1,7 +1,7 @@ import { css } from '@emotion/react'; import styled from '@emotion/styled'; import { limitMaxLength } from '@utils/limitMaxLength'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { MAX_OBJ_CONTENT } from '../../constants/OKR_MAX_LENGTH'; import { IAddObjFlowProps } from '../../types/ObjectInfoTypes'; @@ -10,7 +10,7 @@ import { IAddObjFlowProps } from '../../types/ObjectInfoTypes'; const OBJ_CONTENT_PLACEHOLDER = 'ex) 퇴근 후 누워있기만 하지 말고, 내가 원하는 일을 하며 시간을 알차게 쓰고 싶다.'; -const ObjContent = ({ objInfo, setObjInfo }: IAddObjFlowProps) => { +const ObjContent = ({ objInfo, setObjInfo, onValidNextStep }: IAddObjFlowProps) => { const { objContent } = objInfo; // 글자 수 저장 값 const [currContentCnt, setCurrContentCnt] = useState(objContent ? objContent.length : 0); @@ -24,6 +24,10 @@ const ObjContent = ({ objInfo, setObjInfo }: IAddObjFlowProps) => { setObjInfo({ ...objInfo, objContent: e.target.value }); }; + useEffect(() => { + onValidNextStep(!!objContent); + }, [objContent]); + return (
목표를 달성하고 싶은 이유와 다짐을 기록해주세요 diff --git a/src/AddOkr/components/stepLayout/ObjPeriod.tsx b/src/AddOkr/components/stepLayout/ObjPeriod.tsx index 93fa832a..8d2dbd58 100644 --- a/src/AddOkr/components/stepLayout/ObjPeriod.tsx +++ b/src/AddOkr/components/stepLayout/ObjPeriod.tsx @@ -1,7 +1,7 @@ import { css } from '@emotion/react'; import styled from '@emotion/styled'; import { Dayjs } from 'dayjs'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { CALE_END_DATE, CALE_START_DATE, TODAY } from '../../constants/ADD_OKR_DATES'; import { OBJ_PERIOD_LIST } from '../../constants/OBJ_PERIOD_LIST'; @@ -17,7 +17,13 @@ interface IObjPeriodProps extends IAddObjFlowProps { const DEFAULT_SELECT_PERIOD = '1'; -const ObjPeriod = ({ objInfo, setObjInfo, selectedPeriod, setSelectedPeriod }: IObjPeriodProps) => { +const ObjPeriod = ({ + objInfo, + setObjInfo, + selectedPeriod, + setSelectedPeriod, + onValidNextStep, +}: IObjPeriodProps) => { const { objStartAt, objExpireAt } = objInfo; // dayjs 캘린더에서 사용하는 선택된 기간 값 @@ -57,6 +63,10 @@ const ObjPeriod = ({ objInfo, setObjInfo, selectedPeriod, setSelectedPeriod }: I } }; + useEffect(() => { + onValidNextStep(!!objStartAt && !!objExpireAt && !!selectedPeriod); + }, [objInfo]); + return (
앞으로 몇 개월 동안 목표에 집중해볼까요? diff --git a/src/AddOkr/components/stepLayout/ObjTitleCateg.tsx b/src/AddOkr/components/stepLayout/ObjTitleCateg.tsx index 37ba63ec..2910e55d 100644 --- a/src/AddOkr/components/stepLayout/ObjTitleCateg.tsx +++ b/src/AddOkr/components/stepLayout/ObjTitleCateg.tsx @@ -1,7 +1,7 @@ import { css } from '@emotion/react'; import styled from '@emotion/styled'; import { limitMaxLength } from '@utils/limitMaxLength'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { GUIDE_OBJ_TITLE_PLACEHOLDER } from '../../constants/GUIDE_OBJ_TITLE_PLACEHOLDER'; import { OBJ_CATEG_LIST } from '../../constants/OBJ_CATEG_LIST'; @@ -16,7 +16,7 @@ interface IObjTitleCategProps extends IAddObjFlowProps { // 가이드에 따라 설정하기 기본 placeholder const GUIDE_DEFAULT_PLACEHOLDER = '목표를 입력하세요'; -const ObjTitleCateg = ({ isGuide, objInfo, setObjInfo }: IObjTitleCategProps) => { +const ObjTitleCateg = ({ isGuide, objInfo, setObjInfo, onValidNextStep }: IObjTitleCategProps) => { const { objCategory: selectedObjCateg, objTitle } = objInfo; //글자 수 관리 값 const [currObjCount, setCurrObjCount] = useState(objTitle ? objTitle.length : 0); @@ -77,6 +77,10 @@ const ObjTitleCateg = ({ isGuide, objInfo, setObjInfo }: IObjTitleCategProps) => setHoverObjPlaceHolder(targetPlaceholder); }; + useEffect(() => { + onValidNextStep(!!selectedObjCateg && !!objTitle); + }, [objInfo]); + return (
diff --git a/src/AddOkr/index.tsx b/src/AddOkr/index.tsx index 43d37c83..3df3ba82 100644 --- a/src/AddOkr/index.tsx +++ b/src/AddOkr/index.tsx @@ -1,5 +1,5 @@ import Error from '@components/Error'; -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import { useLocation } from 'react-router-dom'; import PreviewOkr from '../PreviewOkr/PreviewOkr'; @@ -52,13 +52,9 @@ const AddOkr = () => { const [isActiveNext, setIsActiveNext] = useState(false); const [objInfo, setObjInfo] = useState(resetObjInfoState); - const { objTitle, objCategory, objContent, objStartAt, objExpireAt } = objInfo; - const [krListInfo, setKrListInfo] = useState(resetKrListInfo); - // Step 2 ObjPeriod- 선택된 기간 버튼 관리 값 const [selectedPeriod, setSelectedPeriod] = useState(''); - // step 4 - kr 카드 선택 여부 관리 const [clickedCard, setClickedCard] = useState([0]); @@ -87,60 +83,8 @@ const AddOkr = () => { setKrListInfo([...krListInfo]); }; - // 이전, 다음 버튼 활성화 / 비활성화 관리 함수 - const validNextStep = () => { - switch (step) { - case 1: - objCategory && objTitle ? setIsActiveNext(true) : setIsActiveNext(false); - break; - case 2: - objStartAt && objExpireAt && selectedPeriod - ? setIsActiveNext(true) - : setIsActiveNext(false); - break; - case 3: - objContent ? setIsActiveNext(true) : setIsActiveNext(false); - break; - case 4: - // 가이드에 따라 설정 - 첫 번째 kr 카드일 때 - if (selectedMethod === IS_GUIDE) { - krListInfo.filter((kr) => { - return clickedCard.includes(kr.krIdx); - }).length === - krListInfo.filter((kr) => { - const { krTitle, krStartAt, krExpireAt } = kr; - return krTitle && krStartAt && krExpireAt; - }).length - ? setIsActiveNext(true) - : setIsActiveNext(false); - } - - // 직접 설정하기 플로우일 때 - if (selectedMethod !== IS_GUIDE) { - krListInfo.filter((kr) => { - return clickedCard.includes(kr.krIdx); - }).length === - krListInfo.filter((kr) => { - const { krTitle, krTarget, krMetric, krStartAt, krExpireAt } = kr; - return krTitle && krTarget && krMetric && krStartAt && krExpireAt; - }).length - ? setIsActiveNext(true) - : setIsActiveNext(false); - } - break; - case 5: - //가이드에 따라 설정 - 두번째 kr 카드일 떄 - krListInfo.filter((kr) => { - return clickedCard.includes(kr.krIdx); - }).length === - krListInfo.filter((kr) => { - const { krTarget, krMetric } = kr; - return krTarget && krMetric; - }).length - ? setIsActiveNext(true) - : setIsActiveNext(false); - break; - } + const handleValidNextStep = (isValid: boolean) => { + setIsActiveNext(isValid); }; // step에 따라 다른 layout 렌더링하는 함수 @@ -153,6 +97,7 @@ const AddOkr = () => { isGuide={selectedMethod === IS_GUIDE} objInfo={objInfo} setObjInfo={setObjInfo} + onValidNextStep={handleValidNextStep} /> ); case 2: @@ -163,12 +108,19 @@ const AddOkr = () => { setObjInfo={setObjInfo} selectedPeriod={selectedPeriod} setSelectedPeriod={setSelectedPeriod} + onValidNextStep={handleValidNextStep} /> ); case 3: // step 3 - O 내용 설정 - return ; + return ( + + ); case 4: // step 4 - KR 추가 (가이드에 따라 설정 첫번째 kr 카드 or 직접 설정하기) @@ -180,6 +132,7 @@ const AddOkr = () => { handleClickCloseBtn={handleClickCloseBtn} krListInfo={krListInfo} setKrListInfo={setKrListInfo} + onValidateNextStep={handleValidNextStep} /> ) : ( { handleClickCloseBtn={handleClickCloseBtn} krListInfo={krListInfo} setKrListInfo={setKrListInfo} + onValidateNextStep={handleValidNextStep} /> ); case 5: @@ -201,6 +155,7 @@ const AddOkr = () => { handleClickCloseBtn={handleClickCloseBtn} krListInfo={krListInfo} setKrListInfo={setKrListInfo} + onValidateNextStep={handleValidNextStep} /> ); case 6: @@ -218,11 +173,6 @@ const AddOkr = () => { } }; - // 스텝에 따라 검증 - useEffect(() => { - validNextStep(); - }, [step, objInfo, krListInfo, clickedCard]); - if (!location.state.selectedMethod) { return ; } diff --git a/src/AddOkr/types/KrInfoTypes.ts b/src/AddOkr/types/KrInfoTypes.ts index bffd769d..03b8856d 100644 --- a/src/AddOkr/types/KrInfoTypes.ts +++ b/src/AddOkr/types/KrInfoTypes.ts @@ -18,4 +18,5 @@ export interface IAddKrFlowProps { handleClickCloseBtn: (cardIdx: number) => void; krListInfo: IKrListInfoTypes[]; setKrListInfo: React.Dispatch>; + onValidateNextStep: (isValid: boolean) => void; } diff --git a/src/AddOkr/types/ObjectInfoTypes.ts b/src/AddOkr/types/ObjectInfoTypes.ts index e4f2026a..b5321ff3 100644 --- a/src/AddOkr/types/ObjectInfoTypes.ts +++ b/src/AddOkr/types/ObjectInfoTypes.ts @@ -9,4 +9,5 @@ export interface IObjInfoTypes { export interface IAddObjFlowProps { objInfo: IObjInfoTypes; setObjInfo: React.Dispatch>; + onValidNextStep: (isValid: boolean) => void; }