Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions src/AddOkr/components/AddOkrPageLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import ProgressBar from '@components/ProgressBar';
import { css } from '@emotion/react';
import { default as emotionStyled, default as styled } from '@emotion/styled';
import { PropsWithChildren } from 'react';
import { useNavigate } from 'react-router-dom';

import { IS_GUIDE, MAX_BASIC_STEP, MAX_GUIDE_STEP } from '../constants/ADD_OKR_METHOD_N_STEP';
import StepBtns from './commonUse/StepBtns';

interface AddOkrPageLayoutProps extends PropsWithChildren {
isActiveNext: boolean;
selectedMethod: string;
step: number;
onMoveStep: (targetStep: (prev: number) => number) => void;
}

const AddOkrPageLayout = ({
isActiveNext,
selectedMethod,
step,
onMoveStep,
children,
}: AddOkrPageLayoutProps) => {
const navigate = useNavigate();

// 이전, 다음 버튼 관련 handler
const handleClickPrevBtn = () => {
// step 1 -> 0으로 이동시 정보 초기화
if (step === 1) {
navigate('/dashboard', { state: { selectedMethod: selectedMethod } });
}

// default function
onMoveStep((prev) => prev - 1);
};

const handleClickNextBtn = () => {
// 가이드에 따라 설정하기 vs 직접 설정하기 구분 조건 : 직접 설정하기일 때는 step 4 -> step 6로 preview okr로 이동
if (step === 4 && selectedMethod !== IS_GUIDE) {
isActiveNext && onMoveStep((prev) => prev + 2);
return;
}

// default function
isActiveNext && onMoveStep((prev) => prev + 1);
};

return (
<>
{step <= 5 ? (
<section css={AddOkrContainer}>
<StSelectedMethodTxt>{selectedMethod}</StSelectedMethodTxt>
{children}
<>
<StepBtns
isInit={step === 1}
isActiveNext={isActiveNext}
handleClickPrev={handleClickPrevBtn}
handleClickNext={handleClickNextBtn}
/>
<StProgressBarBox $step={step} $selectedMethod={selectedMethod}>
<ProgressBar
currentProgress={step}
maximumProgress={selectedMethod === IS_GUIDE ? MAX_GUIDE_STEP : MAX_BASIC_STEP}
/>
<div css={ProgressTxtBox}>
<StProgressTxt>{`${step}/${
selectedMethod === IS_GUIDE ? MAX_GUIDE_STEP : MAX_BASIC_STEP
}`}</StProgressTxt>
</div>
</StProgressBarBox>
</>
</section>
) : (
// step > 6, 즉 preview-okr에서는 페이지 정렬 다르게
<>{children}</>
)}
</>
);
};

export default AddOkrPageLayout;

const AddOkrContainer = css`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
`;

const StSelectedMethodTxt = emotionStyled.p`
color: ${({ theme }) => theme.colors.gray_300};
${({ theme }) => theme.fonts.body_12_medium};
`;

const marginTopState = (step: number, selectedMethod: string) => {
switch (step) {
case 1:
return selectedMethod === IS_GUIDE ? '6.8rem' : '14.8rem';
case 2:
return '5rem';
case 3:
return '7.3rem';
case 4:
case 5:
return '3.4rem';
}
};
const StProgressBarBox = styled.div<{ $step: number; $selectedMethod: string }>`
position: relative;
display: flex;
flex-direction: column;
gap: 0.8rem;
width: 38rem;
height: 2.7rem;
margin-top: ${({ $step, $selectedMethod }) => marginTopState($step, $selectedMethod)};

& progress {
height: 0.8rem !important;
}
`;

const ProgressTxtBox = css`
position: absolute;
right: 0;
bottom: 0;
width: fit-content;
`;

const StProgressTxt = styled.span`
color: ${({ theme }) => theme.colors.gray_300};
${({ theme }) => theme.fonts.btn_11_medium};
`;
16 changes: 15 additions & 1 deletion src/AddOkr/components/stepLayout/AddGuideFirstKr.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 (
<section css={AddGuideKrContainer}>
<StFirstAddGuideKrTxt>
Expand Down
22 changes: 21 additions & 1 deletion src/AddOkr/components/stepLayout/AddGuideSecondKr.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<section css={AddGuideKrContainer}>
<StSecondAddGuideKrTxt>
Expand Down
16 changes: 15 additions & 1 deletion src/AddOkr/components/stepLayout/AddKr.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 (
Expand Down
8 changes: 6 additions & 2 deletions src/AddOkr/components/stepLayout/ObjContent.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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);
Expand All @@ -24,6 +24,10 @@ const ObjContent = ({ objInfo, setObjInfo }: IAddObjFlowProps) => {
setObjInfo({ ...objInfo, objContent: e.target.value });
};

useEffect(() => {
onValidNextStep(!!objContent);
}, [objContent]);

return (
<section css={ObjContentContainer}>
<StObjContentTitle>목표를 달성하고 싶은 이유와 다짐을 기록해주세요</StObjContentTitle>
Expand Down
14 changes: 12 additions & 2 deletions src/AddOkr/components/stepLayout/ObjPeriod.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 캘린더에서 사용하는 선택된 기간 값
Expand Down Expand Up @@ -57,6 +63,10 @@ const ObjPeriod = ({ objInfo, setObjInfo, selectedPeriod, setSelectedPeriod }: I
}
};

useEffect(() => {
onValidNextStep(!!objStartAt && !!objExpireAt && !!selectedPeriod);
}, [objInfo]);

return (
<section css={ObjPeriodContainer}>
<StPeriodBtnTitle>앞으로 몇 개월 동안 목표에 집중해볼까요?</StPeriodBtnTitle>
Expand Down
8 changes: 6 additions & 2 deletions src/AddOkr/components/stepLayout/ObjTitleCateg.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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);
Expand Down Expand Up @@ -77,6 +77,10 @@ const ObjTitleCateg = ({ isGuide, objInfo, setObjInfo }: IObjTitleCategProps) =>
setHoverObjPlaceHolder(targetPlaceholder);
};

useEffect(() => {
onValidNextStep(!!selectedObjCateg && !!objTitle);
}, [objInfo]);

return (
<section css={ObjTitleCategContainer}>
<StObjTitleCategTitle>
Expand Down
Loading