diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml
index e0107cb..da594a8 100644
--- a/.github/workflows/github-actions.yml
+++ b/.github/workflows/github-actions.yml
@@ -1,4 +1,4 @@
-name: Frontend GitHub Actions
+name: Merge To Ready
run-name: ${{ github.actor }} is testing out GitHub Actions ๐
on:
push:
diff --git a/.github/workflows/sync-to-fork.yml b/.github/workflows/sync-to-fork.yml
new file mode 100644
index 0000000..fa5846f
--- /dev/null
+++ b/.github/workflows/sync-to-fork.yml
@@ -0,0 +1,39 @@
+name: Sync Fork With Upstream
+on:
+ push:
+ branches:
+ - main
+ - develop
+
+jobs:
+ sync:
+ if: github.repository == 'BrainPix-front'
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout develop
+ uses: actions/checkout@v3
+ with:
+ token: ${{secrets.PAT_TOKEN}}
+ ref: develop
+ persition-credentials: false
+
+ - name: Set up Git
+ run: |
+ git config user.name minejeong9919
+ git config user.email "minjeong9919@github.com"
+
+ - name: Add remote-url
+ run: |
+ git remote add forked-repo https://github.com/minjeong9919/BrainPix-front.git
+
+ - name: Push changes to Forked-reop
+ env:
+ GITHUB_USERNAME: minjeong9919
+ GITHUB_TOKEN: ${{secrets.PAT_TOKEN}}
+ run: |
+ git push -f http://$GITHUB_USERNAME:$GITHUB_TOKEN@https://github.com/minjeong9919/BrainPix-front.git develop
+
+ - name: Clean up
+ run: |
+ git remote remove forked-repo
diff --git a/index.html b/index.html
index a1a1f2c..b30f745 100644
--- a/index.html
+++ b/index.html
@@ -5,11 +5,11 @@
+ href="/src/assets/images/brainPixIcon.png" />
-
Vite + React + TS
+ BrainPIX
diff --git a/package-lock.json b/package-lock.json
index 380a4d6..c706553 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,7 @@
"eslint-plugin-jsx-a11y": "^6.10.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
+ "react-hook-form": "^7.54.2",
"react-router-dom": "^7.1.1"
},
"devDependencies": {
@@ -38,7 +39,7 @@
"typescript": "~5.6.2",
"typescript-eslint": "^8.18.2",
"typescript-plugin-css-modules": "^5.1.0",
- "vite": "^6.0.5",
+ "vite": "^6.0.7",
"vite-plugin-svgr": "^4.3.0"
}
},
@@ -5781,6 +5782,22 @@
"react": "^18.3.1"
}
},
+ "node_modules/react-hook-form": {
+ "version": "7.54.2",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz",
+ "integrity": "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==",
+ "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-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
diff --git a/package.json b/package.json
index 2f87cab..cca4cff 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"eslint-plugin-jsx-a11y": "^6.10.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
+ "react-hook-form": "^7.54.2",
"react-router-dom": "^7.1.1"
},
"devDependencies": {
@@ -41,7 +42,7 @@
"typescript": "~5.6.2",
"typescript-eslint": "^8.18.2",
"typescript-plugin-css-modules": "^5.1.0",
- "vite": "^6.0.5",
+ "vite": "^6.0.7",
"vite-plugin-svgr": "^4.3.0"
}
}
diff --git a/src/App.tsx b/src/App.tsx
index 6fbc1c0..91f27c2 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -7,9 +7,10 @@ import IdeaMarketPayment from './pages/idea-market/IdeaMarketPayment/IdeaMarketP
import { RequestAssign } from './pages/request-assign/RequestAssign';
import { Collaboration } from './pages/collaboration/Collaboration';
import { Signup } from './pages/sign-up/Signup';
-import { IndividualMember } from './pages/sign-up/IndividualMember';
-import { CorporateMember } from './pages/sign-up/CorporateMember';
-import { CompleteSignup } from './pages/sign-up/CompleteSignup';
+import { IndividualMember } from './pages/sign-up/individual/IndividualMember';
+import { CorporateMember } from './pages/sign-up/corporate/CorporateMember';
+import { CompleteSignup } from './components/sign-up/CompleteSignup';
+import { Login } from './pages/login/Login';
function App() {
return (
@@ -57,6 +58,10 @@ function App() {
path='/sign-up/complete'
element={}
/>
+ }
+ />
);
diff --git a/src/assets/icons/bookmark.svg b/src/assets/icons/bookmark.svg
new file mode 100644
index 0000000..38fa5df
--- /dev/null
+++ b/src/assets/icons/bookmark.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/icons/eyeNonVisible.svg b/src/assets/icons/eyeNonVisible.svg
new file mode 100644
index 0000000..60c3f62
--- /dev/null
+++ b/src/assets/icons/eyeNonVisible.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/eyeVisible.svg b/src/assets/icons/eyeVisible.svg
new file mode 100644
index 0000000..197965d
--- /dev/null
+++ b/src/assets/icons/eyeVisible.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/profile.svg b/src/assets/icons/profile.svg
new file mode 100644
index 0000000..f57b3eb
--- /dev/null
+++ b/src/assets/icons/profile.svg
@@ -0,0 +1,9 @@
+
diff --git a/src/assets/images/brainPixIcon.png b/src/assets/images/brainPixIcon.png
new file mode 100644
index 0000000..ef3f408
Binary files /dev/null and b/src/assets/images/brainPixIcon.png differ
diff --git a/src/components/button/ButtonGroup.tsx b/src/components/common/button/ButtonGroup.tsx
similarity index 100%
rename from src/components/button/ButtonGroup.tsx
rename to src/components/common/button/ButtonGroup.tsx
diff --git a/src/components/button/PaymentButton.module.scss b/src/components/common/button/PaymentButton.module.scss
similarity index 100%
rename from src/components/button/PaymentButton.module.scss
rename to src/components/common/button/PaymentButton.module.scss
diff --git a/src/components/button/PaymentButton.tsx b/src/components/common/button/PaymentButton.tsx
similarity index 100%
rename from src/components/button/PaymentButton.tsx
rename to src/components/common/button/PaymentButton.tsx
diff --git a/src/components/button/buttonGroup.module.scss b/src/components/common/button/buttonGroup.module.scss
similarity index 100%
rename from src/components/button/buttonGroup.module.scss
rename to src/components/common/button/buttonGroup.module.scss
diff --git a/src/components/header/Header.tsx b/src/components/common/header/Header.tsx
similarity index 100%
rename from src/components/header/Header.tsx
rename to src/components/common/header/Header.tsx
diff --git a/src/components/header/SearchInput.tsx b/src/components/common/header/SearchInput.tsx
similarity index 92%
rename from src/components/header/SearchInput.tsx
rename to src/components/common/header/SearchInput.tsx
index 76595ab..075dd17 100644
--- a/src/components/header/SearchInput.tsx
+++ b/src/components/common/header/SearchInput.tsx
@@ -1,11 +1,11 @@
import classNames from 'classnames';
import { ChangeEvent, useRef, useState, KeyboardEvent } from 'react';
-import { useOutsideClick } from '../../hooks/useOutsideClick';
-import Search from '../../assets/icons/search.svg?react';
-import Delete from '../../assets/icons/delete.svg?react';
-import Clock from '../../assets/icons/clock.svg?react';
-import { debounce } from '../../utils/debounce';
+import Search from '../../../assets/icons/search.svg?react';
+import Delete from '../../../assets/icons/delete.svg?react';
+import Clock from '../../../assets/icons/clock.svg?react';
+import { debounce } from '../../../utils/debounce';
+import { useOutsideClick } from '../../../hooks/useOutsideClick';
import styles from './searchInput.module.scss';
diff --git a/src/components/header/header.module.scss b/src/components/common/header/header.module.scss
similarity index 100%
rename from src/components/header/header.module.scss
rename to src/components/common/header/header.module.scss
diff --git a/src/components/header/searchInput.module.scss b/src/components/common/header/searchInput.module.scss
similarity index 100%
rename from src/components/header/searchInput.module.scss
rename to src/components/common/header/searchInput.module.scss
diff --git a/src/components/preview/PreviewThumbnail.tsx b/src/components/preview/PreviewThumbnail.tsx
new file mode 100644
index 0000000..7f8110e
--- /dev/null
+++ b/src/components/preview/PreviewThumbnail.tsx
@@ -0,0 +1,68 @@
+import React from 'react';
+import styles from './previewThumbnail.module.scss';
+import Bookmark from '../../assets/icons/bookmark.svg?react';
+
+interface PreviewThumbnailProps {
+ imageUrl?: string;
+ profileImage?: string;
+ username?: string;
+ description?: string;
+ price?: number;
+ isBookmarked?: boolean;
+ onBookmarkClick?: () => void;
+ verified?: boolean;
+}
+
+const PreviewThumbnail: React.FC = ({
+ imageUrl = '',
+ profileImage = '',
+ username = '',
+ description = '',
+ price = 0,
+ isBookmarked = false,
+ onBookmarkClick = () => {},
+ verified = false,
+}) => {
+ return (
+
+
+
+
+
+
{username}
+ {verified &&
์ธ์ฆ๋จ}
+
+
+
+ {imageUrl ? (
+
+ ) : (
+
+ )}
+
+
+
+
{description}
+
+ {price?.toLocaleString() ?? 0}์
+
+
+
+
+ );
+};
+
+export default PreviewThumbnail;
diff --git a/src/components/preview/previewThumbnail.module.scss b/src/components/preview/previewThumbnail.module.scss
new file mode 100644
index 0000000..03b9e9d
--- /dev/null
+++ b/src/components/preview/previewThumbnail.module.scss
@@ -0,0 +1,95 @@
+.container {
+ width: 312px;
+ border: 0.5px solid #DBDBDB;
+ border-radius: 5px;
+ }
+
+ .profileSection {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 8px;
+
+ & > span {
+ font-size: 14px;
+ color: #424242;
+ }
+ }
+
+ .profileImage {
+ width: 24px;
+ height: 24px;
+ border-radius: 50%;
+ overflow: hidden;
+
+ & > img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ }
+ }
+
+ .verifiedBadge {
+ padding: 2px 8px;
+ background-color: #006AC6;
+ color: white;
+ border-radius: 4px;
+ font-size: 12px;
+ }
+
+ .thumbnailImage {
+ width: 312px;
+ height: 372px;
+ background-color: #DBDBDB;
+
+ & > img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ }
+ }
+
+ .contentSection {
+ padding: 12px;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+
+ & > p {
+ font-size: 14px;
+ color: #424242;
+ }
+ }
+
+ .priceSection {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ & > span {
+ font-weight: 500;
+ font-size: 16px;
+ color: #424242;
+ }
+
+ & > button {
+ cursor: pointer;
+ background: none;
+ border: none;
+ padding: 0;
+ }
+ }
+
+ .bookmarkIcon {
+ width: 20px;
+ height: 20px;
+ color: #757575;
+
+ &.bookmarked {
+ fill: #757575;
+ }
+
+ &:hover {
+ color: #424242;
+ }
+ }
\ No newline at end of file
diff --git a/src/pages/sign-up/CompleteSignup.tsx b/src/components/sign-up/CompleteSignup.tsx
similarity index 100%
rename from src/pages/sign-up/CompleteSignup.tsx
rename to src/components/sign-up/CompleteSignup.tsx
diff --git a/src/components/sign-up/Input.tsx b/src/components/sign-up/Input.tsx
new file mode 100644
index 0000000..45de3b8
--- /dev/null
+++ b/src/components/sign-up/Input.tsx
@@ -0,0 +1,115 @@
+import {
+ ChangeEvent,
+ InputHTMLAttributes,
+ Dispatch,
+ forwardRef,
+ useRef,
+ useState,
+ SetStateAction,
+} from 'react';
+import styles from './input.module.scss';
+import classNames from 'classnames';
+
+interface InputProps extends InputHTMLAttributes {
+ label?: string;
+ isEmail?: boolean;
+ errorMessage?: string;
+ setEmailDomain?: Dispatch>;
+ onChangeEmailDomain?: (e: ChangeEvent) => void;
+}
+
+export const Input = forwardRef(
+ (
+ {
+ label,
+ isEmail = false,
+ onChangeEmailDomain = null,
+ setEmailDomain,
+ errorMessage,
+ ...rest
+ },
+ ref,
+ ) => {
+ const emailDomainRef = useRef(null);
+ const [inputData, setInputData] = useState('');
+ const [selectedEmailDomain, setSelectedEmailDomain] = useState('์ง์ ์
๋ ฅ');
+
+ const handleChangeEmailDomainInput = (e: ChangeEvent) => {
+ const inputData = e.target.value;
+ setInputData(inputData);
+ setEmailDomain?.(inputData);
+ };
+
+ const handleChangeEmailDomainSelect = (
+ e: ChangeEvent,
+ ) => {
+ const selectedValue = e.target.value;
+ setSelectedEmailDomain(selectedValue);
+ onChangeEmailDomain?.(e);
+ setEmailDomain?.(selectedValue);
+ };
+
+ return (
+
+ {label &&
{label}
}
+
+ {isEmail ? (
+
+
+
+
+
+
+
+
+
+ ) : (
+ <>
+
+ {errorMessage && (
+
{errorMessage}
+ )}
+ >
+ )}
+
+ );
+ },
+);
+
+Input.displayName = 'Input';
diff --git a/src/pages/sign-up/commonSignup.module.scss b/src/components/sign-up/commonSignup.module.scss
similarity index 100%
rename from src/pages/sign-up/commonSignup.module.scss
rename to src/components/sign-up/commonSignup.module.scss
diff --git a/src/pages/sign-up/completeSignup.module.scss b/src/components/sign-up/completeSignup.module.scss
similarity index 100%
rename from src/pages/sign-up/completeSignup.module.scss
rename to src/components/sign-up/completeSignup.module.scss
diff --git a/src/pages/sign-up/input.module.scss b/src/components/sign-up/input.module.scss
similarity index 84%
rename from src/pages/sign-up/input.module.scss
rename to src/components/sign-up/input.module.scss
index 586fe25..14d3673 100644
--- a/src/pages/sign-up/input.module.scss
+++ b/src/components/sign-up/input.module.scss
@@ -1,14 +1,20 @@
.container {
padding-top: 6px;
+}
- & > p {
- margin: 0px;
- margin-top: 5px;
- color: #333;
- font-size: 11px;
- font-weight: 500;
- margin-bottom: 1px;
- }
+.label {
+ margin: 0;
+ margin-top: 5px;
+ color: #333;
+ font-size: 11px;
+ font-weight: 500;
+ margin-bottom: 1px;
+}
+
+.errorMessage {
+ color: red;
+ font-size: 10px;
+ margin-top: 5px;
}
@mixin input {
diff --git a/src/constants/errorMessage.ts b/src/constants/errorMessage.ts
new file mode 100644
index 0000000..a934c4c
--- /dev/null
+++ b/src/constants/errorMessage.ts
@@ -0,0 +1,7 @@
+export const SIGN_UP_ERROR_MESSAGE = {
+ id: '์์ด๋๋ 6~12์์ ์๋ฌธ์ ์๋ฌธ, ์ซ์๋ง ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.',
+ passwordRegex:
+ '๋ฐ๋์ ์๋ฌธ(์๋ฌธ์, ๋๋ฌธ์), ์ซ์, ํน์๋ฌธ์ ์ค 2๊ฐ์ง ์ด์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.',
+ passwordLength: '๋น๋ฐ ๋ฒํธ๋ 8~20์ ์ด๋ด๋ก ์
๋ ฅํด์ผ ํฉ๋๋ค.',
+ passwordCheck: '๋น๋ฐ๋ฒํธ๋ ๋์ผํ๊ฒ ์
๋ ฅํด์ผ ํฉ๋๋ค.',
+};
diff --git a/src/constants/registers.ts b/src/constants/registers.ts
new file mode 100644
index 0000000..a8c6ede
--- /dev/null
+++ b/src/constants/registers.ts
@@ -0,0 +1,106 @@
+import {
+ FieldValues,
+ UseFormRegister,
+ UseFormSetValue,
+ UseFormWatch,
+} from 'react-hook-form';
+import { SIGN_UP_ERROR_MESSAGE } from './errorMessage';
+import { formatBirth } from '../utils/formatBirth';
+
+interface RegistersProps {
+ register: UseFormRegister;
+ watch?: UseFormWatch;
+ setValue?: UseFormSetValue;
+}
+
+export const loginRegisters = (register: UseFormRegister) => {
+ const registers = {
+ id: register('id'),
+ password: register('password'),
+ };
+
+ return registers;
+};
+
+export const IndividualMemberRegisters = ({
+ register,
+ watch,
+ setValue,
+}: RegistersProps) => {
+ if (!watch || !setValue) {
+ return {
+ id: register('id'),
+ password: register('password'),
+ passwordCheck: register('passwordCheck'),
+ name: register('name'),
+ birth: register('birth'),
+ email: register('email'),
+ };
+ }
+ const registers = {
+ id: register('id', {
+ required: SIGN_UP_ERROR_MESSAGE.id,
+ minLength: { value: 6, message: SIGN_UP_ERROR_MESSAGE.id },
+ maxLength: { value: 12, message: SIGN_UP_ERROR_MESSAGE.id },
+ pattern: {
+ value: /^[a-z0-9]+$/,
+ message: SIGN_UP_ERROR_MESSAGE.id,
+ },
+ }),
+ password: register('password', {
+ minLength: { value: 8, message: SIGN_UP_ERROR_MESSAGE.passwordLength },
+ maxLength: { value: 20, message: SIGN_UP_ERROR_MESSAGE.passwordLength },
+ }),
+ passwordCheck: register('passwordCheck', {
+ validate: (value) => {
+ if (watch('password') !== value) {
+ return SIGN_UP_ERROR_MESSAGE.passwordCheck;
+ }
+ return true;
+ },
+ }),
+ name: register('name'),
+ birth: register('birth', {
+ onChange: (e) => {
+ setValue('birth', formatBirth(e.target.value));
+ },
+ }),
+ email: register('email'),
+ };
+
+ return registers;
+};
+
+export const CorporateMemberRegisters = ({
+ register,
+ setValue,
+}: RegistersProps) => {
+ if (!setValue) {
+ return {
+ id: register('id'),
+ password: register('password'),
+ passwordCheck: register('passwordCheck'),
+ name: register('name'),
+ companyName: register('companyName'),
+ birth: register('birth'),
+ email: register('email'),
+ position: register('position'),
+ };
+ }
+ const registers = {
+ id: register('id'),
+ password: register('password'),
+ passwordCheck: register('passwordCheck'),
+ name: register('name'),
+ companyName: register('companyName'),
+ birth: register('birth', {
+ onChange: (e) => {
+ setValue('birth', formatBirth(e.target.value));
+ },
+ }),
+ email: register('email'),
+ position: register('position'),
+ };
+
+ return registers;
+};
diff --git a/src/pages/idea-market/IdeaMarketPayment/IdeaMarketPayment.tsx b/src/pages/idea-market/IdeaMarketPayment/IdeaMarketPayment.tsx
index 01cfc1a..70a0729 100644
--- a/src/pages/idea-market/IdeaMarketPayment/IdeaMarketPayment.tsx
+++ b/src/pages/idea-market/IdeaMarketPayment/IdeaMarketPayment.tsx
@@ -3,7 +3,7 @@ import PaymentTitle from '../../../components/payment/PaymentTitle';
import SellerInfo from '../../../components/info/SellerInfo';
import PaymentMethods from '../../../components/payment/PaymentMethods';
import PaymentSummary from '../../../components/payment/PaymentSummary';
-import PaymentButton from '../../../components/button/PaymentButton';
+import PaymentButton from '../../../components/common/button/PaymentButton';
import styles from './IdeaMarketPayment.module.scss';
const IdeaMarketPayment: React.FC = () => {
diff --git a/src/pages/layout/Layout.tsx b/src/pages/layout/Layout.tsx
index 54915c4..bee1a51 100644
--- a/src/pages/layout/Layout.tsx
+++ b/src/pages/layout/Layout.tsx
@@ -1,5 +1,5 @@
import { Outlet } from 'react-router-dom';
-import { Header } from '../../components/header/Header';
+import { Header } from '../../components/common/header/Header';
export const Layout = () => {
return (
diff --git a/src/pages/login/Login.tsx b/src/pages/login/Login.tsx
new file mode 100644
index 0000000..61aee5a
--- /dev/null
+++ b/src/pages/login/Login.tsx
@@ -0,0 +1,111 @@
+import { useState } from 'react';
+import { FieldValues, SubmitHandler, useForm } from 'react-hook-form';
+import classNames from 'classnames';
+import EyeVisible from '../../assets/icons/eyeVisible.svg?react';
+import EyeNonVisible from '../../assets/icons/eyeNonVisible.svg?react';
+import Delete from '../../assets/icons/delete.svg?react';
+import styles from './login.module.scss';
+import { loginRegisters } from '../../constants/registers';
+
+export const Login = () => {
+ const [isVisiblePassword, setIsVisiblePassword] = useState(false);
+ const [member, setMember] = useState<'individual' | 'corparate'>(
+ 'individual',
+ );
+
+ const { register, handleSubmit, setValue } = useForm({ mode: 'onSubmit' });
+
+ const handleSubmitHandler: SubmitHandler = (payload) => {
+ console.log(payload);
+ };
+
+ const registers = loginRegisters(register);
+
+ const handleClickDelete = (type: 'id' | 'password') => {
+ if (type === 'password') {
+ return setValue('password', '');
+ }
+ if (type === 'id') {
+ return setValue('id', '');
+ }
+ };
+
+ return (
+
+
๋ก๊ณ
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/pages/login/login.module.scss b/src/pages/login/login.module.scss
new file mode 100644
index 0000000..04a90e0
--- /dev/null
+++ b/src/pages/login/login.module.scss
@@ -0,0 +1,149 @@
+.container {
+ padding-top: 75px;
+}
+
+.logo {
+ @include flex-center;
+
+ width: 293px;
+ height: 102px;
+ background-color: #d9d9d9;
+ border-radius: 5px;
+ margin: 0 auto;
+}
+
+.loginContainer {
+ width: 575px;
+ height: 404px;
+ background-color: #d9d9d9;
+ border-radius: 15px;
+ position: relative;
+ margin: 0 auto;
+ margin-top: 33px;
+ animation: shadow-drop-center 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
+}
+
+.buttonWrapper {
+ background-color: #d9d9d9;
+ border-radius: 15px;
+ position: absolute;
+ width: 100%;
+}
+
+.memberButton {
+ width: 50%;
+ background-color: #d9d9d9;
+ border-bottom: none;
+ font-size: 26px;
+ font-weight: 600;
+ color: #515151;
+ border: none;
+ text-align: center;
+ cursor: pointer;
+ border-radius: 15px 15px 0 0;
+}
+
+.clicked {
+ position: relative;
+ color: #222;
+ background-color: white;
+ border: 1px solid black;
+ border-bottom: none;
+ height: 67px;
+ z-index: 10;
+}
+
+.inputContainer {
+ @include flex-center;
+
+ position: absolute;
+ top: 66px;
+ width: 100%;
+ height: 338px;
+ background-color: white;
+ border: 1px solid black;
+
+ &.right {
+ border-radius: 15px 0 15px 15px;
+ }
+
+ &.left {
+ border-radius: 0 15px 15px;
+ }
+}
+
+.form {
+ @include flex-center;
+
+ flex-direction: column;
+ width: 100%;
+ padding: 40px 37px 30px;
+}
+
+.label {
+ width: 100%;
+ color: #333;
+ font-size: 15px;
+ font-weight: 400;
+ text-align: left;
+ margin-bottom: 8px;
+ position: relative;
+}
+
+.iconWrapper {
+ height: 17px;
+ position: absolute;
+ right: 12px;
+ top: 40px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.input {
+ width: 100%;
+ padding: 12px;
+ margin-bottom: 20px;
+ border: 1px solid #7a7a7a;
+ border-radius: 2px;
+
+ &:focus {
+ outline: none;
+ }
+
+ &::placeholder {
+ color: #898989;
+ font-size: 13px;
+ font-weight: 400;
+ }
+}
+
+.loginButton {
+ width: 260px;
+ height: 40px;
+ border-radius: 2px;
+ background-color: black;
+ color: white;
+ font-size: 15px;
+ font-weight: 600;
+ cursor: pointer;
+ margin-bottom: 20px;
+}
+
+.signUpText {
+ color: #898989;
+ font-size: 13px;
+ font-weight: 400;
+ text-decoration: none;
+}
+
+@keyframes shadow-drop-center {
+ 0% {
+ box-shadow: 0 0 0 0 rgb(0 0 0 / 0%);
+ }
+
+ 100% {
+ box-shadow: 0 0 20px 0 rgb(0 0 0 / 35%);
+ }
+}
diff --git a/src/pages/sign-up/CorporateMember.tsx b/src/pages/sign-up/CorporateMember.tsx
deleted file mode 100644
index f94191b..0000000
--- a/src/pages/sign-up/CorporateMember.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import classNames from 'classnames';
-import { Input } from './Input';
-import styles from './corporateMember.module.scss';
-import { useNavigate } from 'react-router-dom';
-
-export const CorporateMember = () => {
- const navigate = useNavigate();
- return (
-
-
๋ก๊ณ
-
- ๊ธฐ์
ํ์
- ๊ฐ์
์ ๋ณด ์
๋ ฅํ๊ธฐ
-
-
-
- );
-};
diff --git a/src/pages/sign-up/IndividualMember.tsx b/src/pages/sign-up/IndividualMember.tsx
deleted file mode 100644
index 21c8b2d..0000000
--- a/src/pages/sign-up/IndividualMember.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import classNames from 'classnames';
-import { useNavigate } from 'react-router-dom';
-import { Input } from './Input';
-import styles from './individualMember.module.scss';
-
-export const IndividualMember = () => {
- const navigate = useNavigate();
- return (
-
-
๋ก๊ณ
-
- ๊ฐ์ธ ํ์ ๊ฐ์
์ ๋ณด ์
๋ ฅํ๊ธฐ
-
-
-
- );
-};
diff --git a/src/pages/sign-up/Input.tsx b/src/pages/sign-up/Input.tsx
deleted file mode 100644
index ff896f0..0000000
--- a/src/pages/sign-up/Input.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import { InputHTMLAttributes } from 'react';
-import styles from './input.module.scss';
-import classNames from 'classnames';
-
-interface InputProps extends InputHTMLAttributes {
- label?: string;
- type?: 'default' | 'email';
-}
-
-export const Input = ({ label, type = 'default', ...rest }: InputProps) => {
- return (
-
- {label &&
{label}
}
- {type === 'default' && (
-
- )}
- {type === 'email' && (
-
-
-
-
-
-
-
-
-
- )}
-
- );
-};
diff --git a/src/pages/sign-up/corporate/CorporateMember.tsx b/src/pages/sign-up/corporate/CorporateMember.tsx
new file mode 100644
index 0000000..dcaa975
--- /dev/null
+++ b/src/pages/sign-up/corporate/CorporateMember.tsx
@@ -0,0 +1,90 @@
+import { FieldValues, SubmitHandler, useForm } from 'react-hook-form';
+import classNames from 'classnames';
+import { Input } from '../../../components/sign-up/Input';
+import styles from './corporateMember.module.scss';
+import { CorporateMemberRegisters } from '../../../constants/registers';
+// import { useNavigate } from 'react-router-dom';
+
+export const CorporateMember = () => {
+ // const navigate = useNavigate();
+
+ const { register, handleSubmit, setValue } = useForm({ mode: 'onTouched' });
+
+ const registers = CorporateMemberRegisters({ register, setValue });
+
+ const handleSubmitHandler: SubmitHandler = (payload) => {
+ console.log(payload);
+ };
+
+ return (
+
+
๋ก๊ณ
+
+ ๊ธฐ์
ํ์
+ ๊ฐ์
์ ๋ณด ์
๋ ฅํ๊ธฐ
+
+
+
+ );
+};
diff --git a/src/pages/sign-up/corporate/corporateMember.module.scss b/src/pages/sign-up/corporate/corporateMember.module.scss
new file mode 100644
index 0000000..e350075
--- /dev/null
+++ b/src/pages/sign-up/corporate/corporateMember.module.scss
@@ -0,0 +1,7 @@
+@import '../../../components/sign-up/commonSignup.module';
+
+.textBlue {
+ & > strong {
+ color: #00a5e1;
+ }
+}
diff --git a/src/pages/sign-up/corporateMember.module.scss b/src/pages/sign-up/corporateMember.module.scss
deleted file mode 100644
index 73ebe0e..0000000
--- a/src/pages/sign-up/corporateMember.module.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-@import './commonSignup.module.scss';
-
-.textBlue {
- & > strong {
- color: #00a5e1;
- }
-}
diff --git a/src/pages/sign-up/individual/IndividualMember.tsx b/src/pages/sign-up/individual/IndividualMember.tsx
new file mode 100644
index 0000000..e457402
--- /dev/null
+++ b/src/pages/sign-up/individual/IndividualMember.tsx
@@ -0,0 +1,106 @@
+import { ChangeEvent, useState } from 'react';
+import classNames from 'classnames';
+import { FieldValues, SubmitHandler, useForm } from 'react-hook-form';
+// import { useNavigate } from 'react-router-dom';
+import { Input } from '../../../components/sign-up/Input';
+import styles from './individualMember.module.scss';
+import { IndividualMemberRegisters } from '../../../constants/registers';
+
+export const IndividualMember = () => {
+ // const navigate = useNavigate();
+ const [emailDomain, setEmailDomain] = useState('');
+
+ const {
+ register,
+ handleSubmit,
+ watch,
+ setValue,
+ formState: { errors },
+ } = useForm({ mode: 'onTouched' });
+
+ const registers = IndividualMemberRegisters({ register, watch, setValue });
+
+ const handleSubmitHandler: SubmitHandler = (payload) => {
+ const data = { ...payload, email: payload.email + '@' + emailDomain };
+ console.log(data);
+ };
+
+ const handleChangeEmailDomain = (e: ChangeEvent) => {
+ setEmailDomain(e.target.value);
+ };
+
+ return (
+
+
๋ก๊ณ
+
+ ๊ฐ์ธ ํ์ ๊ฐ์
์ ๋ณด ์
๋ ฅํ๊ธฐ
+
+
+
+ );
+};
diff --git a/src/pages/sign-up/individual/individualMember.module.scss b/src/pages/sign-up/individual/individualMember.module.scss
new file mode 100644
index 0000000..5b32cba
--- /dev/null
+++ b/src/pages/sign-up/individual/individualMember.module.scss
@@ -0,0 +1 @@
+@import '../../../components/sign-up/commonSignup.module';
diff --git a/src/pages/sign-up/individualMember.module.scss b/src/pages/sign-up/individualMember.module.scss
deleted file mode 100644
index a84e47c..0000000
--- a/src/pages/sign-up/individualMember.module.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import './commonSignup.module.scss';
diff --git a/src/pages/test/Test.tsx b/src/pages/test/Test.tsx
index 66e4e60..08e350b 100644
--- a/src/pages/test/Test.tsx
+++ b/src/pages/test/Test.tsx
@@ -4,7 +4,7 @@ import classNames from 'classnames';
import styles from './test.module.scss';
//๋ฒํผ๊ทธ๋ฃน test
-import ButtonGroup from '../../components/button/ButtonGroup.tsx';
+import ButtonGroup from '../../components/common/button/ButtonGroup.tsx';
//๋๋กญ๋ค์ด ๋ฒํผ test
import Dropdown from '../../components/dropdown/Dropdown.tsx';
diff --git a/src/utils/formatBirth.ts b/src/utils/formatBirth.ts
new file mode 100644
index 0000000..5f4b060
--- /dev/null
+++ b/src/utils/formatBirth.ts
@@ -0,0 +1,16 @@
+export const formatBirth = (birth: string) => {
+ const value = birth.replace(/[^0-9]/g, '');
+ if (value.length > 6) {
+ return (
+ value.substring(0, 4) +
+ '-' +
+ value.substring(4, 6) +
+ '-' +
+ value.substring(6)
+ );
+ }
+ if (value.length > 4) {
+ return value.substring(0, 4) + '-' + value.substring(4);
+ }
+ return value;
+};
diff --git a/vercel.json b/vercel.json
new file mode 100644
index 0000000..3a48e56
--- /dev/null
+++ b/vercel.json
@@ -0,0 +1,3 @@
+{
+ "rewrites": [{ "source": "/(.*)", "destination": "/" }]
+}