From f6011b68a194d69102d3cd7ac28929582c3d3ec3 Mon Sep 17 00:00:00 2001 From: minkyo Date: Tue, 30 Sep 2025 11:48:14 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85?= =?UTF-8?q?=EC=97=90=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 6148 -> 6148 bytes package-lock.json | 33 ++++++-- package.json | 3 +- src/components/Button.tsx | 3 + src/components/CustomInput.tsx | 33 +++++--- src/components/Input/CarrerInput.tsx | 5 ++ src/components/Input/DayInput.tsx | 22 +++++ src/components/Input/EmailInput.tsx | 33 ++++++++ src/components/Input/MonthInput.tsx | 22 +++++ src/components/Input/NameInput.tsx | 21 +++++ src/components/Input/PasswordConfrimInput.tsx | 34 ++++++++ src/components/Input/PasswordInput.tsx | 31 +++++++ src/components/Input/RegioinInput.tsx | 26 ++++++ src/components/styles/CustomInput.css | 60 ++++++++++--- src/page/Auth/Signup/Step1.module.css | 6 -- src/page/Auth/Signup/Step1.tsx | 69 +++++++++------ src/page/Auth/Signup/Step2.module.css | 68 +-------------- src/page/Auth/Signup/Step2.tsx | 70 ++++------------ src/page/Auth/Signup/Step3.module.css | 67 +++++++++++++++ src/page/Auth/Signup/Step3.tsx | 76 +++++++++++++++++ src/page/Auth/Signup/index.css | 0 src/page/Auth/Signup/index.tsx | 79 ++++-------------- src/routes/AppRouter.tsx | 12 ++- 23 files changed, 522 insertions(+), 251 deletions(-) create mode 100644 src/components/Input/CarrerInput.tsx create mode 100644 src/components/Input/DayInput.tsx create mode 100644 src/components/Input/EmailInput.tsx create mode 100644 src/components/Input/MonthInput.tsx create mode 100644 src/components/Input/NameInput.tsx create mode 100644 src/components/Input/PasswordConfrimInput.tsx create mode 100644 src/components/Input/PasswordInput.tsx create mode 100644 src/components/Input/RegioinInput.tsx delete mode 100644 src/page/Auth/Signup/Step1.module.css create mode 100644 src/page/Auth/Signup/Step3.module.css create mode 100644 src/page/Auth/Signup/Step3.tsx delete mode 100644 src/page/Auth/Signup/index.css diff --git a/.DS_Store b/.DS_Store index cebf6cddaa3359becea9b4d8dd574b1eb24af27a..6c9de36402e97d47b1b3be478e28198681651259 100644 GIT binary patch delta 86 zcmZoMXffDe%E5CboctsP1_q9tO#L&m&c_|05-C_E_zN-&gOl@f R3xGNp__r}^KFsJS1^|E089e|1 delta 86 zcmZoMXffDe%E;UsxN9;Gql`#yzKcszPJR*t0|SSSZPEROHpd;I5-C_E_zN-&gOl@f R3xGNp_{}$LKFsJS1^{jq8JGY7 diff --git a/package-lock.json b/package-lock.json index 73500e3..d291908 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,8 +12,9 @@ "lucide-react": "^0.525.0", "react": "^19.1.0", "react-dom": "^19.1.0", + "react-hook-form": "^7.63.0", "react-icons": "^5.5.0", - "react-router-dom": "^7.8.2", + "react-router-dom": "^7.9.2", "styled-components": "^6.1.19" }, "devDependencies": { @@ -3266,6 +3267,22 @@ "react": "^19.1.0" } }, + "node_modules/react-hook-form": { + "version": "7.63.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.63.0.tgz", + "integrity": "sha512-ZwueDMvUeucovM2VjkCf7zIHcs1aAlDimZu2Hvel5C5907gUzMpm4xCrQXtRzCvsBqFjonB4m3x4LzCFI1ZKWA==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, "node_modules/react-icons": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", @@ -3286,9 +3303,9 @@ } }, "node_modules/react-router": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.2.tgz", - "integrity": "sha512-7M2fR1JbIZ/jFWqelpvSZx+7vd7UlBTfdZqf6OSdF9g6+sfdqJDAWcak6ervbHph200ePlu+7G8LdoiC3ReyAQ==", + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.2.tgz", + "integrity": "sha512-i2TPp4dgaqrOqiRGLZmqh2WXmbdFknUyiCRmSKs0hf6fWXkTKg5h56b+9F22NbGRAMxjYfqQnpi63egzD2SuZA==", "license": "MIT", "dependencies": { "cookie": "^1.0.1", @@ -3308,12 +3325,12 @@ } }, "node_modules/react-router-dom": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.8.2.tgz", - "integrity": "sha512-Z4VM5mKDipal2jQ385H6UBhiiEDlnJPx6jyWsTYoZQdl5TrjxEV2a9yl3Fi60NBJxYzOTGTTHXPi0pdizvTwow==", + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.9.2.tgz", + "integrity": "sha512-pagqpVJnjZOfb+vIM23eTp7Sp/AAJjOgaowhP1f1TWOdk5/W8Uk8d/M/0wfleqx7SgjitjNPPsKeCZE1hTSp3w==", "license": "MIT", "dependencies": { - "react-router": "7.8.2" + "react-router": "7.9.2" }, "engines": { "node": ">=20.0.0" diff --git a/package.json b/package.json index 1d893d6..c13333d 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,9 @@ "lucide-react": "^0.525.0", "react": "^19.1.0", "react-dom": "^19.1.0", + "react-hook-form": "^7.63.0", "react-icons": "^5.5.0", - "react-router-dom": "^7.8.2", + "react-router-dom": "^7.9.2", "styled-components": "^6.1.19" }, "devDependencies": { diff --git a/src/components/Button.tsx b/src/components/Button.tsx index f94bb2e..f627b43 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -6,6 +6,7 @@ interface ButtonProps { status?: "active" | "inactive"; size?: "small" | "medium" | "large"; icon?: boolean; + type?: "submit" | "reset" | "button"; disabled?: boolean; onClick?: () => void; } @@ -16,6 +17,7 @@ const Button = ({ size = "medium", icon = false, disabled, + type, onClick, }: ButtonProps) => { return ( @@ -23,6 +25,7 @@ const Button = ({ className={`Button Button_${status} Button_${size}`} onClick={onClick} disabled={disabled} + type={type} > {icon && ( diff --git a/src/components/CustomInput.tsx b/src/components/CustomInput.tsx index 865d5bd..452bb6b 100644 --- a/src/components/CustomInput.tsx +++ b/src/components/CustomInput.tsx @@ -1,12 +1,13 @@ import type React from "react"; import "./styles/CustomInput.css"; -interface CustomInputProps { - size: "large" | "medium" | "small" | "auto"; +interface CustomInputProps extends React.InputHTMLAttributes { + inputSize: "large" | "medium" | "small" | "auto"; icon?: React.ReactNode; error?: string; placeholder?: string; disabled?: boolean; + type?: string; onIconPress?: () => void; } @@ -16,21 +17,27 @@ export default function CustomInput({ error, placeholder, disabled, + type, onIconPress, + ...rest }: CustomInputProps) { return ( -
- -
- {icon} -
-
- {Boolean(error) && {error}} +
+
+ + {icon && ( +
+ {icon} +
+ )}
+ {Boolean(error) &&
{error}
}
); } diff --git a/src/components/Input/CarrerInput.tsx b/src/components/Input/CarrerInput.tsx new file mode 100644 index 0000000..e39bf42 --- /dev/null +++ b/src/components/Input/CarrerInput.tsx @@ -0,0 +1,5 @@ +import CustomInput from "../CustomInput"; + +export default function CarrerInput() { + return ; +} diff --git a/src/components/Input/DayInput.tsx b/src/components/Input/DayInput.tsx new file mode 100644 index 0000000..754a251 --- /dev/null +++ b/src/components/Input/DayInput.tsx @@ -0,0 +1,22 @@ +import { IoIosArrowDown } from "react-icons/io"; + +export default function DayInput() { + const months = Array.from({ length: 31 }, (_, i) => i + 1); + return ( +
+
+ +
+ +
+
+
+ ); +} diff --git a/src/components/Input/EmailInput.tsx b/src/components/Input/EmailInput.tsx new file mode 100644 index 0000000..fc4ecf2 --- /dev/null +++ b/src/components/Input/EmailInput.tsx @@ -0,0 +1,33 @@ +import { RiCheckFill } from "react-icons/ri"; +import CustomInput from "../CustomInput"; +import { useFormContext } from "react-hook-form"; + +export default function EmailInput() { + const { + register, + trigger, + getFieldState, + formState: { errors }, + } = useFormContext(); + + const { error, isDirty } = getFieldState("email"); + + return ( + + } + onIconPress={() => trigger("email")} + error={errors.email?.message as string} + {...register("email", { + required: "이메일을 입력해주세요.", + pattern: { + value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, + message: "올바른 이메일 형식이 아닙니다.", + }, + })} + /> + ); +} diff --git a/src/components/Input/MonthInput.tsx b/src/components/Input/MonthInput.tsx new file mode 100644 index 0000000..da50416 --- /dev/null +++ b/src/components/Input/MonthInput.tsx @@ -0,0 +1,22 @@ +import { IoIosArrowDown } from "react-icons/io"; + +export default function MonthInput() { + const months = Array.from({ length: 12 }, (_, i) => i + 1); + return ( +
+
+ +
+ +
+
+
+ ); +} diff --git a/src/components/Input/NameInput.tsx b/src/components/Input/NameInput.tsx new file mode 100644 index 0000000..86ff4ea --- /dev/null +++ b/src/components/Input/NameInput.tsx @@ -0,0 +1,21 @@ +import CustomInput from "../CustomInput"; +import { useFormContext } from "react-hook-form"; + +export default function NameInput() { + const { + register, + formState: { errors }, + } = useFormContext(); + + return ( + + ); +} diff --git a/src/components/Input/PasswordConfrimInput.tsx b/src/components/Input/PasswordConfrimInput.tsx new file mode 100644 index 0000000..d5be4ea --- /dev/null +++ b/src/components/Input/PasswordConfrimInput.tsx @@ -0,0 +1,34 @@ +import { RiCheckFill } from "react-icons/ri"; +import CustomInput from "../CustomInput"; +import { useFormContext } from "react-hook-form"; + +export default function PasswordConfirmInput() { + const { + register, + watch, + trigger, + getFieldState, + formState: { errors }, + } = useFormContext(); + + const password = watch("password"); + const { error, isDirty } = getFieldState("email"); + + return ( + + } + onIconPress={() => trigger("password")} + error={errors.confirm?.message as string} + {...register("confirm", { + required: "비밀번호 확인은 필수입니다.", + validate: (value) => + value === password || "비밀번호가 일치하지 않습니다.", + })} + /> + ); +} diff --git a/src/components/Input/PasswordInput.tsx b/src/components/Input/PasswordInput.tsx new file mode 100644 index 0000000..b84ee01 --- /dev/null +++ b/src/components/Input/PasswordInput.tsx @@ -0,0 +1,31 @@ +import { RiCheckFill } from "react-icons/ri"; +import CustomInput from "../CustomInput"; +import { useFormContext } from "react-hook-form"; + +export default function PasswordInput() { + const { + register, + trigger, + getFieldState, + formState: { errors }, + } = useFormContext(); + + const { error, isDirty } = getFieldState("password"); + + return ( + + } + onIconPress={() => trigger("email")} + error={errors.password?.message as string} + {...register("password", { + required: "비밀번호는 필수입니다.", + minLength: { value: 8, message: "비밀번호는 8자 이상이어야 합니다." }, + })} + /> + ); +} diff --git a/src/components/Input/RegioinInput.tsx b/src/components/Input/RegioinInput.tsx new file mode 100644 index 0000000..cf5c6c9 --- /dev/null +++ b/src/components/Input/RegioinInput.tsx @@ -0,0 +1,26 @@ +import { IoIosArrowDown } from "react-icons/io"; + +export default function RegionInput() { + return ( +
+
+ +
+ +
+
+
+ ); +} diff --git a/src/components/styles/CustomInput.css b/src/components/styles/CustomInput.css index 5da2913..308e545 100644 --- a/src/components/styles/CustomInput.css +++ b/src/components/styles/CustomInput.css @@ -1,10 +1,40 @@ -.input { +/* 전체 wrapper (input + error 포함) */ +.input-wrapper { + display: flex; + flex-direction: column; + width: 100%; + margin-bottom: 1rem; +} + +.input-select { + color: #7a828a; /* input과 같은 글자색 */ + background-color: #edf2f7; /* input과 같은 배경 */ + border: 1px solid transparent; + border-radius: 0.2rem; + padding: 0.3rem; + width: 100%; + height: 2.5rem; /* input과 높이 통일 */ + box-sizing: border-box; + + /* 기본 화살표 제거 */ + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; +} + +/* 실제 input + icon 감싸는 컨테이너 */ +.input-container { position: relative; display: flex; align-items: center; width: 100%; } +.input-container.has-error .input-field { + border: 1px solid red; + background-color: #ffeaea; +} +/* 사이즈별 width */ .input-small { width: 4rem; } @@ -14,29 +44,37 @@ } .input-large { - width: 20rem; - height: 1.3rem; + width: 22rem; + height: 2rem; +} + +.input-auto { + width: auto; } +/* input 필드 */ .input-field { color: #7a828a; background-color: #edf2f7; border: none; border-radius: 0.2rem; padding: 0.6rem; + width: 100%; + box-sizing: border-box; } +/* 아이콘 */ .input-icon { position: absolute; + right: 0.5rem; cursor: pointer; color: #7a828a; } -.input-small .input-icon { - top: 15%; - right: -0.2rem; -} -.input-large .input-icon { - top: 90%; - right: -0.2rem; - transform: translateY(-50%); + +/* 에러 메시지 */ +.input-error { + margin-top: 0.3rem; + color: red; + font-size: 9px; + padding: 0 5px; } diff --git a/src/page/Auth/Signup/Step1.module.css b/src/page/Auth/Signup/Step1.module.css deleted file mode 100644 index 7379c60..0000000 --- a/src/page/Auth/Signup/Step1.module.css +++ /dev/null @@ -1,6 +0,0 @@ -.input { - display: flex; - flex-direction: row; - gap: 40px; - padding: 10px; -} diff --git a/src/page/Auth/Signup/Step1.tsx b/src/page/Auth/Signup/Step1.tsx index 4dd769b..47a756d 100644 --- a/src/page/Auth/Signup/Step1.tsx +++ b/src/page/Auth/Signup/Step1.tsx @@ -1,12 +1,27 @@ -import { IoIosArrowDown } from "react-icons/io"; +import { Link, useNavigate } from "react-router-dom"; import AuthLeft from "../../../components/AuthLeft"; -import CustomInput from "../../../components/CustomInput"; -import styles from "./Step1.module.css"; import Button from "../../../components/Button"; -import { useNavigate } from "react-router-dom"; +import EmailInput from "../../../components/Input/EmailInput"; +import NameInput from "../../../components/Input/NameInput"; +import PasswordInput from "../../../components/Input/PasswordInput"; +import PasswordConfirmInput from "../../../components/Input/PasswordConfrimInput"; +import { useFormContext } from "react-hook-form"; +import CarrerInput from "../../../components/Input/CarrerInput"; + +type FormValues = { + name: string; + email: string; + password: string; +}; const Step1 = () => { const nav = useNavigate(); + const methods = useFormContext(); + + const onSubmit = (data: FormValues) => { + console.log("폼 데이터:", data); + nav("/auth/signup/step2"); + }; return (
@@ -16,28 +31,30 @@ const Step1 = () => {
회원가입 하기 -
- - } - /> - } - /> -
-
-
+
+
+ + + + + +
+ +
+
+
diff --git a/src/page/Auth/Signup/Step2.module.css b/src/page/Auth/Signup/Step2.module.css index d497512..7379c60 100644 --- a/src/page/Auth/Signup/Step2.module.css +++ b/src/page/Auth/Signup/Step2.module.css @@ -1,66 +1,6 @@ -.termsContainer { +.input { display: flex; - flex-direction: column; - width: 100%; - padding: 2rem; - border-radius: 8px; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); -} - -.termsContainer h2 { - font-size: 1.4rem; - font-weight: 600; - margin-bottom: 1.5rem; -} - -.termItem { - display: flex; - justify-content: space-between; - align-items: flex-start; - padding: 1rem 0; - border-bottom: 1px solid #eee; - gap: 1rem; -} - -.termText { - flex: 1; - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -.termTitle { - font-size: 1rem; - font-weight: 600; - color: #222; -} - -.termContent { - font-size: 0.9rem; - color: #555; - line-height: 1.4; - word-break: keep-all; /*단어 단위 줄바꿈*/ - white-space: pre-line; /*줄바꿈허용*/ -} - -.termItem label { - display: flex; - align-items: center; - gap: 0.4rem; - font-size: 0.9rem; - color: #444; - cursor: pointer; -} - -.termItem input[type="checkbox"] { - width: 18px; - height: 18px; - accent-color: #0056d2; - cursor: pointer; -} - -.button { - margin-top: 2rem; - display: flex; - justify-content: center; + flex-direction: row; + gap: 40px; + padding: 10px; } diff --git a/src/page/Auth/Signup/Step2.tsx b/src/page/Auth/Signup/Step2.tsx index 2631cce..478ff91 100644 --- a/src/page/Auth/Signup/Step2.tsx +++ b/src/page/Auth/Signup/Step2.tsx @@ -1,35 +1,14 @@ -import { useState } from "react"; import AuthLeft from "../../../components/AuthLeft"; -import { useNavigate } from "react-router-dom"; +import CustomInput from "../../../components/CustomInput"; import styles from "./Step2.module.css"; import Button from "../../../components/Button"; - -const termsData = [ - { - id: 1, - title: "개인정보수집 동의", - content: - "개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용", - required: true, - }, - { id: 2, title: "서비스 이용약관 동의", content: "", required: true }, - { id: 3, title: "마케팅 활용 동의", content: "", required: false }, -]; +import { useNavigate } from "react-router-dom"; +import MonthInput from "../../../components/Input/MonthInput"; +import DayInput from "../../../components/Input/DayInput"; const Step2 = () => { const nav = useNavigate(); - const [checkedItems, setCheckedItems] = useState<{ [key: number]: boolean }>( - {} - ); - - const handleCheck = (id: number) => { - setCheckedItems((prev) => ({ ...prev, [id]: !prev[id] })); - }; - const allChecked: boolean = termsData - .filter((term) => term.required) - .every((term) => checkedItems[term.id]); - return (
@@ -37,35 +16,18 @@ const Step2 = () => {
-
-

회원가입 하기

-
- {termsData.map((term) => ( -
-
- {term.title} - {term.content} -
- -
- ))} - -
-
-
+ 회원가입 하기 +
+ + + +
+
+
diff --git a/src/page/Auth/Signup/Step3.module.css b/src/page/Auth/Signup/Step3.module.css new file mode 100644 index 0000000..fa868fc --- /dev/null +++ b/src/page/Auth/Signup/Step3.module.css @@ -0,0 +1,67 @@ +.termsContainer { + display: flex; + flex-direction: column; + width: 90%; + padding: 2rem; + margin: 0.5rem; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); +} + +.termsContainer h2 { + font-size: 1.4rem; + font-weight: 600; + margin-bottom: 1.5rem; +} + +.termItem { + display: flex; + justify-content: space-between; + align-items: flex-start; + padding: 1rem 0; + border-bottom: 1px solid #eee; + gap: 1rem; +} + +.termText { + flex: 1; + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.termTitle { + font-size: 1rem; + font-weight: 600; + color: #222; +} + +.termContent { + font-size: 0.9rem; + color: #555; + line-height: 1.4; + word-break: keep-all; /*단어 단위 줄바꿈*/ + white-space: pre-line; /*줄바꿈허용*/ +} + +.termItem label { + display: flex; + align-items: center; + gap: 0.4rem; + font-size: 0.9rem; + color: #444; + cursor: pointer; +} + +.termItem input[type="checkbox"] { + width: 18px; + height: 18px; + accent-color: #0056d2; + cursor: pointer; +} + +.button { + margin-top: 2rem; + display: flex; + justify-content: center; +} diff --git a/src/page/Auth/Signup/Step3.tsx b/src/page/Auth/Signup/Step3.tsx new file mode 100644 index 0000000..53fb8a8 --- /dev/null +++ b/src/page/Auth/Signup/Step3.tsx @@ -0,0 +1,76 @@ +import { useState } from "react"; +import AuthLeft from "../../../components/AuthLeft"; +import { useNavigate } from "react-router-dom"; +import styles from "./Step3.module.css"; +import Button from "../../../components/Button"; + +const termsData = [ + { + id: 1, + title: "개인정보수집 동의", + content: + "개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용개인정보수집 동의내용", + required: true, + }, + { id: 2, title: "서비스 이용약관 동의", content: "", required: true }, + { id: 3, title: "마케팅 활용 동의", content: "", required: false }, +]; + +const Step3 = () => { + const nav = useNavigate(); + + const [checkedItems, setCheckedItems] = useState<{ [key: number]: boolean }>( + {} + ); + + const handleCheck = (id: number) => { + setCheckedItems((prev) => ({ ...prev, [id]: !prev[id] })); + }; + const allChecked: boolean = termsData + .filter((term) => term.required) + .every((term) => checkedItems[term.id]); + + return ( +
+
+ +
+
+
+
+

회원가입 하기

+
+ {termsData.map((term) => ( +
+
+ {term.title} + {term.content} +
+ +
+ ))} + +
+
+
+
+
+
+
+ ); +}; + +export default Step3; diff --git a/src/page/Auth/Signup/index.css b/src/page/Auth/Signup/index.css deleted file mode 100644 index e69de29..0000000 diff --git a/src/page/Auth/Signup/index.tsx b/src/page/Auth/Signup/index.tsx index 4c16a2b..74fa563 100644 --- a/src/page/Auth/Signup/index.tsx +++ b/src/page/Auth/Signup/index.tsx @@ -1,68 +1,19 @@ -import { Link, useNavigate } from "react-router-dom"; -import AuthLeft from "../../../components/AuthLeft"; -import Button from "../../../components/Button"; -import CustomInput from "../../../components/CustomInput"; -import { RiCheckFill } from "react-icons/ri"; -import { IoIosArrowDown } from "react-icons/io"; -import "./index.css"; +import { FormProvider, useForm } from "react-hook-form"; +import { Outlet } from "react-router-dom"; -const Signup = () => { - const nav = useNavigate(); +type FormValues = { + name: string; + email: string; + password: string; + region: string; +}; + +export default function Signup() { + const methods = useForm({ mode: "onChange" }); return ( -
-
- -
-
-
- 회원가입 하기 -
- } - /> - - } - /> - } - /> - } - /> -
-
-
-
-
-
+ + {/* Step1, Step2, Step3 들어옴 */} + ); -}; - -export default Signup; +} diff --git a/src/routes/AppRouter.tsx b/src/routes/AppRouter.tsx index 27170d9..e3ca751 100644 --- a/src/routes/AppRouter.tsx +++ b/src/routes/AppRouter.tsx @@ -7,8 +7,9 @@ import DiagnosisCheck from "../page/DiagnosisCheck/DiagnosisCheck"; import JobMatch from "../page/JobMatch/JobMatch"; import Login from "../page/Auth/Login"; import Step1 from "../page/Auth/Signup/Step1"; -import SignupLayout from "../page/Auth/Signup/index"; +import Signup from "../page/Auth/Signup/index"; import Step2 from "../page/Auth/Signup/Step2"; +import Step3 from "../page/Auth/Signup/Step3"; function AppRouter() { return ( @@ -17,9 +18,12 @@ function AppRouter() { } /> } /> - } /> - } /> - } /> + }> + } /> + } /> + } /> + } /> + } /> } />