From 26b7cfe27899262c4ee10d992ef3ea86300dbd39 Mon Sep 17 00:00:00 2001 From: chaeseungyun <101871802+chaeseungyun@users.noreply.github.com> Date: Tue, 4 Jun 2024 16:15:48 +0900 Subject: [PATCH 01/14] =?UTF-8?q?[=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4]=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85,=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=B0=BE=EA=B8=B0=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EC=99=84=EC=84=B1=20(#3?= =?UTF-8?q?41)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: auth 단계를 조절하는 훅 추가 * feat: 비밀번호 찾기, 회원가입 공통 레이아웃 추가 * feat: 회원가입, 비밀번호 찾기 완성 페이지 추가 * feat: 공통 레이아웃 적용 * refactor: outlet에 props로 steps 전달 * fix: 오타 수정 --- src/App.tsx | 11 +- src/assets/svg/auth/done.svg | 101 ++++++++++++++++ .../Auth/components/Common/index.module.scss | 88 ++++++++++++++ src/page/Auth/components/Common/index.tsx | 111 ++++++++++++++++++ .../Auth/components/Done/index.module.scss | 21 ++++ src/page/Auth/components/Done/index.tsx | 37 ++++++ src/page/Auth/hook/useStep.ts | 34 ++++++ 7 files changed, 400 insertions(+), 3 deletions(-) create mode 100644 src/assets/svg/auth/done.svg create mode 100644 src/page/Auth/components/Common/index.module.scss create mode 100644 src/page/Auth/components/Common/index.tsx create mode 100644 src/page/Auth/components/Done/index.module.scss create mode 100644 src/page/Auth/components/Done/index.tsx create mode 100644 src/page/Auth/hook/useStep.ts diff --git a/src/App.tsx b/src/App.tsx index 8562f280..d2ce3303 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -22,6 +22,7 @@ import useUserTypeStore from 'store/useUserTypeStore'; import AddingEvent from 'page/ManageEvent/AddingEvent'; import ModifyEvent from 'page/ManageEvent/ModifyEvent'; import LogPage from 'component/common/PageLog'; +import CommonLayout from 'page/Auth/components/Common'; interface ProtectedRouteProps { userTypeRequired: UserType; @@ -74,9 +75,13 @@ function App() { }> }> } /> - } /> - } /> - } /> + }> + } /> + } /> + } /> + + } /> + } /> } /> } /> diff --git a/src/assets/svg/auth/done.svg b/src/assets/svg/auth/done.svg new file mode 100644 index 00000000..bda159b9 --- /dev/null +++ b/src/assets/svg/auth/done.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/page/Auth/components/Common/index.module.scss b/src/page/Auth/components/Common/index.module.scss new file mode 100644 index 00000000..e35cc61c --- /dev/null +++ b/src/page/Auth/components/Common/index.module.scss @@ -0,0 +1,88 @@ +@use "src/utils/styles/mediaQuery" as media; + +.container { + display: flex; + align-items: center; + flex-direction: column; +} + +.top { + display: flex; + position: relative; + justify-content: center; + align-items: center; + width: 50%; + margin-top: 20px; + + @include media.media-breakpoint-down(mobile) { + width: 90%; + } + + &__back { + position: absolute; + left: 0px; + cursor: pointer; + + @include media.media-breakpoint-up(mobile) { + display: none; + } + } +} + +.step { + display: flex; + flex-direction: column; + width: 50%; + margin-top: 20px; + + @include media.media-breakpoint-down(mobile) { + width: 90%; + } + + &__progress { + display: flex; + justify-content: space-between; + color: #175C8E; + font-weight: 600; + margin: 10px 0; + } +} + +.step-container { + position: relative; +} + +.progress-bar { + border: none; + height: 4px; + background-color: #eeeeee; +} + +.title { + font-weight: 600; + font-size: 20px; +} + +.content { + height: calc(100vh - 40vh); + + @include media.media-breakpoint-down(mobile) { + height: calc(100vh - 28vh); + } +} + +.button { + width: 100%; + background-color: #e1e1e1; + height: 50px; + border-radius: 4px; + font-weight: 600; + + &__active { + width: 100%; + background-color: #175C8E; + height: 50px; + border-radius: 4px; + font-weight: 600; + } +} \ No newline at end of file diff --git a/src/page/Auth/components/Common/index.tsx b/src/page/Auth/components/Common/index.tsx new file mode 100644 index 00000000..a56de627 --- /dev/null +++ b/src/page/Auth/components/Common/index.tsx @@ -0,0 +1,111 @@ +import { ReactComponent as BackArrow } from 'assets/svg/common/back-arrow.svg'; +import { FormProvider, useForm } from 'react-hook-form'; +import { Outlet, useLocation, useNavigate } from 'react-router-dom'; +import cn from 'utils/ts/className'; +// eslint-disable-next-line +import { useStep } from '../../hook/useStep'; +// eslint-disable-next-line +import Done from '../Done/index'; +import styles from './index.module.scss'; + +interface FindPassword { + phone_number: string; + certification_code: string; + password: string; +} + +interface Register extends FindPassword { + company_number: string, + name: string, + shop_id: number, + shop_name: string, + attachment_urls: { + file_url: string + }[] +} + +export default function CommonLayout() { + const location = useLocation(); + const navigate = useNavigate(); + + const isFindPassword = location.pathname.includes('find'); + const title = isFindPassword ? '비밀번호 찾기' : '회원가입'; + + const method = useForm({ + mode: 'onChange', + }); + const { formState: { errors } } = method; + + const steps = useStep(isFindPassword ? 'find' : 'register'); + const { + nextStep, previousStep, currentStep, index, totalStep, isComplete, + } = steps; + + // eslint-disable-next-line + const progressPercentage = (index + 1) / totalStep * 100; + + // form에 error가 없으면 다음 단계로 넘어감 + const stepCheck = () => { + if (isComplete) navigate('/login'); + if (!errors.root) { + nextStep(); + } + }; + + return ( +
+ +
+ +
{title}
+
+
+
+
+ + {index + 1} + . + {' '} + + {currentStep} +
+
+ {`${index + 1}/${totalStep}`} +
+
+
+
+
+
+
+ {isComplete ? : } +
+ +
+
+
+ ); +} diff --git a/src/page/Auth/components/Done/index.module.scss b/src/page/Auth/components/Done/index.module.scss new file mode 100644 index 00000000..6697498c --- /dev/null +++ b/src/page/Auth/components/Done/index.module.scss @@ -0,0 +1,21 @@ +@use "src/utils/styles/mediaQuery" as media; + +.container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + gap: 3vh; +} + +.title { + color: #175C8E; + font-weight: bold; +} + +.content { + color: #8e8e8e; + text-align: center; +} \ No newline at end of file diff --git a/src/page/Auth/components/Done/index.tsx b/src/page/Auth/components/Done/index.tsx new file mode 100644 index 00000000..eafa6f63 --- /dev/null +++ b/src/page/Auth/components/Done/index.tsx @@ -0,0 +1,37 @@ +import { ReactComponent as Success } from 'assets/svg/auth/done.svg'; +import styles from './index.module.scss'; + +const completeFindPassword = { + title: '비밀번호 변경 완료', + content: '비밀번호 변경이 완료되었습니다!', + final: '새로운 비밀번호로 로그인해주세요:)', +}; + +const completeRegister = { + title: '회원가입 완료', + content: '회원가입이 완료되었습니다!', + final: '가입 승인 시 로그인이 가능합니다.', +}; + +interface Props { + isFindPassword: boolean; +} +export default function Done({ isFindPassword }: Props) { + const completeObject = isFindPassword ? completeFindPassword : completeRegister; + return ( +
+ +
+ {completeObject.title} +
+
+
+ {completeObject.content} +
+
+ {completeObject.final} +
+
+
+ ); +} diff --git a/src/page/Auth/hook/useStep.ts b/src/page/Auth/hook/useStep.ts new file mode 100644 index 00000000..7cb7502f --- /dev/null +++ b/src/page/Auth/hook/useStep.ts @@ -0,0 +1,34 @@ +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; + +type Type = 'find' | 'register'; + +const findPassword = [ + '계정 인증', '비밀번호 변경', +]; + +const register = ['약관 동의', '기본 정보 입력', '사업자 인증']; + +export const useStep = (type: Type) => { + const target = type === 'find' ? findPassword : register; + const [index, setIndex] = useState(0); + const [isComplete, setIsComplete] = useState(false); + const navigate = useNavigate(); + + const nextStep = () => { + if (index + 1 < target.length) setIndex((prev) => prev + 1); + }; + + const previousStep = () => { + if (index > 0) setIndex((prev) => prev - 1); + else navigate(-1); + }; + + const currentStep = target[index]; + + const totalStep = target.length; + + return { + nextStep, previousStep, currentStep, index, totalStep, isComplete, setIsComplete, + }; +}; From 4b798791693176b84762811acba63f655688cfd6 Mon Sep 17 00:00:00 2001 From: JeongHoon Choi Date: Wed, 5 Jun 2024 14:38:52 +0900 Subject: [PATCH 02/14] =?UTF-8?q?feat=20:=20useStep=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=ED=98=84=EC=9E=AC=20=EB=8B=A8=EA=B3=84=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=95=98=EC=97=AC=20=EB=8B=A4?= =?UTF-8?q?=EC=9D=8C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=ED=86=B5=EC=A0=9C=20(#344)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: (hoooooony) <(cjh41820@gmail.com)> --- .yarn/cache/fsevents-patch-21ad2b1333-8.zip | Bin 0 -> 24420 bytes src/page/Auth/hook/useStep.ts | 19 ++++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 .yarn/cache/fsevents-patch-21ad2b1333-8.zip diff --git a/.yarn/cache/fsevents-patch-21ad2b1333-8.zip b/.yarn/cache/fsevents-patch-21ad2b1333-8.zip new file mode 100644 index 0000000000000000000000000000000000000000..c6a96dfcdfcf2e751ccfbb3b0f070707d39695ea GIT binary patch literal 24420 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 { const target = type === 'find' ? findPassword : register; const [index, setIndex] = useState(0); const [isComplete, setIsComplete] = useState(false); + const [isStepComplete, setIsStepComplete] = useState(false); const navigate = useNavigate(); const nextStep = () => { - if (index + 1 < target.length) setIndex((prev) => prev + 1); + if (isStepComplete && index + 1 < target.length) { + setIndex((prev) => prev + 1); + setIsStepComplete(false); + } else if (isStepComplete && index + 1 === target.length) { + setIsComplete(true); + } }; const previousStep = () => { @@ -25,10 +31,17 @@ export const useStep = (type: Type) => { }; const currentStep = target[index]; - const totalStep = target.length; return { - nextStep, previousStep, currentStep, index, totalStep, isComplete, setIsComplete, + nextStep, + previousStep, + currentStep, + index, + totalStep, + isComplete, + setIsComplete, + isStepComplete, + setIsStepComplete, }; }; From 893a5278b5ae6db5e0d84cc5d8b8bd7f4e5927de Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Wed, 5 Jun 2024 15:55:11 +0900 Subject: [PATCH 03/14] =?UTF-8?q?feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=B0=BE=EA=B8=B0=20=EC=B4=88=EA=B8=B0=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FindPassword/Verify/index.module.scss | 36 ++++++ src/page/Auth/FindPassword/Verify/index.tsx | 115 ++++++++++++++++++ src/page/Auth/FindPassword/index.tsx | 24 ++++ 3 files changed, 175 insertions(+) create mode 100644 src/page/Auth/FindPassword/Verify/index.module.scss create mode 100644 src/page/Auth/FindPassword/Verify/index.tsx create mode 100644 src/page/Auth/FindPassword/index.tsx diff --git a/src/page/Auth/FindPassword/Verify/index.module.scss b/src/page/Auth/FindPassword/Verify/index.module.scss new file mode 100644 index 00000000..c9650ca2 --- /dev/null +++ b/src/page/Auth/FindPassword/Verify/index.module.scss @@ -0,0 +1,36 @@ +.container { + height: calc(100vh - 30vh); +} + +.section { + display: flex; + flex-direction: column; + justify-content: center; + gap: 10px; + margin-top: 25px; +} + +.title { + font-weight: bold; +} + +.input { + background-color: #f5f5f5; + border-radius: 4px; + border: none; + height: 50px; + padding: 2px 10px; + box-sizing: border-box; +} + +.button { + background-color: #eeeeee; + border: 4px; + height: 50px; + width: 40%; +} + +.error { + color: #f7941e; + font-size: 10px; +} \ No newline at end of file diff --git a/src/page/Auth/FindPassword/Verify/index.tsx b/src/page/Auth/FindPassword/Verify/index.tsx new file mode 100644 index 00000000..78b56a33 --- /dev/null +++ b/src/page/Auth/FindPassword/Verify/index.tsx @@ -0,0 +1,115 @@ +import { isKoinError } from '@bcsdlab/koin'; +import { useMutation } from '@tanstack/react-query'; +import { sendVerifyCode, verifyCode } from 'api/auth'; +import { useState } from 'react'; +import { + useFormContext, UseFormGetValues, UseFormSetError, +} from 'react-hook-form'; +import styles from './index.module.scss'; + +// 코드 발송 및 에러 처리 +const code = ( + getValues: UseFormGetValues, + setError: UseFormSetError, + setIsSent: React.Dispatch>, +) => { + sendVerifyCode(getValues('phone_number')) + .then(() => setIsSent(true)) + .catch((e) => { + if (isKoinError(e)) { + setError('phone_number', { type: 'custom', message: e.message }); + } + }); +}; + +const useCheckCode = () => { + const mutate = useMutation({ + mutationFn: ({ + phone_number, + certification_code, + }: { phone_number: string, certification_code: string }) => verifyCode({ + phone_number, + certification_code, + }), + onError: () => { + // + }, + }); + + return mutate; +}; + +interface Verify { + phone_number: string; + certification_code: string; +} + +export default function Verify() { + const method = useFormContext(); + const { + register, getValues, setError, formState: { errors }, + } = method; + const [isSent, setIsSent] = useState(false); + const [id, setId] = useState(null); + const mutate = useCheckCode(); + console.log(mutate); + + // 디바운싱 + const debounce = () => { + if (id) clearTimeout(id); + const timeId = setTimeout(() => code(getValues, setError, setIsSent), 200); + setId(timeId); + }; + + const sendCode = () => { + if (getValues('phone_number').length === 0) { + setError('phone_number', { type: 'custom', message: '필수 입력 항목입니다.' }); + return; + } + debounce(); + }; + + return ( +
+
+
휴대폰 번호
+ +
+ {errors.phone_number && errors.phone_number.message} +
+
+
+
인증번호
+
+ + +
+
+ {errors.certification_code && errors.certification_code.message} +
+
+
+ ); +} diff --git a/src/page/Auth/FindPassword/index.tsx b/src/page/Auth/FindPassword/index.tsx new file mode 100644 index 00000000..e844813f --- /dev/null +++ b/src/page/Auth/FindPassword/index.tsx @@ -0,0 +1,24 @@ +import { useOutletContext } from 'react-router-dom'; +// eslint-disable-next-line +import Verify from './Verify'; + +export interface OutletProps { + nextStep: () => void; + previousStep: () => void; + currentStep: string; + index: number; + totalStep: number; + isComplete: boolean; + setIsComplete: React.Dispatch>; +} + +export default function FindPassword() { + const steps: OutletProps = useOutletContext(); + const { index } = steps; + return ( + <> + {index === 0 && } + {index === 1 &&
비밀번호 변경
} + + ); +} From bd1fab4381caf9e8b2909fe0bfe8dcae71c6657d Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Wed, 5 Jun 2024 15:55:36 +0900 Subject: [PATCH 04/14] =?UTF-8?q?feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=B0=BE=EA=B8=B0=20=EB=AC=B8=EC=9E=90=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20api=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 3 ++- src/api/auth/index.ts | 8 ++++++++ src/page/Auth/components/Common/index.tsx | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index d2ce3303..9bb58b0b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,7 +5,7 @@ import OwnerLayout from 'layout/OwnerLayout'; import CoopLayout from 'layout/CoopLayout'; import Login from 'page/Auth/Login'; import Signup from 'page/Auth/Signup'; -import FindPassword from 'page/Auth/FindPassword/SendAuthNumber'; +// import FindPassword from 'page/Auth/FindPassword/SendAuthNumber'; import NewPassword from 'page/Auth/FindPassword/NewPassword'; import CompleteChangePassword from 'page/Auth/FindPassword/CompleteChangePassword'; import AuthLayout from 'layout/AuthLayout'; @@ -23,6 +23,7 @@ import AddingEvent from 'page/ManageEvent/AddingEvent'; import ModifyEvent from 'page/ManageEvent/ModifyEvent'; import LogPage from 'component/common/PageLog'; import CommonLayout from 'page/Auth/components/Common'; +import FindPassword from 'page/Auth/FindPassword'; interface ProtectedRouteProps { userTypeRequired: UserType; diff --git a/src/api/auth/index.ts b/src/api/auth/index.ts index 1e670088..7ea41d9b 100644 --- a/src/api/auth/index.ts +++ b/src/api/auth/index.ts @@ -34,3 +34,11 @@ export const findPassword = ({ }); export const newPassword = ({ address, password }: { address: string, password: string }) => client.put('/owners/password/reset', { address, password }); + +export const sendVerifyCode = (phone_number: string) => client.post('/owners/password/reset/verification/sms', { + phone_number, +}); + +export const verifyCode = ({ phone_number, certification_code } : { phone_number:string, certification_code:string }) => client.post('/owners/password/reset/send/sms', { + phone_number, certification_code, +}); diff --git a/src/page/Auth/components/Common/index.tsx b/src/page/Auth/components/Common/index.tsx index a56de627..5a2e2192 100644 --- a/src/page/Auth/components/Common/index.tsx +++ b/src/page/Auth/components/Common/index.tsx @@ -21,7 +21,7 @@ interface Register extends FindPassword { shop_name: string, attachment_urls: { file_url: string - }[] + }[], } export default function CommonLayout() { From 02e8c60bf4441cbf5e7f66529427ada6a0f65444 Mon Sep 17 00:00:00 2001 From: chaeseungyun <101871802+chaeseungyun@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:23:42 +0900 Subject: [PATCH 05/14] =?UTF-8?q?[=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4]=20?= =?UTF-8?q?step=20=EC=83=81=ED=83=9C=EC=97=90=20=EB=94=B0=EB=9D=BC=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EC=83=89=EC=83=81=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?(#345)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: step 상태에 따라 button 색상 변경 * refactor: 이전 페이지로 돌아갈 때 isStepComplete 복구 * refactor: className 변경 --- src/page/Auth/components/Common/index.module.scss | 2 +- src/page/Auth/components/Common/index.tsx | 6 +++--- src/page/Auth/hook/useStep.ts | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/page/Auth/components/Common/index.module.scss b/src/page/Auth/components/Common/index.module.scss index e35cc61c..2e0ee9ab 100644 --- a/src/page/Auth/components/Common/index.module.scss +++ b/src/page/Auth/components/Common/index.module.scss @@ -78,7 +78,7 @@ border-radius: 4px; font-weight: 600; - &__active { + &--active { width: 100%; background-color: #175C8E; height: 50px; diff --git a/src/page/Auth/components/Common/index.tsx b/src/page/Auth/components/Common/index.tsx index a56de627..074825af 100644 --- a/src/page/Auth/components/Common/index.tsx +++ b/src/page/Auth/components/Common/index.tsx @@ -38,7 +38,7 @@ export default function CommonLayout() { const steps = useStep(isFindPassword ? 'find' : 'register'); const { - nextStep, previousStep, currentStep, index, totalStep, isComplete, + nextStep, previousStep, currentStep, index, totalStep, isComplete, isStepComplete, } = steps; // eslint-disable-next-line @@ -92,10 +92,10 @@ export default function CommonLayout() { From a9fed85794c469fe0a27057786a6ffa09a88c431 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Fri, 7 Jun 2024 11:58:28 +0900 Subject: [PATCH 08/14] =?UTF-8?q?refactor:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EB=B3=80=EA=B2=BD=20api=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EB=B0=8F=20=ED=83=80=EC=9E=85=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/auth/index.ts | 5 +++ src/model/auth/index.ts | 22 +++++++++++++ src/page/Auth/FindPassword/index.tsx | 6 +++- src/page/Auth/components/Common/index.tsx | 38 ++++++++++++----------- 4 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/api/auth/index.ts b/src/api/auth/index.ts index dd3ca8a6..937bd61a 100644 --- a/src/api/auth/index.ts +++ b/src/api/auth/index.ts @@ -43,3 +43,8 @@ export const sendVerifyCode = (phone_number: string) => client.post('/owners/pas export const verifyCode = ({ phone_number, certification_code } : { phone_number:string, certification_code:string }) => client.post('/owners/password/reset/send/sms', { phone_number, certification_code, }); + +export const changePassword = ({ phone_number, password } : { phone_number:string, password:string }) => client.put('/owners/password/reset/sms', { + phone_number, + password, +}); diff --git a/src/model/auth/index.ts b/src/model/auth/index.ts index 40d4c0f1..5edb3e1a 100644 --- a/src/model/auth/index.ts +++ b/src/model/auth/index.ts @@ -81,3 +81,25 @@ export interface LoginForm extends LoginParams { export interface CertificationResponse { token: string; } + +export interface ChangePasswordForm { + password: string; + passwordCheck: string; + phone_number: string; +} + +interface FindPassword { + phone_number: string; + certification_code: string; + password: string; +} + +export interface Register extends FindPassword { + company_number: string, + name: string, + shop_id: number, + shop_name: string, + attachment_urls: { + file_url: string + }[], +} diff --git a/src/page/Auth/FindPassword/index.tsx b/src/page/Auth/FindPassword/index.tsx index e844813f..087ef37e 100644 --- a/src/page/Auth/FindPassword/index.tsx +++ b/src/page/Auth/FindPassword/index.tsx @@ -1,5 +1,7 @@ import { useOutletContext } from 'react-router-dom'; // eslint-disable-next-line +import ChangePassword from './ChangePassword'; +// eslint-disable-next-line import Verify from './Verify'; export interface OutletProps { @@ -10,6 +12,8 @@ export interface OutletProps { totalStep: number; isComplete: boolean; setIsComplete: React.Dispatch>; + isStepComplete: boolean; + setIsStepComplete: React.Dispatch>; } export default function FindPassword() { @@ -18,7 +22,7 @@ export default function FindPassword() { return ( <> {index === 0 && } - {index === 1 &&
비밀번호 변경
} + {index === 1 && } ); } diff --git a/src/page/Auth/components/Common/index.tsx b/src/page/Auth/components/Common/index.tsx index 332f9a57..5d042f8c 100644 --- a/src/page/Auth/components/Common/index.tsx +++ b/src/page/Auth/components/Common/index.tsx @@ -1,28 +1,29 @@ import { ReactComponent as BackArrow } from 'assets/svg/common/back-arrow.svg'; -import { FormProvider, useForm } from 'react-hook-form'; +import { FormProvider, useForm, UseFormSetError } from 'react-hook-form'; import { Outlet, useLocation, useNavigate } from 'react-router-dom'; import cn from 'utils/ts/className'; +import { Register } from 'model/auth'; // eslint-disable-next-line -import { useStep } from '../../hook/useStep'; +import { changePassword } from 'api/auth'; +import { isKoinError } from '@bcsdlab/koin'; +import { useStep } from 'page/Auth/hook/useStep'; // eslint-disable-next-line import Done from '../Done/index'; import styles from './index.module.scss'; -interface FindPassword { - phone_number: string; - certification_code: string; - password: string; -} - -interface Register extends FindPassword { - company_number: string, - name: string, - shop_id: number, - shop_name: string, - attachment_urls: { - file_url: string - }[], -} +const setNewPassword = ( + phone_number: string, + password: string, + setError: UseFormSetError, +) => { + changePassword({ phone_number, password }) + .then(() => sessionStorage.removeItem('accessToken')) + .catch((e) => { + if (isKoinError(e)) { + setError('password', { type: 'custom', message: e.message }); + } + }); +}; export default function CommonLayout() { const location = useLocation(); @@ -34,7 +35,7 @@ export default function CommonLayout() { const method = useForm({ mode: 'onChange', }); - const { formState: { errors } } = method; + const { formState: { errors }, setError, getValues } = method; const steps = useStep(isFindPassword ? 'find' : 'register'); const { @@ -48,6 +49,7 @@ export default function CommonLayout() { const stepCheck = () => { if (isComplete) navigate('/login'); if (!errors.root) { + if (index + 1 === totalStep && isFindPassword) setNewPassword(getValues('phone_number'), getValues('password'), setError); nextStep(); } }; From e2c79eb534cea8780c3feb1e59541a8e5af47956 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Fri, 7 Jun 2024 11:58:47 +0900 Subject: [PATCH 09/14] =?UTF-8?q?feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EB=B3=80=EA=B2=BD=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FindPassword/ChangePassword/index.tsx | 71 +++++++++++++++++++ .../FindPassword/Verify/index.module.scss | 5 ++ 2 files changed, 76 insertions(+) create mode 100644 src/page/Auth/FindPassword/ChangePassword/index.tsx diff --git a/src/page/Auth/FindPassword/ChangePassword/index.tsx b/src/page/Auth/FindPassword/ChangePassword/index.tsx new file mode 100644 index 00000000..7262f00f --- /dev/null +++ b/src/page/Auth/FindPassword/ChangePassword/index.tsx @@ -0,0 +1,71 @@ +import { useEffect } from 'react'; +import { useFormContext } from 'react-hook-form'; +import { useOutletContext } from 'react-router-dom'; +import { ChangePasswordForm } from 'model/auth'; +// eslint-disable-next-line +import { OutletProps } from 'page/Auth/FindPassword/index'; +// eslint-disable-next-line +import styles from '../Verify/index.module.scss'; + +const passwordRegex = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{6,18}$/; + +export default function ChangePassword() { + const method = useFormContext(); + const { + register, formState: { errors, isValid }, getValues, + } = method; + const steps: OutletProps = useOutletContext(); + const { setIsStepComplete } = steps; + + useEffect(() => { + if (isValid) { + setIsStepComplete(true); + } else { + setIsStepComplete(false); + } + }); + + return ( + +
+
새 비밀번호
+ + {errors.password + ? ( +
+ {errors.password.message} +
+ ) :
* 특수문자 포함 영어와 숫자 6~18 자리
} + +
+
+
새 비밀번호 확인
+ value === getValues('password') || '비밀번호가 일치하지 않습니다.', + })} + /> +
+ {errors.passwordCheck && errors.passwordCheck.message} +
+
+ + ); +} diff --git a/src/page/Auth/FindPassword/Verify/index.module.scss b/src/page/Auth/FindPassword/Verify/index.module.scss index 62c23953..21561641 100644 --- a/src/page/Auth/FindPassword/Verify/index.module.scss +++ b/src/page/Auth/FindPassword/Verify/index.module.scss @@ -64,4 +64,9 @@ .error { color: #f7941e; font-size: 11px; +} + +.comment { + color: #cacaca; + font-size: 11px; } \ No newline at end of file From 9c344e6d09a5d64221b40207ec9435fbb610a118 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Fri, 7 Jun 2024 11:58:58 +0900 Subject: [PATCH 10/14] =?UTF-8?q?feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=B0=BE=EA=B8=B0=20=ED=8E=98=EC=9D=B4=EC=A7=80=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/App.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index 9bb58b0b..f0341d2d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,7 +5,6 @@ import OwnerLayout from 'layout/OwnerLayout'; import CoopLayout from 'layout/CoopLayout'; import Login from 'page/Auth/Login'; import Signup from 'page/Auth/Signup'; -// import FindPassword from 'page/Auth/FindPassword/SendAuthNumber'; import NewPassword from 'page/Auth/FindPassword/NewPassword'; import CompleteChangePassword from 'page/Auth/FindPassword/CompleteChangePassword'; import AuthLayout from 'layout/AuthLayout'; From bf909a76c3898e1a7dc4e1db796f294e5caf2702 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Fri, 7 Jun 2024 18:27:24 +0900 Subject: [PATCH 11/14] =?UTF-8?q?refactor:=20warning=20=EC=95=84=EC=9D=B4?= =?UTF-8?q?=EC=BD=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FindPassword/ChangePassword/index.tsx | 13 ++++++++--- .../FindPassword/Verify/index.module.scss | 3 +++ src/page/Auth/FindPassword/Verify/index.tsx | 22 ++++++++++++++----- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/page/Auth/FindPassword/ChangePassword/index.tsx b/src/page/Auth/FindPassword/ChangePassword/index.tsx index 7262f00f..da6f1fc6 100644 --- a/src/page/Auth/FindPassword/ChangePassword/index.tsx +++ b/src/page/Auth/FindPassword/ChangePassword/index.tsx @@ -4,6 +4,7 @@ import { useOutletContext } from 'react-router-dom'; import { ChangePasswordForm } from 'model/auth'; // eslint-disable-next-line import { OutletProps } from 'page/Auth/FindPassword/index'; +import { ReactComponent as Warning } from 'assets/svg/auth/warning.svg'; // eslint-disable-next-line import styles from '../Verify/index.module.scss'; @@ -47,6 +48,7 @@ export default function ChangePassword() { {errors.password ? (
+ {errors.password.message}
) :
* 특수문자 포함 영어와 숫자 6~18 자리
} @@ -62,9 +64,14 @@ export default function ChangePassword() { validate: (value) => value === getValues('password') || '비밀번호가 일치하지 않습니다.', })} /> -
- {errors.passwordCheck && errors.passwordCheck.message} -
+ + {errors.passwordCheck + && ( +
+ + {errors.passwordCheck.message} +
+ )} ); diff --git a/src/page/Auth/FindPassword/Verify/index.module.scss b/src/page/Auth/FindPassword/Verify/index.module.scss index 21561641..6478dae6 100644 --- a/src/page/Auth/FindPassword/Verify/index.module.scss +++ b/src/page/Auth/FindPassword/Verify/index.module.scss @@ -64,6 +64,9 @@ .error { color: #f7941e; font-size: 11px; + display: flex; + align-items: center; + gap: 5px; } .comment { diff --git a/src/page/Auth/FindPassword/Verify/index.tsx b/src/page/Auth/FindPassword/Verify/index.tsx index 6d3c9aff..78a60d2a 100644 --- a/src/page/Auth/FindPassword/Verify/index.tsx +++ b/src/page/Auth/FindPassword/Verify/index.tsx @@ -7,6 +7,7 @@ import { } from 'react-hook-form'; import { useOutletContext } from 'react-router-dom'; import cn from 'utils/ts/className'; +import { ReactComponent as Warning } from 'assets/svg/auth/warning.svg'; import styles from './index.module.scss'; // eslint-disable-next-line import { OutletProps } from '..'; @@ -112,9 +113,14 @@ export default function Verify() { type="text" placeholder="-없이 번호를 입력해주세요." /> -
- {errors.phone_number && errors.phone_number.message} -
+ + {errors.phone_number + && ( +
+ + {errors.phone_number.message} +
+ )}
인증번호
@@ -141,9 +147,13 @@ export default function Verify() { {isSent ? '인증번호 재발송' : '인증번호 발송'} -
- {errors.certification_code && errors.certification_code.message} -
+ {errors.certification_code + && ( +
+ + {errors.certification_code.message} +
+ )}
); From 29cd4fd20f0f93ba9c27272f5cf5474629d063a6 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Fri, 7 Jun 2024 18:29:02 +0900 Subject: [PATCH 12/14] =?UTF-8?q?chore:=20scss=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FindPassword/ChangePassword/index.tsx | 3 +- src/page/Auth/FindPassword/Verify/index.tsx | 2 +- src/page/Auth/FindPassword/index.module.scss | 75 +++++++++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 src/page/Auth/FindPassword/index.module.scss diff --git a/src/page/Auth/FindPassword/ChangePassword/index.tsx b/src/page/Auth/FindPassword/ChangePassword/index.tsx index da6f1fc6..12751105 100644 --- a/src/page/Auth/FindPassword/ChangePassword/index.tsx +++ b/src/page/Auth/FindPassword/ChangePassword/index.tsx @@ -5,8 +5,7 @@ import { ChangePasswordForm } from 'model/auth'; // eslint-disable-next-line import { OutletProps } from 'page/Auth/FindPassword/index'; import { ReactComponent as Warning } from 'assets/svg/auth/warning.svg'; -// eslint-disable-next-line -import styles from '../Verify/index.module.scss'; +import styles from 'page/Auth/FindPassword/index.module.scss'; const passwordRegex = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{6,18}$/; diff --git a/src/page/Auth/FindPassword/Verify/index.tsx b/src/page/Auth/FindPassword/Verify/index.tsx index 78a60d2a..4cd30edb 100644 --- a/src/page/Auth/FindPassword/Verify/index.tsx +++ b/src/page/Auth/FindPassword/Verify/index.tsx @@ -8,7 +8,7 @@ import { import { useOutletContext } from 'react-router-dom'; import cn from 'utils/ts/className'; import { ReactComponent as Warning } from 'assets/svg/auth/warning.svg'; -import styles from './index.module.scss'; +import styles from 'page/Auth/FindPassword/index.module.scss'; // eslint-disable-next-line import { OutletProps } from '..'; diff --git a/src/page/Auth/FindPassword/index.module.scss b/src/page/Auth/FindPassword/index.module.scss new file mode 100644 index 00000000..6478dae6 --- /dev/null +++ b/src/page/Auth/FindPassword/index.module.scss @@ -0,0 +1,75 @@ +.container { + height: calc(100vh - 30vh); +} + +.section { + display: flex; + flex-direction: column; + justify-content: center; + gap: 10px; + margin-top: 25px; +} + +.title { + font-weight: bold; +} + +.verify { + display: flex; + justify-content: space-between; +} + +.input { + background-color: #f5f5f5; + border-radius: 4px; + border: none; + height: 50px; + padding: 2px 10px; + box-sizing: border-box; + + &--verify { + background-color: #f5f5f5; + border-radius: 4px; + border: none; + height: 50px; + padding: 2px 10px; + box-sizing: border-box; + width: 55%; + } +} + +.button { + background-color: #eeeeee; + border-radius: 4px; + height: 50px; + width: 40%; + + &--active { + background-color: #175C8E; + color: white; + border-radius: 4px; + height: 50px; + width: 40%; + } + + &--error { + background-color: #F7941E; + color: white; + border-radius: 4px; + height: 50px; + width: 40%; + } +} + +.error { + color: #f7941e; + font-size: 11px; + display: flex; + align-items: center; + gap: 5px; +} + +.comment { + color: #cacaca; + font-size: 11px; +} \ No newline at end of file From 9830cf4bfe93f659b6b6ea7ab5f6c349cf473e82 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Fri, 7 Jun 2024 20:09:42 +0900 Subject: [PATCH 13/14] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 6 - .../CompleteChangePassword.module.scss | 51 ------ .../CompleteChangePassword/index.tsx | 32 ---- .../NewPassword/NewPassword.module.scss | 107 ------------- .../Auth/FindPassword/NewPassword/index.tsx | 146 ------------------ .../SendAuthNumber/SendAuthNumber.module.scss | 94 ----------- .../FindPassword/SendAuthNumber/index.tsx | 98 ------------ .../Auth/FindPassword/hooks/useRouteCheck.ts | 16 -- 8 files changed, 550 deletions(-) delete mode 100644 src/page/Auth/FindPassword/CompleteChangePassword/CompleteChangePassword.module.scss delete mode 100644 src/page/Auth/FindPassword/CompleteChangePassword/index.tsx delete mode 100644 src/page/Auth/FindPassword/NewPassword/NewPassword.module.scss delete mode 100644 src/page/Auth/FindPassword/NewPassword/index.tsx delete mode 100644 src/page/Auth/FindPassword/SendAuthNumber/SendAuthNumber.module.scss delete mode 100644 src/page/Auth/FindPassword/SendAuthNumber/index.tsx delete mode 100644 src/page/Auth/FindPassword/hooks/useRouteCheck.ts diff --git a/src/App.tsx b/src/App.tsx index f0341d2d..e5c7f820 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,8 +5,6 @@ import OwnerLayout from 'layout/OwnerLayout'; import CoopLayout from 'layout/CoopLayout'; import Login from 'page/Auth/Login'; import Signup from 'page/Auth/Signup'; -import NewPassword from 'page/Auth/FindPassword/NewPassword'; -import CompleteChangePassword from 'page/Auth/FindPassword/CompleteChangePassword'; import AuthLayout from 'layout/AuthLayout'; import MyShopPage from 'page/MyShopPage'; import ShopRegistration from 'page/ShopRegistration'; @@ -80,11 +78,7 @@ function App() { } /> } /> - } /> - } /> - } /> - } /> diff --git a/src/page/Auth/FindPassword/CompleteChangePassword/CompleteChangePassword.module.scss b/src/page/Auth/FindPassword/CompleteChangePassword/CompleteChangePassword.module.scss deleted file mode 100644 index bf6a6cc7..00000000 --- a/src/page/Auth/FindPassword/CompleteChangePassword/CompleteChangePassword.module.scss +++ /dev/null @@ -1,51 +0,0 @@ -.template { - display: flex; - justify-content: center; - align-items: center; - padding-top: 220px; - padding-bottom: 120px; - flex-direction: column; -} - -.circle-icon { - width: 160px; - height: 160px; - border-radius: 160px; - border: 8px solid #f7941e; - display: flex; - justify-content: center; - align-items: center; -} - -.content { - font-style: normal; - line-height: normal; - - &__title { - margin-top: 70px; - color: #175c8e; - text-align: center; - font-size: 36px; - font-weight: 700; - } - - &__description { - margin-top: 20px; - color: #858585; - text-align: center; - font-size: 18px; - font-weight: 400; - } - - &__button { - margin-top: 80px; - width: 368px; - height: 48px; - background-color: #175c8e; - color: white; - font-size: 16px; - font-style: normal; - font-weight: 500; - cursor: pointer; - } -} diff --git a/src/page/Auth/FindPassword/CompleteChangePassword/index.tsx b/src/page/Auth/FindPassword/CompleteChangePassword/index.tsx deleted file mode 100644 index 25cb16ba..00000000 --- a/src/page/Auth/FindPassword/CompleteChangePassword/index.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { ReactComponent as Check } from 'assets/svg/auth/check.svg'; -import { useNavigate } from 'react-router-dom'; -import { useRouteCheck } from 'page/Auth/FindPassword/hooks/useRouteCheck'; -import styles from './CompleteChangePassword.module.scss'; - -export default function CompleteChangePassword() { - const navigate = useNavigate(); - useRouteCheck('new-password', '/new-password'); - - return ( -
-
- -
-
-
비밀번호 변경 완료
-
- 비밀번호가 변경되었습니다. -
- 새로운 비밀번호로 로그인 부탁드립니다. -
- -
-
- ); -} diff --git a/src/page/Auth/FindPassword/NewPassword/NewPassword.module.scss b/src/page/Auth/FindPassword/NewPassword/NewPassword.module.scss deleted file mode 100644 index ca890b73..00000000 --- a/src/page/Auth/FindPassword/NewPassword/NewPassword.module.scss +++ /dev/null @@ -1,107 +0,0 @@ -.template { - display: flex; - justify-content: center; - align-items: center; - padding-top: 220px; - padding-bottom: 120px; - flex-direction: column; -} - -.logo { - margin: auto; -} - -.cursor-pointer { - cursor: pointer; - background: none; - border: none; -} - -.form { - width: 368px; - margin-top: 48px; - display: flex; - flex-direction: column; - gap: 16px; - - &__input { - width: 368px; - height: 48px; - padding: 14px 16px; - color: #222; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: normal; - box-sizing: border-box; - outline: none; - border: none; - } - - &__input-container { - display: flex; - align-items: center; - border: 1px solid #d2dae2; - padding-right: 16px; - - &--error { - border: 1px solid #f7941e; - } - - &--normal { - border: 1px solid #d2dae2; - } - } - - &__label { - color: #252525; - font-size: 18px; - font-style: normal; - font-weight: 500; - line-height: normal; - display: flex; - flex-direction: column; - gap: 8px; - } - - &__tip { - color: #d2dae2; - font-size: 12px; - font-style: normal; - font-weight: 400; - line-height: normal; - - &--error { - display: none; - } - } - - &__button { - width: 368px; - height: 48px; - color: white; - background: #175c8e; - cursor: pointer; - margin-top: 250px; - box-sizing: border-box; - - &:disabled { - background-color: #c4c4c4; - } - } - - &__error { - display: flex; - color: #f7941e; - font-size: 12px; - align-items: center; - gap: 8px; - } -} - -.input-container { - display: flex; - align-items: center; - border: 1px solid #d2dae2; - padding-right: 16px; -} diff --git a/src/page/Auth/FindPassword/NewPassword/index.tsx b/src/page/Auth/FindPassword/NewPassword/index.tsx deleted file mode 100644 index 91ca1666..00000000 --- a/src/page/Auth/FindPassword/NewPassword/index.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import { ReactComponent as KoinLogo } from 'assets/svg/auth/koin-logo.svg'; -import { ReactComponent as ShowIcon } from 'assets/svg/auth/show.svg'; -import { ReactComponent as BlindIcon } from 'assets/svg/auth/blind.svg'; -import { ReactComponent as ErrorIcon } from 'assets/svg/error/auth-error.svg'; -import { useRouteCheck } from 'page/Auth/FindPassword/hooks/useRouteCheck'; -import useBooleanState from 'utils/hooks/useBooleanState'; -import { useState } from 'react'; -import { useNewPassword } from 'query/auth'; -import useEmailAuthStore from 'store/useEmailAuth'; -import cn from 'utils/ts/className'; -import sha256 from 'utils/ts/SHA-256'; -import styles from './NewPassword.module.scss'; - -export default function NewPassword() { - const [password, setPassword] = useState(''); - const [passwordCheck, setPasswordCheck] = useState(''); - const [passwordError, setPasswordError] = useState(''); - const [passwordCheckError, setPasswordCheckError] = useState(''); - const { value: isBlind, changeValue: changeIsBlind } = useBooleanState(true); - const { email } = useEmailAuthStore(); - const submit = useNewPassword(); - useRouteCheck('find-password', '/find-password'); - - const handlePasswordChange = (e: React.ChangeEvent) => { - const { value } = e.target; - setPassword(value); - - const PASSWORD_REG_EX = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{6,18}$/; - if (!PASSWORD_REG_EX.test(value)) { - setPasswordError('비밀번호가 조건에 충족하지 않습니다.'); - } else { - setPasswordError(''); - } - }; - - const handlePasswordCheckChange = (e: React.ChangeEvent) => { - const { value } = e.target; - setPasswordCheck(value); - - if (password !== value) { - setPasswordCheckError('비밀번호가 일치하지 않습니다.'); - } else { - setPasswordCheckError(''); - } - }; - - const handleSubmit = async (e: React.MouseEvent) => { - e.preventDefault(); - const hashedPassword = await sha256(password); - if (!passwordError) { - submit({ email, password: hashedPassword }); - } - }; - - return ( -
- -
- - - * 특수문자 포함 영어와 숫자 조합 6~18자리 - - - -
-
- ); -} diff --git a/src/page/Auth/FindPassword/SendAuthNumber/SendAuthNumber.module.scss b/src/page/Auth/FindPassword/SendAuthNumber/SendAuthNumber.module.scss deleted file mode 100644 index ae3d1172..00000000 --- a/src/page/Auth/FindPassword/SendAuthNumber/SendAuthNumber.module.scss +++ /dev/null @@ -1,94 +0,0 @@ -.template { - display: flex; - justify-content: center; - align-items: center; - padding-top: 220px; - padding-bottom: 120px; - flex-direction: column; -} - -.logo { - margin: auto; -} - -.form { - width: 368px; - margin-top: 48px; - display: flex; - flex-direction: column; - gap: 20px; - - &__input { - width: 368px; - height: 48px; - padding: 14px 16px; - border: 1px solid #d2dae2; - color: #222; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: normal; - box-sizing: border-box; - - &--auth { - width: 255px; - } - - &--error { - border: 1px solid #f7941e; - } - - &--normal { - border: 1px solid #d2dae2; - } - } - - &__label { - color: #252525; - font-size: 18px; - font-style: normal; - font-weight: 500; - line-height: normal; - cursor: pointer; - display: flex; - flex-direction: column; - gap: 8px; - } - - &__error { - display: flex; - color: #f7941e; - font-size: 12px; - align-items: center; - gap: 8px; - } -} - -.auth-button { - width: 97px; - height: 48px; - background-color: #175c8e; - color: white; - cursor: pointer; -} - -.submit { - width: 368px; - height: 48px; - color: white; - background: #175c8e; - cursor: pointer; - margin-top: 250px; - box-sizing: border-box; - - &:disabled { - background-color: #c4c4c4; - } -} - -.auth-container { - display: flex; - flex-direction: row; - align-items: center; - gap: 16px; -} diff --git a/src/page/Auth/FindPassword/SendAuthNumber/index.tsx b/src/page/Auth/FindPassword/SendAuthNumber/index.tsx deleted file mode 100644 index 40a250dc..00000000 --- a/src/page/Auth/FindPassword/SendAuthNumber/index.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { Outlet } from 'react-router-dom'; -import { ReactComponent as KoinLogo } from 'assets/svg/auth/koin-logo.svg'; -import { ReactComponent as ErrorIcon } from 'assets/svg/error/auth-error.svg'; -import { useEffect, useState } from 'react'; -import cn from 'utils/ts/className'; -import { useVerifyEmail, useSubmit } from 'query/auth'; -import useEmailAuthStore from 'store/useEmailAuth'; -import styles from './SendAuthNumber.module.scss'; - -export default function FindPassword() { - const { email, setEmail } = useEmailAuthStore(); - const [verify, setVerify] = useState(''); - const { verifyEmail } = useVerifyEmail(); - const { authNumber } = useSubmit(); - - useEffect(() => { - const handleBeforeUnload = () => { - sessionStorage.removeItem('email-storage'); - setEmail(''); - }; - window.addEventListener('beforeunload', handleBeforeUnload); - - return () => { - window.removeEventListener('beforeunload', handleBeforeUnload); - }; - }, [setEmail]); - - return ( - <> -
- -
- - - -
-
- - - ); -} diff --git a/src/page/Auth/FindPassword/hooks/useRouteCheck.ts b/src/page/Auth/FindPassword/hooks/useRouteCheck.ts deleted file mode 100644 index a6fc4f97..00000000 --- a/src/page/Auth/FindPassword/hooks/useRouteCheck.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { useEffect } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom'; - -type Route = 'new-password' | 'find-password'; - -export const useRouteCheck = (prevRoute: Route, entryRoute: string) => { - const location = useLocation(); - const navigate = useNavigate(); - - useEffect(() => { - const hasPrevState = location.state && (prevRoute in location.state); - if (!hasPrevState) { - navigate(entryRoute, { replace: true }); - } - }, [location.state, navigate, entryRoute, prevRoute]); -}; From 297e8b30d067aacf5c7fa77a5d31e922fd2660b3 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Fri, 7 Jun 2024 20:10:13 +0900 Subject: [PATCH 14/14] =?UTF-8?q?refactor:=20import=20cycle=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Auth/FindPassword/ChangePassword/index.tsx | 3 +-- src/page/Auth/FindPassword/Verify/index.tsx | 3 +-- src/page/Auth/FindPassword/entity.ts | 11 +++++++++++ src/page/Auth/FindPassword/index.tsx | 15 +-------------- 4 files changed, 14 insertions(+), 18 deletions(-) create mode 100644 src/page/Auth/FindPassword/entity.ts diff --git a/src/page/Auth/FindPassword/ChangePassword/index.tsx b/src/page/Auth/FindPassword/ChangePassword/index.tsx index 12751105..4ccefd5c 100644 --- a/src/page/Auth/FindPassword/ChangePassword/index.tsx +++ b/src/page/Auth/FindPassword/ChangePassword/index.tsx @@ -2,8 +2,7 @@ import { useEffect } from 'react'; import { useFormContext } from 'react-hook-form'; import { useOutletContext } from 'react-router-dom'; import { ChangePasswordForm } from 'model/auth'; -// eslint-disable-next-line -import { OutletProps } from 'page/Auth/FindPassword/index'; +import { OutletProps } from 'page/Auth/FindPassword/entity'; import { ReactComponent as Warning } from 'assets/svg/auth/warning.svg'; import styles from 'page/Auth/FindPassword/index.module.scss'; diff --git a/src/page/Auth/FindPassword/Verify/index.tsx b/src/page/Auth/FindPassword/Verify/index.tsx index 4cd30edb..06927be2 100644 --- a/src/page/Auth/FindPassword/Verify/index.tsx +++ b/src/page/Auth/FindPassword/Verify/index.tsx @@ -9,8 +9,7 @@ import { useOutletContext } from 'react-router-dom'; import cn from 'utils/ts/className'; import { ReactComponent as Warning } from 'assets/svg/auth/warning.svg'; import styles from 'page/Auth/FindPassword/index.module.scss'; -// eslint-disable-next-line -import { OutletProps } from '..'; +import { OutletProps } from 'page/Auth/FindPassword/entity'; // 코드 발송 및 에러 처리 const code = ( diff --git a/src/page/Auth/FindPassword/entity.ts b/src/page/Auth/FindPassword/entity.ts new file mode 100644 index 00000000..661e5788 --- /dev/null +++ b/src/page/Auth/FindPassword/entity.ts @@ -0,0 +1,11 @@ +export interface OutletProps { + nextStep: () => void; + previousStep: () => void; + currentStep: string; + index: number; + totalStep: number; + isComplete: boolean; + setIsComplete: React.Dispatch>; + isStepComplete: boolean; + setIsStepComplete: React.Dispatch>; +} diff --git a/src/page/Auth/FindPassword/index.tsx b/src/page/Auth/FindPassword/index.tsx index 087ef37e..a5418a56 100644 --- a/src/page/Auth/FindPassword/index.tsx +++ b/src/page/Auth/FindPassword/index.tsx @@ -1,21 +1,8 @@ import { useOutletContext } from 'react-router-dom'; -// eslint-disable-next-line import ChangePassword from './ChangePassword'; -// eslint-disable-next-line +import { OutletProps } from './entity'; import Verify from './Verify'; -export interface OutletProps { - nextStep: () => void; - previousStep: () => void; - currentStep: string; - index: number; - totalStep: number; - isComplete: boolean; - setIsComplete: React.Dispatch>; - isStepComplete: boolean; - setIsStepComplete: React.Dispatch>; -} - export default function FindPassword() { const steps: OutletProps = useOutletContext(); const { index } = steps;