Skip to content

Commit

Permalink
fix: conflict fixing
Browse files Browse the repository at this point in the history
  • Loading branch information
eun-hak committed May 13, 2024
2 parents 2d93632 + 06543df commit a9552a3
Show file tree
Hide file tree
Showing 22 changed files with 3,070 additions and 125 deletions.
1,599 changes: 1,489 additions & 110 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
"react": "^18",
"react-cookie": "^7.1.4",
"react-dom": "^18",
"react-toastify": "^10.0.5"
"react-hook-form": "^7.51.4",
"react-icons": "^5.2.1",
"react-markdown": "^9.0.1",
"react-query": "^3.39.3",
"react-toastify": "^10.0.5",
"remark-gfm": "^4.0.0"
},
"devDependencies": {
"@types/node": "^20",
Expand Down
Binary file added public/sign/positionCircle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/sign/positionClose.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/sign/positionColorCircle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions src/api/auth/auth.post.api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// import { ICommon } from '../types/common';
import { basicResponse } from '../../models/response';

Check warning on line 2 in src/api/auth/auth.post.api.ts

View workflow job for this annotation

GitHub Actions / Lint

'basicResponse' is defined but never used

Check failure on line 2 in src/api/auth/auth.post.api.ts

View workflow job for this annotation

GitHub Actions / Lint

'basicResponse' is defined but never used
import { postRequest } from '../request';
import {
ISignIn,
Expand Down Expand Up @@ -70,7 +71,7 @@ export const emailauthverify = async ({ emailAddress, code }: IEmailAuth) => {
/* 휴대전화 번호 인증 요청*/

export const phoneauthrequest = async ({ phoneNumber }: IPhoneNumber) => {
const response = await postRequest<null, IPhoneNumber>('/auth/phone', {
const response = await postRequest<null, IPhoneNumber>(`auth/phone`, {
phoneNumber
});

Expand All @@ -80,7 +81,7 @@ export const phoneauthrequest = async ({ phoneNumber }: IPhoneNumber) => {
/* 휴대전화 번호 코드 검증*/

export const phoneauthverify = async ({ phoneNumber, code }: IPhoneAuth) => {
const response = await postRequest<null, IPhoneAuth>('/auth/phone/verify', {
const response = await postRequest<null, IPhoneAuth>(`auth/phone/verify`, {
phoneNumber,
code
});
Expand Down
250 changes: 250 additions & 0 deletions src/components/findpassword/EmailCertification.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
import React, { ChangeEvent, Dispatch, useEffect, useRef, useState } from 'react';
import ToBack from '../shared/sign/ToBack';
import { SignupBtnStatus } from '@/models/signupBtnStatus';
import { motion } from 'framer-motion';
import { useMutation } from 'react-query';
import { invertSecond } from '@/utils/invertSecond';
import { emailauthrequest, emailauthverify } from '@/api/auth/auth.post.api';

interface EmailCertificationProps {
setStep: Dispatch<React.SetStateAction<number>>;
}

const EmailCertification = ({ setStep }: EmailCertificationProps) => {
const [userEmail, setUserEmail] = useState<string>('');
const [emailValid, setEmailValid] = useState(false);
const [btnStatus, setBtnStatus] = useState<SignupBtnStatus>('FIRST');
const [isRequest, setIsRequest] = useState(false);
const [validNumber, setValidNumber] = useState<string>('');
const [validTime, setValidTime] = useState<number>(300);
const [isError, setIsError] = useState(false);
const [emailError, setEmailError] = useState(false);
const inputRef = useRef<HTMLInputElement>(null);
const startRef = useRef<HTMLInputElement>(null);

const { mutateAsync: emailRequest } = useMutation((email: string) => {
return emailauthrequest({ emailAddress: email });
});

const { mutateAsync: emailVerify } = useMutation(
({ emailAddress, code }: { emailAddress: string; code: number }) => {
return emailauthverify({ emailAddress, code });
}
);

const handleEmailChange = (e: ChangeEvent<HTMLInputElement>) => {
setUserEmail(e.target.value);
const emailRegEx =
/^[A-Za-z0-9]([-_.]?[A-Za-z0-9])*@[A-Za-z0-9]([-_.]?[A-Za-z0-9])*\.[A-Za-z]{2,3}$/;
const isValid = emailRegEx.test(e.target.value);
setEmailValid(isValid);
};

const handleValidNumberChange = (e: ChangeEvent<HTMLInputElement>) => {
const regex = e.target.value.replace(/[^0-9]/g, '');
setValidNumber(regex);
};

useEffect(() => {
startRef.current?.focus();
}, []);

useEffect(() => {
if (emailValid) {
setBtnStatus('SECOND');
} else {
setBtnStatus('FIRST');
}
}, [emailValid]);

useEffect(() => {
if (isRequest) {
inputRef.current?.focus();
}
}, [isRequest]);

useEffect(() => {
let timeoutId: NodeJS.Timeout;
if (isError || emailError) {
timeoutId = setTimeout(() => {
setIsError(false);
setEmailError(false);
}, 4000);
}
return () => clearTimeout(timeoutId);
}, [isError, emailError]);

useEffect(() => {
let intervalId: NodeJS.Timeout;

if (isRequest && validTime > 0) {
intervalId = setInterval(() => {
setValidTime((prevTime) => prevTime - 1);
}, 1000);
}

return () => clearInterval(intervalId);
}, [isRequest, validTime]);

const handleClick = async () => {
if (btnStatus == 'SECOND') {
const { status } = (await emailRequest(userEmail)) as { status: string };
if (status == 'SUCCESS') {
setIsRequest(true);
setBtnStatus('THIRD');
}
if (status == 'FAIL') {
setUserEmail('');
setEmailError(true);
return;
}
}
if (btnStatus == 'THIRD') {
if (validNumber.length != 6) {
setValidNumber('');
setIsError(true);
inputRef.current?.focus();
return;
}
const { status } = (await emailVerify({
emailAddress: userEmail,
code: Number(validNumber)
})) as { status: string };

if (status == 'SUCCESS') {
setStep((prev) => prev + 1);
}
if (status == 'FAIL') {
setValidNumber('');
setIsError(true);
inputRef.current?.focus();
return;
}
}
};

return (
<div className="max-w-[360px] mx-auto">
<ToBack />

<motion.div
initial={{ opacity: 0, translateX: -90 }}
transition={{
duration: 0.4,
ease: 'easeInOut',
delay: 0.3
}}
animate={{
opacity: 1,
translateX: 0
}}>
<div className="text-black text-[22px] font-semibold font-pretendard leading-[30.80px] mt-[24px] ml-4">
가입한 이메일을 <br />
입력해주세요.
</div>
</motion.div>

<motion.div
initial={{ opacity: 0, translateX: -90 }}
transition={{
duration: 0.4,
ease: 'easeInOut',
delay: 0.6
}}
animate={{
opacity: 1,
translateX: 0
}}>
<div className="mt-[70px] border-b border-neutral-300 ml-4">
<div className="flex mb-[13px]">
<label
htmlFor="email"
className="text-neutral-600 text-base font-semibold font-pretendard">
이메일
</label>
<div className="w-1.5 h-1.5 bg-yellow-400 rounded-full" />
</div>
<div className="pb-2 flex">
<div className="flex-grow flex items-center">
<input
id="email"
style={{ backgroundColor: isRequest ? 'white' : '' }}
disabled={isRequest}
type="text"
className="outline-none"
placeholder="이메일을 입력해주세요."
value={userEmail}
onChange={handleEmailChange}
ref={startRef}
/>
</div>
<button
disabled={btnStatus == 'FIRST'}
className={`w-[83px] h-[31px] px-3.5 py-1.5 rounded border justify-center items-center gap-2.5 flex text-center text-sm font-normal font-pretendard ${
btnStatus === 'FIRST'
? 'bg-white text-zinc-400'
: 'bg-space-purple text-white'
}`}
onClick={handleClick}>
{btnStatus == 'THIRD' ? '인증확인' : '인증전송'}
</button>
</div>
</div>
{emailError ? (
<div className="flex ml-4">
<div className="text-red-700 text-xs font-normal font-pretendard leading-tight">
*등록되지 않은 이메일입니다.
</div>
</div>
) : (
''
)}
</motion.div>

{isRequest && (
<>
<div className="mt-[48px] border-b border-neutral-300 ml-4">
{isError ? (
<div className="flex flex-row-reverse">
<div className="text-red-700 text-xs font-normal font-pretendard leading-tight">
*올바르지 않은 코드입니다.
</div>
</div>
) : (
<div className="pt-[15px]" />
)}
<div className="pb-2 flex">
<div className="flex-grow flex">
<input
disabled={validTime == 0}
type="tel"
maxLength={6}
className="outline-none"
placeholder="6자리 숫자 입력 "
ref={inputRef}
value={validNumber}
onChange={handleValidNumberChange}
/>
</div>
<div className="text-red-700 text-base font-medium font-pretendard">
{invertSecond(validTime)}
</div>
</div>
</div>
<div className="flex items-center mt-2 gap-2 ml-4">
<div className="w-3.5 h-3.5 relative">
<div className="w-3.5 h-3.5 left-0 top-0 absolute bg-slate-200 rounded-full">
<img src="/sign/emailerror.png" alt="" />
</div>
</div>
<div className="text-neutral-400 text-sm font-normal font-pretendard leading-tight">
이메일로 발송된 코드를 입력해주세요.
</div>
</div>
</>
)}
</div>
);
};

export default EmailCertification;
15 changes: 15 additions & 0 deletions src/components/shared/sign/ToBack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Link from 'next/link';
import React from 'react';
import { IoIosArrowRoundBack } from 'react-icons/io';

const ToBack = () => {
return (
<div className="w-[80px] mt-[60px]">
<Link href={'/sign'}>
<IoIosArrowRoundBack size={80} />
</Link>
</div>
);
};

export default ToBack;
Loading

0 comments on commit a9552a3

Please sign in to comment.