Skip to content

Commit d18c379

Browse files
authored
Merge pull request #90 from miind-palace/feature-#67
Feature #67 로그인/회원가입 통신 로직 개선 및 버그 해결
2 parents c2cc499 + 53fa3a8 commit d18c379

File tree

8 files changed

+247
-134
lines changed

8 files changed

+247
-134
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { ChangeEvent, FormEvent } from 'react'
2+
import styled from '@emotion/styled'
3+
import Input from '@/components/common/Input/Input'
4+
import BasicButton from '../common/Button/BasicButton'
5+
import Spacing from '../common/Spacing/Spacing'
6+
import { axiosHttp } from '@/lib/utils/httpCore'
7+
import { validateEmail } from '@/lib/utils/validateUserInfo'
8+
9+
interface CheckEmailFormProps {
10+
email: string
11+
onChangeEmail: (e: ChangeEvent<HTMLInputElement>) => void
12+
goNextStep: () => void
13+
}
14+
15+
export default function CheckEmailForm({ email, onChangeEmail, goNextStep }: CheckEmailFormProps) {
16+
const checkValidateEmail = async (email: string) => {
17+
const { data } = await axiosHttp.post(`/member/mailCheck?memberEmail=${email}`)
18+
const result = {
19+
...data,
20+
}
21+
return result
22+
}
23+
24+
const handleValidateEmail = async (e: FormEvent) => {
25+
e.preventDefault()
26+
console.log('clicked!')
27+
28+
// 이메일 형식 체크 로직
29+
const isValidEmail = validateEmail(email)
30+
if (!isValidEmail) {
31+
alert('이메일 형식이 올바르지 않습니다.')
32+
return
33+
}
34+
35+
// 이메일 중복 검증 로직
36+
const { duplicated, message } = await checkValidateEmail(email)
37+
if (duplicated) {
38+
alert(message)
39+
return
40+
}
41+
42+
alert('사용할 수 있는 이메일입니다.')
43+
goNextStep()
44+
}
45+
46+
return (
47+
<Wrapper>
48+
<form onSubmit={handleValidateEmail} autoComplete="off">
49+
<Spacing size={20} />
50+
<Input
51+
inputLabel="Email"
52+
id="email"
53+
type="text"
54+
name="email"
55+
colorType="PENETRATED_WHITE"
56+
onChange={onChangeEmail}
57+
/>
58+
<Spacing size={10} />
59+
<BasicButton type="submit">이메일 중복 확인</BasicButton>
60+
</form>
61+
</Wrapper>
62+
)
63+
}
64+
65+
const Wrapper = styled.div`
66+
display: flex;
67+
flex-direction: column;
68+
`
69+
70+
const AVAILABLE_EMAIL_MSG = '사용가능한 이메일입니다!'

components/Layout/Layout.tsx

+17-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
11
import styled from '@emotion/styled'
2+
import { useRouter } from 'next/router'
23
import { PropsWithChildren } from 'react'
34

45
const Layout = ({ children }: PropsWithChildren) => {
6+
const router = useRouter()
7+
8+
const tempLogout = () => {
9+
localStorage.removeItem('memberId')
10+
router.push('/sign-in')
11+
alert('로그아웃 되었습니다.')
12+
}
13+
514
return (
6-
<TempBody>
7-
<LayoutContainer>{children}</LayoutContainer>
8-
</TempBody>
15+
<LayoutContainer>
16+
<TempLogoutButton onClick={tempLogout}>로그아웃(임시)</TempLogoutButton>
17+
{children}
18+
</LayoutContainer>
919
)
1020
}
1121

1222
export default Layout
1323

14-
const TempBody = styled.div`
15-
// 작업 편의성을 위하여 임시로 부여한 스타일.
16-
// 데모데이 직전에 본 부분 제거 예정입니다.
17-
background: #f4f4f4;
24+
const TempLogoutButton = styled.button`
25+
position: fixed;
26+
top: 10px;
27+
left: 10px;
1828
`
1929

2030
const LayoutContainer = styled.div`

components/SigninForm/SigninForm.tsx

+24-37
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,80 @@
11
import { useState, FormEvent, ChangeEvent, MouseEvent, useEffect } from 'react'
22
import { useRouter } from 'next/router'
3-
import axios from 'axios'
43
import styled from '@emotion/styled'
54
import { SecurityIcon } from '../Icons'
65
import Input from '@/components/common/Input/Input'
76
import Link from 'next/link'
87
import BasicButton from '../common/Button/BasicButton'
98
import Spacing from '../common/Spacing/Spacing'
9+
import { axiosHttp } from '@/lib/utils/httpCore'
10+
11+
const initialSignInValue = {
12+
email: '',
13+
password: '',
14+
}
1015

1116
export default function SigninForm() {
1217
const router = useRouter()
1318

1419
useEffect(() => {
15-
// 마운트 시 토큰 존재하면 업로드 페이지 이동 -> ( api 받으면 추후 세션 방식으로 바꿔야 한다 ) - 자동 로그인 되어있을 경우 업로드로 라우팅도 구현해야
20+
// 마운트시 localStorage에 memberId 있으면 upload 페이지로 라우팅
1621
if (localStorage.getItem('memberId')) {
1722
router.push('/upload')
1823
}
1924
}, [router])
2025

21-
const [signinConditions, setSigninConditions] = useState({
22-
email: '',
23-
password: '',
24-
})
26+
const [signInValue, setSignInValue] = useState(initialSignInValue)
2527

26-
const updateSigninConditions = (e: ChangeEvent<HTMLInputElement>) => {
27-
// input 값에 onChange 를 통해 Conditions 을 변화시키는 함수
28+
const handleChangeSigninValue = (e: ChangeEvent<HTMLInputElement>) => {
2829
const { value, name } = e.target
29-
setSigninConditions((prevConditions) => ({
30-
...prevConditions,
31-
[name]: value, // 네임 가져와서 네임에 맞는 애로 변경
30+
setSignInValue((prev) => ({
31+
...prev,
32+
[name]: value,
3233
}))
3334
}
3435

35-
const signinFunction = async (e: FormEvent) => {
36-
// 로그인 버튼 클릭시 폼 제출 후 업로드 페이지로 라우팅
36+
const handleSignIn = async (e: FormEvent) => {
3737
e.preventDefault()
38-
39-
if (!signinConditions.email || !signinConditions.password) return alert('아이디나 비밀번호를 입력하세요!')
38+
if (!signInValue.email || !signInValue.password) return alert('아이디 혹은 비밀번호를 입력하세요!')
4039

4140
try {
42-
const response = await axios.post(`${process.env.NEXT_PUBLIC_SERVER_DEFAULT_END_POINT}member/login`, {
43-
memberEmail: signinConditions.email,
44-
memberPassword: signinConditions.password,
41+
const response = await axiosHttp.post(`/member/login`, {
42+
memberEmail: signInValue.email,
43+
memberPassword: signInValue.password,
4544
})
46-
47-
if (response.data === '로그인 실패') return alert(response.data)
48-
4945
localStorage.setItem('memberId', response.data.id)
5046
router.push('/upload')
5147
} catch (error) {
52-
alert('아이디나 비밀번호를 확인하세요!')
48+
if (error instanceof Error) alert(error.message)
5349
}
5450
}
5551

56-
const goToSignupPage = (e: MouseEvent<HTMLAnchorElement>) => {
57-
// Make an Account 클릭시 회원가입 페이지로 이동
58-
e.preventDefault()
59-
60-
router.push('/sign-up')
61-
}
62-
6352
return (
6453
<Wrapper>
65-
<form onSubmit={signinFunction}>
54+
<form onSubmit={handleSignIn}>
6655
<Spacing size={20} />
6756
<Input
68-
value={signinConditions.email}
57+
value={signInValue.email}
6958
inputLabel="Email"
7059
type="text"
7160
name="email"
72-
onChange={updateSigninConditions}
61+
onChange={handleChangeSigninValue}
7362
colorType="PENETRATED_BLACK"
7463
/>
7564
<Spacing size={20} />
7665
<Input
77-
value={signinConditions.password}
66+
value={signInValue.password}
7867
inputLabel="Password"
7968
type="password"
8069
name="password"
81-
onChange={updateSigninConditions}
70+
onChange={handleChangeSigninValue}
8271
svgIcon={<SecurityIcon width="16" height="17" color="white" />}
8372
colorType="PENETRATED_BLACK"
8473
/>
8574
<Spacing size={70} />
8675
<BasicButton>Log in</BasicButton>
8776
<Spacing size={20} />
88-
<StyledLink href="#" onClick={goToSignupPage}>
89-
Make an account
90-
</StyledLink>
77+
<StyledLink href="/sign-up">Make an account</StyledLink>
9178
</form>
9279
</Wrapper>
9380
)

0 commit comments

Comments
 (0)