diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 54a2e19..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "env": { - "node": true, - "browser": true, - "es2021": true - }, - "settings": { - "react": { - "version": "detect" - } - }, - "extends": [ - "eslint:recommended", - "plugin:react/recommended", - "plugin:react-hooks/recommended", - "plugin:import/recommended", - "plugin:jsx-a11y/recommended", - "prettier" - ], - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": "latest", - "sourceType": "module" - }, - "plugins": ["react"], - "rules": { - "react/jsx-uses-react": "off", - "react/react-in-jsx-scope": "off", - "import/no-unresolved": "off", - "react/prop-types": "off", - "import/no-named-as-default": "off", - "jsx-a11y/label-has-associated-control": "off", - "eqeqeq": "error", - "no-undef": "off", - "no-unused-vars": "off" - } -} diff --git a/bun.lockb b/bun.lockb index 4abc8b4..631423c 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..160515c --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,88 @@ +import pluginJs from '@eslint/js'; +import tseslint from '@typescript-eslint/eslint-plugin'; +import parser from '@typescript-eslint/parser'; +import pluginImport from 'eslint-plugin-import'; +import pluginJsxA11y from 'eslint-plugin-jsx-a11y'; +import pluginReact from 'eslint-plugin-react'; +import pluginReactHooks from 'eslint-plugin-react-hooks'; +import pluginSimpleImportSort from 'eslint-plugin-simple-import-sort'; +import globals from 'globals'; + +const commonRules = { + ...pluginJs.configs.recommended.rules, + ...tseslint.configs.recommended.rules, + ...pluginReact.configs.recommended.rules, + ...pluginImport.configs.rules, + ...pluginReactHooks.configs.recommended.rules, + ...pluginJsxA11y.configs.recommended.rules, + 'react/jsx-uses-react': 'off', + 'react/react-in-jsx-scope': 'off', + 'import/no-unresolved': 'off', + 'react/prop-types': 'off', + 'import/no-named-as-default': 'off', + 'import/no-named-as-default-member': 'off', + 'jsx-a11y/label-has-associated-control': 'off', + eqeqeq: 'error', + 'no-undef': 'off', + 'no-unused-vars': 'off', + 'simple-import-sort/imports': 'error', + 'simple-import-sort/exports': 'error', +}; + +export default [ + { + files: ['**/*.{js,mjs,cjs,ts,jsx,tsx}'], + languageOptions: { + globals: globals.browser, + parser: parser, + parserOptions: { + ecmaVersion: 2021, + sourceType: 'module', + }, + }, + settings: { + react: { + version: 'detect', + }, + }, + plugins: { + '@typescript-eslint': tseslint, + react: pluginReact, + 'react-hooks': pluginReactHooks, + import: pluginImport, + 'jsx-a11y': pluginJsxA11y, + 'simple-import-sort': pluginSimpleImportSort, + }, + rules: { + ...commonRules, + }, + }, + //! ts override (지우면 ts와 충돌) + { + files: ['**/*.{ts,tsx}'], + languageOptions: { + parser: parser, + parserOptions: { + ecmaVersion: 2021, + sourceType: 'module', + project: ['./tsconfig.json'], + }, + }, + rules: { + ...commonRules, + //TODO: 추후 제거 예정 (변경 시 현재 동작에 영향이 가는 것을 고려해야함) + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/consistent-type-imports': [ + 'error', + { + prefer: 'type-imports', + disallowTypeAnnotations: false, + }, + ], + 'padding-line-between-statements': [ + 'error', + { blankLine: 'always', prev: '*', next: 'return' }, + ], + }, + }, +]; diff --git a/package.json b/package.json index 503e97e..f0b4054 100644 --- a/package.json +++ b/package.json @@ -26,20 +26,26 @@ "compile": "tsc" }, "devDependencies": { - "@types/node": "^18.19.47", - "@types/react": "^18.3.4", + "@eslint/js": "^9.9.1", + "@types/node": "^22.5.1", + "@types/react": "^18.3.5", "@types/react-dom": "^18.3.0", "@types/react-star-ratings": "^2.3.3", + "@typescript-eslint/eslint-plugin": "^8.3.0", + "@typescript-eslint/parser": "^8.3.0", "@vitejs/plugin-react": "^4.3.1", - "eslint": "^8.57.0", - "eslint-config-prettier": "^8.10.0", + "eslint": "^9.9.1", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsx-a11y": "^6.9.0", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.35.0", "eslint-plugin-react-hooks": "^4.6.2", - "prettier": "^2.8.8", + "eslint-plugin-simple-import-sort": "^12.1.1", + "globals": "^15.9.0", + "prettier": "^3.3.3", "typescript": "^4.9.5", + "typescript-eslint": "^8.3.0", "vite": "^5.4.2" } } diff --git a/src/App.tsx b/src/App.tsx index d169695..1b903c6 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,5 @@ -import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom'; import { Footer, Nav, ScrollButton } from 'components'; +import RouteChangeTracker from 'components/RouteChangeTracker'; import { BadGateway, BanReason, @@ -20,7 +20,7 @@ import { Search, SignUp, } from 'pages'; -import RouteChangeTracker from 'components/RouteChangeTracker'; +import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom'; const App = () => { return ( diff --git a/src/api/ApiController.ts b/src/api/ApiController.ts index 08de309..5608229 100644 --- a/src/api/ApiController.ts +++ b/src/api/ApiController.ts @@ -3,6 +3,7 @@ import axios from 'axios'; import jwtDecode, { type JwtPayload } from 'jwt-decode'; import { useRecoilState } from 'recoil'; import { isLoginStorage } from 'utils/loginStorage'; + import { logout, refresh } from './etc'; const PROXY_URL = window.location.hostname === 'localhost' ? '/api' : '/proxy'; @@ -19,6 +20,7 @@ const JwtInterceptors = () => { if (!token) return false; const tokenInfo = jwtDecode(token); if (tokenInfo.exp && tokenInfo.exp <= Date.now() / 1000) return false; + return true; }; //토큰 리프레시 @@ -29,6 +31,7 @@ const JwtInterceptors = () => { throw new Error(`Response status is ${res?.status}`); } else { setToken(res.data.AccessToken); + return res; } } catch (error) { @@ -57,8 +60,9 @@ const JwtInterceptors = () => { }, function (error) { alert('해당 요청이 정상적으로 이루어지지 않았어요.\n 다시 시도해주세요.'); + return Promise.reject(error); - } + }, ); instance.interceptors.response.use( @@ -69,9 +73,11 @@ const JwtInterceptors = () => { if (error.response.status === 502) { location.href = '/502'; } + return Promise.reject(error); - } + }, ); + return { instance }; }; diff --git a/src/api/Auth.ts b/src/api/Auth.ts index a71da83..704c811 100644 --- a/src/api/Auth.ts +++ b/src/api/Auth.ts @@ -1,7 +1,7 @@ import { useNavigate } from 'react-router-dom'; import { useSetRecoilState } from 'recoil'; -import { AxiosResponseSuccess } from 'types/common'; -import { +import type { AxiosResponseSuccess } from 'types/common'; +import type { FindPassword, ResetPassword, ResponseUserCheckID, @@ -12,6 +12,7 @@ import { UserLoginResponse, } from 'types/user'; import { removeStorage, setStorage } from 'utils/loginStorage'; + import { tokenState } from '../app/recoilStore'; import JwtInterceptors from './ApiController'; diff --git a/src/api/Lecture.ts b/src/api/Lecture.ts index fe13d38..f5216fd 100644 --- a/src/api/Lecture.ts +++ b/src/api/Lecture.ts @@ -1,8 +1,9 @@ -import { AxiosError } from 'axios'; -import { ExamPostsResponse } from 'types/exam'; +import type { AxiosError } from 'axios'; +import type { Review } from 'types/evaluate'; +import type { ExamPostsResponse } from 'types/exam'; import type { LectureDetailItem, MainLecture } from 'types/lecture'; + import JwtInterceptors from './ApiController'; -import { Review } from 'types/evaluate'; const Lecture = () => { const { instance } = JwtInterceptors(); @@ -13,6 +14,7 @@ const Lecture = () => { const data: MainLecture = await instance.get( `/lecture/all/?option=${lecture}&page=${page}&majorType=${majorType}` ); + return data; } catch (error) { const axiosError = error as AxiosError; @@ -60,6 +62,7 @@ const Lecture = () => { const { data } = await instance.get( `/evaluate-posts/?lectureId=${selectId}&page=${pageParam}` ); + return { data, isLast: data.length < 10, @@ -77,6 +80,7 @@ const Lecture = () => { const data: ExamPostsResponse = await instance.get( `/exam-posts/?lectureId=${selectId}&page=${pageParam}` ); + return { data, isLast: data.data.length < 10, diff --git a/src/api/Major.ts b/src/api/Major.ts index 7ec939c..4659a12 100644 --- a/src/api/Major.ts +++ b/src/api/Major.ts @@ -1,6 +1,7 @@ -import { AxiosError } from 'axios'; +import type { AxiosError } from 'axios'; +import type { VersionCheckSuccess } from 'types/common'; + import JwtInterceptors from './ApiController'; -import { VersionCheckSuccess } from 'types/common'; const Major = () => { const { instance } = JwtInterceptors(); @@ -9,6 +10,7 @@ const Major = () => { const version = async () => { try { const res: VersionCheckSuccess = await instance.get('/suwiki/version'); + return res; } catch (error) { const axiosError = error as AxiosError; @@ -20,6 +22,7 @@ const Major = () => { const type = async () => { try { const res = await instance.get('/suwiki/majorType'); + return res; } catch (error) { const axiosError = error as AxiosError; @@ -31,6 +34,7 @@ const Major = () => { const searchFavorite = async () => { try { const res = await instance.get('/user/favorite-major'); + return res; } catch (error) { const axiosError = error as AxiosError; @@ -42,6 +46,7 @@ const Major = () => { const favoriting = async (majorType: string) => { try { const res = await instance.post('/user/favorite-major', { majorType }); + return res; } catch (error) { const axiosError = error as AxiosError; diff --git a/src/api/Notice.ts b/src/api/Notice.ts index 22b667e..45e0bcb 100644 --- a/src/api/Notice.ts +++ b/src/api/Notice.ts @@ -1,6 +1,7 @@ +import type { AxiosError } from 'axios'; + +import type { NoticeDetail,NoticeItem } from '../types/notice'; import JwtInterceptors from './ApiController'; -import type { NoticeItem, NoticeDetail } from '../types/notice'; -import { AxiosError } from 'axios'; const Notices = () => { const { instance } = JwtInterceptors(); @@ -8,6 +9,7 @@ const Notices = () => { const list = async (pageParam = 1) => { try { const res = await instance.get(`/notice/all?page=${pageParam}`); + return { data: res, nextPage: pageParam + 1, @@ -23,12 +25,14 @@ const Notices = () => { const detail = async (notice: string) => { try { const res = await instance.get(`/notice/?noticeId=${notice}`); + return res; } catch (error) { const axiosError = error as AxiosError; alert(axiosError.message); } }; + return { list, detail }; }; diff --git a/src/api/User.ts b/src/api/User.ts index 7c0b9a0..8246614 100644 --- a/src/api/User.ts +++ b/src/api/User.ts @@ -1,5 +1,7 @@ -import { AxiosError } from 'axios'; +import type { AxiosError } from 'axios'; import type { AxiosResponseSuccess } from 'types/common'; +import type { Review } from 'types/evaluate'; +import type { MyExam } from 'types/exam'; import type { BlacklistInfo, EvaluatePostCreate, @@ -12,10 +14,9 @@ import type { RestrictionInfo, UserProfileInfo, } from 'types/user'; + import { queryClient } from '../main'; import JwtInterceptors from './ApiController'; -import { Review } from 'types/evaluate'; -import { MyExam } from 'types/exam'; const User = () => { const { instance } = JwtInterceptors(); @@ -23,6 +24,7 @@ const User = () => { const info = async () => { try { const data: UserProfileInfo = await instance.get('/user/my-page'); + return data; } catch (error) { const axiosError = error as AxiosError; @@ -34,6 +36,7 @@ const User = () => { const evaluateList = async (pageParam = 1) => { try { const { data } = await instance.get(`/evaluate-posts/written/?page=${pageParam}`); + return { data, isLast: data.length < 10, @@ -49,6 +52,7 @@ const User = () => { const examInfoList = async (pageParam = 1) => { try { const { data } = await instance.get(`/exam-posts/written/?page=${pageParam}`); + return { data, isLast: data.length < 10, @@ -74,6 +78,7 @@ const User = () => { const banList = async () => { try { const data: BlacklistInfo[] = await instance.get('user/blacklist-reason'); + return data; } catch (error) { const axiosError = error as AxiosError; @@ -85,6 +90,7 @@ const User = () => { const resList = async () => { try { const data: RestrictionInfo[] = await instance.get('user/restricted-reason'); + return data; } catch (error) { const axiosError = error as AxiosError; diff --git a/src/api/etc.ts b/src/api/etc.ts index 48ba760..d59ccf4 100644 --- a/src/api/etc.ts +++ b/src/api/etc.ts @@ -1,11 +1,13 @@ -import axios, { AxiosError } from 'axios'; -import { ClientRefresh } from 'types/user'; +import type { AxiosError } from 'axios'; +import axios from 'axios'; +import type { ClientRefresh } from 'types/user'; import { removeStorage } from 'utils/loginStorage'; // 전공 선택 의존성때문에 따로 빼놓은 것 export const type = async (Authorization: string) => { try { const { data } = await axios.get(`/suwiki/majorType`, { headers: { Authorization } }); + return data; } catch (error) { const axiosError = error as AxiosError; @@ -18,6 +20,7 @@ export const searchFavorite = async (Authorization: string) => { const { data } = await axios.get(`/user/favorite-major`, { headers: { Authorization }, }); + return data; } catch (error) { const axiosError = error as AxiosError; @@ -43,6 +46,7 @@ export const logout = async () => { export const refresh = () => { try { const res = axios.post(`/user/client-refresh`); + return res; } catch (error) { const axiosError = error as AxiosError; diff --git a/src/api/index.ts b/src/api/index.ts index d0bc3da..31d954f 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,6 +1,6 @@ +export { default as ApiController } from './ApiController'; export { default as Auth } from './Auth'; export { default as Lecture } from './Lecture'; export { default as Major } from './Major'; export { default as Notice } from './Notice'; export { default as User } from './User'; -export { default as ApiController } from './ApiController'; diff --git a/src/app/recoilStore.ts b/src/app/recoilStore.ts index acb760c..edd6733 100644 --- a/src/app/recoilStore.ts +++ b/src/app/recoilStore.ts @@ -1,5 +1,5 @@ import { atom } from 'recoil'; -import { Review } from 'types/evaluate'; +import type { Review } from 'types/evaluate'; export const lectureState = atom({ key: 'lectureState', diff --git a/src/components/AsyncBoundary.tsx b/src/components/AsyncBoundary.tsx index a351f3e..f74334a 100644 --- a/src/components/AsyncBoundary.tsx +++ b/src/components/AsyncBoundary.tsx @@ -1,4 +1,5 @@ -import { PropsWithChildren, Suspense, type ComponentProps } from 'react'; +import type {PropsWithChildren} from 'react'; +import { type ComponentProps, Suspense } from 'react'; import { ErrorBoundary, type FallbackProps } from 'react-error-boundary'; type ErrorBoundaryProps = ComponentProps; diff --git a/src/components/ErrorFrame.tsx b/src/components/ErrorFrame.tsx index 83c8e64..f4b1217 100644 --- a/src/components/ErrorFrame.tsx +++ b/src/components/ErrorFrame.tsx @@ -10,6 +10,7 @@ interface ErrorFrameProps { const ErrorFrame = ({ mainMsg, subMsg }: ErrorFrameProps) => { const navigate = useNavigate(); + return ( diff --git a/src/components/Etc/Button.tsx b/src/components/Etc/Button.tsx index 107d33e..51a144f 100644 --- a/src/components/Etc/Button.tsx +++ b/src/components/Etc/Button.tsx @@ -1,5 +1,5 @@ import styled from '@emotion/styled'; -import { PropsWithChildren } from 'react'; +import type { PropsWithChildren } from 'react'; interface ButtonProps { onClick?: () => void; diff --git a/src/components/Etc/Modal.tsx b/src/components/Etc/Modal.tsx index 3e102eb..6a98a80 100644 --- a/src/components/Etc/Modal.tsx +++ b/src/components/Etc/Modal.tsx @@ -1,5 +1,6 @@ import styled from '@emotion/styled'; -import { PropsWithChildren, useEffect } from 'react'; +import type { PropsWithChildren} from 'react'; +import { useEffect } from 'react'; interface ModalProps { isOpen: boolean; @@ -14,6 +15,7 @@ const Modal = ({ isOpen, onRequestClose, children }: PropsWithChildren window.removeEventListener('keydown', onKeyPress); }, [onRequestClose]); diff --git a/src/components/Etc/RangeInput.tsx b/src/components/Etc/RangeInput.tsx index 680c7c2..06d5af0 100644 --- a/src/components/Etc/RangeInput.tsx +++ b/src/components/Etc/RangeInput.tsx @@ -1,5 +1,5 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import styled from '@emotion/styled'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; interface RangeInputProps { min?: number; @@ -46,6 +46,7 @@ const RangeInput = ({ inputElement.addEventListener('mousedown', handleDown); inputElement.addEventListener('mouseup', handleUpAndLeave); inputElement.addEventListener('mouseleave', handleUpAndLeave); + return () => { inputElement.removeEventListener('mousemove', changeInputProgressPercentStyle); inputElement.removeEventListener('mousedown', handleDown); diff --git a/src/components/Etc/ScrollButton.tsx b/src/components/Etc/ScrollButton.tsx index 34de15d..6347c9f 100644 --- a/src/components/Etc/ScrollButton.tsx +++ b/src/components/Etc/ScrollButton.tsx @@ -1,5 +1,5 @@ -import { useState, useEffect } from 'react'; import styled from '@emotion/styled'; +import { useEffect,useState } from 'react'; const ScrollButton = () => { const [ScrollY, setScrollY] = useState(0); @@ -19,6 +19,7 @@ const ScrollButton = () => { useEffect(() => { window.addEventListener('scroll', handleFollow); + return () => { window.removeEventListener('scroll', handleFollow); }; diff --git a/src/components/Etc/Spinner.tsx b/src/components/Etc/Spinner.tsx index 3be0f1e..3956aac 100644 --- a/src/components/Etc/Spinner.tsx +++ b/src/components/Etc/Spinner.tsx @@ -1,5 +1,5 @@ -import styled from '@emotion/styled'; import { keyframes } from '@emotion/react'; +import styled from '@emotion/styled'; const Spinner = ({ id }: { id?: string }) => { return ( diff --git a/src/components/EvaluationDetail.tsx b/src/components/EvaluationDetail.tsx index 61b37b3..b46818d 100644 --- a/src/components/EvaluationDetail.tsx +++ b/src/components/EvaluationDetail.tsx @@ -1,6 +1,6 @@ import styled from '@emotion/styled'; -import { SetNumber, SetTeamNumber } from 'types/common'; -import { Review } from 'types/evaluate'; +import type { SetNumber, SetTeamNumber } from 'types/common'; +import type { Review } from 'types/evaluate'; import { floatFix } from 'utils/floatFix'; const team = { diff --git a/src/components/Lecture/IsTestInfo.tsx b/src/components/Lecture/IsTestInfo.tsx index 1a3cc1f..8db11eb 100644 --- a/src/components/Lecture/IsTestInfo.tsx +++ b/src/components/Lecture/IsTestInfo.tsx @@ -1,9 +1,9 @@ import styled from '@emotion/styled'; -import { Button, Spinner, SearchTestInfoList } from 'components'; +import { User } from 'api'; +import { Button, SearchTestInfoList,Spinner } from 'components'; import { fakeEvaluationList } from 'constants/placeholderData'; -import { isLoginStorage } from 'utils/loginStorage'; import useLectureQuery from 'hooks/useLectureQuery'; -import { User } from 'api'; +import { isLoginStorage } from 'utils/loginStorage'; interface IsTestInfoProps { selectId: string; diff --git a/src/components/Lecture/LectureCard.tsx b/src/components/Lecture/LectureCard.tsx index 90b3493..fa914a4 100644 --- a/src/components/Lecture/LectureCard.tsx +++ b/src/components/Lecture/LectureCard.tsx @@ -2,7 +2,7 @@ import styled from '@emotion/styled'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import StarRatings from 'react-star-ratings'; -import { LectureDetailItem } from 'types/lecture'; +import type { LectureDetailItem } from 'types/lecture'; import { floatFix } from 'utils/floatFix'; import { subStr } from 'utils/subString'; diff --git a/src/components/Lecture/LectureContainer.tsx b/src/components/Lecture/LectureContainer.tsx index 48889e1..8f762d4 100644 --- a/src/components/Lecture/LectureContainer.tsx +++ b/src/components/Lecture/LectureContainer.tsx @@ -1,6 +1,6 @@ import styled from '@emotion/styled'; -import { FlexWrap } from 'styles/common'; import { LectureCard } from 'components'; +import { FlexWrap } from 'styles/common'; import type { LectureDetailItem } from 'types/lecture'; const LectureContainer = ({ data }: { data?: LectureDetailItem[] }) => { diff --git a/src/components/Lecture/LectureInfoBox.tsx b/src/components/Lecture/LectureInfoBox.tsx index 2f87cd1..5cc48db 100644 --- a/src/components/Lecture/LectureInfoBox.tsx +++ b/src/components/Lecture/LectureInfoBox.tsx @@ -1,9 +1,9 @@ import styled from '@emotion/styled'; -import { useNavigate } from 'react-router-dom'; import { Button } from 'components'; +import { useNavigate } from 'react-router-dom'; +import type { SetNumber, SetTeamNumber } from 'types/common'; +import type { LectureDetailItem } from 'types/lecture'; import { floatFix } from 'utils/floatFix'; -import { LectureDetailItem } from 'types/lecture'; -import { SetNumber, SetTeamNumber } from 'types/common'; interface LectureInfoBoxProps { current: LectureDetailItem; diff --git a/src/components/List/EvaluationList.tsx b/src/components/List/EvaluationList.tsx index 5512577..0318d39 100644 --- a/src/components/List/EvaluationList.tsx +++ b/src/components/List/EvaluationList.tsx @@ -1,12 +1,12 @@ import styled from '@emotion/styled'; -import StarRatings from 'react-star-ratings'; -import { useState } from 'react'; -import { subStr } from 'utils/subString'; -import { EvaluationDetail, WriteEvaluation, Spinner, Modal } from 'components'; +import { User } from 'api'; +import { EvaluationDetail, Modal,Spinner, WriteEvaluation } from 'components'; import useUserQuery from 'hooks/useUserQuery'; +import { useState } from 'react'; +import StarRatings from 'react-star-ratings'; +import type { Review } from 'types/evaluate'; import { floatFix } from 'utils/floatFix'; -import { User } from 'api'; -import { Review } from 'types/evaluate'; +import { subStr } from 'utils/subString'; const EvaluationList = () => { const { EvaluationList } = useUserQuery(); diff --git a/src/components/List/LectureList.tsx b/src/components/List/LectureList.tsx index ef9cc3f..87f0085 100644 --- a/src/components/List/LectureList.tsx +++ b/src/components/List/LectureList.tsx @@ -2,7 +2,7 @@ import { LectureContainer } from 'components'; import { fakeLectureList } from 'constants/placeholderData'; import useLectureQuery from 'hooks/useLectureQuery'; import { FlexWrap } from 'styles/common'; -import { MainLecture } from 'types/lecture'; +import type { MainLecture } from 'types/lecture'; interface LectureListProps { pages: diff --git a/src/components/List/SearchEvaluationList.tsx b/src/components/List/SearchEvaluationList.tsx index bcc1f6c..ecb6026 100644 --- a/src/components/List/SearchEvaluationList.tsx +++ b/src/components/List/SearchEvaluationList.tsx @@ -1,12 +1,12 @@ import styled from '@emotion/styled'; -import StarRatings from 'react-star-ratings'; -import { useState, Fragment } from 'react'; import { User } from 'api'; import { EvaluationDetail, Spinner } from 'components'; import { fakeEvaluationList } from 'constants/placeholderData'; import useLectureQuery from 'hooks/useLectureQuery'; +import { Fragment,useState } from 'react'; +import StarRatings from 'react-star-ratings'; +import type { Review } from 'types/evaluate'; import { floatFix } from 'utils/floatFix'; -import { Review } from 'types/evaluate'; export const FakeList = () => { return ( diff --git a/src/components/List/SearchTestInfoList.tsx b/src/components/List/SearchTestInfoList.tsx index 8df9555..ca0616f 100644 --- a/src/components/List/SearchTestInfoList.tsx +++ b/src/components/List/SearchTestInfoList.tsx @@ -1,6 +1,6 @@ import styled from '@emotion/styled'; import { User } from 'api'; -import { ExamPost } from 'types/exam'; +import type { ExamPost } from 'types/exam'; interface SearchTestInfoListProps { page: ExamPost[]; diff --git a/src/components/List/TestInfoList.tsx b/src/components/List/TestInfoList.tsx index 1c9b069..895e492 100644 --- a/src/components/List/TestInfoList.tsx +++ b/src/components/List/TestInfoList.tsx @@ -1,11 +1,12 @@ import styled from '@emotion/styled'; -import { useState } from 'react'; -import { WriteTestInfo, Spinner, Modal } from 'components'; -import { subStr } from 'utils/subString'; -import useUserQuery from 'hooks/useUserQuery'; import { User } from 'api'; +import { Modal, Spinner, WriteTestInfo } from 'components'; +import useUserQuery from 'hooks/useUserQuery'; +import { useState } from 'react'; import type { MyExam } from 'types/exam'; -import { ExamDiff } from './SearchTestInfoList'; +import { subStr } from 'utils/subString'; + +import type { ExamDiff } from './SearchTestInfoList'; const TestInfoList = () => { const { TestInfoList } = useUserQuery(); @@ -22,9 +23,7 @@ const TestInfoList = () => { data.pages.map((page) => { return ( - {page?.data.map((row) => ( - - ))} + {page?.data.map((row) => )} ); }) @@ -43,7 +42,10 @@ export const TestInfoCard = ({ row }: { row: MyExam }) => { let mobileTitle = subStr(row.lectureName, 14); const onDelete = () => { - window.confirm('시험정보를 삭제하시겠습니까?') && deleteExamInfo(row.id.toString()); + const isConfirmed = window.confirm('시험정보를 삭제하시겠습니까?'); + if (isConfirmed) { + deleteExamInfo(row.id.toString()); + } }; const examDifficultySet = row.examDifficulty; diff --git a/src/components/Major/MajorSearch.tsx b/src/components/Major/MajorSearch.tsx index ca67c98..4efb8aa 100644 --- a/src/components/Major/MajorSearch.tsx +++ b/src/components/Major/MajorSearch.tsx @@ -1,8 +1,8 @@ import styled from '@emotion/styled'; -import * as styles from '@mui/material/styles'; -import { Fragment, useState } from 'react'; import { TextField } from '@mui/material'; +import * as styles from '@mui/material/styles'; import useFavoriteMajor from 'hooks/useFavoriteMajor'; +import { Fragment, useState } from 'react'; const MajorSearch = ({ setModalIsOpen, diff --git a/src/components/Major/MajorSelect.tsx b/src/components/Major/MajorSelect.tsx index 30d2430..a9a6f28 100644 --- a/src/components/Major/MajorSelect.tsx +++ b/src/components/Major/MajorSelect.tsx @@ -1,8 +1,8 @@ +import { MajorSearch, Modal } from 'components'; import { useState } from 'react'; import { useSearchParams } from 'react-router-dom'; -import { MajorSearch, Modal } from 'components'; -import { subStr } from 'utils/subString'; import { Arrows, OptionBox, SelectedOption, SelectedOption_M } from 'styles/common'; +import { subStr } from 'utils/subString'; const MajorSelect = () => { const [searchParams] = useSearchParams(); diff --git a/src/components/Nav.tsx b/src/components/Nav.tsx index ec204c1..d312d6c 100644 --- a/src/components/Nav.tsx +++ b/src/components/Nav.tsx @@ -1,8 +1,8 @@ import styled from '@emotion/styled'; +import { logout } from 'api/etc'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { isLoginStorage } from 'utils/loginStorage'; -import { logout } from 'api/etc'; const Nav = () => { const navigate = useNavigate(); diff --git a/src/components/OptionSelect.tsx b/src/components/OptionSelect.tsx index 136cd3d..fcf99ca 100644 --- a/src/components/OptionSelect.tsx +++ b/src/components/OptionSelect.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; import { Arrows, Option, OptionBox, Options, SelectedOption } from 'styles/common'; -import { SortOption } from 'types/common'; +import type { SortOption } from 'types/common'; interface OptionSelectProps { list: SortOption[]; @@ -21,9 +21,11 @@ const OptionSelect = ({ list, itemTitle, location }: OptionSelectProps) => { const isMain = location === 'main'; const handleSelect = (option: string) => { - isMain - ? navigate(`/?option=${option}&majorType=${majorType}`) - : navigate(`/search?q=${searchValue}&option=${option}&majorType=${majorType}`); + if (isMain) { + navigate(`/?option=${option}&majorType=${majorType}`); + } else { + navigate(`/search?q=${searchValue}&option=${option}&majorType=${majorType}`); + } }; return ( @@ -32,7 +34,7 @@ const OptionSelect = ({ list, itemTitle, location }: OptionSelectProps) => { select={select} icon={isMain ? selectedOption?.icon : undefined} onClick={(e) => { - e.stopPropagation; + e.stopPropagation(); onSelect(!select); }} > diff --git a/src/components/RouteChangeTracker.ts b/src/components/RouteChangeTracker.ts index 2cfc016..bcdff6c 100644 --- a/src/components/RouteChangeTracker.ts +++ b/src/components/RouteChangeTracker.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; -import { useLocation } from 'react-router-dom'; import { initialize, pageview } from 'react-ga'; +import { useLocation } from 'react-router-dom'; const RouteChangeTracker = () => { const location = useLocation(); diff --git a/src/components/SemesterSelect.tsx b/src/components/SemesterSelect.tsx index b8b17ff..72294c7 100644 --- a/src/components/SemesterSelect.tsx +++ b/src/components/SemesterSelect.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { OptionBox, SelectedOption, Arrows, Options, Option } from 'styles/common'; +import { Arrows, Option, OptionBox, Options, SelectedOption } from 'styles/common'; interface SemesterSelectProps { list: string[]; @@ -9,12 +9,13 @@ interface SemesterSelectProps { const SemesterSelect = ({ list, selected, setSelect }: SemesterSelectProps) => { const [modal, setModal] = useState(false); + return ( { - e.stopPropagation; + e.stopPropagation(); setModal(!modal); }} > diff --git a/src/components/UserInfo/UserAccount.tsx b/src/components/UserInfo/UserAccount.tsx index 52e1211..660022e 100644 --- a/src/components/UserInfo/UserAccount.tsx +++ b/src/components/UserInfo/UserAccount.tsx @@ -1,5 +1,5 @@ import styled from '@emotion/styled'; -import { UserEmail, UserId } from 'types/user'; +import type { UserEmail, UserId } from 'types/user'; interface UserAccountProps extends UserId, UserEmail { isLogin: boolean; diff --git a/src/components/UserInfo/UserInfo.tsx b/src/components/UserInfo/UserInfo.tsx index 3d1875d..5e48a3f 100644 --- a/src/components/UserInfo/UserInfo.tsx +++ b/src/components/UserInfo/UserInfo.tsx @@ -1,9 +1,9 @@ import styled from '@emotion/styled'; -import { useNavigate } from 'react-router-dom'; import { UserAccount, UserPoint } from 'components'; import { fakeUserInfo } from 'constants/placeholderData'; +import { useNavigate } from 'react-router-dom'; +import type { UserProfileInfo } from 'types/user'; import { isLoginStorage } from 'utils/loginStorage'; -import { UserProfileInfo } from 'types/user'; interface UserInfoProps { my: UserProfileInfo; @@ -14,7 +14,11 @@ const UserInfo = ({ my }: UserInfoProps) => { const isLogin = isLoginStorage(); const handleNavigate = () => { - isLogin ? navigate('/myposting') : navigate('/login'); + if (isLogin) { + navigate('/myposting'); + } else { + navigate('/login'); + } }; const optionSlice = (start: number, end: number) => { diff --git a/src/components/UserInfo/UserPoint.tsx b/src/components/UserInfo/UserPoint.tsx index 0315371..73544c6 100644 --- a/src/components/UserInfo/UserPoint.tsx +++ b/src/components/UserInfo/UserPoint.tsx @@ -1,5 +1,5 @@ import styled from '@emotion/styled'; -import { UserProfileInfo } from 'types/user'; +import type { UserProfileInfo } from 'types/user'; interface UserPointProps { my: UserProfileInfo; diff --git a/src/components/Write/WriteEvaluation.tsx b/src/components/Write/WriteEvaluation.tsx index 1c21bfa..c137d34 100644 --- a/src/components/Write/WriteEvaluation.tsx +++ b/src/components/Write/WriteEvaluation.tsx @@ -1,5 +1,4 @@ import styled from '@emotion/styled'; -import { Fragment } from 'react'; import SemesterSelect from 'components/SemesterSelect'; import { EvaluationSelectOptions, @@ -7,6 +6,7 @@ import { semesters, } from 'constants/placeholderData'; import useWriteEvaluation from 'hooks/useWriteEvaluation'; +import { Fragment } from 'react'; import type { Review } from 'types/evaluate'; export interface WriteEvaluationProps { @@ -29,6 +29,7 @@ const WriteEvaluation = ({ setModalIsOpen, row, type }: WriteEvaluationProps) => onChangeLectureOptions, onEvaluate, } = useWriteEvaluation({ setModalIsOpen, row, type }); + return ( @@ -61,6 +62,7 @@ const WriteEvaluation = ({ setModalIsOpen, row, type }: WriteEvaluationProps) => {EvaluationSliderOptions.map(({ id, name }) => { const { state, Slider } = SliderOptions[id as SliderId]; + return ( diff --git a/src/components/Write/WriteTestInfo.tsx b/src/components/Write/WriteTestInfo.tsx index b11b1fc..1250bc9 100644 --- a/src/components/Write/WriteTestInfo.tsx +++ b/src/components/Write/WriteTestInfo.tsx @@ -1,9 +1,9 @@ import styled from '@emotion/styled'; -import { useState } from 'react'; -import { useMutation } from 'react-query'; import { User } from 'api'; import SemesterSelect from 'components/SemesterSelect'; import { ExamSelectOptions, examTypes, semesters } from 'constants/placeholderData'; +import { useState } from 'react'; +import { useMutation } from 'react-query'; import type { MyExam } from 'types/exam'; type WriteTestProps = 'examDifficulty' | 'examInfo'; @@ -50,7 +50,7 @@ const WriteTestInfo = ({ setModalIsOpen, row, type }: WriteTestInfoProps) => { examType, examDifficulty: examOptions.examDifficulty, content, - }) + }), ); const examInfoUpdate = useMutation(() => @@ -60,7 +60,7 @@ const WriteTestInfo = ({ setModalIsOpen, row, type }: WriteTestInfoProps) => { examType, examDifficulty: examOptions.examDifficulty, content, - }) + }), ); const onTest = () => { @@ -70,7 +70,11 @@ const WriteTestInfo = ({ setModalIsOpen, row, type }: WriteTestInfoProps) => { if (examOptions.examInfo.length === 0) return alert('시험유형(란)을 선택해주세요'); if (content.length < 30 || content.length > 1000) return alert('최소 30자 이상 최대 1000자 이내로 입력해주세요'); - type === 'update' ? examInfoUpdate.mutate() : examWriting.mutate(); + if (type === 'update') { + examInfoUpdate.mutate(); + } else { + examWriting.mutate(); + } setModalIsOpen(false); }; diff --git a/src/components/index.ts b/src/components/index.ts index 4753f77..d953d1b 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,37 +1,31 @@ +export { default as BanFrame } from './BanFrame'; +export { default as ErrorFrame } from './ErrorFrame'; export { default as Button } from './Etc/Button'; +export { default as Modal } from './Etc/Modal'; export { default as RangeInput } from './Etc/RangeInput'; export { default as ScrollButton } from './Etc/ScrollButton'; export { default as Spinner } from './Etc/Spinner'; -export { default as Modal } from './Etc/Modal'; - +export { default as EvaluationDetail } from './EvaluationDetail'; +export { default as Footer } from './Footer'; export { default as IsTestInfo } from './Lecture/IsTestInfo'; export { default as LectureCard } from './Lecture/LectureCard'; export { default as LectureContainer } from './Lecture/LectureContainer'; export { default as LectureDetail } from './Lecture/LectureDetail'; export { default as LectureInfoBox } from './Lecture/LectureInfoBox'; export { default as LectureSearch } from './Lecture/LectureSearch'; - export { default as EvaluationList } from './List/EvaluationList'; export { default as LectureList } from './List/LectureList'; export { default as MainList } from './List/MainList'; export { default as SearchEvaluationList } from './List/SearchEvaluationList'; export { default as SearchTestInfoList } from './List/SearchTestInfoList'; export { default as TestInfoList } from './List/TestInfoList'; - -export { default as MajorSelect } from './Major/MajorSelect'; +export { default as MainBanner } from './MainBanner'; export { default as MajorSearch } from './Major/MajorSearch'; - +export { default as MajorSelect } from './Major/MajorSelect'; +export { default as Nav } from './Nav'; +export { default as OptionSelect } from './OptionSelect'; export { default as UserAccount } from './UserInfo/UserAccount'; export { default as UserInfo } from './UserInfo/UserInfo'; export { default as UserPoint } from './UserInfo/UserPoint'; - export { default as WriteEvaluation } from './Write/WriteEvaluation'; export { default as WriteTestInfo } from './Write/WriteTestInfo'; - -export { default as BanFrame } from './BanFrame'; -export { default as ErrorFrame } from './ErrorFrame'; -export { default as EvaluationDetail } from './EvaluationDetail'; -export { default as Footer } from './Footer'; -export { default as Nav } from './Nav'; -export { default as OptionSelect } from './OptionSelect'; -export { default as MainBanner } from './MainBanner'; diff --git a/src/hooks/useFavoriteMajor.ts b/src/hooks/useFavoriteMajor.ts index fd32409..6bc6980 100644 --- a/src/hooks/useFavoriteMajor.ts +++ b/src/hooks/useFavoriteMajor.ts @@ -26,6 +26,7 @@ const useFavoriteMajor = (setModalIsOpen: React.Dispatch { const { data: getMainLecture } = useQuery( ['main', option, major], () => lecture.main(option, 1, major), - { keepPreviousData: true, suspense: true } + { keepPreviousData: true, suspense: true }, ); // 검색 쿼리(key: 검색어,정렬,전공) @@ -43,16 +43,18 @@ const useLectureQuery = () => { { getNextPageParam: (lastPage) => { if (lastPage && !lastPage.isLast) return lastPage.nextPage; + return undefined; }, keepPreviousData: true, - } + }, ); useEffect(() => { if (inView) { getNextSearch(); } }, [inView, getNextSearch]); + return { data, searchLoading, nextLoading, value, ref }; }; @@ -86,8 +88,9 @@ const useLectureQuery = () => { totalAvg: 0, }); }, - } + }, ); + return { data, isLoading, isLogin: isLogin }; }; @@ -100,19 +103,21 @@ const useLectureQuery = () => { { getNextPageParam: (lastPage) => { if (lastPage && !lastPage.isLast) return lastPage.nextPage; + return undefined; }, onSuccess: (data) => setWritten(data.pages[0]!.data), cacheTime: CACHE_TIME.MINUTE_0, staleTime: CACHE_TIME.MINUTE_0, enabled: isLogin, - } + }, ); useEffect(() => { if (inView && isLogin) { fetchNextPage(); } }, [inView, fetchNextPage]); + return { data, isFetchingNextPage, isLoading, ref }; }; @@ -125,19 +130,21 @@ const useLectureQuery = () => { { getNextPageParam: (lastPage) => { if (lastPage && !lastPage.isLast) return lastPage.nextPage; + return undefined; }, onSuccess: (data) => setWritten(data.pages[0]!.data), cacheTime: CACHE_TIME.MINUTE_0, staleTime: CACHE_TIME.MINUTE_0, enabled: isLogin, - } + }, ); useEffect(() => { if (inView && isLogin) { fetchNextPage(); } }, [inView, fetchNextPage]); + return { data, isFetchingNextPage, isLoading, ref }; }; diff --git a/src/hooks/useSearch.ts b/src/hooks/useSearch.ts index 0462885..f5ba757 100644 --- a/src/hooks/useSearch.ts +++ b/src/hooks/useSearch.ts @@ -1,4 +1,5 @@ -import { KeyboardEvent, useEffect, useRef } from 'react'; +import type { KeyboardEvent} from 'react'; +import { useEffect, useRef } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; interface SearchHook { @@ -23,6 +24,7 @@ const useSearch: SearchHook = (key = 'q') => { const inputValue = inputRef.current?.value.trim() || ''; if (inputValue.length < 2) { alert('두 글자 이상 입력해주세요'); + return; } navigate(`/search?q=${inputValue}&option=${option}&majorType=${majorType}`); diff --git a/src/hooks/useUserQuery.ts b/src/hooks/useUserQuery.ts index 276bb64..88fe8bd 100644 --- a/src/hooks/useUserQuery.ts +++ b/src/hooks/useUserQuery.ts @@ -1,9 +1,9 @@ -import { useInfiniteQuery } from 'react-query'; import { User } from 'api'; -import { isLoginStorage } from 'utils/loginStorage'; +import { CACHE_TIME } from 'constants/cacheTime'; import { useEffect } from 'react'; import { useInView } from 'react-intersection-observer'; -import { CACHE_TIME } from 'constants/cacheTime'; +import { useInfiniteQuery } from 'react-query'; +import { isLoginStorage } from 'utils/loginStorage'; const useUserQuery = () => { const user = User(); @@ -16,6 +16,7 @@ const useUserQuery = () => { { getNextPageParam: (lastPage) => { if (lastPage && !lastPage.isLast) return lastPage.nextPage; + return undefined; }, enabled: isLoginStorage(), @@ -28,6 +29,7 @@ const useUserQuery = () => { fetchNextPage(); } }, [inView, fetchNextPage]); + return { data, isLoading, isFetchingNextPage, ref }; }; @@ -40,6 +42,7 @@ const useUserQuery = () => { { getNextPageParam: (lastPage) => { if (lastPage && !lastPage.isLast) return lastPage.nextPage; + return undefined; }, enabled: isLoginStorage(), @@ -52,6 +55,7 @@ const useUserQuery = () => { fetchNextPage(); } }, [inView, fetchNextPage]); + return { data, isLoading, isFetchingNextPage, ref }; }; diff --git a/src/hooks/useWriteEvaluation.ts b/src/hooks/useWriteEvaluation.ts index 318d91c..8cc5351 100644 --- a/src/hooks/useWriteEvaluation.ts +++ b/src/hooks/useWriteEvaluation.ts @@ -49,11 +49,16 @@ const useWriteEvaluation = ({ setModalIsOpen, row, type }: WriteEvaluationProps) if (lectureOptions.difficulty === undefined) return alert('학점(란)을 선택해주세요'); if (content.length < 30 || content.length > 1000) return alert('최소 30자 이상 최대 1000자 이내로 입력해주세요'); - type === 'update' - ? updateEvaluation(row.id.toString(), data) - : writeEvaluation(row.id.toString(), data); + + if (type === 'update') { + updateEvaluation(row.id.toString(), data); + } else { + writeEvaluation(row.id.toString(), data); + } + setModalIsOpen(false); }; + return { SliderOptions, lectureOptions, diff --git a/src/main.tsx b/src/main.tsx index c1f84fb..db9f93b 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,16 +1,17 @@ import './styles/globalStyle.css'; import axios from 'axios'; +import AsyncBoundary from 'components/AsyncBoundary'; import { CACHE_TIME } from 'constants/cacheTime'; +import { BadGateway } from 'pages'; import React from 'react'; import ReactDOM from 'react-dom/client'; import { initialize } from 'react-ga'; import { QueryClient, QueryClientProvider } from 'react-query'; import { ReactQueryDevtools } from 'react-query/devtools'; import { RecoilRoot } from 'recoil'; + import App from './App'; -import AsyncBoundary from 'components/AsyncBoundary'; -import { BadGateway } from 'pages'; initialize('G-KG7KQ8K3GP'); export const queryClient = new QueryClient({ diff --git a/src/pages/Exit.tsx b/src/pages/Exit.tsx index e378e99..05c0065 100644 --- a/src/pages/Exit.tsx +++ b/src/pages/Exit.tsx @@ -1,9 +1,10 @@ import { Auth } from 'api'; import { Button } from 'components'; import { CssTextField } from 'components/Etc/CssTextField'; -import { SubmitHandler, useForm } from 'react-hook-form'; +import type { SubmitHandler} from 'react-hook-form'; +import { useForm } from 'react-hook-form'; import { AuthWrapper, Container, Img, Sub, Title } from 'styles/common'; -import { UserLogin } from 'types/user'; +import type { UserLogin } from 'types/user'; const Exit = () => { const { quit } = Auth(); diff --git a/src/pages/IdSearch.tsx b/src/pages/IdSearch.tsx index 84fbd3f..650cdbf 100644 --- a/src/pages/IdSearch.tsx +++ b/src/pages/IdSearch.tsx @@ -2,7 +2,7 @@ import { Auth } from 'api'; import { Button } from 'components'; import { CssTextField } from 'components/Etc/CssTextField'; import { Loader } from 'components/Etc/Spinner'; -import { useForm, type SubmitHandler } from 'react-hook-form'; +import { type SubmitHandler,useForm } from 'react-hook-form'; import { AuthWrapper, Container, Img, Sub, Title } from 'styles/common'; import type { UserEmail } from 'types/user'; import { validateEmail } from 'utils/validate'; diff --git a/src/pages/LectureInfo.tsx b/src/pages/LectureInfo.tsx index 00790ee..4bd7488 100644 --- a/src/pages/LectureInfo.tsx +++ b/src/pages/LectureInfo.tsx @@ -66,8 +66,8 @@ const LectureInfo = () => { !isLogin ? alert('로그인해 주세요') : !written - ? setModalIsOpen(true) - : alert(`이미 작성한 ${check}가 있습니다`) + ? setModalIsOpen(true) + : alert(`이미 작성한 ${check}가 있습니다`) } /> diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 6547cbe..875056c 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -1,7 +1,8 @@ import styled from '@emotion/styled'; import { Auth } from 'api'; import { CssTextField } from 'components/Etc/CssTextField'; -import { FieldValues, SubmitHandler, useForm } from 'react-hook-form'; +import type { FieldValues, SubmitHandler} from 'react-hook-form'; +import { useForm } from 'react-hook-form'; import { useNavigate } from 'react-router-dom'; import { AuthWrapper, Container, Img } from 'styles/common'; diff --git a/src/pages/Main.tsx b/src/pages/Main.tsx index 2c2551d..8dd0c31 100644 --- a/src/pages/Main.tsx +++ b/src/pages/Main.tsx @@ -2,6 +2,7 @@ import styled from '@emotion/styled'; import { versionCheck } from 'app/versionCheck'; import { LectureSearch, MainBanner, MainList, MajorSelect, OptionSelect } from 'components'; import { useNavigate } from 'react-router-dom'; + import { sortOptions } from '../constants/placeholderData'; const Main = () => { diff --git a/src/pages/MyInfo.tsx b/src/pages/MyInfo.tsx index 3b920ac..2435f26 100644 --- a/src/pages/MyInfo.tsx +++ b/src/pages/MyInfo.tsx @@ -1,9 +1,9 @@ -import { useQuery } from 'react-query'; import { User } from 'api'; import { UserInfo } from 'components'; +import { CACHE_TIME } from 'constants/cacheTime'; import { fakeUserInfo } from 'constants/placeholderData'; +import { useQuery } from 'react-query'; import { isLoginStorage } from 'utils/loginStorage'; -import { CACHE_TIME } from 'constants/cacheTime'; const MyInfo = () => { const user = User(); diff --git a/src/pages/MyPosting.tsx b/src/pages/MyPosting.tsx index 42de355..f01cf2c 100644 --- a/src/pages/MyPosting.tsx +++ b/src/pages/MyPosting.tsx @@ -1,7 +1,7 @@ import styled from '@emotion/styled'; +import { Button, EvaluationList, TestInfoList } from 'components'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { Button, EvaluationList, TestInfoList } from 'components'; import { isLoginStorage } from 'utils/loginStorage'; const MyPosting = () => { diff --git a/src/pages/PwSearch.tsx b/src/pages/PwSearch.tsx index 7395b99..d68786f 100644 --- a/src/pages/PwSearch.tsx +++ b/src/pages/PwSearch.tsx @@ -2,7 +2,7 @@ import { Auth } from 'api'; import { Button } from 'components'; import { CssTextField } from 'components/Etc/CssTextField'; import { Loader } from 'components/Etc/Spinner'; -import { useForm, type SubmitHandler } from 'react-hook-form'; +import { type SubmitHandler,useForm } from 'react-hook-form'; import { AuthWrapper, Container, Img, Sub, Title } from 'styles/common'; import type { UserFindPw } from 'types/user'; import { validateEmail } from 'utils/validate'; diff --git a/src/pages/ResetPassword.tsx b/src/pages/ResetPassword.tsx index 1e07a84..8b1ff2c 100644 --- a/src/pages/ResetPassword.tsx +++ b/src/pages/ResetPassword.tsx @@ -1,7 +1,7 @@ import { Auth } from 'api'; import { Button } from 'components'; import { CssTextField } from 'components/Etc/CssTextField'; -import { useForm, type SubmitHandler } from 'react-hook-form'; +import { type SubmitHandler,useForm } from 'react-hook-form'; import { AuthWrapper, Checking, Container, Img, Sub, Title } from 'styles/common'; import type { ResetPassword as ResetPasswordType } from 'types/user'; import { validatePassword } from 'utils/validate'; diff --git a/src/pages/SignUp.tsx b/src/pages/SignUp.tsx index 0cc9cfb..ee600f0 100644 --- a/src/pages/SignUp.tsx +++ b/src/pages/SignUp.tsx @@ -2,7 +2,7 @@ import styled from '@emotion/styled'; import { Auth } from 'api'; import { CssTextField } from 'components/Etc/CssTextField'; import { useEffect, useState } from 'react'; -import { useForm, type SubmitHandler } from 'react-hook-form'; +import { type SubmitHandler, useForm } from 'react-hook-form'; import { AuthWrapper, Button, Checking, Container, Img } from 'styles/common'; import type { UserJoin } from 'types/user'; import { @@ -32,14 +32,17 @@ const SignUp = () => { // 체크박스 전체선택시 모두선택 체크박스 활성화시키기 const handleCheck = (e: React.ChangeEvent) => { const targetName = e.target.name as CheckList; - e.target.checked - ? setCheckList([...checkList, targetName]) - : setCheckList(checkList.filter((el) => el !== targetName)); + setCheckList((prevCheckList) => + e.target.checked + ? [...prevCheckList, targetName] + : prevCheckList.filter((item) => item !== targetName), + ); }; // 전체체크 선택시 전체 선택 or 전체해제 const checkAll = (e: React.ChangeEvent) => { - e.target.checked ? setCheckList(['terms', 'privacy']) : setCheckList([]); + const isChecked = e.target.checked; + setCheckList(isChecked ? ['terms', 'privacy'] : []); }; const handleIdCheck = () => checkId(setIdCheck, { loginId: formValues.loginId }); diff --git a/src/types/user.ts b/src/types/user.ts index a235020..88b001c 100644 --- a/src/types/user.ts +++ b/src/types/user.ts @@ -60,7 +60,7 @@ export interface EvaluatePostBase { content: string; } -export interface EvaluatePostUpdate extends EvaluatePostBase {} +export type EvaluatePostUpdate = EvaluatePostBase; export interface EvaluatePostCreate extends EvaluatePostBase { lectureName: string; diff --git a/src/utils/fakeData.ts b/src/utils/fakeData.ts index 8ac4dc3..104e279 100644 --- a/src/utils/fakeData.ts +++ b/src/utils/fakeData.ts @@ -5,6 +5,7 @@ const createFakeData = (count: number, generator: Generator): T[] => { for (let i = 0; i < data.length; i++) { data[i] = generator(i); } + return data; }; diff --git a/src/utils/loginStorage.ts b/src/utils/loginStorage.ts index 2330214..81e3a01 100644 --- a/src/utils/loginStorage.ts +++ b/src/utils/loginStorage.ts @@ -2,6 +2,7 @@ const storage = localStorage; export const isLoginStorage = () => { const state = localStorage.login; + return !!state; }; @@ -12,6 +13,7 @@ export const getStorage = (key: string, defaultValue = undefined) => { return storedValue || defaultValue; } catch (error) { console.error(error); + return defaultValue; } };