diff --git a/src/api/lib/postLogin.ts b/src/api/lib/postLogin.ts index 1879c6ef..4d9a5e16 100644 --- a/src/api/lib/postLogin.ts +++ b/src/api/lib/postLogin.ts @@ -1,9 +1,17 @@ +import { AxiosError } from 'axios'; + import { LoginData } from '@/types/auth'; import { instance } from '..'; const postLogin = async (loginData: LoginData) => { - const response = await instance.post('/v1/member/login', loginData); - return response.data; + try { + const response = await instance.post('/v1/member/login', loginData); + return response; + } catch (error) { + if (error instanceof AxiosError) { + return error.response; + } + } }; export default postLogin; diff --git a/src/components/Login/LoginForm/index.tsx b/src/components/Login/LoginForm/index.tsx index efe564b9..02d537c2 100644 --- a/src/components/Login/LoginForm/index.tsx +++ b/src/components/Login/LoginForm/index.tsx @@ -1,5 +1,4 @@ import { useLocation, useNavigate } from 'react-router-dom'; -import { AxiosError } from 'axios'; import styled from '@emotion/styled'; import { FormProvider, @@ -8,7 +7,7 @@ import { FieldValues } from 'react-hook-form'; -import { InputValidation } from '@/types/login'; +import { InputValidation, LoginFormProps } from '@/types/login'; import { AuthButton, AuthInputNormal, @@ -18,13 +17,11 @@ import { LoginData } from '@/types/auth'; import { postLogin } from 'src/api'; import { setCookies } from '@utils/lib/cookies'; -const LoginForm = () => { +const LoginForm = ({ handleModalOpen }: LoginFormProps) => { const navigate = useNavigate(); const { state } = useLocation(); - const methods = useForm({ - mode: 'onBlur' - }); + const methods = useForm({ mode: 'onBlur' }); const { formState: { errors, isValid }, handleSubmit @@ -41,25 +38,30 @@ const LoginForm = () => { email: data.login_id, password: data.login_password }; - try { - const response = await postLogin(formData); - setCookies('userName', response.name, response.expires_in); - setCookies('userEmail', response.email, response.expires_in); - setCookies('accessToken', response.access_token, response.expires_in); - setCookies('refreshToken', response.refresh_token, response.expires_in); + + const response = await postLogin(formData); + + if (response?.status === 200) { + setCookies('userName', response.data.name, response.data.expires_in); + setCookies('userEmail', response.data.email, response.data.expires_in); + setCookies( + 'accessToken', + response.data.access_token, + response.data.expires_in + ); + setCookies( + 'refreshToken', + response.data.refresh_token, + response.data.expires_in + ); if (state) { navigate(state); } else { navigate('/'); } - } catch (error) { - if (error instanceof AxiosError) { - console.log(error); - // TODO : 에러코드에 따라 모달 표시 예정 - // error.response?.data.code; - // error.response?.data.message; - } + } else if (response?.status === 404) { + handleModalOpen(response?.data.message); } }; diff --git a/src/components/common/ErrorModal/index.tsx b/src/components/common/ErrorModal/index.tsx new file mode 100644 index 00000000..918186cd --- /dev/null +++ b/src/components/common/ErrorModal/index.tsx @@ -0,0 +1,102 @@ +import styled from '@emotion/styled'; + +import ErrorIcon from '@assets/icons/ic-error.svg'; +import { ErrorModalProps } from '@/types/errorModal'; + +const ErrorModal = ({ modalContent, ButtonFunc }: ErrorModalProps) => { + return ( + + + + {modalContent.text} + {modalContent.errorText} + 확인 + + + ); +}; + +export default ErrorModal; + +const Backdrop = styled.div` + position: fixed; + + width: 100vw; + height: 100vh; + + background: rgba(66, 66, 66, 0.5); + + z-index: 110; +`; + +const Modal = styled.div` + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + + width: 517px; + height: 249px; + + padding: 59px auto 32px; + border-radius: 16px; + + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + background-color: #fff; + box-shadow: 0px 5px 10px 5px rgba(0, 0, 0, 0.25); +`; + +const Icon = styled.img` + width: 28px; + height: 28px; + + margin-bottom: 14px; +`; + +const Text = styled.p` + color: #404446; + text-align: center; + font-family: 'Noto Sans KR'; + font-size: 15px; + font-weight: 500; + line-height: 22px; +`; + +const ErrorText = styled.p` + margin-bottom: 28px; + + color: #da1e28; + text-align: center; + font-family: 'Noto Sans KR'; + font-size: 15px; + font-weight: 700; + line-height: 22px; +`; + +const ConfirmButton = styled.button` + width: 220px; + height: 44px; + + border-radius: 12px; + border: none; + + color: #fff; + font-family: 'Noto Sans KR'; + font-size: 18px; + font-weight: 700; + line-height: 32px; + + background-color: #1a2849; + + &:hover { + background-color: #5f6980; + cursor: pointer; + } +`; diff --git a/src/components/common/index.tsx b/src/components/common/index.tsx index 72b83916..55216cec 100644 --- a/src/components/common/index.tsx +++ b/src/components/common/index.tsx @@ -2,3 +2,4 @@ export { default as Layout } from './Layout'; export { default as DashboardHeader } from './DashboardHeader'; export { default as MobileDashboardHeader } from './MobileDashboardHeader'; export { default as Footer } from './Footer'; +export { default as ErrorModal } from './ErrorModal'; diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx index 128a460f..4283e532 100644 --- a/src/pages/Login/index.tsx +++ b/src/pages/Login/index.tsx @@ -1,19 +1,38 @@ +import { useState } from 'react'; import styled from '@emotion/styled'; -import { Footer } from '@components/common'; +import { ErrorModal, Footer } from '@components/common'; import { LoginForm, LoginTitle } from '@components/Login'; const Login = () => { + const initialValue = { + text: '이메일 또는 비밀번호를 잘못 입력했습니다.', + errorText: '입력하신 내용을 다시 확인해주세요.' + }; + const [modalContent, setModalContent] = useState(initialValue); + const [isModalOpen, setIsModalOpen] = useState(false); + + const handleModalClose = () => setIsModalOpen(prev => !prev); + const handleModalOpen = (text: string) => { + setModalContent(prev => ({ ...prev, text })); + setIsModalOpen(true); + }; + return ( - +