Skip to content

Commit

Permalink
feat: 로그인 페이지 구현 (#31)
Browse files Browse the repository at this point in the history
* feat: Provider폴더 추가

* feat: useLocalStorage 훅 추가

* feat: 이메일 유효성 검사 Blur시 처리

* feat: index.ts 폴더 추가

* refactor: defaultValue 선택으로 받도록 수정

* feat: 유효성 에러 나타내는 컴포넌트 추가

* feat: 유효한 이메일 형식이 아닌 경우 disabled처리

* refactor: Provider폴더 제거

* refactor: useLocalStorage 훅 수정

* refactor: 로그인 그룹 마크업 수정

* feat: 회원가입 페이지로 이동 설정

* refactor: 텍스트 글자 크기 수정

* refactor: 페이지 로고그룹 , 로그인 그룹으로 분리

* refactor: LoginGroup 클래스 수정

* refactor: tsconfig src 옵션 재설정

* chore: zod,react-hook-form 설치

* feat: 로그인 zod 스키마 추가

* refactor: ErrorAlrt 최대 길이 수정

* refactor: react-hook-form으로 수정

* refactor: 불필요한 유틸 함수 제거

* refactor: 비밀번호 입력 아이콘 추가

* refactor: 아이콘 누를 때 input type 수정

* refactor: tsconfig 수정 , 로그인 로직 수정

* refactor: 로컬스토리지 훅 제거, 로그인 시 정보 스토리지에 저장

* refactor: 잘못된 속성 명 변경

* refactor: input 스타일 수정

* refactor: 페이지 디자인 수정

* refactor: icon폴더 제거, 페이지 스타일 재설정

* refactor: zod 제거,유효성 검사 부분 제거

* refactor: 유효성 검사 zod 제거

* refactor: 기존 input에서 Input컴포넌트로 교체

* refactor: 회원가입 이동 버튼에 마진 적용

* refactor: LogoGroup스타일 수정
  • Loading branch information
khj0426 authored Nov 7, 2023
1 parent 90762cc commit f31a8e0
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 41 deletions.
36 changes: 35 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,18 @@
"postinstall": "husky install"
},
"dependencies": {
"@hookform/resolvers": "^3.3.2",
"@tanstack/react-query": "^5.4.3",
"@tanstack/react-query-devtools": "^5.4.3",
"axios": "^1.5.1",
"dayjs": "^1.11.10",
"framer-motion": "^10.16.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.47.0",
"react-router-dom": "^6.17.0",
"rippleui": "^1.12.1"
"rippleui": "^1.12.1",
"zod": "^3.22.4"
},
"devDependencies": {
"@commitlint/cli": "^18.0.0",
Expand Down
3 changes: 3 additions & 0 deletions src/components/Input/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ChangeEvent, ComponentPropsWithoutRef, useState } from 'react'
import { UseFormRegisterReturn } from 'react-hook-form'
import { EyeOffIcon, EyeOnIcon } from '@/assets/icons'
import { INPUT_TYPE } from './constants'

Expand All @@ -8,6 +9,7 @@ interface InputProps
disabled?: boolean
type: keyof typeof INPUT_TYPE
message?: string
register?: UseFormRegisterReturn
}

const Input = ({ disabled, type, handleInputChange, message }: InputProps) => {
Expand Down Expand Up @@ -60,3 +62,4 @@ const Input = ({ disabled, type, handleInputChange, message }: InputProps) => {
}

export default Input

9 changes: 8 additions & 1 deletion src/mocks/handlers/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ export const loginHandlers = [
rest.post('/login', async (_, res, ctx) => {
const rand = Math.floor(Math.random() * 10)

return res(ctx.status(200), ctx.json(jwt[rand]))
return res(
ctx.status(200),
ctx.json({
accessToken: jwt[rand],
name: '효중',
email: '[email protected]',
}),
)
}),
]
42 changes: 42 additions & 0 deletions src/pages/LoginPage/components/LoginGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useForm } from 'react-hook-form'
import Input from '@/components/Input'
import { PATH } from '@/routes/constants'

//TODO - 비밀번호 유효성 검사 필요
interface LoginGroupProps {
handleLogin: (email: string, password: string) => void
}
const LoginGroup = ({ handleLogin }: LoginGroupProps) => {
const { register, handleSubmit } = useForm()

return (
<form
className="flex flex-col gap-5"
onSubmit={handleSubmit((data) => {
handleLogin(data.email, data.password)
})}
>
<div>
<Input type="email" register={register('email')} />
</div>
<div>
<div>
<Input type="password" register={register('password')} />
</div>
</div>
<div className="flex w-full flex-col">
<button className="pointer-cursor h-14 rounded-xl bg-active-orange text-lg text-white hover:border hover:border-black disabled:bg-opacity-50 dark:text-black md:text-xl">
로그인
</button>
<a
href={PATH.SIGN_UP}
className="mt-2.5 flex w-[350px] max-w-[350px] justify-end text-xs text-active-orange md:text-sm"
>
회원가입
</a>
</div>
</form>
)
}

export default LoginGroup
19 changes: 19 additions & 0 deletions src/pages/LoginPage/components/LogoGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { LogoColIcon } from '@/assets/icons'
import { rangers } from '@/assets/images'

const LogoGroup = () => {
return (
<>
<div className="md:hidden">
<LogoColIcon className="h-[4rem] w-[5.8rem]" />
</div>
<img
className="h-24 w-24 md:h-40 md:w-40"
src={rangers}
alt="리뷰레인저 모음집"
/>
</>
)
}

export default LogoGroup
2 changes: 2 additions & 0 deletions src/pages/LoginPage/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as LoginGroup } from './LoginGroup'
export { default as LogoGroup } from './LogoGroup'
54 changes: 16 additions & 38 deletions src/pages/LoginPage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,55 +1,33 @@
import { useState, ChangeEvent } from 'react'
import { useLogin } from '@/apis/hooks'
import { LoginGroup, LogoGroup } from './components'

const LoginPage = () => {
const [email, setEmail] = useState<string>('')
const [password, setPassword] = useState<string>('')
const [token, setToken] = useState('')
export interface LoginProps {
email: string
password: string
}

const LoginPage = () => {
const { mutate: login } = useLogin()

const handleEmailChange = (e: ChangeEvent<HTMLInputElement>) => {
setEmail(e.target.value)
}

const handlePasswordChange = (e: ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value)
}

const handleLoginButtonClick = () => {
const handleLoginButtonClick = (email: string, password: string) => {
login(
{ email, password },
{
onSuccess: ({ data }) => {
setToken(data.token)
//TODO - 로그인 성공,실패 처리 추가 필요
onSuccess({ data }) {
localStorage.setItem('user', JSON.stringify(data))
},
},
)
}

return (
<div className="flex w-fit flex-col gap-2">
<div>로그인 페이지</div>
<input
value={email}
type="text"
className="border border-black"
onChange={handleEmailChange}
placeholder="email"
/>
<input
value={password}
type="text"
className="border border-black"
onChange={handlePasswordChange}
placeholder="password"
/>
<button className="btn" onClick={handleLoginButtonClick}>
로그인
</button>
<div className="flex flex-row gap-2">
<p className="font-bold">JWT : </p>
<p>{token}</p>
<div className="flex h-full flex-col items-center justify-center gap-4 bg-main-ivory px-5 dark:bg-main-red-100 md:px-64">
<div className="items-around flex h-full flex-col gap-14 pt-14">
<div className="flex flex-col items-center justify-center">
<LogoGroup />
</div>
<LoginGroup handleLogin={handleLoginButtonClick} />
</div>
</div>
)
Expand Down
3 changes: 3 additions & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export default {
xl: '1rem',
'2xl': '1.125rem',
},
spacing: {
2.5: '0.625rem',
},
},
},
plugins: [rippleui],
Expand Down

0 comments on commit f31a8e0

Please sign in to comment.