From aa41ad3f5fecb6f3bf8263af6dbc297ec14ce2e9 Mon Sep 17 00:00:00 2001 From: benidene <111226162+benidene@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:43:30 +0900 Subject: [PATCH] Signup (#11) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #10 : 회원가입 페이지 추가 * #8 : 로고부분 클릭시 메인페이지로 이동 추가와 input 수정 * #10 : id, email, phoneNumber 체크 기능 추가 * #10 : 회원가입 페이지 1차 완성 * #10 : 로그인, 회원가입 로직 완성 --- src/App.jsx | 6 +- src/pages/Login/Login.jsx | 27 ++++- src/pages/SignUp/SignUp.jsx | 211 ++++++++++++++++++++++++++++++++++++ src/util/checkPassword.js | 36 +++++- src/util/useLoginLogic.js | 96 ++++++++++++++-- 5 files changed, 357 insertions(+), 19 deletions(-) create mode 100644 src/pages/SignUp/SignUp.jsx diff --git a/src/App.jsx b/src/App.jsx index 5653b29..6015034 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,8 +1,9 @@ import { Routes, Route, useNavigate } from 'react-router-dom'; -import Home from './pages/Home/Home.jsx'; -import Login from './pages/Login/Login.jsx'; import { useEffect, createContext, useMemo } from 'react'; import useLocalStorage from './util/useLocalStorage.js'; +import Home from './pages/Home/Home.jsx'; +import Login from './pages/Login/Login.jsx'; +import SignUp from 'pages/SignUp/SignUp.jsx'; export const userContext = createContext({ setIsLoggedIn: () => {}, @@ -44,6 +45,7 @@ function App() { } /> } /> + } /> ); diff --git a/src/pages/Login/Login.jsx b/src/pages/Login/Login.jsx index cd70cb5..7d9e47c 100644 --- a/src/pages/Login/Login.jsx +++ b/src/pages/Login/Login.jsx @@ -1,9 +1,9 @@ import { styled } from 'styled-components'; -// import { useState } from 'react'; -import useLoginLogic from '../../util/useLoginLogic'; import { faGoogle } from '@fortawesome/free-brands-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import useLoginLogic from '../../util/useLoginLogic'; import MainImg from 'asset/logo192.png'; +import { Link } from 'react-router-dom'; function Login() { const initialInputs = { @@ -11,7 +11,7 @@ function Login() { password: '' }; const LOGIN_POST_URL = `${process.env.REACT_APP_URL}/login`; - const msg = 'User name and password cannot be empty.'; + const msg = '아이디와 비밀번호를 채워주세요'; const [inputs, onChange, onClick] = useLoginLogic( initialInputs, @@ -27,11 +27,20 @@ function Login() { - + + + - + + + + + + + + + + + 중복체크 + + + + + + + + + + + + + 인증번호 발송 + + + + 확인 + + + + 회원가입 + + + ); +} + +const Wrapper = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-around; + height: 100vh; +`; + +const Container = styled.div` + display: flex; + flex-direction: column; + align-items: center; + width: 460px; + height: 50vh; +`; + +const LogoBox = styled(Link)` + height: 100px; + width: 100px; + margin-bottom: -8vh; +`; + +const Logo = styled.img` + height: 100px; + width: 100px; +`; + +const InputBoxTop = styled.div` + display: flex; + align-items: center; + flex-direction: row; + height: 60px; + width: 405px; + padding: 0px 10px 0px 45px; + margin-top: 30px; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + border: 1px solid lightgray; +`; + +const InputBox = styled.div` + display: flex; + align-items: center; + height: 60px; + width: 405px; + padding: 0px 10px 0px 45px; + border: 1px solid lightgray; + border-width: 0px 1px 1px 1px; + border: 1px solid lightgray; +`; + +const Input = styled.input` + height: 50px; + width: 280px; + font-size: 18px; + margin-right: 10px; + border: none; +`; + +const InputBoxDown = styled.div` + display: flex; + align-items: center; + height: 60px; + width: 405px; + padding: 0px 10px 0px 45px; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + border: 1px solid lightgray; + border-width: 0px 1px 1px 1px; +`; + +const AuthButton = styled.button` + width: 100px; + height: 40px; + font-size: 15px; + margin-right: -30px; +`; + +const LoginButton = styled.button` + height: 60px; + width: 460px; + background-color: yellow; + color: #565656; + border-radius: 4px; + border: 1px solid yellow; + font-size: 18px; +`; + +export default SignUp; diff --git a/src/util/checkPassword.js b/src/util/checkPassword.js index fb395aa..03c4d3c 100644 --- a/src/util/checkPassword.js +++ b/src/util/checkPassword.js @@ -1,11 +1,41 @@ +export const checkId = (str) => { + const regexp = /^[a-z]+[a-z0-9]{5,19}$/g; + const result = regexp.test(str); + + if (!result) { + alert('아이디를 영문자 또는 숫자 6~20자로 입력해주세요'); + } + return result; +}; + export const checkPassword = (str) => { const regexp = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z0-9^\W_]{8,20}$/; const result = regexp.test(str); if (!result) { - alert( - 'Passwords must contain at least eight characters, including at least 1 letter and 1 number.' - ); + alert('비밀번호를 영문자 또는 숫자 8~20자로 입력해주세요.'); + } + return result; +}; + +export const checkEmail = (str) => { + const regexp = + // eslint-disable-next-line + /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i; + const result = regexp.test(str); + + if (!result) { + alert('이메일 형식을 올바르게 입력해주세요.'); + } + return result; +}; + +export const checkPhoneNumber = (str) => { + const regexp = /^01(?:0|1|[6-9])(?:\d{3}|\d{4})\d{4}$/; + const result = regexp.test(str); + + if (!result) { + alert('휴대폰 번호는 숫자만 입력해주세요.'); } return result; }; diff --git a/src/util/useLoginLogic.js b/src/util/useLoginLogic.js index 26c19dc..d1ee888 100644 --- a/src/util/useLoginLogic.js +++ b/src/util/useLoginLogic.js @@ -2,11 +2,13 @@ import { useState, useContext } from 'react'; import { useNavigate } from 'react-router-dom'; import { userContext } from '../App'; import { usePost } from './api'; -import { checkPassword } from './checkPassword'; +import { checkPassword, checkId, checkEmail, checkPhoneNumber } from './checkPassword'; -function useLoginLogic(initialInputs, url, alertMsg, key1, key2, key3) { +function useLoginLogic(initialInputs, url, alertMsg, key1, key2, key3, key4, key5, key6, key7) { const navigate = useNavigate(); const [inputs, setInputs] = useState(initialInputs); + const [usableId, setUsableId] = useState(false); + const [auth, setAuth] = useState(false); const { setIsLoggedIn, setTokens } = useContext(userContext); const onChange = (e) => { @@ -14,21 +16,99 @@ function useLoginLogic(initialInputs, url, alertMsg, key1, key2, key3) { setInputs({ ...inputs, [name]: value }); }; - const onClick = async (e) => { + const clickCheckId = async (e) => { e.preventDefault(); + const resultId = checkId(inputs.userIdentifier); + if (!resultId) return; - if (inputs[key1] === '' || inputs[key2] === '' || inputs[key3] === '') { + const res = await usePost(url, inputs.userIdentifier); + if (res.status === 400) { + alert('이미 사용중인 아이디입니다'); + setUsableId(false); + } + if (res.ok) { + alert('사용 가능한 아이디입니다'); + setUsableId(true); + } + }; + + const clickPhoneNumber = async (e) => { + e.preventDefault(); + const resultPhoneNumber = checkPhoneNumber(inputs.phoneNumber); + if (!resultPhoneNumber) return; + + const res = await usePost(url, inputs.phoneNumber); + if (res.status === 400) { + alert('인증번호가 발송되지 않았습니다'); + } + if (res.ok) { + alert('인증번호 발송되었습니다'); + } + }; + + const clickAuthPhoneNumber = async (e) => { + e.preventDefault(); + if (inputs.phoneNumberCheck === '') { + alert('인증번호를 입력하시오'); + return; + } + + const res = await usePost(url, inputs.phoneNumberCheck); + if (res.status === 400) { + alert('인증번호가 일치하지않습니다'); + setAuth(false); + } + if (res.ok) { + alert('인증번호 확인되었습니다'); + setAuth(true); + } + }; + + const onSubmit = async (e) => { + e.preventDefault(); + + if ( + inputs[key1] === '' || + inputs[key2] === '' || + inputs[key3] === '' || + inputs[key4] === '' || + inputs[key5] === '' || + inputs[key6] == '' || + inputs[key7] == '' + ) { alert(alertMsg); return; } + if (usableId === false) { + alert('아이디 중복체크 하세요'); + return; + } + if (auth === false) { + alert('인증번호를 확인하세요'); + return; + } + const resultId = checkId(inputs.userIdentifier); + if (!resultId) return; + const resultPassword = checkPassword(inputs.password); + if (!resultPassword) return; + const resultEmail = checkEmail(inputs.email); + if (!resultEmail) return; + const resultPhoneNumber = checkPhoneNumber(inputs.phoneNumber); + if (!resultPhoneNumber) return; - const result = checkPassword(inputs.password); - if (!result) return; + const isSame = inputs.password === inputs.passwordCheck; + if (!isSame) { + alert('비밀번호가 다릅니다'); + return; + } const res = await usePost(url, inputs); const accessToken = res.headers.get('Authorization'); const refreshToken = res.headers.get('Refresh'); - + if (!res) { + // 에러 처리 로직 + return; + } if (res.ok) { setTokens({ accessToken, @@ -39,7 +119,7 @@ function useLoginLogic(initialInputs, url, alertMsg, key1, key2, key3) { } }; - return [inputs, onChange, onClick]; + return [inputs, onChange, onSubmit, clickCheckId, clickPhoneNumber, clickAuthPhoneNumber]; } export default useLoginLogic;