diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx new file mode 100644 index 00000000..5ebb9f5e --- /dev/null +++ b/src/app/login/page.tsx @@ -0,0 +1,17 @@ +import { Icon } from '@/components/icon'; +import { LoginForm } from '@/components/pages/login'; +import { AuthSwitch } from '@/components/shared'; + +const LoginPage = () => { + return ( +
+
+
+ +
+ ); +}; + +export default LoginPage; diff --git a/src/app/signup/page.tsx b/src/app/signup/page.tsx new file mode 100644 index 00000000..20aca9bb --- /dev/null +++ b/src/app/signup/page.tsx @@ -0,0 +1,17 @@ +import { Icon } from '@/components/icon'; +import { SignupForm } from '@/components/pages/signup'; +import { AuthSwitch } from '@/components/shared'; + +const SignupPage = () => { + return ( +
+
+
+ +
+ ); +}; + +export default SignupPage; diff --git a/src/components/pages/login/login-form/index.tsx b/src/components/pages/login/login-form/index.tsx index 774326fa..22689bdd 100644 --- a/src/components/pages/login/login-form/index.tsx +++ b/src/components/pages/login/login-form/index.tsx @@ -1,12 +1,17 @@ 'use client'; -import { useForm } from '@tanstack/react-form'; +import { type AnyFieldApi, useForm } from '@tanstack/react-form'; import { FormInput } from '@/components/shared'; import { Button } from '@/components/ui'; import { loginSchema } from '@/lib/schema/auth'; -const getHintMessage = (errors: unknown[], isTouched: boolean, submissionAttempts: number) => { +const getHintMessage = (field: AnyFieldApi) => { + const { + meta: { errors, isTouched }, + } = field.state; + const { submissionAttempts } = field.form.state; + const firstError = errors[0] as { message?: string } | undefined; const showError = isTouched || submissionAttempts > 0; @@ -40,10 +45,7 @@ export const LoginForm = () => {
{(field) => { - const { - meta: { errors, isTouched }, - } = field.state; - const hintMessage = getHintMessage(errors, isTouched, form.state.submissionAttempts); + const hintMessage = getHintMessage(field); return ( { {(field) => { - const { - meta: { errors, isTouched }, - } = field.state; - const hintMessage = getHintMessage(errors, isTouched, form.state.submissionAttempts); + const hintMessage = getHintMessage(field); return ( { selector={(state) => ({ canSubmit: state.canSubmit, isSubmitting: state.isSubmitting, + isPristine: state.isPristine, })} > - {({ canSubmit, isSubmitting }) => { - const disabled = !canSubmit || isSubmitting; + {({ canSubmit, isSubmitting, isPristine }) => { + const disabled = !canSubmit || isSubmitting || isPristine; return ( - ); diff --git a/src/components/pages/signup/signup-form/index.tsx b/src/components/pages/signup/signup-form/index.tsx index 3ca1b20c..81d02e48 100644 --- a/src/components/pages/signup/signup-form/index.tsx +++ b/src/components/pages/signup/signup-form/index.tsx @@ -1,12 +1,17 @@ 'use client'; -import { useForm } from '@tanstack/react-form'; +import { type AnyFieldApi, useForm } from '@tanstack/react-form'; import { FormInput } from '@/components/shared'; import { Button } from '@/components/ui'; import { signupSchema } from '@/lib/schema/auth'; -const getHintMessage = (errors: unknown[], isTouched: boolean, submissionAttempts: number) => { +const getHintMessage = (field: AnyFieldApi) => { + const { + meta: { errors, isTouched }, + } = field.state; + const { submissionAttempts } = field.form.state; + const firstError = errors[0] as { message?: string } | undefined; const showError = isTouched || submissionAttempts > 0; @@ -42,10 +47,7 @@ export const SignupForm = () => {
{(field) => { - const { - meta: { errors, isTouched }, - } = field.state; - const hintMessage = getHintMessage(errors, isTouched, form.state.submissionAttempts); + const hintMessage = getHintMessage(field); return ( { {(field) => { - const { - meta: { errors, isTouched }, - } = field.state; - const hintMessage = getHintMessage(errors, isTouched, form.state.submissionAttempts); + const hintMessage = getHintMessage(field); return ( { {(field) => { - const { - meta: { errors, isTouched }, - } = field.state; - const hintMessage = getHintMessage(errors, isTouched, form.state.submissionAttempts); + const hintMessage = getHintMessage(field); return ( { {(field) => { - const { - meta: { errors, isTouched }, - } = field.state; - const hintMessage = getHintMessage(errors, isTouched, form.state.submissionAttempts); + const hintMessage = getHintMessage(field); return ( { selector={(state) => ({ canSubmit: state.canSubmit, isSubmitting: state.isSubmitting, + isPristine: state.isPristine, })} > - {({ canSubmit, isSubmitting }) => { - const disabled = !canSubmit || isSubmitting; + {({ canSubmit, isSubmitting, isPristine }) => { + const disabled = !canSubmit || isSubmitting || isPristine; return ( - ); diff --git a/src/components/shared/auth-switch-link/index.tsx b/src/components/shared/auth-switch-link/index.tsx new file mode 100644 index 00000000..da617eb1 --- /dev/null +++ b/src/components/shared/auth-switch-link/index.tsx @@ -0,0 +1,33 @@ +import Link from 'next/link'; + +const authSwitchContent = { + login: { + description: '이미 회원이신가요?', + linkText: '로그인하기', + href: '/login', + }, + signup: { + description: 'WEGO가 처음이신가요?', + linkText: '회원가입하기', + href: '/signup', + }, +} as const; + +type AuthSwitchType = keyof typeof authSwitchContent; + +interface AuthSwitchProps { + type?: AuthSwitchType; +} + +export const AuthSwitch = ({ type = 'login' }: AuthSwitchProps) => { + const content = authSwitchContent[type]; + + return ( +

+ {content.description} + + {content.linkText} + +

+ ); +}; diff --git a/src/components/shared/index.ts b/src/components/shared/index.ts index a4f1c19e..dee0b291 100644 --- a/src/components/shared/index.ts +++ b/src/components/shared/index.ts @@ -1,3 +1,4 @@ +export { AuthSwitch } from './auth-switch-link'; export { FormInput } from './form-input'; export { SearchBar } from './search-bar'; export { TabNavigation } from './tab-navigation';