Skip to content
4 changes: 2 additions & 2 deletions src/app/(auth)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ export default function DashboardLayout({
children: React.ReactNode
}) {
return (
<div className="flex min-h-screen w-full items-center justify-center">
<div className="flex w-520 flex-col items-center justify-center gap-24 px-12 sm:px-0">
<div className="flex h-full items-center justify-center">
<div className="flex w-520 flex-col items-center justify-center gap-24 px-0 tablet:px-12">
{children}
</div>
</div>
Expand Down
11 changes: 5 additions & 6 deletions src/app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
'use client'

import { useMounted } from '@hooks/useMounted'
import Link from 'next/link'
import { useEffect, useState } from 'react'

import AuthLogo from '@/app/features/auth/components/AuthLogo'
import LoginForm from '@/app/features/auth/components/LoginForm'

export default function Login() {
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])
if (!mounted) {
return null
}
const mounted = useMounted()
if (!mounted) return null

return (
<>
<AuthLogo text="오늘도 만나서 반가워요!" />
Expand Down
15 changes: 15 additions & 0 deletions src/app/(auth)/signup/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
'use client'

import { useMounted } from '@hooks/useMounted'
import Link from 'next/link'

import AuthLogo from '@/app/features/auth/components/AuthLogo'
import SignupForm from '@/app/features/auth/components/SignupForm'

export default function Signup() {
const mounted = useMounted()
if (!mounted) return null

return (
<>
<AuthLogo text="환영합니다!" />
<SignupForm />
<p className="text-16 font-normal">
이미 회원이신가요?{' '}
<Link className="Text-violet underline" href="/login">
로그인
</Link>
</p>
</>
)
}
2 changes: 1 addition & 1 deletion src/app/features/auth/components/LoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function LoginForm() {
return (
<form
className="flex w-full flex-col gap-16"
onSubmit={handleSubmit(async (data) => await loginMutate(data))}
onSubmit={handleSubmit((data) => loginMutate(data))}
>
<Input
labelName="이메일"
Expand Down
21 changes: 12 additions & 9 deletions src/app/features/auth/components/SignupForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useState } from 'react'
import { useForm } from 'react-hook-form'

import { useConfirmPasswordValidation } from '../hooks/useConfirmPasswordValidation'
import { useSignupSubmit } from '../hooks/useSignupSubmit'
import { useSignupMutation } from '../hooks/useSignupMutation'
import { signupValidation } from '../schemas/signupValidation'
import { SignupFormData } from '../types/auth.type'

Expand All @@ -16,7 +16,7 @@ export default function SignupForm() {
handleSubmit,
trigger,
getValues,
formState: { errors, isSubmitting, isValid },
formState: { errors, isValid },
} = useForm<SignupFormData>({
mode: 'onChange',
defaultValues: {
Expand All @@ -28,15 +28,20 @@ export default function SignupForm() {
})

const [isChecked, setIsChecked] = useState(false)
const { submit } = useSignupSubmit()
const { mutate: signupMtate, isPending } = useSignupMutation()
const validation = useConfirmPasswordValidation(getValues)

function handleAgree() {
setIsChecked((prev) => !prev)
}

return (
<form className="flex flex-col gap-16" onSubmit={handleSubmit(submit)}>
<form
className="flex w-full flex-col gap-16"
onSubmit={handleSubmit(({ email, nickname, password }) =>
signupMtate({ email, nickname, password }),
)}
>
<Input
labelName="이메일"
type="email"
Expand Down Expand Up @@ -92,13 +97,11 @@ export default function SignupForm() {
type="submit"
className={cn(
'mt-8 h-50 w-full rounded-8 text-lg font-medium text-white',
isValid && isChecked && !isSubmitting
? 'BG-blue'
: 'BG-blue-disabled',
isValid && isChecked && !isPending ? 'BG-blue' : 'BG-blue-disabled',
)}
disabled={isSubmitting || !isValid || !isChecked}
disabled={isPending || !isValid || !isChecked}
>
회원가입
{isPending ? '처리 중..' : '회원가입'}
</button>
</form>
)
Expand Down
7 changes: 0 additions & 7 deletions src/app/features/auth/hooks/useAuth.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { User } from '@/app/shared/types/user.type'

import { signup as signupApi } from '../api/authApi'
import { useAuthStore } from '../store/useAuthStore'
import { SignupRequest } from '../types/auth.type'

export function useAuth() {
const { setAccessToken, setUser, clearAuthState } = useAuthStore()
Expand All @@ -18,18 +16,13 @@ export function useAuth() {
setUser(user)
}

async function signup(data: SignupRequest) {
await signupApi(data)
}

function logout() {
clearAuthState()
useAuthStore.persist.clearStorage()
}

return {
updateAuthState,
signup,
logout,
}
}
34 changes: 34 additions & 0 deletions src/app/features/auth/hooks/useSignupMutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { showError, showSuccess } from '@lib/toast'
import { useMutation } from '@tanstack/react-query'
import type { AxiosError } from 'axios'
import axios from 'axios'
import { useRouter } from 'next/navigation'

import { User } from '@/app/shared/types/user.type'

import { signup } from '../api/authApi'
import { SignupRequest } from '../types/auth.type'

export function useSignupMutation() {
const router = useRouter()

return useMutation<User, AxiosError | Error, SignupRequest>({
mutationFn: signup,
onSuccess: async () => {
showSuccess('회원가입이 완료되었습니다!')
await new Promise((resolve) => setTimeout(resolve, 400))
router.push('/login')
},
onError: (error) => {
if (axios.isAxiosError(error)) {
const severMessage = (
error.response?.data as { message?: string } | undefined
)?.message
const fallback = error.message || '로그인 실패'
showError(severMessage ?? fallback)
} else {
showError('알 수 없는 에러 발생')
}
},
})
}
28 changes: 0 additions & 28 deletions src/app/features/auth/hooks/useSignupSubmit.ts

This file was deleted.

5 changes: 5 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
--font-sans: 'Pretendard', 'Noto Sans KR', sans-serif;
}

html,
body {
height: 100%;
}

body {
font-family: var(--font-sans);
}
Expand Down
11 changes: 11 additions & 0 deletions src/app/shared/hooks/useMounted.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { useEffect, useState } from 'react'

export function useMounted() {
const [mounted, setMounted] = useState(false)

useEffect(() => {
setMounted(true)
}, [])

return mounted
}
Comment on lines +1 to +11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

마운트 상태 관리 훅을 따로 만들어주셨군요!!

4 changes: 2 additions & 2 deletions src/app/shared/types/user.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ export interface User {
email: string
nickname: string
profileImageUrl: string | null
createdAt?: string
updatedAt?: string
createdAt: string
updatedAt: string
}