From 12554dafc5e93e042240a43ce8dc3b76ba3a7053 Mon Sep 17 00:00:00 2001 From: yoonyesol Date: Mon, 17 Jun 2024 16:37:52 +0900 Subject: [PATCH 01/18] =?UTF-8?q?Feat:=20#5=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EB=B0=8F=20=EB=A7=88=ED=81=AC=EC=97=85,=20CSS=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/assets/authGULogo.svg | 7 +++ src/index.css | 10 ++++ src/layouts/AuthLayout.tsx | 11 ++++ src/pages/user/SignUpPage.tsx | 95 ++++++++++++++++++++++++++++++++++- src/routes/MainRouter.tsx | 7 ++- tailwind.config.js | 2 +- yarn.lock | 38 ++++++++++++-- 8 files changed, 163 insertions(+), 8 deletions(-) create mode 100644 src/assets/authGULogo.svg create mode 100644 src/layouts/AuthLayout.tsx diff --git a/package.json b/package.json index 5f0f3a10..c8a38fb7 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "react-dom": "^18.2.0", "react-hook-form": "^7.51.4", "react-router-dom": "^6.23.1", + "tailwind-scrollbar-hide": "^1.1.7", "zustand": "^4.5.2" }, "devDependencies": { diff --git a/src/assets/authGULogo.svg b/src/assets/authGULogo.svg new file mode 100644 index 00000000..be5b9088 --- /dev/null +++ b/src/assets/authGULogo.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/index.css b/src/index.css index b5c61c95..51bd59d9 100644 --- a/src/index.css +++ b/src/index.css @@ -1,3 +1,13 @@ @tailwind base; @tailwind components; @tailwind utilities; + +@layer components { + .auth-btn { + @apply h-[4.38rem] bg-[#E1F4D9] rounded-[10px] text-base font-bold; + } + + .auth-input { + @apply h-[4.38rem] bg-white rounded-[10px] p-4 placeholder:text-[#5E5E5E] text-sm; + } +} diff --git a/src/layouts/AuthLayout.tsx b/src/layouts/AuthLayout.tsx new file mode 100644 index 00000000..0b7dc448 --- /dev/null +++ b/src/layouts/AuthLayout.tsx @@ -0,0 +1,11 @@ +import { Outlet } from 'react-router-dom'; +import AuthGULogo from '../assets/authGULogo.svg'; + +export default function AuthLayout() { + return ( +
+ Auth GU Logo + +
+ ); +} diff --git a/src/pages/user/SignUpPage.tsx b/src/pages/user/SignUpPage.tsx index be64afeb..6b162c96 100644 --- a/src/pages/user/SignUpPage.tsx +++ b/src/pages/user/SignUpPage.tsx @@ -1,3 +1,96 @@ export default function SignUpPage() { - return
SignUpPage
; + return ( +
+
+
+
+ img +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+ + + +
+ + +
+
+ + +
+
+ +

로그인 페이지로 돌아가기

+
+
+
+ ); } diff --git a/src/routes/MainRouter.tsx b/src/routes/MainRouter.tsx index c85d5c57..4817f600 100644 --- a/src/routes/MainRouter.tsx +++ b/src/routes/MainRouter.tsx @@ -2,6 +2,7 @@ import { RouterProvider, createBrowserRouter } from 'react-router-dom'; import AfterLoginRoute from '@routes/AfterLoginRoute'; import BeforeLoginRoute from '@routes/BeforeLoginRoute'; +import AuthLayout from '@layouts/AuthLayout'; import TeamLayout from '@layouts/TeamLayout'; import DefaultLayout from '@layouts/DefaultLayout'; import SettingLayout from '@layouts/SettingLayout'; @@ -23,7 +24,11 @@ export default function MainRouter() { const router = createBrowserRouter([ { path: '/', - element: , + element: ( + + + + ), errorElement: , children: [ { path: 'signup', element: }, diff --git a/tailwind.config.js b/tailwind.config.js index d21f1cda..076945b2 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -4,5 +4,5 @@ export default { theme: { extend: {}, }, - plugins: [], + plugins: [require('tailwind-scrollbar-hide')], }; diff --git a/yarn.lock b/yarn.lock index e4366539..79ed4db5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3887,8 +3887,16 @@ string-argv@0.3.2: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - name string-width-cjs +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -3961,7 +3969,14 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -4041,6 +4056,11 @@ symbol-tree@^3.2.4: resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +tailwind-scrollbar-hide@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/tailwind-scrollbar-hide/-/tailwind-scrollbar-hide-1.1.7.tgz#90b481fb2e204030e3919427416650c54f56f847" + integrity sha512-X324n9OtpTmOMqEgDUEA/RgLrNfBF/jwJdctaPZDzB3mppxJk7TLIDmOreEDm1Bq4R9LSPu4Epf8VSdovNU+iA== + tailwindcss@^3.4.3: version "3.4.3" resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz" @@ -4448,8 +4468,7 @@ word-wrap@^1.2.5: resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - name wrap-ansi-cjs +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -4467,6 +4486,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" From d758f80c5d8d4ee555f16f9dd5e99754ef754786 Mon Sep 17 00:00:00 2001 From: yoonyesol Date: Mon, 17 Jun 2024 16:44:51 +0900 Subject: [PATCH 02/18] =?UTF-8?q?Feat:=20#5=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EC=9E=85=EB=A0=A5=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.cjs | 1 + src/constants/regex.ts | 2 + src/index.css | 2 +- src/pages/user/SignUpPage.tsx | 189 ++++++++++++++++++++++++++++------ 4 files changed, 161 insertions(+), 33 deletions(-) create mode 100644 src/constants/regex.ts diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 852b0288..984b6f74 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -31,6 +31,7 @@ module.exports = { 'import/extensions': 'off', 'jsx-a11y/no-noninteractive-element-interactions': 'warn', 'vitest/valid-title': 'off', + 'react/jsx-props-no-spreading': 'off', }, ignorePatterns: [ 'dist', diff --git a/src/constants/regex.ts b/src/constants/regex.ts new file mode 100644 index 00000000..aec5d462 --- /dev/null +++ b/src/constants/regex.ts @@ -0,0 +1,2 @@ +export const EMAIL_REGEX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i; +export const PASSWORD_REGEX = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,16}$/; diff --git a/src/index.css b/src/index.css index 51bd59d9..ed412e81 100644 --- a/src/index.css +++ b/src/index.css @@ -8,6 +8,6 @@ } .auth-input { - @apply h-[4.38rem] bg-white rounded-[10px] p-4 placeholder:text-[#5E5E5E] text-sm; + @apply h-[4.38rem] bg-white rounded-[10px] p-4 placeholder:text-[#5E5E5E] text-sm outline-none; } } diff --git a/src/pages/user/SignUpPage.tsx b/src/pages/user/SignUpPage.tsx index 6b162c96..f9d300dc 100644 --- a/src/pages/user/SignUpPage.tsx +++ b/src/pages/user/SignUpPage.tsx @@ -1,7 +1,67 @@ +import { ChangeEvent, useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { EMAIL_REGEX, PASSWORD_REGEX } from '@/constants/regex'; + +type FormData = { + email: string; + verificationCode: string; + name: string; + password: string; + checkPassword: string; + bio: string; + website: string[]; +}; + export default function SignUpPage() { + const [link, setLink] = useState(''); + const [websiteList, setWebsiteList] = useState([]); + + const { + register, + handleSubmit, + formState: { errors, isSubmitting }, + watch, + setValue, + } = useForm({ + mode: 'onChange', + defaultValues: { + email: '', + verificationCode: '', + name: '', + password: '', + checkPassword: '', + bio: '', + website: [''], + }, + }); + + const handleLinkChange = (e: ChangeEvent) => { + setLink(e.target.value); + }; + + const handleAddLink = (newLink: string) => { + if (newLink.trim() === '') { + return; + } + setWebsiteList([...websiteList, newLink.trim()]); + setValue('website', [...websiteList, newLink.trim()]); + setLink(''); + }; + + const handleRemoveLink = (idx: number) => { + const filteredData = websiteList.filter((_, index) => index !== idx); + setWebsiteList(filteredData); + setValue('website', filteredData); + }; + + const onSubmit = (data: FormData) => { + const { verificationCode, checkPassword, ...filteredData } = data; + console.log(filteredData); + }; + return (
-
+
등록 - +
+
+ {errors.email &&

{errors.email.message}

} +
+ {errors.verificationCode &&

{errors.verificationCode.message}

} +
- - - -
- - -
+ {errors.name &&

{errors.name.message}

} + + + {errors.password &&

{errors.password.message}

} + + value === watch('password') || '비밀번호가 일치하지 않습니다.', + })} + placeholder="(필수) 비밀번호를 한 번 더 입력해 주세요." + type="password" + id="checkPassword" + className={`auth-input ${errors.checkPassword && `border-2 border-[#FF0000]`}`} + /> + {errors.checkPassword &&

{errors.checkPassword.message}

} + + + + {websiteList && + websiteList.map((item, index) => ( + // eslint-disable-next-line react/no-array-index-key +
+ + +
+ ))} +
-
+
- +

로그인 페이지로 돌아가기

From 5517b4b42a71675810b02f0761b38f2229549c30 Mon Sep 17 00:00:00 2001 From: yoonyesol Date: Tue, 18 Jun 2024 01:43:14 +0900 Subject: [PATCH 03/18] =?UTF-8?q?Design:=20#5=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=EB=A7=81=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20,=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.css | 4 +- src/pages/user/SignUpPage.tsx | 102 +++++++++++++++++++++------------- 2 files changed, 64 insertions(+), 42 deletions(-) diff --git a/src/index.css b/src/index.css index ed412e81..49c2804a 100644 --- a/src/index.css +++ b/src/index.css @@ -4,10 +4,10 @@ @layer components { .auth-btn { - @apply h-[4.38rem] bg-[#E1F4D9] rounded-[10px] text-base font-bold; + @apply h-12 bg-[#E1F4D9] rounded-[10px] font-bold px-[0.8rem]; } .auth-input { - @apply h-[4.38rem] bg-white rounded-[10px] p-4 placeholder:text-[#5E5E5E] text-sm outline-none; + @apply flex flex-1 h-12 bg-white rounded-[10px] p-4 placeholder:text-[#5E5E5E] outline-none; } } diff --git a/src/pages/user/SignUpPage.tsx b/src/pages/user/SignUpPage.tsx index f9d300dc..867c7a4d 100644 --- a/src/pages/user/SignUpPage.tsx +++ b/src/pages/user/SignUpPage.tsx @@ -1,8 +1,9 @@ -import { ChangeEvent, useState } from 'react'; +import { ChangeEvent, useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { EMAIL_REGEX, PASSWORD_REGEX } from '@/constants/regex'; type FormData = { + profile: File[]; email: string; verificationCode: string; name: string; @@ -13,6 +14,7 @@ type FormData = { }; export default function SignUpPage() { + const [imagePreview, setImagePreview] = useState(''); const [link, setLink] = useState(''); const [websiteList, setWebsiteList] = useState([]); @@ -25,6 +27,7 @@ export default function SignUpPage() { } = useForm({ mode: 'onChange', defaultValues: { + profile: [], email: '', verificationCode: '', name: '', @@ -35,6 +38,19 @@ export default function SignUpPage() { }, }); + const image = watch('profile'); + useEffect(() => { + if (image && image.length > 0) { + const file = image[0]; + setImagePreview(URL.createObjectURL(file)); + } + }, [image]); + + const handleRemoveImg = () => { + setValue('profile', []); + setImagePreview(''); + }; + const handleLinkChange = (e: ChangeEvent) => { setLink(e.target.value); }; @@ -60,31 +76,37 @@ export default function SignUpPage() { }; return ( -
-
-
-
- img -
-
- - +
+ +
+
+ {imagePreview ? ( + <> + Profile +
+

+ 삭제 +

+
+ + ) : ( + + )}
-
+
-
{errors.email &&

{errors.email.message}

} -
+
-
{errors.verificationCode &&

{errors.verificationCode.message}

} -
+
-
@@ -177,43 +199,43 @@ export default function SignUpPage() { placeholder="(선택) 자신을 소개해 주세요." type="text" id="bio" - className="h-[9.38rem] auth-input" + className="auth-input h-[9.38rem] w-[30rem]" /> {websiteList && websiteList.map((item, index) => ( // eslint-disable-next-line react/no-array-index-key -
-
+
+ -
))} -
+
-
-
+
-

로그인 페이지로 돌아가기

+

로그인 페이지로 돌아가기

From 32c9850e5a6382609072354cecfeeb6fe0eb8778 Mon Sep 17 00:00:00 2001 From: yoonyesol Date: Sun, 23 Jun 2024 02:00:58 +0900 Subject: [PATCH 04/18] =?UTF-8?q?Feat:=20#27=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/{authGULogo.svg => auth_logo.svg} | 0 src/assets/social_google_icon.svg | 15 +++ src/assets/social_kakao_icon.svg | 9 ++ src/globals.css | 2 +- src/layouts/page/AuthLayout.tsx | 2 +- src/pages/user/SignInPage.tsx | 111 ++++++++++++++++++- src/pages/user/SignUpPage.tsx | 24 ++-- src/types/UserType.tsx | 14 +++ 8 files changed, 161 insertions(+), 16 deletions(-) rename src/assets/{authGULogo.svg => auth_logo.svg} (100%) create mode 100644 src/assets/social_google_icon.svg create mode 100644 src/assets/social_kakao_icon.svg create mode 100644 src/types/UserType.tsx diff --git a/src/assets/authGULogo.svg b/src/assets/auth_logo.svg similarity index 100% rename from src/assets/authGULogo.svg rename to src/assets/auth_logo.svg diff --git a/src/assets/social_google_icon.svg b/src/assets/social_google_icon.svg new file mode 100644 index 00000000..0b87f9a7 --- /dev/null +++ b/src/assets/social_google_icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/assets/social_kakao_icon.svg b/src/assets/social_kakao_icon.svg new file mode 100644 index 00000000..249c5857 --- /dev/null +++ b/src/assets/social_kakao_icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/globals.css b/src/globals.css index 915e23d4..ab29be75 100644 --- a/src/globals.css +++ b/src/globals.css @@ -95,7 +95,7 @@ @apply absolute left-0 top-0 block h-30 w-4 bg-main content-['']; } .auth-btn { - @apply h-30 rounded-lg bg-sub px-8 font-bold; + @apply flex h-30 items-center justify-center rounded-lg bg-sub px-8 font-bold; } .auth-input { diff --git a/src/layouts/page/AuthLayout.tsx b/src/layouts/page/AuthLayout.tsx index e3d5357d..417ab362 100644 --- a/src/layouts/page/AuthLayout.tsx +++ b/src/layouts/page/AuthLayout.tsx @@ -1,5 +1,5 @@ import { Outlet } from 'react-router-dom'; -import AuthGULogo from '@/assets/authGULogo.svg'; +import AuthGULogo from '@/assets/auth_logo.svg'; export default function AuthLayout() { return ( diff --git a/src/pages/user/SignInPage.tsx b/src/pages/user/SignInPage.tsx index 2ac27c76..63d48e7c 100644 --- a/src/pages/user/SignInPage.tsx +++ b/src/pages/user/SignInPage.tsx @@ -1,3 +1,112 @@ +import { useNavigate } from 'react-router-dom'; +import { useForm } from 'react-hook-form'; +import Kakao from '@assets/social_kakao_icon.svg'; +import Google from '@assets/social_google_icon.svg'; +import { EMAIL_REGEX, PASSWORD_REGEX } from '@/constants/regex'; +import { UserSignIn } from '@/types/UserType'; + export default function SignInPage() { - return
SignInPage
; + const nav = useNavigate(); + const { + register, + handleSubmit, + formState: { errors, isSubmitting }, + } = useForm({ + mode: 'onChange', + defaultValues: { + email: '', + password: '', + }, + }); + + const onSubmit = (data: UserSignIn) => { + console.log(data); + }; + + return ( +
+
+
+ Welcome to our site! +
Grow Up your Life with us. +
+
+ +
+ {errors.email &&

{errors.email.message}

} + + + {errors.password &&

{errors.password.message}

} + +
+ +
+ +
+

nav('/search/id')} onKeyDown={() => nav('/search/id')}> + 아이디 찾기 +

+

|

+

nav('/search/password')} + onKeyDown={() => nav('/search/password')} + > + 비밀번호 찾기 +

+
+ +
+

회원이 아니신가요?

+ +
+ +
+ + +
+
+
+ ); } diff --git a/src/pages/user/SignUpPage.tsx b/src/pages/user/SignUpPage.tsx index 4178b81c..01b113c3 100644 --- a/src/pages/user/SignUpPage.tsx +++ b/src/pages/user/SignUpPage.tsx @@ -1,22 +1,14 @@ /* eslint-disable jsx-a11y/control-has-associated-label */ +import { useNavigate } from 'react-router-dom'; import { GoPlusCircle } from 'react-icons/go'; import { FaRegTrashCan, FaPlus, FaMinus } from 'react-icons/fa6'; import { ChangeEvent, useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { EMAIL_REGEX, PASSWORD_REGEX } from '@/constants/regex'; - -type FormData = { - profile: File[]; - email: string; - verificationCode: string; - name: string; - password: string; - checkPassword: string; - bio: string; - website: string[]; -}; +import { UserSignUp } from '@/types/UserType'; export default function SignUpPage() { + const nav = useNavigate(); const [imagePreview, setImagePreview] = useState(''); const [link, setLink] = useState(''); const [websiteList, setWebsiteList] = useState([]); @@ -73,7 +65,7 @@ export default function SignUpPage() { setValue('website', filteredData); }; - const onSubmit = (data: FormData) => { + const onSubmit = (data: UserSignUp) => { const { verificationCode, checkPassword, ...filteredData } = data; console.log(filteredData); }; @@ -238,7 +230,13 @@ export default function SignUpPage() { 회원가입 -

로그인 페이지로 돌아가기

+

nav('/signin')} + onKeyDown={() => nav('/signin')} + > + 로그인 페이지로 돌아가기 +

diff --git a/src/types/UserType.tsx b/src/types/UserType.tsx new file mode 100644 index 00000000..1df5325a --- /dev/null +++ b/src/types/UserType.tsx @@ -0,0 +1,14 @@ +// 회원가입, 로그인 시 필요한 유저 타입 정의 +export type UserSignIn = { + email: string; + password: string; +}; + +export type UserSignUp = UserSignIn & { + profile: File[]; + verificationCode: string; + name: string; + checkPassword: string; + bio: string; + website: string[]; +}; From 54630e1508e1a63462ce03f6a16103aa3e78a437 Mon Sep 17 00:00:00 2001 From: yoonyesol Date: Sat, 29 Jun 2024 18:59:10 +0900 Subject: [PATCH 05/18] =?UTF-8?q?design:=20=EC=88=98=EC=A0=95=EB=90=9C=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=ED=8F=BC=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20UI=20=EC=88=98=EC=A0=95,=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EB=B3=B4=EC=9D=B4=EA=B8=B0=20=EB=B0=8F=20?= =?UTF-8?q?=EC=88=A8=EA=B9=80=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/auth_logo.svg | 13 +- src/globals.css | 2 +- src/layouts/page/AuthLayout.tsx | 2 +- src/pages/user/SignUpPage.tsx | 290 +++++++++++++++++++------------- 4 files changed, 178 insertions(+), 129 deletions(-) diff --git a/src/assets/auth_logo.svg b/src/assets/auth_logo.svg index be5b9088..f4dfe7bb 100644 --- a/src/assets/auth_logo.svg +++ b/src/assets/auth_logo.svg @@ -1,7 +1,8 @@ - - - - - - + + + + + + + diff --git a/src/globals.css b/src/globals.css index ab29be75..796ec49f 100644 --- a/src/globals.css +++ b/src/globals.css @@ -99,6 +99,6 @@ } .auth-input { - @apply h-30 flex-grow rounded-lg px-8 text-sm outline-none placeholder:text-emphasis; + @apply h-30 flex-grow rounded-lg border border-input px-8 text-sm outline-none placeholder:text-emphasis; } } diff --git a/src/layouts/page/AuthLayout.tsx b/src/layouts/page/AuthLayout.tsx index 417ab362..8c984b84 100644 --- a/src/layouts/page/AuthLayout.tsx +++ b/src/layouts/page/AuthLayout.tsx @@ -3,7 +3,7 @@ import AuthGULogo from '@/assets/auth_logo.svg'; export default function AuthLayout() { return ( -
+
Auth GU Logo
diff --git a/src/pages/user/SignUpPage.tsx b/src/pages/user/SignUpPage.tsx index 01b113c3..77cfb5ee 100644 --- a/src/pages/user/SignUpPage.tsx +++ b/src/pages/user/SignUpPage.tsx @@ -4,11 +4,13 @@ import { GoPlusCircle } from 'react-icons/go'; import { FaRegTrashCan, FaPlus, FaMinus } from 'react-icons/fa6'; import { ChangeEvent, useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; +import { RiEyeFill, RiEyeOffFill } from 'react-icons/ri'; import { EMAIL_REGEX, PASSWORD_REGEX } from '@/constants/regex'; import { UserSignUp } from '@/types/UserType'; export default function SignUpPage() { const nav = useNavigate(); + const [showPassword, setShowPassword] = useState(false); const [imagePreview, setImagePreview] = useState(''); const [link, setLink] = useState(''); const [websiteList, setWebsiteList] = useState([]); @@ -70,18 +72,22 @@ export default function SignUpPage() { console.log(filteredData); }; + const togglePasswordVisibility = () => { + setShowPassword((prev) => !prev); + }; + return ( -
+
-
+
{imagePreview ? ( <> Profile

@@ -101,140 +107,182 @@ export default function SignUpPage() {

-
- - +
+

이메일 (아이디)

+
+ + {errors.email &&

{errors.email.message}

} + +
- {errors.email &&

{errors.email.message}

} -
- - +
+

인증번호

+
+ + +
+ {errors.verificationCode &&

{errors.verificationCode.message}

} +
+ +
+

닉네임

+
+ + +
+ {errors.name &&

{errors.name.message}

} +
+ +
+

비밀번호

+
+ +
+ {showPassword ? ( + + ) : ( + + )} +
+
+ + {errors.password ? ( +

{errors.password.message}

+ ) : ( +

영문자, 숫자, 기호 포함 8~16자리

+ )}
- {errors.verificationCode &&

{errors.verificationCode.message}

} -
+
+

비밀번호 확인

value === watch('password') || '비밀번호가 일치하지 않습니다.', })} - placeholder="(필수) 닉네임을 입력하세요." - type="text" - id="name" - className={`auth-input ${errors.name && `border-2 border-[#FF0000]`}`} + placeholder="" + type="password" + id="checkPassword" + className={`auth-input ${errors.checkPassword && `border-2 border-[#FF0000]`}`} /> - + {errors.checkPassword &&

{errors.checkPassword.message}

}{' '}
- {errors.name &&

{errors.name.message}

} - - - {errors.password &&

{errors.password.message}

} - - value === watch('password') || '비밀번호가 일치하지 않습니다.', - })} - placeholder="(필수) 비밀번호를 한 번 더 입력해 주세요." - type="password" - id="checkPassword" - className={`auth-input ${errors.checkPassword && `border-2 border-[#FF0000]`}`} - /> - {errors.checkPassword &&

{errors.checkPassword.message}

} - - - - {websiteList && - websiteList.map((item, index) => ( - // eslint-disable-next-line react/no-array-index-key -
- - -
- ))} -
- +
+

자기소개

+

optional

+
+