Skip to content

Commit

Permalink
Merge pull request #111 from Team-inglo/fix/109
Browse files Browse the repository at this point in the history
Fix/109 - 기타 언어 레벨 UI, ID 중복검사 수정
  • Loading branch information
hyeona01 authored Nov 4, 2024
2 parents c3608b2 + 41e6902 commit 77548c9
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 59 deletions.
12 changes: 5 additions & 7 deletions src/components/Language/EtcLevelSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,11 @@ const EtcLevelSection = ({ level, setLevel }: EtcLevelSectionProps) => {
</p>
{/* 레벨 선택 바텀시트 */}
{bottomSheetOpen && (
<div className="w-screen h-screen">
<LevelBottomSheet
level={level}
setLevel={setLevel}
setBottomSheetOpen={setBottomSheetOpen}
/>
</div>
<LevelBottomSheet
level={level}
setLevel={setLevel}
setBottomSheetOpen={setBottomSheetOpen}
/>
)}
</>
);
Expand Down
7 changes: 7 additions & 0 deletions src/components/Signin/SigninInputSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Button from '@/components/Common/Button';
import { useLocation, useNavigate } from 'react-router-dom';
import { validateId, validatePassword } from '@/utils/signin';
import { useSignIn } from '@/hooks/api/useAuth';
import { useUserInfoforSigninStore } from '@/store/signup';

const SigninInputSection = () => {
const navigate = useNavigate();
Expand All @@ -17,6 +18,7 @@ const SigninInputSection = () => {
const [isValid, setIsValid] = useState(false);

const { mutate: signIn } = useSignIn();
const { updateId, updatePassword } = useUserInfoforSigninStore();

// ===== handler =====
const handleIdChange = (value: string) => {
Expand All @@ -36,6 +38,11 @@ const SigninInputSection = () => {
formData.append('serial_id', idValue);
formData.append('password', passwordValue);

// 전역 상태 업데이트
updateId(idValue);
updatePassword(passwordValue);

// api 훅 호출
signIn(formData);
};

Expand Down
47 changes: 28 additions & 19 deletions src/components/Signup/EmailInput.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import Input from '@/components/Common/Input';
import Button from '@/components/Common/Button';
import { useLocation, useNavigate } from 'react-router-dom';
Expand All @@ -21,25 +21,34 @@ const EmailInput = ({ email, onEmailChange, onSubmit }: EmailInputProps) => {

const { data: ValidationResponse } = useGetEmailValidation(email);

// ===== handler =====
const handleEmailChange = async (value: string) => {
onEmailChange(value);
useEffect(() => {
const validateEmailAsync = async () => {
if (!email) return; // 이메일이 없을 경우 바로 반환

// 이메일 형식 유효성 검사
if (!validateEmail(value, setEmailError, pathname)) {
setIsValid(false); // 유효성 검사 실패 시 버튼 비활성화
return;
}
onEmailChange(email);

// 이메일 중복 검사 API 호출 결과 처리
if (ValidationResponse && ValidationResponse.data.is_valid) {
setEmailError(null); // email 중복 오류 메시지 초기화
setIsValid(true); // 중복 검사 통과 시 버튼 활성화
} else {
setEmailError(signInputTranclation.invalidEmail[isEmployer(pathname)]); // email 중복 오류 메시지
setIsValid(false); // 중복 검사 실패 시 버튼 비활성화
}
};
// 이메일 형식 유효성 검사
if (!validateEmail(email, setEmailError, pathname)) {
setIsValid(false); // 유효성 검사 실패 시 버튼 비활성화
return;
}

// 이메일 중복 검사 API 호출 결과 처리
if (ValidationResponse && ValidationResponse.data.is_valid === false) {
setEmailError(
signInputTranclation.emailAvailability[isEmployer(pathname)],
);
setIsValid(false); // 중복 검사 실패 시 버튼 비활성화
} else if (ValidationResponse && ValidationResponse.data.is_valid) {
setEmailError(null); // email 중복 오류 메시지 초기화
setIsValid(true); // 중복 검사 통과 시 버튼 활성화
} else {
setIsValid(false); // 예외처리
}
};

validateEmailAsync();
}, [email, pathname, ValidationResponse, onEmailChange]);

const handleSignupClick = () => {
if (!isValid) return;
Expand All @@ -60,7 +69,7 @@ const EmailInput = ({ email, onEmailChange, onSubmit }: EmailInputProps) => {
inputType="TEXT"
placeholder={signInputTranclation.enterEmail[isEmployer(pathname)]}
value={email}
onChange={handleEmailChange}
onChange={onEmailChange}
canDelete={false}
isInvalid={!isValid}
/>
Expand Down
86 changes: 54 additions & 32 deletions src/components/Signup/SignupInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,44 +31,60 @@ const SignupInput = ({

// // ===== state =====
const [confirmPasswordValue, setConfirmPasswordValue] = useState<string>('');
const [idError, setIdError] = useState<string | null>(null);
const [passwordError, setPasswordError] = useState<string | null>(null);
const [idError, setIdError] = useState<string | null>();
const [passwordError, setPasswordError] = useState<string | null>();
const [confirmPasswordError, setConfirmPasswordError] = useState<
string | null
>(null);
const [isValid, setIsValid] = useState(false);
const [idValid, setIdValid] = useState(false);

const { data: validationResponse } = useGetIdValidation(id);

// ===== handler =====
const handleIdChange = async (value: string) => {
onIdChange(value);
// ID 검사
useEffect(() => {
if (!id) {
setIdError(null);
setIdValid(false);
return;
}
onIdChange(id);

// ID 유효성 검사
if (validateId(value, setIdError, pathname)) {
// ID 중복 검사 API 호출 결과 처리
if (validationResponse && validationResponse.data.is_valid) {
setIdError(null); // ID 중복 오류 메시지 초기화
} else {
setIdError(signInputTranclation.invalidId[isEmployer(pathname)]); // ID 중복 오류 메시지
}
if (validateId(id, setIdError, pathname)) {
setIdValid(true);
}
};

const handlePasswordChange = (value: string) => {
onPasswordChange(value);
validatePassword(value, setPasswordError, pathname); // 비밀번호 입력 시 유효성 검사
};
// ID 중복 검사
const validateIdAsync = async () => {
if (validationResponse && validationResponse.data.is_valid === false) {
setIdError(signInputTranclation.idAvailability[isEmployer(pathname)]);
setIdValid(false);
}
};

const handleConfirmPasswordChange = (value: string) => {
setConfirmPasswordValue(value);
validatedConfirmPassword(
password,
value,
setConfirmPasswordError,
pathname,
);
};
validateIdAsync();
}, [id, onIdChange, validationResponse, idError, idValid]);

// password 유효성 검사
useEffect(() => {
if (password) {
onPasswordChange(password);
validatePassword(password, setPasswordError, pathname);
}
}, [password, pathname, onPasswordChange]);

// password 일치 유효성 검사
useEffect(() => {
if (confirmPasswordValue) {
validatedConfirmPassword(
password,
confirmPasswordValue,
setConfirmPasswordError,
pathname,
);
}
}, [password, confirmPasswordValue, pathname]);

// 모든 필드의 유효성 검사 후, Continue 버튼 활성화
useEffect(() => {
Expand All @@ -81,6 +97,10 @@ const SignupInput = ({
}
}, [id, password, confirmPasswordValue]);

const handleConfirmPasswordChange = (value: string) => {
setConfirmPasswordValue(value);
};

return (
<>
<div className="title-1 text-center py-6">
Expand All @@ -96,11 +116,13 @@ const SignupInput = ({
inputType="TEXT"
placeholder={signInputTranclation.enterId[isEmployer(pathname)]}
value={id}
onChange={handleIdChange}
onChange={onIdChange}
canDelete={false}
isInvalid={!!idError}
isInvalid={!idValid}
/>
{idError && <p className="text-[#FF6F61] text-xs p-2">{idError}</p>}
{!idValid && (
<p className="text-[#FF6F61] text-xs p-2">{idError}</p>
)}
</div>
<div>
<p className="py-2 px-1 body-2 text-[#656565]">
Expand All @@ -112,9 +134,9 @@ const SignupInput = ({
signInputTranclation.enterPassword[isEmployer(pathname)]
}
value={password}
onChange={handlePasswordChange}
onChange={onPasswordChange}
canDelete={false}
isInvalid={!!passwordError}
isInvalid={passwordError ? true : false}
/>
{passwordError && (
<p className="text-[#FF6F61] text-xs p-2">{passwordError}</p>
Expand All @@ -132,7 +154,7 @@ const SignupInput = ({
value={confirmPasswordValue}
onChange={handleConfirmPasswordChange}
canDelete={false}
isInvalid={!!confirmPasswordError}
isInvalid={confirmPasswordError ? true : false}
/>
{confirmPasswordError && (
<p className="text-[#FF6F61] text-xs p-2">
Expand Down
4 changes: 4 additions & 0 deletions src/constants/translation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export const signInputTranclation = {
ko: '아이디를 입력해주세요',
en: 'Invalid id format',
},
idAvailability: {
ko: '아이디가 이미 존재합니다',
en: 'This id already exists',
},
password: {
ko: '비밀번호',
en: 'Password',
Expand Down
24 changes: 24 additions & 0 deletions src/hooks/api/useAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
} from '@/utils/auth';
import { useNavigate } from 'react-router-dom';
import { useMutation, useQuery } from '@tanstack/react-query';
import { useUserInfoforSigninStore } from '@/store/signup';
import { useEmailTryCountStore } from '@/store/signup';
import { RESTYPE } from '@/types/api/common';
import { clearAllStore } from '@/utils/clearAllStore';
Expand Down Expand Up @@ -160,13 +161,36 @@ export const useTempSignUp = () => {
// 2.5 기본 유저 회원가입 훅
export const useSignUp = () => {
const navigate = useNavigate();
const { id, password, updateId, updatePassword } =
useUserInfoforSigninStore();

return useMutation({
mutationFn: signUp,
onSuccess: (data: RESTYPE<SignInResponse>) => {
if (data.success) {
deleteTemporaryToken();
setAccessToken(data.data.access_token);
setRefreshToken(data.data.refresh_token);

// 회원가입 후 자동 로그인
const signinData = new FormData();
signinData.append('serial_id', id);
signinData.append('password', password);

// 로그인 hook 호출
const { mutate: signin } = useSignIn();
signin(signinData, {
onSuccess: () => {
navigate('/splash');
},
onError: () => {
navigate('/signin');
},
});

// id, password 저장소 삭제
updateId('');
updatePassword('');
}
},
onError: () => {
Expand Down
24 changes: 23 additions & 1 deletion src/store/signup.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';

// 회원가입시, 이메일 인증 횟수 제한 확인을 위한 전역상태 관리
type EmailTryCountStore = {
try_cnt: number;
updateTryCnt: (cnt: number) => void;
};

export const useEmailTryCountStore = create(
persist<EmailTryCountStore>(
(set) => ({
Expand All @@ -17,3 +17,25 @@ export const useEmailTryCountStore = create(
},
),
);

// 회원가입 후 자동 로그인을 위한 전역상태 관리
type UserInfoforSigninStore = {
id: string;
password: string;
updateId: (id: string) => void;
updatePassword: (password: string) => void;
};

export const useUserInfoforSigninStore = create(
persist<UserInfoforSigninStore>(
(set) => ({
id: '',
password: '',
updateId: (id) => set(() => ({ id: id })),
updatePassword: (password) => set(() => ({ password: password })),
}),
{
name: 'userInfoforSigninStore',
},
),
);

0 comments on commit 77548c9

Please sign in to comment.