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} +
+ {username} + {verified && ์ธ์ฆ๋จ} +
+ +
+ {imageUrl ? ( + {description} + ) : ( + placeholder + )} +
+ +
+

{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 ( +
+
๋กœ๊ณ 
+

+ ๊ฐœ์ธ ํšŒ์› ๊ฐ€์ž… ์ •๋ณด ์ž…๋ ฅํ•˜๊ธฐ +

+
+
+
+ ๊ณ„์ • ์ •๋ณด +
+
+
+ + + +
+
+
+
+ ํšŒ์› ์ •๋ณด +
+
+
+ + + handleChangeEmailDomain(e)} + setEmailDomain={setEmailDomain} + isEmail + {...registers.email} + /> +
+
+ +
+
+ ); +}; 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": "/" }] +}