Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { ROUTES } from "./constants/router";
import AuthLayout from "./layouts/AuthLayout";
import MainLayout from "./layouts/MainLayout";

const SignupPage = lazy(() => import("@/pages/SignupPage"));
const SigninPage = lazy(() => import("@/pages/SigninPage"));
const SignupPage = lazy(() => import("@/pages/AuthPage/SignupPage"));
const SigninPage = lazy(() => import("@/pages/AuthPage/SigninPage"));

const ProfilePage = lazy(() => import("@/pages/ProfilePage/ProfilePage"));
const ProfileRegisterPage = lazy(() => import("@/pages/ProfileRegisterPage"));
Expand Down
2 changes: 1 addition & 1 deletion src/layouts/AuthLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Outlet } from "react-router-dom";

export default function AuthLayout() {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="min-h-screen flex items-start justify-center pt-[8.75rem] sm:pt-[17.5rem] lg:pt-[19.5rem] ">
<div className="w-[21.875rem]">
<Outlet />
</div>
Expand Down
24 changes: 18 additions & 6 deletions src/pages/SigninPage.tsx → src/pages/AuthPage/SigninPage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { useState } from "react";

import { AxiosError } from "axios";
import { useNavigate, Link } from "react-router-dom";

import Logo from "../assets/logo/thejulge.svg?react";
import { useAuthForm } from "../hooks/useAuthForm";
import Logo from "../../assets/logo/thejulge.svg?react";

import Spinner from "./components/Spinner";
import { useAuthForm } from "./hooks/useAuthForm";

import { postAuthentication } from "@/apis/services/authenticationService";
import Button from "@/components/Button";
Expand All @@ -19,7 +23,12 @@ export default function SigninPage() {
const { formData, errors, isFormValid, handleChange, resetForm } =
useAuthForm("signin");

const [isSubmitting, setIsSubmitting] = useState(false);

const handleSubmit = async () => {
if (isSubmitting) return;
setIsSubmitting(true);

try {
const res = await postAuthentication({
email: formData.email,
Expand Down Expand Up @@ -72,13 +81,15 @@ export default function SigninPage() {
},
],
});
} finally {
setIsSubmitting(false);
}
};

return (
<div className="w-full">
<Link to={ROUTES.NOTICE.ROOT}>
<Logo className="mx-auto mb-2 h-[2.8125rem] w-[15.5rem]" />
<Logo className="mx-auto mb-2 h-[2.375rem] sm:h-[2.8125rem] w-[13rem] sm:w-[15.5rem]" />
</Link>

<form
Expand Down Expand Up @@ -115,11 +126,12 @@ export default function SigninPage() {
<Button
type="submit"
fullWidth
className="py-[0.875rem]"
className="py-[0.875rem] flex justify-center items-center gap-2"
onClick={handleSubmit}
disabled={!isFormValid}
disabled={!isFormValid || isSubmitting}
>
로그인하기
{isSubmitting && <Spinner />}
{isSubmitting ? "로그인 중..." : "로그인하기"}
</Button>
</form>

Expand Down
26 changes: 19 additions & 7 deletions src/pages/SignupPage.tsx → src/pages/AuthPage/SignupPage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { useState } from "react";

import { AxiosError } from "axios";
import clsx from "clsx";
import { useNavigate, Link } from "react-router-dom";

import IconCheck from "../assets/icon/check.svg?react";
import Logo from "../assets/logo/thejulge.svg?react";
import { useAuthForm } from "../hooks/useAuthForm";
import IconCheck from "../../assets/icon/check.svg?react";
import Logo from "../../assets/logo/thejulge.svg?react";

import Spinner from "./components/Spinner";
import { useAuthForm } from "./hooks/useAuthForm";

import { postAuthentication } from "@/apis/services/authenticationService";
import { postUser } from "@/apis/services/userService";
Expand All @@ -28,7 +32,12 @@ export default function SignupPage() {
resetForm,
} = useAuthForm("signup");

const [isSubmitting, setIsSubmitting] = useState(false);

const handleSubmit = async () => {
if (isSubmitting) return;
setIsSubmitting(true);

try {
const response = await postUser({
email: formData.email,
Expand Down Expand Up @@ -90,13 +99,15 @@ export default function SignupPage() {
},
],
});
} finally {
setIsSubmitting(false);
}
};

return (
<div className="w-full">
<Link to={ROUTES.NOTICE.ROOT}>
<Logo className="mx-auto mb-2 h-[2.8125rem] w-[15.5rem]" />
<Logo className="mx-auto mb-2 h-[2.375rem] sm:h-[2.8125rem] w-[13rem] sm:w-[15.5rem]" />
</Link>

<form
Expand Down Expand Up @@ -215,10 +226,11 @@ export default function SignupPage() {
<Button
type="submit"
fullWidth
className="py-[0.875rem]"
disabled={!isFormValid}
className="py-[0.875rem] flex justify-center items-center gap-2"
disabled={!isFormValid || isSubmitting}
>
가입하기
{isSubmitting && <Spinner />}
{isSubmitting ? "가입 중..." : "가입하기"}
</Button>
</form>

Expand Down
5 changes: 5 additions & 0 deletions src/pages/AuthPage/components/Spinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default function Spinner() {
return (
<div className="w-5 h-5 border-2 border-t-white border-gray-300 rounded-full animate-spin" />
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,34 @@ export function useAuthForm(mode: Mode) {
(field: keyof FormData) => (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setFormData((prev) => ({ ...prev, [field]: value }));

if (field === "email") {
const isValidEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
setErrors((prev) => ({
...prev,
email: isValidEmail ? undefined : "올바른 이메일 형식이 아닙니다.",
email:
value.length === 0
? undefined
: value.includes("@")
? /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
? undefined
: "올바른 이메일 형식이 아닙니다."
: undefined,
}));
}

if (field === "password") {
const trimmed = value.trim();
setErrors((prev) => ({
...prev,
password:
value.length >= 8 ? undefined : "비밀번호는 8자 이상이어야 합니다.",
value.length > 0 && trimmed.length === 0
? "비밀번호에 공백만 입력할 수 없습니다."
: trimmed.length > 0 && trimmed.length < 8
? "비밀번호는 최소 8자 이상이어야 합니다."
: undefined,
...(mode === "signup" &&
formData.confirmPassword && {
confirmPassword:
value !== formData.confirmPassword
trimmed !== formData.confirmPassword
? "비밀번호가 일치하지 않습니다."
: undefined,
}),
Expand Down