From 7a256a80ec2f627cef1e2650b2439811e01f35d4 Mon Sep 17 00:00:00 2001 From: Mayreeel Date: Tue, 26 Sep 2023 00:33:57 +0900 Subject: [PATCH 01/12] =?UTF-8?q?chore=20:=20tailwindcss=20=EC=BB=A4?= =?UTF-8?q?=EC=8A=A4=ED=85=80=20=EC=84=A4=EC=A0=95=20=EB=B0=8F=20=ED=8F=B0?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tsconfig include에 설정파일 추가 --- frontend/src/app/globals.css | 29 ++++++++++++++++++ frontend/tailwind.config.cjs | 58 ++++++++++++++++++++++++++++++++++++ frontend/tailwind.config.ts | 20 ------------- frontend/tsconfig.json | 10 ++++++- 4 files changed, 96 insertions(+), 21 deletions(-) create mode 100644 frontend/tailwind.config.cjs delete mode 100644 frontend/tailwind.config.ts diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index b5c61c95..d6724da5 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -1,3 +1,32 @@ @tailwind base; @tailwind components; @tailwind utilities; + +.ql-editor { + min-height: 600px; +} + +@font-face { + font-family: 'LeferiBaseRegular'; + src: url('../../public/fonts/LeferiBaseRegular.ttf'); +} +@font-face { + font-family: 'LeferiBaseBold'; + src: url('../../public/fonts/LeferiBaseBold.ttf'); +} +@font-face { + font-family: 'LatoBold'; + src: url('../../public/fonts/LatoBold.ttf'); +} +@font-face { + font-family: 'LatoLight'; + src: url('../../public/fonts/LatoLight.ttf'); +} +@font-face { + font-family: 'LatoRegular'; + src: url('../../public/fonts/LatoRegular.ttf'); +} +@font-face { + font-family: 'LatoSemibold'; + src: url('../../public/fonts/LatoSemibold.ttf'); +} diff --git a/frontend/tailwind.config.cjs b/frontend/tailwind.config.cjs new file mode 100644 index 00000000..2dea46e5 --- /dev/null +++ b/frontend/tailwind.config.cjs @@ -0,0 +1,58 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ['./src/**/*.{html,js,ts,tsx}'], + theme: { + extend: { + spacing: { + 660: '660px', + 630: '630px', + 555: '555px', + 460: '460px', + 355: '350px', + 504: '54px', + }, + colors: { + graphybg: '#F9F8F8', + graphyblue: '#505F9A', + graphypink: '#CA92C7', + mainbannerleft: '#678EF4', + mainbannerright: '#FF93AE', + subbanner: '#C1D0EF', + gptbutton: '#7082CA', + button: '#364A9A', + }, + width: { + 284: '17.75rem', + }, + height: { + 49: '3.063rem', + 110: '6.875rem', + 228: '14.25rem', + }, + minWidth: { + 284: '17.75rem', + }, + maxWidth: { + 1100: '68.75rem', + }, + minHeight: { + 56: '14rem', + 96: '24rem', + }, + fontFamily: { + sans: ['NanumGothic', 'Arial', 'sans-serif'], + ng: ['NanumGothic', 'sans-serif'], + 'ng-b': ['NanumGothicBold', 'sans-serif'], + 'ng-eb': ['NanumGothicExtraBold', 'sans-serif'], + 'ng-l': ['NanumGothicLight', 'sans-serif'], + lef: ['LeferiBaseRegular', 'sans-serif'], + 'lef-b': ['LeferiBaseBold', 'sans-serif'], + lato: ['LatoRegular', 'sans-serif'], + 'lato-b': ['LatoBold', 'sans-serif'], + 'lato-l': ['LatoLight', 'sans-serif'], + 'lato-sb': ['LatoSemibold', 'sans-serif'], + }, + }, + }, + plugins: [], +} diff --git a/frontend/tailwind.config.ts b/frontend/tailwind.config.ts deleted file mode 100644 index 1af3b8f0..00000000 --- a/frontend/tailwind.config.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { Config } from 'tailwindcss' - -const config: Config = { - content: [ - './src/pages/**/*.{js,ts,jsx,tsx,mdx}', - './src/components/**/*.{js,ts,jsx,tsx,mdx}', - './src/app/**/*.{js,ts,jsx,tsx,mdx}', - ], - theme: { - extend: { - backgroundImage: { - 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', - 'gradient-conic': - 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', - }, - }, - }, - plugins: [], -} -export default config diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index e59724b2..5a90d522 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -22,6 +22,14 @@ "@/*": ["./src/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + "postcss.config.js", + "tailwind.config.cjs", + "next.config.js" + ], "exclude": ["node_modules"] } From ab5ffcd24b6c348b769c5ee8a59fa7fe6ae1d67e Mon Sep 17 00:00:00 2001 From: Mayreeel Date: Tue, 26 Sep 2023 00:36:04 +0900 Subject: [PATCH 02/12] =?UTF-8?q?chore=20:=20yup,=20react-hook-form=20?= =?UTF-8?q?=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit yarn add yup react-hook-form @hookform/resolvers --- frontend/package.json | 5 ++++- frontend/yarn.lock | 45 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index b99c28f3..4d166ded 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,6 +11,7 @@ "format:fix": "prettier --write --ignore-path .gitignore ." }, "dependencies": { + "@hookform/resolvers": "^3.3.1", "@types/node": "20.6.3", "@types/react": "18.2.22", "@types/react-dom": "18.2.7", @@ -26,9 +27,11 @@ "prettier": "^3.0.3", "react": "18.2.0", "react-dom": "18.2.0", + "react-hook-form": "^7.46.2", "recoil": "^0.7.7", "tailwindcss": "3.3.3", - "typescript": "5.2.2" + "typescript": "5.2.2", + "yup": "^1.3.0" }, "devDependencies": { "eslint-config-prettier": "^9.0.0" diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 8feb674f..9ff84e6b 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -51,6 +51,11 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.49.0.tgz#86f79756004a97fa4df866835093f1df3d03c333" integrity sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w== +"@hookform/resolvers@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-3.3.1.tgz#b7cbfe767434f52cba6b99b0a9a0b73eb8895188" + integrity sha512-K7KCKRKjymxIB90nHDQ7b9nli474ru99ZbqxiqDAWYsYhOsU3/4qLxW91y+1n04ic13ajjZ66L3aXbNef8PELQ== + "@humanwhocodes/config-array@^0.11.11": version "0.11.11" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.11.tgz#88a04c570dbbc7dd943e4712429c3df09bc32844" @@ -2034,6 +2039,11 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" +property-expr@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.5.tgz#278bdb15308ae16af3e3b9640024524f4dc02cb4" + integrity sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA== + punycode@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" @@ -2052,6 +2062,11 @@ react-dom@18.2.0: loose-envify "^1.1.0" scheduler "^0.23.0" +react-hook-form@^7.46.2: + version "7.46.2" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.46.2.tgz#051e3cb2a73f3e86de739f2198c6042902158c43" + integrity sha512-x1DWmHQchV7x2Rq9l99M/cQHC8JGchAnw9Z0uTz5KrPa0bTl/Inm1NR7ceOARfIrkNuQNAhuSuZPYa6k7QYn3Q== + react-is@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -2078,6 +2093,11 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +recoil-persist@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/recoil-persist/-/recoil-persist-5.1.0.tgz#c4232fe04f2e4b6afcc815baff56f2521f6dcde1" + integrity sha512-sew4k3uBVJjRWKCSFuBw07Y1p1pBOb0UxLJPxn4G2bX/9xNj+r2xlqYy/BRfyofR/ANfqBU04MIvulppU4ZC0w== + recoil@^0.7.7: version "0.7.7" resolved "https://registry.yarnpkg.com/recoil/-/recoil-0.7.7.tgz#c5f2c843224384c9c09e4a62c060fb4c1454dc8e" @@ -2384,6 +2404,11 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" +tiny-case@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03" + integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q== + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -2391,6 +2416,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +toposort@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" + integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg== + ts-api-utils@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" @@ -2428,6 +2458,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + typed-array-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" @@ -2587,6 +2622,16 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +yup@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/yup/-/yup-1.3.0.tgz#fba191b4f5e6fd5141377111bb9da84647f86e05" + integrity sha512-e7sDRCv7/jmzHqTTnV+xoGIOYyBxAL5s9h+a3JdiJx15FrXjIWebal0KHXPEdJ1GjhcDLojnDiywXzkYXi/mSA== + dependencies: + property-expr "^2.0.5" + tiny-case "^1.0.3" + toposort "^2.0.2" + type-fest "^2.19.0" + zod@3.21.4: version "3.21.4" resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db" From 7cff19d9a7c8c8a3ac9f054f43813d66109b11a1 Mon Sep 17 00:00:00 2001 From: Mayreeel Date: Tue, 26 Sep 2023 00:42:08 +0900 Subject: [PATCH 03/12] =?UTF-8?q?feat=20:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A7=88=EC=9D=B4=EA=B7=B8?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit img 태그 => 'next/image'의 Image 컴포넌트로 변경 useNavigate=> useRouter axios => fetch alert => Error 객체로 공식문서 Error.js 코드 가져와서 넣음 eslint import/no-extraneous-dependencies off --- frontend/.eslintrc.json | 3 +- frontend/package.json | 1 + frontend/src/app/(user)/login/error.tsx | 18 +++ frontend/src/app/(user)/login/page.tsx | 181 ++++++++++++++++++++++++ frontend/src/app/global-error.tsx | 21 +++ frontend/src/utils/atoms.ts | 12 ++ 6 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 frontend/src/app/(user)/login/error.tsx create mode 100644 frontend/src/app/global-error.tsx diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index 66033337..4dd15c4f 100644 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -9,6 +9,7 @@ "project": "./tsconfig.json" }, "rules": { - "react/react-in-jsx-scope": "off" + "react/react-in-jsx-scope": "off", + "import/no-extraneous-dependencies": "off" } } diff --git a/frontend/package.json b/frontend/package.json index 4d166ded..110d4806 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -29,6 +29,7 @@ "react-dom": "18.2.0", "react-hook-form": "^7.46.2", "recoil": "^0.7.7", + "recoil-persist": "^5.1.0", "tailwindcss": "3.3.3", "typescript": "5.2.2", "yup": "^1.3.0" diff --git a/frontend/src/app/(user)/login/error.tsx b/frontend/src/app/(user)/login/error.tsx new file mode 100644 index 00000000..be27e9de --- /dev/null +++ b/frontend/src/app/(user)/login/error.tsx @@ -0,0 +1,18 @@ +'use client' + +export default function Error({ + error, + reset, +}: { + error: Error & { digest?: string } + reset: () => void +}) { + return ( +
+

{error.message}

+ +
+ ) +} diff --git a/frontend/src/app/(user)/login/page.tsx b/frontend/src/app/(user)/login/page.tsx index e69de29b..0158a59e 100644 --- a/frontend/src/app/(user)/login/page.tsx +++ b/frontend/src/app/(user)/login/page.tsx @@ -0,0 +1,181 @@ +'use client' + +/* eslint-disable react/jsx-props-no-spreading */ + +import { yupResolver } from '@hookform/resolvers/yup' +import { useEffect } from 'react' +import { SubmitHandler, useForm } from 'react-hook-form' +import { useRouter } from 'next/navigation' +import { useRecoilState } from 'recoil' +import * as yup from 'yup' + +import Image from 'next/image' +import Email from '../../../../public/images/svg/email.svg' +import { autoLoginState } from '../../../utils/atoms' + +type DataObject = { + email: string + password: string +} + +const schema = yup.object().shape({ + email: yup + .string() + .email('이메일 형식이 맞지 않습니다.') + .required('이메일이 필요합니다.'), + password: yup + .string() + .min(8, '비밀번호는 최소 8자리 이상이여야 합니다.') + .matches( + /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]+$/, + '1개 이상의 대소문자, 숫자, 특수문자가 포함되어야 합니다.', + ) + .required('비밀번호가 필요합니다.'), +}) + +export default function Login() { + const router = useRouter() + const accessToken = + typeof window !== 'undefined' ? sessionStorage.getItem('accessToken') : null + const persistToken = + typeof window !== 'undefined' ? localStorage.getItem('persistToken') : null + const [autoLogin, setAutoLogin] = useRecoilState(autoLoginState) + + const handleCheckboxChange = (event: React.ChangeEvent) => { + setAutoLogin(event.target.checked) + } + + const handleButtonClick = () => { + setAutoLogin(!autoLogin) + } + + const { + register, + handleSubmit, + formState: { errors }, + } = useForm({ + resolver: yupResolver(schema), + }) + + function toMain() { + router.push('/') + } + + function toSignup() { + router.push('/registration') + } + + const onSubmit: SubmitHandler = async (data: DataObject) => { + const res = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/auth/signin`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + email: data.email, + password: data.password, + }), + }) + + if (!res.ok) { + throw new Error('로그인에 실패했습니다.') + } + + const resData = await res.json() + + if (autoLogin) { + localStorage.setItem('persistToken', resData.data.accessToken) + } else { + sessionStorage.setItem('accessToken', resData.data.accessToken) + } + router.push('/') + } + + useEffect(() => { + if (!navigator.onLine) { + throw new Error('오프라인 상태입니다. 네트워크 연결을 확인해주세요.') + } + if (accessToken || persistToken) { + // eslint-disable-next-line no-alert + alert('이미 로그인 상태입니다.') + router.push('/') + } + }, [accessToken, persistToken, router]) + + return ( +
+ +
+ + 로그인 + +
+ +

{errors.email?.message}

+ +

{errors.password?.message}

+ +
+
+
+ + +
+ {/* */} +
+
+ 아직 회원이 아니세요? + +
+
+
+ ) +} diff --git a/frontend/src/app/global-error.tsx b/frontend/src/app/global-error.tsx new file mode 100644 index 00000000..cbe956a3 --- /dev/null +++ b/frontend/src/app/global-error.tsx @@ -0,0 +1,21 @@ +'use client' + +export default function GlobalError({ + error, + reset, +}: { + error: Error & { digest?: string } + reset: () => void +}) { + return ( + + +

Something went wrong!

+

{error.digest}

+ + + + ) +} diff --git a/frontend/src/utils/atoms.ts b/frontend/src/utils/atoms.ts index e69de29b..5cece52e 100644 --- a/frontend/src/utils/atoms.ts +++ b/frontend/src/utils/atoms.ts @@ -0,0 +1,12 @@ +import { atom } from 'recoil' +import { recoilPersist } from 'recoil-persist' + +const { persistAtom } = recoilPersist() + +const autoLoginState = atom({ + key: 'autoLoginState', + default: false, + effects_UNSTABLE: [persistAtom], +}) + +export { autoLoginState } From ece273d314f970b44f3f4d475902d2268a2dabe7 Mon Sep 17 00:00:00 2001 From: Mayreeel Date: Tue, 26 Sep 2023 09:11:29 +0900 Subject: [PATCH 04/12] =?UTF-8?q?fix=20:=20eslint=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/page.tsx | 1 + frontend/src/utils/atoms.ts | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index b772bfb7..3d494060 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -1,3 +1,4 @@ export default function Home() { + // eslint-disable-next-line no-useless-return return } diff --git a/frontend/src/utils/atoms.ts b/frontend/src/utils/atoms.ts index 5cece52e..caa114ab 100644 --- a/frontend/src/utils/atoms.ts +++ b/frontend/src/utils/atoms.ts @@ -9,4 +9,9 @@ const autoLoginState = atom({ effects_UNSTABLE: [persistAtom], }) -export { autoLoginState } +const exampleState = atom({ + key: 'exampleState', + default: 'example', +}) + +export { autoLoginState, exampleState } From 47f9b53748d8b1349f61b8258e106a5b34a43e5c Mon Sep 17 00:00:00 2001 From: Mayreeel Date: Tue, 26 Sep 2023 09:14:54 +0900 Subject: [PATCH 05/12] =?UTF-8?q?feat=20:=20FE/#207=EB=B8=8C=EB=9E=9C?= =?UTF-8?q?=EC=B9=98=20CI=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 37b41d9d..a34ac04d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: ["feature"] + branches: ["feature", "FE/#207"] pull_request: - branches: ["feature"] + branches: ["feature", "FE/#207"] jobs: backend-test: From bc1018e211a4a724393e797de4cf3cb09615a33f Mon Sep 17 00:00:00 2001 From: Mayreeel Date: Tue, 26 Sep 2023 09:18:36 +0900 Subject: [PATCH 06/12] =?UTF-8?q?fix=20:=20frontend=20CI=20=EB=AA=85?= =?UTF-8?q?=EB=A0=B9=EC=96=B4=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/CI.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index a34ac04d..d3146fe8 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -70,15 +70,15 @@ jobs: - name: Install packages working-directory: frontend - run: npm ci + run: yarn install --immutable --immutable-cache --check-cache - name: Prettier working-directory: frontend - run: npm run format + run: yarn format - name: ESLint working-directory: frontend - run: npm run lint + run: yarn lint # - name: Frontend Test # working-directory: frontend From 162f70be8447defec56f1d1e0619bfafc93c20d1 Mon Sep 17 00:00:00 2001 From: Mayreeel Date: Tue, 26 Sep 2023 13:44:52 +0900 Subject: [PATCH 07/12] =?UTF-8?q?chore=20:=20next=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 13.5.1=>13.5.3 --- frontend/package.json | 2 +- frontend/yarn.lock | 124 +++++++++++++++++++++--------------------- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 110d4806..0f90ae57 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -22,7 +22,7 @@ "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-next": "13.5.1", - "next": "13.5.1", + "next": "^13.5.3", "postcss": "8.4.30", "prettier": "^3.0.3", "react": "18.2.0", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 9ff84e6b..f1b0d34c 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -107,10 +107,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@next/env@13.5.1": - version "13.5.1" - resolved "https://registry.yarnpkg.com/@next/env/-/env-13.5.1.tgz#337f5f3d325250f91ed23d783cbf8297800ee7d3" - integrity sha512-CIMWiOTyflFn/GFx33iYXkgLSQsMQZV4jB91qaj/TfxGaGOXxn8C1j72TaUSPIyN7ziS/AYG46kGmnvuk1oOpg== +"@next/env@13.5.3": + version "13.5.3" + resolved "https://registry.yarnpkg.com/@next/env/-/env-13.5.3.tgz#402da9a0af87f93d853519f0c2a602b1ab637c2c" + integrity sha512-X4te86vsbjsB7iO4usY9jLPtZ827Mbx+WcwNBGUOIuswuTAKQtzsuoxc/6KLxCMvogKG795MhrR1LDhYgDvasg== "@next/eslint-plugin-next@13.5.1": version "13.5.1" @@ -119,50 +119,50 @@ dependencies: glob "7.1.7" -"@next/swc-darwin-arm64@13.5.1": - version "13.5.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.1.tgz#dc21234afce27910a8d141e6a7ab5e821725dc94" - integrity sha512-Bcd0VFrLHZnMmJy6LqV1CydZ7lYaBao8YBEdQUVzV8Ypn/l5s//j5ffjfvMzpEQ4mzlAj3fIY+Bmd9NxpWhACw== - -"@next/swc-darwin-x64@13.5.1": - version "13.5.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.1.tgz#29591ac96cc839903918621cf2d8f79c40cba3ca" - integrity sha512-uvTZrZa4D0bdWa1jJ7X1tBGIxzpqSnw/ATxWvoRO9CVBvXSx87JyuISY+BWsfLFF59IRodESdeZwkWM2l6+Kjg== - -"@next/swc-linux-arm64-gnu@13.5.1": - version "13.5.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.1.tgz#349ce2714dc87d1db6911758652f3b2b0810dd6f" - integrity sha512-/52ThlqdORPQt3+AlMoO+omicdYyUEDeRDGPAj86ULpV4dg+/GCFCKAmFWT0Q4zChFwsAoZUECLcKbRdcc0SNg== - -"@next/swc-linux-arm64-musl@13.5.1": - version "13.5.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.1.tgz#3f8bc223db9100887ffda998ad963820f39d944b" - integrity sha512-L4qNXSOHeu1hEAeeNsBgIYVnvm0gg9fj2O2Yx/qawgQEGuFBfcKqlmIE/Vp8z6gwlppxz5d7v6pmHs1NB6R37w== - -"@next/swc-linux-x64-gnu@13.5.1": - version "13.5.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.1.tgz#4503d43d27aa178efb4a5c9efe229faae37d67a8" - integrity sha512-QVvMrlrFFYvLtABk092kcZ5Mzlmsk2+SV3xYuAu8sbTuIoh0U2+HGNhVklmuYCuM3DAAxdiMQTNlRQmNH11udw== - -"@next/swc-linux-x64-musl@13.5.1": - version "13.5.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.1.tgz#a6e81f0df0be2fac78392705f487036695cf7b10" - integrity sha512-bBnr+XuWc28r9e8gQ35XBtyi5KLHLhTbEvrSgcWna8atI48sNggjIK8IyiEBO3KIrcUVXYkldAzGXPEYMnKt1g== - -"@next/swc-win32-arm64-msvc@13.5.1": - version "13.5.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.1.tgz#9d8517fe1dd6aa348c7be36b933ad8195f961294" - integrity sha512-EQGeE4S5c9v06jje9gr4UlxqUEA+zrsgPi6kg9VwR+dQHirzbnVJISF69UfKVkmLntknZJJI9XpWPB6q0Z7mTg== - -"@next/swc-win32-ia32-msvc@13.5.1": - version "13.5.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.1.tgz#42e711d00642f538edaabf9535545697d093b2f7" - integrity sha512-1y31Q6awzofVjmbTLtRl92OX3s+W0ZfO8AP8fTnITcIo9a6ATDc/eqa08fd6tSpFu6IFpxOBbdevOjwYTGx/AQ== - -"@next/swc-win32-x64-msvc@13.5.1": - version "13.5.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.1.tgz#34bc139cf37704d595fe84eb803b1578a539e35e" - integrity sha512-+9XBQizy7X/GuwNegq+5QkkxAPV7SBsIwapVRQd9WSvvU20YO23B3bZUpevdabi4fsd25y9RJDDncljy/V54ww== +"@next/swc-darwin-arm64@13.5.3": + version "13.5.3" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.3.tgz#f72eac8c7b71d33e0768bd3c8baf68b00fea0160" + integrity sha512-6hiYNJxJmyYvvKGrVThzo4nTcqvqUTA/JvKim7Auaj33NexDqSNwN5YrrQu+QhZJCIpv2tULSHt+lf+rUflLSw== + +"@next/swc-darwin-x64@13.5.3": + version "13.5.3" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.3.tgz#96eda3a1247a713579eb241d76d3f503291c8938" + integrity sha512-UpBKxu2ob9scbpJyEq/xPgpdrgBgN3aLYlxyGqlYX5/KnwpJpFuIHU2lx8upQQ7L+MEmz+fA1XSgesoK92ppwQ== + +"@next/swc-linux-arm64-gnu@13.5.3": + version "13.5.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.3.tgz#132e155a029310fffcdfd3e3c4255f7ce9fd2714" + integrity sha512-5AzM7Yx1Ky+oLY6pHs7tjONTF22JirDPd5Jw/3/NazJ73uGB05NqhGhB4SbeCchg7SlVYVBeRMrMSZwJwq/xoA== + +"@next/swc-linux-arm64-musl@13.5.3": + version "13.5.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.3.tgz#981d7d8fdcf040bd0c89588ef4139c28805f5cf1" + integrity sha512-A/C1shbyUhj7wRtokmn73eBksjTM7fFQoY2v/0rTM5wehpkjQRLOXI8WJsag2uLhnZ4ii5OzR1rFPwoD9cvOgA== + +"@next/swc-linux-x64-gnu@13.5.3": + version "13.5.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.3.tgz#b8263663acda7b84bc2c4ffa39ca4b0172a78060" + integrity sha512-FubPuw/Boz8tKkk+5eOuDHOpk36F80rbgxlx4+xty/U71e3wZZxVYHfZXmf0IRToBn1Crb8WvLM9OYj/Ur815g== + +"@next/swc-linux-x64-musl@13.5.3": + version "13.5.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.3.tgz#cd0bed8ee92032c25090bed9d95602ac698d925f" + integrity sha512-DPw8nFuM1uEpbX47tM3wiXIR0Qa+atSzs9Q3peY1urkhofx44o7E1svnq+a5Q0r8lAcssLrwiM+OyJJgV/oj7g== + +"@next/swc-win32-arm64-msvc@13.5.3": + version "13.5.3" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.3.tgz#7f556674ca97e6936220d10c58252cc36522d80a" + integrity sha512-zBPSP8cHL51Gub/YV8UUePW7AVGukp2D8JU93IHbVDu2qmhFAn9LWXiOOLKplZQKxnIPUkJTQAJDCWBWU4UWUA== + +"@next/swc-win32-ia32-msvc@13.5.3": + version "13.5.3" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.3.tgz#4912721fb8695f11daec4cde42e73dc57bcc479f" + integrity sha512-ONcL/lYyGUj4W37D4I2I450SZtSenmFAvapkJQNIJhrPMhzDU/AdfLkW98NvH1D2+7FXwe7yclf3+B7v28uzBQ== + +"@next/swc-win32-x64-msvc@13.5.3": + version "13.5.3" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.3.tgz#97340a709febb60ff73003566b99d127d4e5b881" + integrity sha512-2Vz2tYWaLqJvLcWbbTlJ5k9AN6JD7a5CN2pAeIzpbecK8ZF/yobA39cXtv6e+Z8c5UJuVOmaTldEAIxvsIux/Q== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -1759,12 +1759,12 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -next@13.5.1: - version "13.5.1" - resolved "https://registry.yarnpkg.com/next/-/next-13.5.1.tgz#cf51e950017121f5404eedbde7d59d9ed310839b" - integrity sha512-GIudNR7ggGUZoIL79mSZcxbXK9f5pwAIPZxEM8+j2yLqv5RODg4TkmUlaKSYVqE1bPQueamXSqdC3j7axiTSEg== +next@^13.5.3: + version "13.5.3" + resolved "https://registry.yarnpkg.com/next/-/next-13.5.3.tgz#631efcbcc9d756c610855d9b94f3d8c4e73ee131" + integrity sha512-4Nt4HRLYDW/yRpJ/QR2t1v63UOMS55A38dnWv3UDOWGezuY0ZyFO1ABNbD7mulVzs9qVhgy2+ppjdsANpKP1mg== dependencies: - "@next/env" "13.5.1" + "@next/env" "13.5.3" "@swc/helpers" "0.5.2" busboy "1.6.0" caniuse-lite "^1.0.30001406" @@ -1773,15 +1773,15 @@ next@13.5.1: watchpack "2.4.0" zod "3.21.4" optionalDependencies: - "@next/swc-darwin-arm64" "13.5.1" - "@next/swc-darwin-x64" "13.5.1" - "@next/swc-linux-arm64-gnu" "13.5.1" - "@next/swc-linux-arm64-musl" "13.5.1" - "@next/swc-linux-x64-gnu" "13.5.1" - "@next/swc-linux-x64-musl" "13.5.1" - "@next/swc-win32-arm64-msvc" "13.5.1" - "@next/swc-win32-ia32-msvc" "13.5.1" - "@next/swc-win32-x64-msvc" "13.5.1" + "@next/swc-darwin-arm64" "13.5.3" + "@next/swc-darwin-x64" "13.5.3" + "@next/swc-linux-arm64-gnu" "13.5.3" + "@next/swc-linux-arm64-musl" "13.5.3" + "@next/swc-linux-x64-gnu" "13.5.3" + "@next/swc-linux-x64-musl" "13.5.3" + "@next/swc-win32-arm64-msvc" "13.5.3" + "@next/swc-win32-ia32-msvc" "13.5.3" + "@next/swc-win32-x64-msvc" "13.5.3" node-releases@^2.0.13: version "2.0.13" From 08960723d75adddc5fc62d991fa947db2fb56a3c Mon Sep 17 00:00:00 2001 From: Mayreeel Date: Tue, 26 Sep 2023 13:50:04 +0900 Subject: [PATCH 08/12] =?UTF-8?q?refactor=20:=20=ED=95=A8=EC=88=98,=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=AA=85=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/(user)/login/error.tsx | 2 +- frontend/src/app/(user)/login/page.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/(user)/login/error.tsx b/frontend/src/app/(user)/login/error.tsx index be27e9de..c65be747 100644 --- a/frontend/src/app/(user)/login/error.tsx +++ b/frontend/src/app/(user)/login/error.tsx @@ -1,6 +1,6 @@ 'use client' -export default function Error({ +export default function LoginError({ error, reset, }: { diff --git a/frontend/src/app/(user)/login/page.tsx b/frontend/src/app/(user)/login/page.tsx index 0158a59e..5d53bb3c 100644 --- a/frontend/src/app/(user)/login/page.tsx +++ b/frontend/src/app/(user)/login/page.tsx @@ -61,7 +61,7 @@ export default function Login() { router.push('/') } - function toSignup() { + function toRegistration() { router.push('/registration') } @@ -170,7 +170,7 @@ export default function Login() { From 2025254cafe15c4a1a7bb372a581d8fb11e6d5aa Mon Sep 17 00:00:00 2001 From: Mayreeel Date: Tue, 26 Sep 2023 13:52:14 +0900 Subject: [PATCH 09/12] =?UTF-8?q?feat=20:=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=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eslint 의존성 배열 강제 규칙 제거(의도대로 동작 안함) img태그 => 'next/image'의 image 컴포넌트로 변경 useNavigate => useRouter axios => fetch alert => Error 객체 Error.js에 공식문서 기본 코드 삽입 --- frontend/.eslintrc.json | 3 +- frontend/src/app/(user)/login/page.tsx | 2 +- .../src/app/(user)/registration/error.tsx | 18 ++ frontend/src/app/(user)/registration/page.tsx | 214 ++++++++++++++++++ 4 files changed, 235 insertions(+), 2 deletions(-) create mode 100644 frontend/src/app/(user)/registration/error.tsx diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index 4dd15c4f..55df3af7 100644 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -10,6 +10,7 @@ }, "rules": { "react/react-in-jsx-scope": "off", - "import/no-extraneous-dependencies": "off" + "import/no-extraneous-dependencies": "off", + "react-hooks/exhaustive-deps": "off" } } diff --git a/frontend/src/app/(user)/login/page.tsx b/frontend/src/app/(user)/login/page.tsx index 5d53bb3c..05eebf21 100644 --- a/frontend/src/app/(user)/login/page.tsx +++ b/frontend/src/app/(user)/login/page.tsx @@ -100,7 +100,7 @@ export default function Login() { alert('이미 로그인 상태입니다.') router.push('/') } - }, [accessToken, persistToken, router]) + }, []) return (
diff --git a/frontend/src/app/(user)/registration/error.tsx b/frontend/src/app/(user)/registration/error.tsx new file mode 100644 index 00000000..0c95a0f5 --- /dev/null +++ b/frontend/src/app/(user)/registration/error.tsx @@ -0,0 +1,18 @@ +'use client' + +export default function RegistrationError({ + error, + reset, +}: { + error: Error & { digest?: string } + reset: () => void +}) { + return ( +
+

{error.message}

+ +
+ ) +} diff --git a/frontend/src/app/(user)/registration/page.tsx b/frontend/src/app/(user)/registration/page.tsx index e69de29b..d62baf5e 100644 --- a/frontend/src/app/(user)/registration/page.tsx +++ b/frontend/src/app/(user)/registration/page.tsx @@ -0,0 +1,214 @@ +'use client' + +/* eslint-disable react/jsx-props-no-spreading */ + +import { yupResolver } from '@hookform/resolvers/yup' +import { useEffect } from 'react' +import { SubmitHandler, useForm } from 'react-hook-form' +import { useRouter } from 'next/navigation' +import { useRecoilState } from 'recoil' +import * as yup from 'yup' + +import Image from 'next/image' +import Email from '../../../../public/images/svg/email.svg' +import { autoLoginState } from '../../../utils/atoms' + +type DataObject = { + email: string + password: string + confirmPassword: string + nickname: string + introduction?: string +} + +const schema = yup.object().shape({ + email: yup + .string() + .email('이메일 형식이 맞지 않습니다.') + .required('이메일이 필요합니다.'), + password: yup + .string() + .min(8, '비밀번호는 최소 8자리 이상이여야 합니다.') + .matches( + /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]+$/, + '1개 이상의 대소문자, 숫자, 특수문자가 포함되어야 합니다.', + ) + .required('비밀번호가 필요합니다.'), + confirmPassword: yup + .string() + .oneOf([yup.ref('password'), ''], '비밀번호가 일치하지 않습니다.') + .required('비밀번호 확인이 필요합니다.'), + nickname: yup + .string() + .max(10, '닉네임은 최대 10자리까지 가능합니다.') + .required('닉네임이 필요합니다.'), + introduction: yup + .string() + .max(20, '한 줄 소개는 최대 20자리까지 가능합니다.'), +}) + +export default function Registration() { + const router = useRouter() + const accessToken = + typeof window !== 'undefined' ? sessionStorage.getItem('accessToken') : null + const persistToken = + typeof window !== 'undefined' ? localStorage.getItem('persistToken') : null + const [autoLogin] = useRecoilState(autoLoginState) + const { + register, + handleSubmit, + formState: { errors }, + } = useForm({ + resolver: yupResolver(schema), + }) + + function toMain() { + router.push('/') + } + + function toLogin() { + router.push('/login') + } + + const onSubmit: SubmitHandler = async (data: DataObject) => { + const res1 = await fetch( + `${process.env.NEXT_PUBLIC_BASE_URL}/auth/signup`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + email: data.email, + password: data.password, + nickname: data.nickname, + introduction: data.introduction, + }), + }, + ) + + const res1Data = await res1.json() + + if (!res1.ok) { + throw new Error(res1Data.message) + } + + const res2 = await fetch( + `${process.env.NEXT_PUBLIC_BASE_URL}/auth/signin`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + email: data.email, + password: data.password, + }), + }, + ) + + if (!res2.ok) { + throw new Error('회원가입 시 자동 로그인 실패') + } + + const res2Data = await res2.json() + + if (autoLogin) { + localStorage.setItem('persistToken', res2Data.data.accessToken) + } else { + sessionStorage.setItem('accessToken', res2Data.data.accessToken) + } + router.push('/') + } + + useEffect(() => { + if (!navigator.onLine) { + throw new Error('오프라인 상태입니다. 네트워크 연결을 확인해주세요.') + } + if (accessToken || persistToken) { + // eslint-disable-next-line no-alert + alert('이미 로그인 상태입니다.') + router.push('/') + } + }, []) + + return ( +
+ +
+ + 회원가입 + +
+ +

{errors.email?.message}

+ +

{errors.password?.message}

+ +

{errors.confirmPassword?.message}

+ +

{errors.nickname?.message}

+ +

{errors.introduction?.message}

+ +
+
+ 이미 회원이세요? + +
+
+
+ ) +} From 0de5da68d3a750d70e2d226e2baf761bf2894bc1 Mon Sep 17 00:00:00 2001 From: Mayreeel Date: Tue, 26 Sep 2023 14:20:37 +0900 Subject: [PATCH 10/12] =?UTF-8?q?refactor=20:=20getter=EB=A7=8C=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EB=8A=94=20Recoil=20hook=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit useRecoilState => useRecoilValue --- frontend/src/app/(user)/registration/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/(user)/registration/page.tsx b/frontend/src/app/(user)/registration/page.tsx index d62baf5e..ac8d5a3e 100644 --- a/frontend/src/app/(user)/registration/page.tsx +++ b/frontend/src/app/(user)/registration/page.tsx @@ -6,7 +6,7 @@ import { yupResolver } from '@hookform/resolvers/yup' import { useEffect } from 'react' import { SubmitHandler, useForm } from 'react-hook-form' import { useRouter } from 'next/navigation' -import { useRecoilState } from 'recoil' +import { useRecoilValue } from 'recoil' import * as yup from 'yup' import Image from 'next/image' @@ -53,7 +53,7 @@ export default function Registration() { typeof window !== 'undefined' ? sessionStorage.getItem('accessToken') : null const persistToken = typeof window !== 'undefined' ? localStorage.getItem('persistToken') : null - const [autoLogin] = useRecoilState(autoLoginState) + const autoLogin = useRecoilValue(autoLoginState) const { register, handleSubmit, From 0c67f98f8195bd896791ee394e9e75cd15bbcbb4 Mon Sep 17 00:00:00 2001 From: Mayreeel Date: Tue, 26 Sep 2023 19:39:08 +0900 Subject: [PATCH 11/12] =?UTF-8?q?feat=20:=20=EC=98=88=EC=99=B8=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=EC=9A=A9=20state=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/(user)/login/page.tsx | 14 ++++++++------ frontend/src/app/(user)/registration/page.tsx | 7 ++++++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/(user)/login/page.tsx b/frontend/src/app/(user)/login/page.tsx index 05eebf21..09c420d0 100644 --- a/frontend/src/app/(user)/login/page.tsx +++ b/frontend/src/app/(user)/login/page.tsx @@ -3,7 +3,7 @@ /* eslint-disable react/jsx-props-no-spreading */ import { yupResolver } from '@hookform/resolvers/yup' -import { useEffect } from 'react' +import { useEffect, useState } from 'react' import { SubmitHandler, useForm } from 'react-hook-form' import { useRouter } from 'next/navigation' import { useRecoilState } from 'recoil' @@ -40,6 +40,7 @@ export default function Login() { const persistToken = typeof window !== 'undefined' ? localStorage.getItem('persistToken') : null const [autoLogin, setAutoLogin] = useRecoilState(autoLoginState) + const [errorMessage, setErrorMessage] = useState('') const handleCheckboxChange = (event: React.ChangeEvent) => { setAutoLogin(event.target.checked) @@ -77,11 +78,14 @@ export default function Login() { }), }) + const resData = await res.json() + if (!res.ok) { - throw new Error('로그인에 실패했습니다.') + setErrorMessage('아이디 비밀번호를 확인해주세요.') + throw new Error(resData.message) } - const resData = await res.json() + setErrorMessage('') if (autoLogin) { localStorage.setItem('persistToken', resData.data.accessToken) @@ -135,6 +139,7 @@ export default function Login() { autoComplete="current-password" />

{errors.password?.message}

+ {errorMessage ?

{errorMessage}

: null}
- {/* */}
아직 회원이 아니세요? diff --git a/frontend/src/app/(user)/registration/page.tsx b/frontend/src/app/(user)/registration/page.tsx index ac8d5a3e..77b45277 100644 --- a/frontend/src/app/(user)/registration/page.tsx +++ b/frontend/src/app/(user)/registration/page.tsx @@ -3,7 +3,7 @@ /* eslint-disable react/jsx-props-no-spreading */ import { yupResolver } from '@hookform/resolvers/yup' -import { useEffect } from 'react' +import { useEffect, useState } from 'react' import { SubmitHandler, useForm } from 'react-hook-form' import { useRouter } from 'next/navigation' import { useRecoilValue } from 'recoil' @@ -54,6 +54,7 @@ export default function Registration() { const persistToken = typeof window !== 'undefined' ? localStorage.getItem('persistToken') : null const autoLogin = useRecoilValue(autoLoginState) + const [errorMessage, setErrorMessage] = useState('') const { register, handleSubmit, @@ -90,9 +91,12 @@ export default function Registration() { const res1Data = await res1.json() if (!res1.ok) { + setErrorMessage(res1Data.message) throw new Error(res1Data.message) } + setErrorMessage('') + const res2 = await fetch( `${process.env.NEXT_PUBLIC_BASE_URL}/auth/signin`, { @@ -188,6 +192,7 @@ export default function Registration() { placeholder="한 줄 소개" />

{errors.introduction?.message}

+ {errorMessage ?

{errorMessage}

: null}