diff --git a/package.json b/package.json index 11fb14f6..a42d07cb 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ ] }, "devDependencies": { + "@types/react": "^18.2.8", "@typescript-eslint/eslint-plugin": "^5.30.0", "@typescript-eslint/parser": "^5.30.0", "eslint": "^8.18.0", diff --git a/src/api/register/index.ts b/src/api/register/index.ts new file mode 100644 index 00000000..c143dfea --- /dev/null +++ b/src/api/register/index.ts @@ -0,0 +1,19 @@ +import { client } from 'api'; +import { + AuthCodeParam, AuthCodeResponse, EmailRegisterParam, EmailRegisterResponse, +} from 'model/register'; + +export const getEmailDuplicate = async (param: string) => { + const { status } = await client.get(`/user/check/email?address=${param}`); + return status; +}; + +export const getEmailAuthCode = async (param: EmailRegisterParam) => { + const { data } = await client.post('/owners/verification/email', param); + return EmailRegisterResponse.parse(data); +}; + +export const verificationAuthCode = async (param:AuthCodeParam) => { + const { data } = await client.post('/owners/verification/code', param); + return AuthCodeResponse.parse(data); +}; diff --git a/src/component/common/CustomModal/index.tsx b/src/component/common/CustomModal/index.tsx index 71d81b7a..89fca10d 100644 --- a/src/component/common/CustomModal/index.tsx +++ b/src/component/common/CustomModal/index.tsx @@ -32,7 +32,7 @@ export default function CustomModal({ {hasFooter && (
- +
)} diff --git a/src/page/Auth/Signup/component/ProgressBar/ProgressBar.module.scss b/src/component/common/ProgressBar/ProgressBar.module.scss similarity index 100% rename from src/page/Auth/Signup/component/ProgressBar/ProgressBar.module.scss rename to src/component/common/ProgressBar/ProgressBar.module.scss diff --git a/src/page/Auth/Signup/component/ProgressBar/index.tsx b/src/component/common/ProgressBar/index.tsx similarity index 100% rename from src/page/Auth/Signup/component/ProgressBar/index.tsx rename to src/component/common/ProgressBar/index.tsx diff --git a/src/model/register/index.ts b/src/model/register/index.ts new file mode 100644 index 00000000..8613e5d9 --- /dev/null +++ b/src/model/register/index.ts @@ -0,0 +1,28 @@ +import { z } from 'zod'; + +export const EmailRegisterParam = z.object({ + address: z.string().email(), +}); +export type EmailRegisterParam = z.infer; + +export const EmailRegisterResponse = z.string(); +export type EmailRegisterResponse = z.infer; + +export const AuthCodeParam = z.object({ + address: z.string().email(), + certification_code: z.string(), +}); +export type AuthCodeParam = z.infer; + +export const AuthCodeResponse = z.object({ + token: z.string(), +}); +export type AuthCodeResponse = z.infer; + +export const RegisterParam = z.object({ + email: z.string(), + password: z.string(), + isAuthentication: z.boolean().refine((value) => value === true), +}); + +export type RegisterParam = z.infer; diff --git a/src/page/Auth/Signup/SignUp.module.scss b/src/page/Auth/Signup/SignUp.module.scss index 96fffe0f..8991256a 100644 --- a/src/page/Auth/Signup/SignUp.module.scss +++ b/src/page/Auth/Signup/SignUp.module.scss @@ -25,9 +25,13 @@ @include media.media-breakpoint-down(mobile) { width: 78%; - height: 80vh; + height: 79vh; margin-bottom: 60px; overflow-y: scroll; + scrollbar-width: none; /* 파이어폭스 */ + &::-webkit-scrollbar { + display: none; + } } &__steps { diff --git a/src/page/Auth/Signup/component/CustomButton/index.tsx b/src/page/Auth/Signup/component/CustomButton/index.tsx index d770009b..1d0c1bee 100644 --- a/src/page/Auth/Signup/component/CustomButton/index.tsx +++ b/src/page/Auth/Signup/component/CustomButton/index.tsx @@ -2,18 +2,19 @@ import styles from './CustomButton.module.scss'; interface ButtonProps { content:string, - buttonType:string, + buttonSize: 'small' | 'mobile' | 'large', disable?: boolean, + submit?:boolean onClick?: () => void } export default function CustomButton({ - content, buttonType, disable, onClick, + content, buttonSize, disable, onClick, submit, }:ButtonProps) { return ( )} - * 특수문자 포함 영어와 숫자 조합 6~18 자리 + {formErrors.password ? ( + ) : * 특수문자 포함 영어와 숫자 조합 6~18 자리} -
- +
+ {!isMobile && ( - )} -
- - 비밀번호가 일치하지 않습니다. -
+ {formErrors.passwordConfirm + && }
); diff --git a/src/page/Auth/Signup/constant/terms.ts b/src/page/Auth/Signup/constant/terms.ts index 20558e7d..72f0d6a1 100644 --- a/src/page/Auth/Signup/constant/terms.ts +++ b/src/page/Auth/Signup/constant/terms.ts @@ -1,4 +1,4 @@ -const Terms = [ +const TEMRS = [ { id: 'term_1', title: '개인정보 이용약관', @@ -19,4 +19,4 @@ const Terms = [ }, ]; -export default Terms; +export default TEMRS; diff --git a/src/page/Auth/Signup/hooks/useAuthCheck.ts b/src/page/Auth/Signup/hooks/useAuthCheck.ts new file mode 100644 index 00000000..89488bcf --- /dev/null +++ b/src/page/Auth/Signup/hooks/useAuthCheck.ts @@ -0,0 +1,41 @@ +import { useGenerateAuthCode } from 'query/register'; +import { useEffect, useState } from 'react'; +import { SubmitHandler } from 'react-hook-form'; +import { RegisterData } from 'page/Auth/Signup/types/RegisterData'; + +export default function useAuthCheck(userEmail:string, isMobile:boolean) { + const [email, setEmail] = useState(''); + const [errorMessage, setMessage] = useState(''); + const [isOpen, setOpen] = useState(false); + const { + status, refetch, isError, error, + } = useGenerateAuthCode(email); + + const onSubmit:SubmitHandler = (data) => { + setEmail(() => (data.email ? data.email : '')); + }; + + useEffect(() => { + if (isMobile) { + setEmail(userEmail); + } + }, [isMobile, userEmail]); + + useEffect(() => { + if (email !== '') { + refetch(); + } + }, [email, refetch]); + + useEffect(() => { + if (status === 'success') { + setOpen(true); + } else { + setMessage(Object(error).response?.data.message); + } + }, [status, isError, error]); + + return { + onSubmit, isOpen, errorMessage, email, refetch, + }; +} diff --git a/src/page/Auth/Signup/hooks/useCheckEmailDuplicate.ts b/src/page/Auth/Signup/hooks/useCheckEmailDuplicate.ts new file mode 100644 index 00000000..d7afb1bb --- /dev/null +++ b/src/page/Auth/Signup/hooks/useCheckEmailDuplicate.ts @@ -0,0 +1,38 @@ +import { useCheckDuplicate } from 'query/register'; +import { useEffect, useState } from 'react'; +import { SubmitHandler } from 'react-hook-form'; +import { RegisterData } from 'page/Auth/Signup/types/RegisterData'; + +export default function useCheckEmailDuplicate( + userData:RegisterData, + setId: (data:RegisterData) => void, + isMobile: boolean, +) { + const [email, setEmail] = useState(''); + const [errorMessage, setMessage] = useState(''); + const { status, refetch, error } = useCheckDuplicate(email); + + const onSubmit:SubmitHandler = (data) => { + setEmail(() => (data.email ? data.email : '')); + }; + const onMobileSubmit:SubmitHandler = (data) => { + if (isMobile) { + onSubmit(data); + } + }; + useEffect(() => { + if (email !== '') { + refetch(); + } + }, [email, refetch]); + useEffect(() => { + if (status === 'success' && userData.email !== email) { + setId({ ...userData, email }); + } else { + setMessage(Object(error).response?.data.message); + } + }, [status, setId, email, userData, error]); + return { + status, onSubmit, onMobileSubmit, email, errorMessage, + }; +} diff --git a/src/page/Auth/Signup/hooks/useCheckNextStep.ts b/src/page/Auth/Signup/hooks/useCheckNextStep.ts new file mode 100644 index 00000000..342d6f90 --- /dev/null +++ b/src/page/Auth/Signup/hooks/useCheckNextStep.ts @@ -0,0 +1,15 @@ +import { useState } from 'react'; +import { RegisterData } from 'page/Auth/Signup/types/RegisterData'; +import { RegisterParam } from 'model/register'; + +export default function useCheckNextStep() { + const [isDone, setDone] = useState(false); + + const checkNextStep = (userData:RegisterData) => { + if (RegisterParam.safeParse(userData).success) { + setDone(true); + } + }; + + return { isDone, checkNextStep }; +} diff --git a/src/page/Auth/Signup/hooks/usePasswordConfirm.ts b/src/page/Auth/Signup/hooks/usePasswordConfirm.ts new file mode 100644 index 00000000..e9f7163b --- /dev/null +++ b/src/page/Auth/Signup/hooks/usePasswordConfirm.ts @@ -0,0 +1,37 @@ +import { useForm } from 'react-hook-form'; + +const REG_EX = /^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,18}$/i; + +type PasswordForm = { + password: string, + passwordConfirm:string +}; + +export default function usePasswordConfirm() { + const { + register, + formState: { errors }, + getValues, + handleSubmit, + } = useForm(); + + const passwordRegister = register('password', { + required: { value: true, message: '비밀번호를 입력해주세요.' }, + pattern: { + value: REG_EX, + message: '특수문자 포함 영어와 숫자 조합 6~18 자리를 입력해주세요', + }, + }); + + const passwordConfirmRegister = register('passwordConfirm', { + required: { value: true, message: '비밀번호 확인을 입력해주세요.' }, + pattern: { + value: REG_EX, + message: '특수문자 포함 영어와 숫자 조합 6~18 자리를 입력해주세요', + }, + validate: (password) => password === getValues('password') || '비밀번호가 일치하지 않습니다', + }); + return { + passwordRegister, errors, passwordConfirmRegister, handleSubmit, + }; +} diff --git a/src/page/Auth/Signup/hooks/useRegisterStep.ts b/src/page/Auth/Signup/hooks/useRegisterStep.ts new file mode 100644 index 00000000..0188b791 --- /dev/null +++ b/src/page/Auth/Signup/hooks/useRegisterStep.ts @@ -0,0 +1,47 @@ +import { useCallback, useEffect, useState } from 'react'; +import useUploadToken from 'store/uploadToken'; +import useStepStore from 'store/useStepStore'; +import useMediaQuery from 'utils/hooks/useMediaQuery'; + +export default function useRegisterStep() { + const { + step, setStep, increaseStep, decreaseStep, + } = useStepStore(); + const { isMobile } = useMediaQuery(); + const [registerStep, setRegisterStep] = useState(0); + const { uploadToken } = useUploadToken(); + + useEffect(() => { + setStep(0); + setRegisterStep(0); + }, [isMobile, setStep]); + + const goNext = useCallback(() => { + increaseStep(); + setRegisterStep((regiStep) => regiStep + 1); + window.scrollTo({ top: 0 }); + }, [increaseStep, setRegisterStep]); + + useEffect(() => { + if (uploadToken && isMobile) { + goNext(); + } + }, [uploadToken, goNext, isMobile]); + + const goPrev = () => { + if (registerStep === 2) { + setRegisterStep(1); + setStep(1); + } else if (step === 2) { + setStep(1); + setRegisterStep(1); + } else { + setRegisterStep(registerStep - 1); + decreaseStep(); + } + window.scrollTo({ top: 0 }); + }; + return { + goNext, registerStep, goPrev, step, + }; +} diff --git a/src/page/Auth/Signup/hooks/useValidateEmail.ts b/src/page/Auth/Signup/hooks/useValidateEmail.ts new file mode 100644 index 00000000..9f86a00b --- /dev/null +++ b/src/page/Auth/Signup/hooks/useValidateEmail.ts @@ -0,0 +1,23 @@ +import { useForm } from 'react-hook-form'; +import { RegisterData } from 'page/Auth/Signup/types/RegisterData'; + +const REG_EX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i; + +export default function useValidateEmail() { + const { + register: emailRegister, + handleSubmit: emailHandleSubmit, + formState: { errors }, + watch, + } = useForm({ mode: 'onSubmit' }); + const emailDuplicateRegister = emailRegister('email', { + required: { value: true, message: '이메일을 입력해주세요.' }, + pattern: { + value: REG_EX, + message: '유효한 이메일 주소를 입력해주세요.', + }, + }); + return { + emailHandleSubmit, errors, emailDuplicateRegister, watch, + }; +} diff --git a/src/page/Auth/Signup/hooks/useVerification.ts b/src/page/Auth/Signup/hooks/useVerification.ts new file mode 100644 index 00000000..1395b26f --- /dev/null +++ b/src/page/Auth/Signup/hooks/useVerification.ts @@ -0,0 +1,40 @@ +import { useVerificationAuthCode } from 'query/register'; +import { useEffect, useRef, useState } from 'react'; +import { RegisterData } from 'page/Auth/Signup/types/RegisterData'; + +export default function useVerification( + eamil:string, + setAuthenticate:(data:RegisterData) => void, + userData:RegisterData, +) { + const [code, setCode] = useState(''); + const [errorMessage, setMessage] = useState(null); + const codeInput = useRef(null); + const { + status, refetch, isError, error, + } = useVerificationAuthCode(code, eamil); + + const verificationCode = () => { + if (codeInput.current) { + setCode(codeInput.current.value); + } + }; + + useEffect(() => { + if (code !== '') { + refetch(); + } + }, [code, refetch]); + + useEffect(() => { + if (status === 'success' && !userData.isAuthentication) { + setAuthenticate({ ...userData, isAuthentication: true }); + setMessage(null); + } else if (isError) { + setMessage(Object(error).response.data.violations[0]); + } + }, [status, userData, setAuthenticate, error, isError]); + return { + isError, error, verificationCode, status, codeInput, errorMessage, + }; +} diff --git a/src/page/Auth/Signup/index.tsx b/src/page/Auth/Signup/index.tsx index 4e5bf697..fc9e04b7 100644 --- a/src/page/Auth/Signup/index.tsx +++ b/src/page/Auth/Signup/index.tsx @@ -1,85 +1,71 @@ -import { useEffect, useState } from 'react'; import useMediaQuery from 'utils/hooks/useMediaQuery'; import { ReactComponent as Logo } from 'assets/svg/auth/koin-logo.svg'; import { ReactComponent as Back } from 'assets/svg/common/back-arrow.svg'; import { Link } from 'react-router-dom'; -import UserEmail from './component/UserEmail'; -import ProgressBar from './component/ProgressBar'; +import ProgressBar from 'component/common/ProgressBar'; +import PreviousStep from 'component/common/Auth/PreviousStep'; +import { useRef } from 'react'; import OwnerData from './view/OwnerDataPage'; import TermsOfService from './view/TermsOfServicePage'; import UserData from './view/UserDataPage'; import styles from './SignUp.module.scss'; import Complete from './view/CompletePage'; +import useRegisterStep from './hooks/useRegisterStep'; export default function Signup() { - const [step, setStep] = useState(0); - const { isMobile } = useMediaQuery(); - useEffect(() => { - setStep(0); - }, [isMobile]); - - const PC_STEPS = [ - setStep(step + 1)} />, - setStep(step + 1)} />, - setStep(step + 1)} />, - ]; - - const MOBILE_STEPS = [ - setStep(step + 1)} />, - setStep(step + 1)} />, - setStep(step + 1)} />, - setStep(step + 1)} />, + const { + goNext, registerStep, goPrev, step, + } = useRegisterStep(); + const termsRef = useRef(null); + const STEPS = [ + , + , + , ]; - return (
{!isMobile ? ( <> - {step < 3 && ( + {registerStep < 3 && (
- {PC_STEPS[step]} + {STEPS[registerStep]}
)} - {step === 3 && } + {registerStep === 3 && } ) : ( <> - - {step < 4 && ( + {registerStep < 3 && ( <> - {step === 0 ? ( + {registerStep === 0 ? ( - ) : ( -
- setStep(step - 1)} /> -
- )} -
+ ) : } +
사장님용
회원가입
- {step < 4 && ( + {registerStep < 3 && ( <> - {step > 0 && } - {MOBILE_STEPS[step]} + {registerStep > 0 && } + {STEPS[registerStep]} )}
)} - {step === 4 && } + {registerStep === 3 && } )}
diff --git a/src/page/Auth/Signup/types/RegisterData.ts b/src/page/Auth/Signup/types/RegisterData.ts new file mode 100644 index 00000000..db08d368 --- /dev/null +++ b/src/page/Auth/Signup/types/RegisterData.ts @@ -0,0 +1,5 @@ +export type RegisterData = { + email?: string, + password?: string, + isAuthentication?: boolean +}; diff --git a/src/page/Auth/Signup/view/OwnerDataPage/index.tsx b/src/page/Auth/Signup/view/OwnerDataPage/index.tsx index 8e45ea1a..8c21e041 100644 --- a/src/page/Auth/Signup/view/OwnerDataPage/index.tsx +++ b/src/page/Auth/Signup/view/OwnerDataPage/index.tsx @@ -52,7 +52,7 @@ export default function OwnerData({ clickEvent }:ButtonClickEvent) {
- +
); diff --git a/src/page/Auth/Signup/view/TermsOfServicePage/TermsOfService.module.scss b/src/page/Auth/Signup/view/TermsOfServicePage/TermsOfService.module.scss index f0abb57d..70cc8e62 100644 --- a/src/page/Auth/Signup/view/TermsOfServicePage/TermsOfService.module.scss +++ b/src/page/Auth/Signup/view/TermsOfServicePage/TermsOfService.module.scss @@ -101,6 +101,10 @@ padding: 16px; margin-bottom: 18px; white-space: pre-line; + scrollbar-width: none; /* 파이어폭스 */ + &::-webkit-scrollbar { + display: none; + } @include media.media-breakpoint-down(mobile) { border: 1px dashed #d2dae2; diff --git a/src/page/Auth/Signup/view/TermsOfServicePage/index.tsx b/src/page/Auth/Signup/view/TermsOfServicePage/index.tsx index 157f7a0b..32147d7d 100644 --- a/src/page/Auth/Signup/view/TermsOfServicePage/index.tsx +++ b/src/page/Auth/Signup/view/TermsOfServicePage/index.tsx @@ -1,48 +1,105 @@ import { Link } from 'react-router-dom'; import CustomButton from 'page/Auth/Signup/component/CustomButton'; import useMediaQuery from 'utils/hooks/useMediaQuery'; -import Terms from 'page/Auth/Signup/constant/terms'; +import TERMS from 'page/Auth/Signup/constant/terms'; +import React, { useEffect, useRef, useState } from 'react'; + import styles from './TermsOfService.module.scss'; type ButtonClickEventProps = { clickEvent: () => void; + termsRef: React.RefObject +}; +const useTermCheck = (ref:React.RefObject) => { + const [isUserTermAgree, setUserTermAgree] = useState(false); + const [isKoinTermAgree, setKoinTermAgree] = useState(false); + const [isAllAgree, setAllAgree] = useState(false); + const sectionRef = useRef(null); + const checkAll = () => { + if (isAllAgree) { + setUserTermAgree(false); + setKoinTermAgree(false); + } else { + setUserTermAgree(true); + setKoinTermAgree(true); + } + }; + useEffect(() => { + setAllAgree(isKoinTermAgree && isUserTermAgree); + }, [isKoinTermAgree, isUserTermAgree]); + useEffect(() => { + if (isAllAgree && ref.current) { + console.log( + ref.current.scrollHeight, + ref.current.scrollTop, + ); + ref.current.scrollTo({ top: ref.current.scrollHeight }); + console.log( + ref.current.scrollHeight, + ref.current.scrollTop, + ); + } + }, [isAllAgree, ref]); + return { + isUserTermAgree, + setUserTermAgree, + isKoinTermAgree, + setKoinTermAgree, + isAllAgree, + checkAll, + sectionRef, + }; }; -export default function TermsOfService({ clickEvent }:ButtonClickEventProps) { +export default function TermsOfService({ clickEvent, termsRef }:ButtonClickEventProps) { const { isMobile } = useMediaQuery(); + const USER_TERM = TERMS[0]; + const KOIN_TERM = TERMS[1]; + const { + isUserTermAgree, setUserTermAgree, isKoinTermAgree, setKoinTermAgree, isAllAgree, checkAll, + } = useTermCheck(termsRef); return ( <> -
+
- {Terms.map((term) => ( -
- {term.title} -
- {term.text} -
- +
+ {USER_TERM.title} +
+ {USER_TERM.text}
- ))} + +
+
+ {KOIN_TERM.title} +
+ {KOIN_TERM.text} +
+ +
{isMobile ? ( <> 취소 - clickEvent()} /> + ) - : clickEvent()} />} + : }
); diff --git a/src/page/Auth/Signup/view/UserDataPage/index.tsx b/src/page/Auth/Signup/view/UserDataPage/index.tsx index 9221d7b7..4b7b7782 100644 --- a/src/page/Auth/Signup/view/UserDataPage/index.tsx +++ b/src/page/Auth/Signup/view/UserDataPage/index.tsx @@ -3,23 +3,81 @@ import UserId from 'page/Auth/Signup/component/UserId'; import UserPassword from 'page/Auth/Signup/component/UserPassword'; import useMediaQuery from 'utils/hooks/useMediaQuery'; import CustomButton from 'page/Auth/Signup/component/CustomButton'; +import { useEffect, useState } from 'react'; +import { RegisterData } from 'page/Auth/Signup/types/RegisterData'; +import useStepStore from 'store/useStepStore'; +import useCheckNextStep from 'page/Auth/Signup/hooks/useCheckNextStep'; +import { RegisterParam } from 'model/register'; import styles from './UserData.module.scss'; type ButtonClickEventProps = { - clickEvent: () => void; + goNext: () => void; }; -export default function UserData({ clickEvent }:ButtonClickEventProps) { + +const useCheckEmailStep = () => { + const [isFilled, setIsFilled] = useState(false); + const checkEmailStep = (userData:RegisterData) => { + if (RegisterParam.pick({ email: true, password: true }).safeParse(userData).success) { + setIsFilled(true); + } + }; + return { isFilled, checkEmailStep }; +}; +export default function UserData({ goNext }:ButtonClickEventProps) { const { isMobile } = useMediaQuery(); + const [userData, setData] = useState({}); + const { isDone, checkNextStep } = useCheckNextStep(); + const { increaseStep, step } = useStepStore(); + const [registerStep, setRegisterStep] = useState(0); + const { isFilled, checkEmailStep } = useCheckEmailStep(); + + useEffect(() => { + if (step === 1) { + setRegisterStep(0); + } + }, [step]); + + useEffect(() => { + if (isMobile) { + checkEmailStep(userData); + } + checkNextStep(userData); + }, [userData, checkNextStep, isMobile, checkEmailStep]); + + const goEmailAuth = () => { + setRegisterStep(1); + increaseStep(); + }; + return ( - <> -
- - - {!isMobile && } -
-
- clickEvent()} /> -
- + !isMobile + ? ( + <> +
+ + + +
+
+ +
+ + ) + : ( + <> +
+ {registerStep === 0 ? ( + <> + + + + ) : } +
+
+ {registerStep === 0 && } + {registerStep > 1 && } +
+ + ) ); } diff --git a/src/page/StoreRegistration/view/PC/index.tsx b/src/page/StoreRegistration/view/PC/index.tsx index c4f04484..98aa2c2e 100644 --- a/src/page/StoreRegistration/view/PC/index.tsx +++ b/src/page/StoreRegistration/view/PC/index.tsx @@ -90,7 +90,7 @@ export default function StoreRegistrationPC() { 카테고리
- +
가게명
- +
00:00 ~ 24:00 - + diff --git a/src/query/register.ts b/src/query/register.ts new file mode 100644 index 00000000..6d988f97 --- /dev/null +++ b/src/query/register.ts @@ -0,0 +1,44 @@ +import { useQuery } from '@tanstack/react-query'; +import { getEmailAuthCode, getEmailDuplicate, verificationAuthCode } from 'api/register'; +import useUploadToken from 'store/uploadToken'; + +export const useCheckDuplicate = (email:string) => { + const { status, refetch, error } = useQuery(['emailDuplicateCheck', email], () => getEmailDuplicate(email), { enabled: false }); + return { status, refetch, error }; +}; + +export const useGenerateAuthCode = (email:string) => { + const { + status, refetch, isError, error, + } = useQuery( + ['generateEmailAuthCode', email], + () => getEmailAuthCode({ address: email }), + { + enabled: false, + }, + ); + return { + status, refetch, isError, error, + }; +}; + +export const useVerificationAuthCode = (code:string, email:string) => { + const { setUploadToken } = useUploadToken(); + const { + status, refetch, isError, error, + } = useQuery( + ['verificationCode', code], + () => verificationAuthCode({ certification_code: code, address: email }), + { + enabled: false, + onSuccess: (response) => { + if (response.token) { + setUploadToken(response.token); + } + }, + }, + ); + return { + status, refetch, isError, error, + }; +}; diff --git a/src/store/uploadToken.ts b/src/store/uploadToken.ts new file mode 100644 index 00000000..af92d7ca --- /dev/null +++ b/src/store/uploadToken.ts @@ -0,0 +1,15 @@ +import { create } from 'zustand'; + +interface UploadToken { + uploadToken:string | null, + setUploadToken:(token:string) => void, + removeToken:()=>void +} + +const useUploadToken = create((set) => ({ + uploadToken: null, + setUploadToken: (token) => set({ uploadToken: token }), + removeToken: () => set({ uploadToken: null }), +})); + +export default useUploadToken;