Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

200 feat seperate api request to authts #209

Merged
merged 4 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions src/api/auth.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
import axios from 'axios';

export const authRequest = {
withdrawal: async (password?: string) =>
await axios.post(
login: (email: string, password: string) =>
axios.post(
'/api/login',
{
email,
password,
},
{withCredentials: true},
),

login_kakao: () =>
axios.post('/api/oauth2/authorization/kakao', null, {
withCredentials: true,
}),

withdrawal: (password?: string) =>
axios.post(
'/api/members/sign-out',
{
password,
Expand Down
34 changes: 15 additions & 19 deletions src/components/Auth/Input/InputEmail.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,36 @@
import styles from "./Input.module.scss";
import styles from './Input.module.scss';

import InputRemove from "@/assets/icons/InputRemove.svg?react";
import validationForm from "@/utils/inputValidation";
import InputRemove from '@/assets/icons/InputRemove.svg?react';
import validationForm from '@/utils/inputValidation';

import { InputEmailProps } from "@/types/auth";
import {InputEmailProps} from '@/types/auth';

function InputEmail({ register, dirty, error, resetField }: InputEmailProps) {
function InputEmail({register, dirty, error, resetField}: InputEmailProps) {
const resetEmail = () => {
resetField("email");
resetField('email');
};

return (
<section className={styles.email}>
<label htmlFor="email">아이디(이메일 주소)</label>
<label htmlFor='email'>아이디(이메일 주소)</label>

<input
id="email"
className={`${styles.input} ${dirty && error ? styles.error : ""}`}
type="text"
placeholder="이메일 주소를 입력해주세요"
{...register("email", {
id='email'
className={`${styles.input} ${dirty && error ? styles.error : ''}`}
type='text'
placeholder='이메일 주소를 입력해주세요'
autoComplete='off'
{...register('email', {
required: true,
pattern: {
value: validationForm.email,
message: "이메일 형식이 올바르지 않습니다.",
message: '이메일 형식이 올바르지 않습니다.',
},
})}
/>

{dirty && (
<button
type="button"
className={styles.removeBtn}
onClick={resetEmail}
tabIndex={-1}
>
<button type='button' className={styles.removeBtn} onClick={resetEmail} tabIndex={-1}>
<InputRemove className={styles.svg} />
</button>
)}
Expand Down
1 change: 1 addition & 0 deletions src/components/Auth/Input/InputEmailSert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ function InputEmailSert({register, email, due, setDue, type}: InputEmailSertProp
maxLength={8}
placeholder='인증코드 8자리를 입력해주세요'
disabled={due === 0}
autoComplete='off'
{...register('emailSert', {
required: true,
pattern: {
Expand Down
38 changes: 16 additions & 22 deletions src/components/Auth/Input/InputNickname.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,38 @@
import styles from "./Input.module.scss";
import styles from './Input.module.scss';

import InputRemove from "@/assets/icons/InputRemove.svg?react";
import validationForm from "@/utils/inputValidation";
import InputRemove from '@/assets/icons/InputRemove.svg?react';
import validationForm from '@/utils/inputValidation';

import { InputNickname } from "@/types/auth";
import {InputNickname} from '@/types/auth';

function InputNickname({ register, dirty, error, resetField }: InputNickname) {
function InputNickname({register, dirty, error, resetField}: InputNickname) {
const resetNickname = () => {
resetField("nickname");
resetField('nickname');
};

return (
<section className={styles.nickname}>
<label htmlFor="nickname">닉네임</label>
<label htmlFor='nickname'>닉네임</label>

<p className={styles.nickname__disc}>
일행 간 구분을 위해 본인을 잘 나타낼 수 있는 닉네임을 권장해요.
</p>
<p className={styles.nickname__disc}>일행 간 구분을 위해 본인을 잘 나타낼 수 있는 닉네임을 권장해요.</p>

<input
id="nickname"
className={`${styles.input} ${dirty && error ? styles.error : ""}`}
type="text"
placeholder="영어/한글/숫자 최대 10자 (공백 포함)"
{...register("nickname", {
id='nickname'
className={`${styles.input} ${dirty && error ? styles.error : ''}`}
type='text'
placeholder='영어/한글/숫자 최대 10자 (공백 포함)'
autoComplete='off'
{...register('nickname', {
required: true,
pattern: {
value: validationForm.nickname,
message: "닉네임 형식을 확인해주세요.",
message: '닉네임 형식을 확인해주세요.',
},
})}
/>

{dirty && (
<button
type="button"
className={styles.removeBtn}
onClick={resetNickname}
tabIndex={-1}
>
<button type='button' className={styles.removeBtn} onClick={resetNickname} tabIndex={-1}>
<InputRemove className={styles.svg} />
</button>
)}
Expand Down
27 changes: 11 additions & 16 deletions src/components/Auth/Login/LoginForm.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import axios from 'axios';
import {useState} from 'react';
import {SubmitHandler, useForm} from 'react-hook-form';
import {FormEvent, useState} from 'react';
import {useForm} from 'react-hook-form';
import {useNavigate} from 'react-router-dom';

import styles from './LoginForm.module.scss';

import AuthButton from '@/components/Auth/Button/AuthButton';

import {authRequest} from '@/api/auth';
import validationForm from '@/utils/inputValidation';

import InputEmail from './LoginInput/InputEmail';
Expand All @@ -18,7 +18,7 @@ function LoginForm() {
const {
register,
resetField,
handleSubmit,
getValues,
formState: {dirtyFields},
} = useForm<AuthForm>({
defaultValues: {
Expand All @@ -41,21 +41,16 @@ function LoginForm() {
return false;
};

const onSubmit: SubmitHandler<AuthForm> = async (data) => {
const {email, password} = data;
const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();

const {email, password} = getValues();

if (showError(email as string, password as string)) return;

try {
const res = await axios.post(
'/api/login',
{
email,
password,
},
{withCredentials: true},
);
console.log(res);
const res = await authRequest.login(email as string, password as string);
console.log('login response', res);

if (res.data.responseCode === 401) {
setValidationError(true);
Expand All @@ -69,7 +64,7 @@ function LoginForm() {
};

return (
<form className={styles.container} onSubmit={handleSubmit(onSubmit)}>
<form className={styles.container} onSubmit={onSubmit}>
<InputEmail label='이메일' register={register} resetField={resetField} dirtyFields={dirtyFields} />

<InputPassword label='비밀번호' register={register} resetField={resetField} dirtyFields={dirtyFields} />
Expand Down
32 changes: 14 additions & 18 deletions src/components/Auth/Login/LoginInput/InputEmail.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,35 @@
import styles from "./Input.module.scss";
import styles from './Input.module.scss';

import InputRemove from "@/assets/icons/InputRemove.svg?react";
import validationForm from "@/utils/inputValidation";
import InputRemove from '@/assets/icons/InputRemove.svg?react';
import validationForm from '@/utils/inputValidation';

import { LoginInput } from "@/types/auth";
import {LoginInput} from '@/types/auth';

function InputEmail({ label, register, dirtyFields, resetField }: LoginInput) {
function InputEmail({label, register, dirtyFields, resetField}: LoginInput) {
const resetEmail = () => {
resetField("email");
resetField('email');
};

return (
<section className={styles.container}>
<label htmlFor="email">{label}</label>
<label htmlFor='email'>{label}</label>

<input
id="email"
id='email'
className={styles.input}
type="text"
placeholder="이메일 주소를 입력해주세요"
{...register("email", {
type='text'
placeholder='이메일 주소를 입력해주세요'
autoComplete='off'
{...register('email', {
pattern: {
value: validationForm.email,
message: "이메일 형식이 올바르지 않습니다.",
message: '이메일 형식이 올바르지 않습니다.',
},
})}
/>

{dirtyFields.email && (
<button
type="button"
className={styles.removeBtn}
onClick={resetEmail}
tabIndex={-1}
>
<button type='button' className={styles.removeBtn} onClick={resetEmail} tabIndex={-1}>
<InputRemove className={styles.svg} />
</button>
)}
Expand Down
7 changes: 3 additions & 4 deletions src/pages/Auth/Login/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {useGetMyInfo} from '@/hooks/User/useUser';

import LoginForm from '@/components/Auth/Login/LoginForm';

import {authRequest} from '@/api/auth';
import KakaoIcon from '@/assets/kakao/kakao_path.svg?react';
import Logo from '@/assets/logo.svg?react';

Expand All @@ -22,10 +23,8 @@ function Login() {

const onClickKakao = async () => {
try {
const res = axios.post('/api/oauth2/authorization/kakao', null, {
withCredentials: true,
});
console.log(res);
const res = await authRequest.login_kakao();
console.log('login_kakao response', res);
} catch (error) {
if (axios.isAxiosError(error)) {
console.log(error);
Expand Down
19 changes: 11 additions & 8 deletions src/pages/Auth/Withdrawal/Withdrawal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,33 +29,36 @@ function Withdrawal() {
password: '',
},
});

const password = watch('password');
const setIsModalOpen = useSetRecoilState(isModalOpenState);
const showToast = CustomToast();
const navigate = useNavigate();

const showFailedSignout = () => {
showToast('비밀번호가 일치하지 않습니다.');
resetField('password');
setIsModalOpen(false);
};

const signout = async () => {
try {
const res =
data?.data.provider === 'NONE' ? await authRequest.withdrawal(password) : await authRequest.withdrawal();

console.log(res);
console.log('signout response', res);

if (res.data.responseCode === 206) {
showToast('비밀번호가 일치하지 않습니다.');
resetField('password');
setIsModalOpen(false);
showFailedSignout();
return;
}

setIsModalOpen(false);
navigate('/');
navigate('/', {replace: true});
} catch (error) {
console.log(error);
// 백엔드 validation 오류 - 리팩토링 시 responseCode 조건 걸 예정
showToast('비밀번호가 일치하지 않습니다.');
resetField('password');
setIsModalOpen(false);
showFailedSignout();
}
};

Expand Down
20 changes: 11 additions & 9 deletions src/pages/User/UserPrivacy/UserPrivacy.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {useQueryClient} from '@tanstack/react-query';
import axios from 'axios';
import {Link, useNavigate} from 'react-router-dom';

Expand All @@ -10,13 +11,21 @@ import Header from '@/components/Auth/Header/Header';
function UserPrivacy() {
const navigate = useNavigate();
const {data, error, isFetching} = useGetMyInfo(true);
const queryClient = useQueryClient();

if (isFetching) {
return <div></div>;
}

if (error) navigate('/auth/login');

const clickLogout = () => {
axios.post('/api/logout', {}, {withCredentials: true});

// remove query cache for logout
queryClient.removeQueries({queryKey: ['myInfo']});
navigate('/');
};

return (
<div className={styles.container}>
<Header content='계정 관리' />
Expand All @@ -32,14 +41,7 @@ function UserPrivacy() {
<Link to='/auth/password/modify'>재설정</Link>
</li>

<li
onClick={() => {
axios.post('/api/logout');
navigate('/auth/login');
}}
>
로그아웃
</li>
<li onClick={clickLogout}>로그아웃</li>

<li>
<Link to='/auth/withdrawal'>회원 탈퇴</Link>
Expand Down
Loading