From 254f6bb89cc26c74db97524e10e81fb12362522d Mon Sep 17 00:00:00 2001 From: harry kim <73218463+hanyugeon@users.noreply.github.com> Date: Sun, 16 Jun 2024 20:12:31 +0900 Subject: [PATCH] =?UTF-8?q?[#627]=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C?= =?UTF-8?q?=20utils,=20hooks,=20constants=20=EC=A0=95=EB=A6=AC=20=EB=B0=8F?= =?UTF-8?q?=20import=EB=AC=B8=20=ED=86=B5=EC=9D=BC=20(#631)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 불필요한 constants, utils, hooks 제거 * chore: 컴포넌트 import문 절대경로 수정 * chore: 누락된 import문 수정 * fix: 잘못된 변경내용 삭제 --- src/apis/user.tsx | 2 +- src/app/bookshelf/[bookshelfId]/page.tsx | 2 +- src/app/login/page.tsx | 2 +- src/app/profile/me/page.tsx | 7 +- src/constants/FormRule/index.ts | 120 ------- src/constants/groupRadioValues.ts | 43 --- src/constants/index.ts | 1 + src/constants/initialBookGroupComments.ts | 38 --- src/hooks/auth/atoms/index.ts | 22 -- src/hooks/auth/index.ts | 1 - src/hooks/auth/useAuth.ts | 23 -- src/hooks/toast/atoms/index.ts | 12 - src/hooks/toast/index.ts | 1 - src/hooks/toast/useToast.ts | 29 -- src/hooks/useScroll.ts | 21 -- src/hooks/useToggle.ts | 10 - src/ui/AuthRequired/index.tsx | 23 -- src/ui/BookDetail/BookComment.tsx | 189 ---------- src/ui/BookDetail/BookCommentList.tsx | 171 ---------- src/ui/BookDetail/index.tsx | 1 - src/ui/FormInput/index.tsx | 128 ------- src/ui/FormSelect/index.tsx | 56 --- src/ui/Group/EditGroupForm.tsx | 83 ----- src/ui/Group/GroupComment/index.tsx | 141 -------- src/ui/Group/GroupDetail/GroupInfo.tsx | 322 ------------------ src/ui/Group/GroupDetail/index.tsx | 123 ------- src/ui/common/Toast/ToastItem.tsx | 46 --- src/ui/common/Toast/index.tsx | 22 -- src/utils/{storage.tsx => storage.ts} | 0 src/v1/base/BottomActionButton.tsx | 3 +- src/v1/base/Drawer.tsx | 4 +- src/v1/base/FloatingButton.tsx | 2 +- src/v1/base/LoginBottomActionButton.tsx | 5 +- src/v1/base/Menu.tsx | 2 +- src/v1/base/ShareButton.tsx | 3 +- src/v1/base/TextArea.tsx | 4 +- src/v1/base/Toast/ToastItem.tsx | 3 +- src/v1/base/Toast/ToastProvider.tsx | 6 +- src/v1/base/Toast/useToast.ts | 5 +- src/v1/book/BookCover.tsx | 3 +- src/v1/bookGroup/DetailBookGroupCard.tsx | 7 +- .../create/CreateBookGroupFunnel.tsx | 4 +- .../steps/EnterTitleStep/EnterTitleStep.tsx | 4 +- .../SelectJoinTypeStep/SelectJoinTypeStep.tsx | 7 +- .../fields/JoinTypeFieldset.tsx | 6 +- src/v1/bookGroup/detail/ShortMemberInfo.tsx | 7 +- src/v1/bookShelf/BookShelfCard.tsx | 5 +- src/v1/bookShelf/BookShelfRow.tsx | 5 +- src/v1/comment/BookCommentList.tsx | 7 +- src/v1/comment/BookGroupCommentList.tsx | 5 +- src/v1/comment/CommentList.tsx | 3 +- .../bookShelf/MyProfileBookshelfContainer.tsx | 3 +- src/v1/profile/bookShelf/ProfileBookShelf.tsx | 4 +- .../UserProfileBookshelfContainer.tsx | 3 +- src/v1/profile/group/ProfileGroup.tsx | 2 +- .../profile/group/ProfileGroupContainer.tsx | 2 +- .../profile/info/MyProfileInfoContainer.tsx | 10 +- src/v1/profile/info/ProfileInfo.tsx | 4 +- .../profile/info/UserProfileInfoContainer.tsx | 5 +- 59 files changed, 83 insertions(+), 1689 deletions(-) delete mode 100644 src/constants/FormRule/index.ts delete mode 100644 src/constants/initialBookGroupComments.ts delete mode 100644 src/hooks/auth/atoms/index.ts delete mode 100644 src/hooks/auth/index.ts delete mode 100644 src/hooks/auth/useAuth.ts delete mode 100644 src/hooks/toast/atoms/index.ts delete mode 100644 src/hooks/toast/index.ts delete mode 100644 src/hooks/toast/useToast.ts delete mode 100644 src/hooks/useScroll.ts delete mode 100644 src/hooks/useToggle.ts delete mode 100644 src/ui/AuthRequired/index.tsx delete mode 100644 src/ui/BookDetail/BookComment.tsx delete mode 100644 src/ui/BookDetail/BookCommentList.tsx delete mode 100644 src/ui/FormInput/index.tsx delete mode 100644 src/ui/FormSelect/index.tsx delete mode 100644 src/ui/Group/EditGroupForm.tsx delete mode 100644 src/ui/Group/GroupComment/index.tsx delete mode 100644 src/ui/Group/GroupDetail/GroupInfo.tsx delete mode 100644 src/ui/Group/GroupDetail/index.tsx delete mode 100644 src/ui/common/Toast/ToastItem.tsx delete mode 100644 src/ui/common/Toast/index.tsx rename src/utils/{storage.tsx => storage.ts} (100%) diff --git a/src/apis/user.tsx b/src/apis/user.tsx index c4910924e..bc9e03e1f 100644 --- a/src/apis/user.tsx +++ b/src/apis/user.tsx @@ -1,6 +1,6 @@ import { APIJob, APIJobGroup } from '@/types/job'; import { APIUser, APIUserProfile } from '@/types/user'; -import { publicApi } from './core/axios'; +import { publicApi } from '@/apis/core/axios'; const userAPI = { getUserProfile: ({ userId }: { userId: APIUser['userId'] }) => diff --git a/src/app/bookshelf/[bookshelfId]/page.tsx b/src/app/bookshelf/[bookshelfId]/page.tsx index d3e933949..cfea954bf 100644 --- a/src/app/bookshelf/[bookshelfId]/page.tsx +++ b/src/app/bookshelf/[bookshelfId]/page.tsx @@ -12,7 +12,7 @@ import useMutateBookshelfLikeQuery from '@/queries/bookshelf/useMutateBookshelfL import { useMyProfileId } from '@/queries/user/useMyProfileQuery'; import { checkAuthentication } from '@/utils/helpers'; import { IconKakao } from '@public/icons'; -import { KAKAO_LOGIN_URL } from '@/constants/url'; +import { KAKAO_LOGIN_URL } from '@/constants'; import useToast from '@/v1/base/Toast/useToast'; import TopNavigation from '@/v1/base/TopNavigation'; diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 76709dbd4..23566dbea 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -4,7 +4,7 @@ import Image from 'next/image'; import Link from 'next/link'; import { IconKakao } from '@public/icons'; -import { KAKAO_LOGIN_URL } from '@/constants/url'; +import { KAKAO_LOGIN_URL } from '@/constants'; import Button from '@/v1/base/Button'; diff --git a/src/app/profile/me/page.tsx b/src/app/profile/me/page.tsx index 4c5722fa5..ac94e0b60 100644 --- a/src/app/profile/me/page.tsx +++ b/src/app/profile/me/page.tsx @@ -2,11 +2,13 @@ import Link from 'next/link'; import { useRouter } from 'next/navigation'; +import { useQueryClient } from '@tanstack/react-query'; import userAPI from '@/apis/user'; +import userKeys from '@/queries/user/key'; import { checkAuthentication, removeAuth } from '@/utils/helpers'; - +import { KAKAO_LOGIN_URL } from '@/constants'; import { IconArrowRight } from '@public/icons'; import SSRSafeSuspense from '@/components/SSRSafeSuspense'; @@ -20,11 +22,8 @@ import BookShelf from '@/v1/bookShelf/BookShelf'; import ProfileBookShelf from '@/v1/profile/bookShelf/ProfileBookShelf'; import ProfileGroup from '@/v1/profile/group/ProfileGroup'; import ProfileInfo from '@/v1/profile/info/ProfileInfo'; -import userKeys from '@/queries/user/key'; -import { useQueryClient } from '@tanstack/react-query'; const USER_ID = 'me'; -const KAKAO_LOGIN_URL = `${process.env.NEXT_PUBLIC_API_URL}/oauth2/authorize/kakao?redirect_uri=${process.env.NEXT_PUBLIC_CLIENT_REDIRECT_URI}`; const MyProfilePage = () => { const isAuthenticated = checkAuthentication(); diff --git a/src/constants/FormRule/index.ts b/src/constants/FormRule/index.ts deleted file mode 100644 index 9b8a3b818..000000000 --- a/src/constants/FormRule/index.ts +++ /dev/null @@ -1,120 +0,0 @@ -import type { RegisterOptions } from 'react-hook-form'; - -const FORM_RULES: { - [index: string]: RegisterOptions; -} = { - nickname: { - required: '닉네임을 입력해주세요.', - minLength: { - value: 2, - message: '닉네임을 2자 이상 입력해주세요.', - }, - maxLength: { - value: 10, - message: '닉네임을 10자 이하로 입력해주세요.', - }, - pattern: { - value: /^[가-힣0-9a-zA-Z]{2,10}$/, - message: '한글, 영문, 숫자만 입력 가능해요.', - }, - }, - email: { - required: '이메일을 입력해주세요', - pattern: { - value: - /([\w-.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/, - message: '이메일 형식을 다시 확인해주세요.', - }, - }, - jobGroup: { - required: '직군을 선택해주세요.', - }, - job: { - required: '직업을 선택해주세요.', - }, - title: { - required: '모임 제목을 입력해 주세요.', - minLength: { - value: 2, - message: '모임 제목을 2자 이상 입력해 주세요.', - }, - maxLength: { - value: 30, - message: '모임 제목을 30자 이하로 입력해 주세요.', - }, - }, - introduce: { - required: '모임 설명을 입력해 주세요.', - minLength: { - value: 10, - message: '모임 설명을 10자 이상 입력해 주세요.', - }, - maxLength: { - value: 150, - message: '모임 설명을 150자 이하로 입력해 주세요.', - }, - }, - maxMemberCount: { - required: '모임 인원을 입력해 주세요.', - min: { - value: 1, - message: '모임 인원을 1명 이상 입력해 주세요.', - }, - max: { - value: 500, - message: '인원이 너무 많습니다.', - }, - pattern: { - value: /^[0-9]+$/, - message: '숫자를 입력해 주세요.', - }, - }, - startDate: { - required: '모임 시작일을 선택해 주세요.', - validate: value => - new Date(value).setHours(0, 0, 0, 0) >= new Date().setHours(0, 0, 0, 0) || - '시작일은 오늘부터 가능해요.', - }, - endDate: { - required: '모임 종료일을 선택해 주세요.', - validate: { - possible: (_, { startDate, endDate }) => - new Date(startDate) <= new Date(endDate) || - '종료일은 시작일보다 늦어야 해요.', - }, - }, - bookId: { - required: true, - validate: { - positive: value => Number(value) > 0, - }, - }, - joinQuestion: { - required: '문제 설명을 입력해 주세요.', - minLength: { - value: 5, - message: '문제 설명을 5자 이상 입력해 주세요.', - }, - maxLength: { - value: 30, - message: '문제 설명을 30자 이하로 입력해 주세요.', - }, - }, - joinPasswd: { - required: '정답을 입력해 주세요.', - minLength: { - value: 1, - message: '정답을 1자 이상 입력해 주세요.', - }, - maxLength: { - value: 30, - message: '정답을 10자 이하로 입력해 주세요.', - }, - pattern: { - value: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9]{1,10}$/, - message: '띄어쓰기 없이 정답을 입력해 주세요.', - }, - }, -} as const; - -export default FORM_RULES; diff --git a/src/constants/groupRadioValues.ts b/src/constants/groupRadioValues.ts index 264d931c3..6851c1b04 100644 --- a/src/constants/groupRadioValues.ts +++ b/src/constants/groupRadioValues.ts @@ -1,46 +1,3 @@ -export const MAX_MEMBER_COUNT_VALUE = [ - { - value: 'null', - text: '제한없음', - }, - { - value: '500', - text: '500명', - }, - { - value: '200', - text: '200명', - }, - { - value: '100', - text: '100명', - }, - { - value: '50', - text: '50명', - }, - { - value: '직접입력', - text: '직접입력', - }, -]; - -export const MAX_MEMBER_DEFAULT_VALUE = 'null'; - -export const IS_PUBLICK_VALUE = [ - { value: 'true', text: '공개' }, - { value: 'false', text: '비공개' }, -]; - -export const IS_PUBLICK_DEFAULT_VALUE = 'true'; - -export const HAS_JOIN_PASSWORD_VALUE = [ - { value: 'true', text: '필요' }, - { value: 'false', text: '불필요' }, -]; - -export const HAS_JOIN_PASSWORD_DEFAULT_VALUE = 'false'; - export const MAX_MEMBER_COUNT_OPTIONS = [ { label: '제한없음', value: 9999 }, { label: '50명', value: 50 }, diff --git a/src/constants/index.ts b/src/constants/index.ts index a42b42ad7..c8d049316 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -1,3 +1,4 @@ export * from './storage'; export * from './error'; export * from './groupRadioValues'; +export * from './url'; diff --git a/src/constants/initialBookGroupComments.ts b/src/constants/initialBookGroupComments.ts deleted file mode 100644 index 7a7ad88ff..000000000 --- a/src/constants/initialBookGroupComments.ts +++ /dev/null @@ -1,38 +0,0 @@ -export const initialBookGroupComments = [ - { - userId: 1, - commentId: 11414, - contents: - '다독 서비스 개발자 백민종님은 누구보다 열정적이고 훌륭한 개발자입니다. 리더십이 뛰어납니다. 그리고 내기를 좋아합니다. 도박을 좋아하는 것은 아니고 콜라, 커피내기를 주로 합니다. 승률은 낮습니다.', - userProfileImage: '', - nickname: '고양시MZ', - writtenByCurrentUser: false, - }, - { - userId: 2, - commentId: 53452, - contents: - '다독 서비스 개발자 우대현님은 착하고 성실하고 성숙하고 센스있고 어른스럽습니다. 죄송합니다. 제가 이 부분을 만들었기 때문에 제가 상상하는 미래의 제 모습을 적어 보았습니다.', - userProfileImage: '', - nickname: 'OLDBOY', - writtenByCurrentUser: false, - }, - { - userId: 3, - commentId: 36363, - contents: - '다독 서비스 개발자 김규란님은 근면성실은 아니지만 정말 열심히 공부하고 개발하는 개발자 입니다. 운동신경이 뛰어납니다. 저희 팀 내에서 운동 관련 승률이 가장 높습니다. 이기고 싶다면 규란님과 팀을 해야 합니다.', - userProfileImage: '', - nickname: 'fired계란', - writtenByCurrentUser: false, - }, - { - userId: 4, - commentId: 67951, - contents: - '다독 서비스 개발자 김재현님은 의외성 No.1 입니다. 맡은 일을 뚝딱뚝딱 잘해내 팀원들을 놀라게 하는것이 특기입니다. 또한 프로젝트 기간 동안 데브코스 강의장과 가장 가까이 지내면서 여유를 부리다 늦게와 구론산을 많이 샀습니다.(늦게 오는것은 아니고 항상 1-3분 정도? ㅎ)', - userProfileImage: '', - nickname: 'OneMetro', - writtenByCurrentUser: false, - }, -]; diff --git a/src/hooks/auth/atoms/index.ts b/src/hooks/auth/atoms/index.ts deleted file mode 100644 index db67d71fd..000000000 --- a/src/hooks/auth/atoms/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { atom, useRecoilState, useResetRecoilState } from 'recoil'; - -import { ACCESS_TOKEN_STORAGE_KEY } from '@/constants/index'; -import webStorage from '@/utils/storage'; - -const accessTokenAtom = atom({ - key: 'accessToken', - default: null, - effects: [ - ({ setSelf }) => { - const storage = webStorage(ACCESS_TOKEN_STORAGE_KEY); - const storedToken = storage.get(); - - storedToken && setSelf(storedToken); - }, - ], -}); - -const useAccessToken = () => useRecoilState(accessTokenAtom); -const useResetAccessToken = () => useResetRecoilState(accessTokenAtom); - -export { useAccessToken, useResetAccessToken }; diff --git a/src/hooks/auth/index.ts b/src/hooks/auth/index.ts deleted file mode 100644 index 7fa087d9f..000000000 --- a/src/hooks/auth/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as useAuth } from './useAuth'; diff --git a/src/hooks/auth/useAuth.ts b/src/hooks/auth/useAuth.ts deleted file mode 100644 index 6a7783a3b..000000000 --- a/src/hooks/auth/useAuth.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ACCESS_TOKEN_STORAGE_KEY } from '@/constants/index'; -import webStorage from '@/utils/storage'; - -const useAuth = () => { - const storage = webStorage(ACCESS_TOKEN_STORAGE_KEY); - const accessToken = storage.get(); - - const setAuth = (newToken: string) => { - storage.set(newToken); - }; - - const removeAuth = () => { - storage.remove(); - }; - - return { - isAuthed: !!accessToken, - setAuth, - removeAuth, - }; -}; - -export default useAuth; diff --git a/src/hooks/toast/atoms/index.ts b/src/hooks/toast/atoms/index.ts deleted file mode 100644 index 6d5cb7af7..000000000 --- a/src/hooks/toast/atoms/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { atom } from 'recoil'; - -export interface ToastAtom { - id: number; - message: string; - duration?: number; -} - -export const toastsAtom = atom({ - key: 'toasts', - default: [], -}); diff --git a/src/hooks/toast/index.ts b/src/hooks/toast/index.ts deleted file mode 100644 index 1077520cf..000000000 --- a/src/hooks/toast/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as useToast } from './useToast'; diff --git a/src/hooks/toast/useToast.ts b/src/hooks/toast/useToast.ts deleted file mode 100644 index 1d6759cc1..000000000 --- a/src/hooks/toast/useToast.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { useCallback } from 'react'; -import { useSetRecoilState } from 'recoil'; -import { ToastAtom, toastsAtom } from './atoms'; - -const useToast = () => { - const setToasts = useSetRecoilState(toastsAtom); - - const hideToast = useCallback( - (toastId: ToastAtom['id']) => { - setToasts(currentToasts => - currentToasts.filter(toast => toast.id !== toastId) - ); - }, - [setToasts] - ); - - const showToast = useCallback( - ({ message, duration = 2000 }: Pick) => { - const id = new Date().getTime(); - setToasts(currentToasts => [...currentToasts, { message, duration, id }]); - setTimeout(() => hideToast(id), 500 + duration); - }, - [hideToast, setToasts] - ); - - return { showToast }; -}; - -export default useToast; diff --git a/src/hooks/useScroll.ts b/src/hooks/useScroll.ts deleted file mode 100644 index a2aefbb73..000000000 --- a/src/hooks/useScroll.ts +++ /dev/null @@ -1,21 +0,0 @@ -import debounce from '@/utils/debounce'; -import { useState, useEffect } from 'react'; - -export function useScroll() { - const [scroll, setScroll] = useState(0); - - const listener = () => { - setScroll(window.pageYOffset); - }; - - const delay = 60; - - useEffect(() => { - window.addEventListener('scroll', debounce(listener, delay)); - return () => window.removeEventListener('scroll', listener); - }); - - return { - scroll, - }; -} diff --git a/src/hooks/useToggle.ts b/src/hooks/useToggle.ts deleted file mode 100644 index a51f7d437..000000000 --- a/src/hooks/useToggle.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { useState } from 'react'; - -const useToggle = () => { - const [value, setValue] = useState(false); - const toggle = () => setValue(value => !value); - - return { value, toggle, setValue }; -}; - -export default useToggle; diff --git a/src/ui/AuthRequired/index.tsx b/src/ui/AuthRequired/index.tsx deleted file mode 100644 index a58f4877b..000000000 --- a/src/ui/AuthRequired/index.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { ReactNode, useEffect, useState } from 'react'; - -import { useAuth } from '@/hooks/auth'; -import { useRouter } from 'next/navigation'; - -const AuthRequired = ({ children }: { children: ReactNode }) => { - const router = useRouter(); - const [mounted, setMounted] = useState(false); - const { isAuthed } = useAuth(); - - useEffect(() => { - if (!isAuthed) { - router.push('/'); - } - setMounted(true); - }, [isAuthed, router]); - - if (!isAuthed) return null; - - return <>{mounted && children}; -}; - -export default AuthRequired; diff --git a/src/ui/BookDetail/BookComment.tsx b/src/ui/BookDetail/BookComment.tsx deleted file mode 100644 index 476da6469..000000000 --- a/src/ui/BookDetail/BookComment.tsx +++ /dev/null @@ -1,189 +0,0 @@ -import { - AlertDialog, - AlertDialogBody, - AlertDialogContent, - AlertDialogFooter, - AlertDialogOverlay, - Avatar, - Button, - Flex, - Text, - useDisclosure, - useTheme, - VStack, -} from '@chakra-ui/react'; -import { CSSProperties, MutableRefObject, useRef } from 'react'; -import Link from 'next/link'; - -import { useToast } from '@/hooks/toast'; -import type { APIBookComment } from '@/types/book'; -import { Menu, MenuItem } from '@/ui/common/Menu'; - -import CommentDrawer from './CommentDrawer'; - -interface Props - extends Pick< - APIBookComment, - | 'commentId' - | 'userId' - | 'nickname' - | 'userProfileImage' - | 'createdAt' - | 'contents' - > { - style?: CSSProperties; - editable?: boolean; - onEdit?: (commentId: number, comment: string) => void; - onDelete?: (commentId: number) => void; -} - -const BookComment = ({ - commentId, - userId, - nickname, - userProfileImage, - createdAt, - contents, - editable = false, - onEdit, - onDelete, - style, -}: Props) => { - const { - isOpen: isDeleteModalOpen, - onClose: onDeleteModalClose, - onOpen: onDeleteModalOpen, - } = useDisclosure(); - const { - isOpen: isEditDrawerOpen, - onClose: onEditDrawerClose, - onOpen: onEditDrawerOpen, - } = useDisclosure(); - const { showToast } = useToast(); - - const cancelRef = useRef(null); - const textareaRef = useRef(null); - - const handleCommentEdit = () => { - const comment = textareaRef.current?.value; - - if (!comment) { - showToast({ message: '코멘트를 입력해주세요!' }); - return; - } - - onEdit && onEdit(commentId, comment); - onEditDrawerClose(); - }; - - const handleCommentDelete = () => { - onDelete && onDelete(commentId); - onDeleteModalClose(); - }; - - return ( - - - - - - {nickname} - - - {createdAt} - - - {editable && ( - - - - - - - - - )} - - - {contents} - - - ); -}; - -const DeleteComfirmDialog = ({ - cancelRef, - isOpen, - onClose, - onDelete, -}: { - isOpen: boolean; - onClose: () => void; - onDelete: () => void; - cancelRef: MutableRefObject; -}) => { - const theme = useTheme(); - - return ( - - - - - 코멘트를 정말 삭제할까요? - - - - - - - - - ); -}; - -export default BookComment; diff --git a/src/ui/BookDetail/BookCommentList.tsx b/src/ui/BookDetail/BookCommentList.tsx deleted file mode 100644 index 2a10671de..000000000 --- a/src/ui/BookDetail/BookCommentList.tsx +++ /dev/null @@ -1,171 +0,0 @@ -'use clinet'; - -import { useDisclosure, VStack } from '@chakra-ui/react'; -import { useMemo, useRef } from 'react'; - -import bookAPI from '@/apis/book'; -import useBookCommentsQuery from '@/queries/book/useBookCommentsQuery'; -import Button from '@/ui/common/Button'; -import BookComment from './BookComment'; -import CommentDrawer from './CommentDrawer'; - -import type { APIBookComment, APIBookmarkedUserList } from '@/types/book'; - -import { SERVICE_ERROR_MESSAGE } from '@/constants'; -import { useToast } from '@/hooks/toast'; -import LoginBottomSheet from '@/ui/LoginBottomSheet'; -import { - checkAuthentication, - isAxiosErrorWithCustomCode, -} from '@/utils/helpers'; - -interface Props { - bookId: number; - isInMyBookshelf: APIBookmarkedUserList['isInMyBookshelf']; -} - -type CommentType = 'me' | 'user'; -type CommentRecordType = Record; - -const BookCommentList = ({ bookId, isInMyBookshelf }: Props) => { - const isAuthenticated = checkAuthentication(); - const { showToast } = useToast(); - const commentTextAreaRef = useRef(null); - const bookCommentsQueryInfo = useBookCommentsQuery(bookId); - - const { - isOpen: isCreateDrawerOpen, - onOpen: onCreateDrawerOpen, - onClose: onCreateDrawerClose, - } = useDisclosure(); - const { - isOpen: isLoginBottomSheetOpen, - onOpen: onLoginBottomSheetOpen, - onClose: onLoginBottomSheetsClose, - } = useDisclosure(); - - const comments = useMemo(() => { - const defaultComments = { me: [], user: [] }; - - if (!bookCommentsQueryInfo.isSuccess) { - return defaultComments; - } - - return bookCommentsQueryInfo.data.bookComments - .filter(comment => comment.bookId == bookId) - .reduce( - (acc, comment) => ({ - ...acc, - [comment.writtenByCurrentUser ? 'me' : 'user']: [ - ...acc[comment.writtenByCurrentUser ? 'me' : 'user'], - comment, - ], - }), - defaultComments - ); - }, [bookCommentsQueryInfo, bookId]); - - const handleCommentError = (error: unknown) => { - if (!isAxiosErrorWithCustomCode(error)) { - return; - } - - const { code } = error.response.data; - const message = SERVICE_ERROR_MESSAGE[code]; - - if (code === 'BC1' || code === 'BC2') { - showToast({ message, duration: 3000 }); - } - }; - - const handleCommentCreate = () => { - const comment = commentTextAreaRef.current?.value; - - if (!comment) { - showToast({ message: '코멘트를 입력해주세요!' }); - return; - } - - bookAPI - .creaetComment(bookId, comment) - .then(() => bookCommentsQueryInfo.refetch()) - .catch(handleCommentError) - .finally(onCreateDrawerClose); - }; - - const handleCommentEdit = (commentId: number, comment: string) => { - bookAPI - .patchComment({ bookId, data: { commentId, comment } }) - .then(() => bookCommentsQueryInfo.refetch()) - .catch(handleCommentError); - }; - - const handleCommentDelete = (commentId: number) => { - bookAPI - .deletComment(bookId, commentId) - .then(() => bookCommentsQueryInfo.refetch()) - .catch(handleCommentError); - }; - - const handleCreateCommentDrawerOpen = () => { - if (!isAuthenticated) { - onLoginBottomSheetOpen(); - return; - } - - if (!isInMyBookshelf) { - showToast({ - message: '책장에 책을 꽂은 후에 코멘트를 남길 수 있어요.', - duration: 3000, - }); - return; - } - - onCreateDrawerOpen(); - }; - - return ( - - {!isAuthenticated && ( - - )} - {!bookCommentsQueryInfo.isLoading && !comments.me.length && ( - <> - - - - )} - {comments.me.map(comment => ( - - ))} - {comments.user.map(comment => ( - - ))} - - ); -}; - -export default BookCommentList; diff --git a/src/ui/BookDetail/index.tsx b/src/ui/BookDetail/index.tsx index 9ed5ae067..8f1eb6a80 100644 --- a/src/ui/BookDetail/index.tsx +++ b/src/ui/BookDetail/index.tsx @@ -1,2 +1 @@ export { default as BookInfo } from './BookInfo'; -export { default as BookCommentList } from './BookCommentList'; diff --git a/src/ui/FormInput/index.tsx b/src/ui/FormInput/index.tsx deleted file mode 100644 index b1057f71a..000000000 --- a/src/ui/FormInput/index.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import FORM_RULES from '@/constants/FormRule'; -import { - FormControl, - FormErrorMessage, - FormLabel, - Input, - InputGroup, - InputRightElement, - Text, - useTheme, -} from '@chakra-ui/react'; -import CloseIcon from '@public/icons/close.svg'; -import { useEffect, useState } from 'react'; -import { useFormContext } from 'react-hook-form'; -import type { MouseEvent, TouchEvent } from 'react'; - -interface FormInputProps - extends Partial> { - label: string; - name: string; -} - -const FormInput = ({ - label, - name, - disabled = false, - type = 'text', -}: FormInputProps) => { - const theme = useTheme(); - const { colors } = theme; - - const { - register, - unregister, - setValue, - trigger, - getValues, - formState: { errors }, - } = useFormContext(); - - const error = errors[name]; - - const rules = FORM_RULES[name]; - - const onClearButtonClick = async ( - event: MouseEvent | TouchEvent - ) => { - setValue(name, ''); - await trigger(name); - event.preventDefault(); - }; - - const [isFocus, setIsFocus] = useState(false); - - const onInputFocus = () => { - setIsFocus(true); - }; - - const onInputBlur = () => { - setIsFocus(false); - }; - - useEffect(() => { - return () => { - unregister(name); - }; - }, [unregister, name, disabled]); - - return ( - - - {label} - {!!rules.required && ( - - * - - )} - - - {disabled ? ( - - ) : ( - - )} - - {isFocus && getValues(name).length && ( - - - - )} - - {error?.message && ( - {String(error.message)} - )} - - ); -}; - -export default FormInput; diff --git a/src/ui/FormSelect/index.tsx b/src/ui/FormSelect/index.tsx deleted file mode 100644 index f2b234425..000000000 --- a/src/ui/FormSelect/index.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import FORM_RULES from '@/constants/FormRule'; -import { - FormControl, - FormErrorMessage, - FormLabel, - Select, - Text, - useTheme, -} from '@chakra-ui/react'; -import type { ReactNode } from 'react'; -import { useFormContext } from 'react-hook-form'; - -interface FormSelectProps { - label: string; - name: string; - children: ReactNode; -} - -const FormSelect = ({ label, name, children }: FormSelectProps) => { - const theme = useTheme(); - const { - register, - formState: { errors }, - } = useFormContext(); - - const error = errors[name]; - const rules = FORM_RULES[name]; - - return ( - - - {label} - {!!rules.required && ( - - * - - )} - - - {error?.message && ( - {String(error.message)} - )} - - ); -}; - -export default FormSelect; diff --git a/src/ui/Group/EditGroupForm.tsx b/src/ui/Group/EditGroupForm.tsx deleted file mode 100644 index 1c272e134..000000000 --- a/src/ui/Group/EditGroupForm.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { Box, Flex, Image, useTheme } from '@chakra-ui/react'; -import { FormProvider, useForm } from 'react-hook-form'; - -import FormInput from '@/ui/FormInput'; -import { APIGroupDetail } from '@/types/group'; -import GroupAPI from '@/apis/group'; -import { useRouter } from 'next/navigation'; - -interface EditGroupFormProps { - group: APIGroupDetail; -} - -const EditGroupForm = ({ group }: EditGroupFormProps) => { - const theme = useTheme(); - const router = useRouter(); - const methods = useForm({ - mode: 'all', - defaultValues: { - title: group.title, - introduce: group.introduce, - startDate: group.startDate, - maxMemberCount: group.maxMemberCount, - endDate: group.endDate, - }, - }); - - const onSubmit: Parameters[0] = async ({ - title, - introduce, - maxMemberCount, - endDate, - }) => { - try { - await GroupAPI.updateGroupInfo({ - bookGroupId: group.bookGroupId, - group: { title, introduce, endDate, maxMemberCount }, - }); - - router.push(`/group/${group.bookGroupId}`); - } catch (error) { - console.error(error); - } - }; - - return ( - <> - - - - book-cover - - - - - - - - - 모임 수정하기 - - - - - ); -}; - -export default EditGroupForm; diff --git a/src/ui/Group/GroupComment/index.tsx b/src/ui/Group/GroupComment/index.tsx deleted file mode 100644 index 78ddac9e8..000000000 --- a/src/ui/Group/GroupComment/index.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import { Avatar, Box, Flex, Highlight, Text } from '@chakra-ui/react'; -import Link from 'next/link'; - -import { initialBookGroupComments } from '@/constants/initialBookGroupComments'; -import { APIGroupComment } from '@/types/group'; -import { checkAuthentication } from '@/utils/helpers'; -import CommentDeleteModal from './CommentDeleteModal'; -import CommentModifyModal from './CommentModifyModal'; -import GuideMessage from './GuideMessage'; -import { Menu, MenuItem } from '@/ui/common/Menu'; - -interface commentsListProps { - isGroupMember: boolean; - isPublic: boolean; - isEmpty: boolean; - commentsListData: APIGroupComment[]; - handleDeleteCommentBtnClick: (commentId: number) => void; - handleModifyCommentBtnClick: ( - modifiedComment: string, - commentId: number - ) => void; -} - -const CommentsList = ({ - isGroupMember, - isPublic, - isEmpty, - commentsListData, - handleDeleteCommentBtnClick, - handleModifyCommentBtnClick, -}: commentsListProps) => { - const isAuthenticated = checkAuthentication(); - const getFilteredComments = () => { - const commentsLength = commentsListData.length; - - if (!isAuthenticated && !isPublic && commentsLength < 5) { - return initialBookGroupComments.slice(0, commentsLength); - } else if (!isAuthenticated && !isPublic) { - return initialBookGroupComments; - } - - if (isAuthenticated && !isPublic && !isGroupMember && commentsLength < 5) { - return initialBookGroupComments.slice(0, commentsLength); - } else if (isAuthenticated && !isPublic && !isGroupMember) { - return initialBookGroupComments; - } - return commentsListData; - }; - - const filteredComments = getFilteredComments(); - - return isEmpty ? ( - - - 첫 번째 글 작성의 주인공이 되어주세요. - - - ) : ( - - - 댓글 - - - {filteredComments && - filteredComments.map( - ({ - commentId, - userId, - contents, - userProfileImage, - nickname, - writtenByCurrentUser, - }) => { - return ( - - - - - - {nickname} - - - {writtenByCurrentUser && ( - - - - - - - - - )} - - - {contents} - - - ); - } - )} - - - - ); -}; - -export default CommentsList; diff --git a/src/ui/Group/GroupDetail/GroupInfo.tsx b/src/ui/Group/GroupDetail/GroupInfo.tsx deleted file mode 100644 index 6d0caa759..000000000 --- a/src/ui/Group/GroupDetail/GroupInfo.tsx +++ /dev/null @@ -1,322 +0,0 @@ -import { - AlertDialog, - AlertDialogBody, - AlertDialogContent, - AlertDialogFooter, - AlertDialogOverlay, - Box, - Button, - Flex, - Image, - Input, - Text, - useDisclosure, - useTheme, -} from '@chakra-ui/react'; -import { MutableRefObject, useRef, useState } from 'react'; -import Link from 'next/link'; - -import { APIGroupDetail } from '@/types/group'; -import BottomSheet from '@/ui/common/BottomSheet'; - -import { useToast } from '@/hooks/toast'; -import TopNavigation from '@/ui/common/TopNavigation'; -import { Menu, MenuItem } from '@/ui/common/Menu'; -import LoginBottomSheet from '@/ui/LoginBottomSheet'; -import { checkAuthentication } from '@/utils/helpers'; - -interface GroupInfoProps { - groupInfoData: APIGroupDetail; - handleParticipateBtnClick: ( - password?: string, - onSuccess?: () => void, - onFailed?: () => void - ) => void; - handleDeleteGroupBtnClick: () => void; -} - -const GroupInfo = ({ - groupInfoData, - handleParticipateBtnClick, - handleDeleteGroupBtnClick, -}: GroupInfoProps) => { - const isAuthenticated = checkAuthentication(); - const [password, setPassword] = useState(''); - const cancelRef = useRef(null); - const { - isOpen: isLoginModalOpen, - onOpen: onLoginModalOpen, - onClose: onLoginModalClose, - } = useDisclosure(); - const { - isOpen: isPasswordModalOpen, - onOpen: onPasswordModalOpen, - onClose: onPasswordModalClose, - } = useDisclosure(); - const { - isOpen: isDeleteModalOpen, - onClose: onDeleteModalClose, - onOpen: onDeleteModalOpen, - } = useDisclosure(); - - const { showToast } = useToast(); - - const { - bookGroupId, - title, - introduce, - startDate, - endDate, - hasJoinPasswd, - joinQuestion, - isPublic: _isPublic, - maxMemberCount: _maxMemberCount, - currentMemberCount, - commentCount, - owner: _owner, - book, - isOwner, - isGroupMember, - } = groupInfoData; - - const message = hasJoinPasswd ? '가입 비밀번호 입력 필요' : '바로 참여 가능'; - - const onDeleteGroupClick = () => { - if (currentMemberCount > 1) { - showToast({ - message: '혼자가 아니면 다른 모임원들이 있어 모임 삭제가 불가능해요!', - }); - onDeleteModalClose(); - return; - } - handleDeleteGroupBtnClick(); - onDeleteModalClose(); - }; - - const onChangePassword = (event: React.ChangeEvent) => { - setPassword(event.target.value); - }; - - const onPartInButtonClick = () => { - if (!isAuthenticated) { - onLoginModalOpen(); - return; - } - hasJoinPasswd ? onPasswordModalOpen() : handleParticipateBtnClick(); - }; - - return ( - <> - - - {isOwner && ( - - - - - - - )} - - - - - {title} - - - {introduce} - - - - - - - - {startDate} ~ {endDate} - - - - {book.title} - - - - - - {isGroupMember ? '' : message} - - - - - peopleIcon - - - {currentMemberCount} - - - - - commentIcon - - - {commentCount} - - - - - - - - - bookCover - - - - - {!isOwner && ( - <> - - - - - - - 질문 - - - {joinQuestion} - - - - - 정답 - - - - - - - - )} - - - - ); -}; - -export default GroupInfo; - -const DeleteComfirmDialog = ({ - cancelRef, - isOpen, - onClose, - onDelete, -}: { - isOpen: boolean; - onClose: () => void; - onDelete: () => void; - cancelRef: MutableRefObject; -}) => { - const theme = useTheme(); - - return ( - - - - - 모임을 정말 삭제할까요? - - - - - - - - - ); -}; diff --git a/src/ui/Group/GroupDetail/index.tsx b/src/ui/Group/GroupDetail/index.tsx deleted file mode 100644 index b9f8756e1..000000000 --- a/src/ui/Group/GroupDetail/index.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { Flex, VStack, Skeleton } from '@chakra-ui/react'; -import { useRouter } from 'next/navigation'; - -import GroupInfo from '@/ui/Group/GroupDetail/GroupInfo'; -import CommentInputBox from '../GroupComment/CommentInputBox'; -import CommentsList from '../GroupComment'; -import useGroupInfoQuery from '@/queries/group/useGroupInfoQuery'; -import useGroupCommentsQuery from '@/queries/group/useBookGroupCommentsQuery'; -import GroupAPI from '@/apis/group'; -import { useToast } from '@/hooks/toast'; - -interface GroupDetailProps { - bookGroupId: number; -} - -const GroupDetail = ({ bookGroupId }: GroupDetailProps) => { - const groupInfoQuery = useGroupInfoQuery({ bookGroupId }); - const groupCommentsQuery = useGroupCommentsQuery(bookGroupId); - const { showToast } = useToast(); - const router = useRouter(); - - if (groupInfoQuery.isLoading || groupCommentsQuery.isLoading) - return ( - - - - - - - ); - - const isSuccess = groupInfoQuery.isSuccess && groupCommentsQuery.isSuccess; - if (!isSuccess) return null; - - const handleParticipateBtnClick = async ( - password?: string, - onSuccess?: () => void - ) => { - try { - await GroupAPI.joinGroup({ bookGroupId, password }); - onSuccess && onSuccess(); - showToast({ message: '모임에 가입되었어요' }); - } catch (error) { - error && - showToast({ message: '정답이 아니에요 다시 한 번 도전해 주세요' }); - } - groupInfoQuery.refetch(); - }; - - const handleCreateCommentBtnClick = async (comment: string) => { - if (comment.trim() === '') return; - try { - await GroupAPI.createGroupComment({ bookGroupId, comment }); - } catch (error) { - console.error(error); - } - groupInfoQuery.refetch(); - groupCommentsQuery.refetch(); - }; - - const handleModifyCommentBtnClick = async ( - modifiedComment: string, - commentId: number - ) => { - try { - await GroupAPI.updateGroupComment({ - bookGroupId, - commentId, - comment: modifiedComment, - }); - } catch (error) { - console.error(error); - } - groupCommentsQuery.refetch(); - }; - - const handleDeleteCommentBtnClick = async (commentId: number) => { - try { - await GroupAPI.deleteGroupComment({ bookGroupId, commentId }); - } catch (error) { - console.error(error); - } - groupInfoQuery.refetch(); - groupCommentsQuery.refetch(); - }; - - const handleDeleteGroupBtnClick = async () => { - try { - await GroupAPI.deleteGroup({ bookGroupId }); - } catch (error) { - console.error(error); - } - - router.push('/group'); - }; - - const { isGroupMember, isPublic } = groupInfoQuery.data; - const { bookGroupComments, isEmpty } = groupCommentsQuery.data; - - return ( - - - - - - ); -}; - -export default GroupDetail; diff --git a/src/ui/common/Toast/ToastItem.tsx b/src/ui/common/Toast/ToastItem.tsx deleted file mode 100644 index 3ae621890..000000000 --- a/src/ui/common/Toast/ToastItem.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { ToastAtom } from '@/hooks/toast/atoms'; -import { Box } from '@chakra-ui/react'; -import { PropsWithChildren, useEffect, useState } from 'react'; - -const ToastItem = ({ - duration, - children, -}: PropsWithChildren>) => { - const [visible, setVisible] = useState(false); - - useEffect(() => { - setTimeout(() => { - setVisible(true); - }, 100); - - const handleSetTimeout = setTimeout(() => { - setVisible(false); - clearTimeout(handleSetTimeout); - }, duration); - }, [duration]); - - return ( - - - {children} - - - ); -}; - -export default ToastItem; diff --git a/src/ui/common/Toast/index.tsx b/src/ui/common/Toast/index.tsx deleted file mode 100644 index 990d2c60e..000000000 --- a/src/ui/common/Toast/index.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { toastsAtom } from '@/hooks/toast/atoms'; -import { Box, Center } from '@chakra-ui/react'; -import { useRecoilValue } from 'recoil'; -import ToastItem from './ToastItem'; - -const Toast = () => { - const toasts = useRecoilValue(toastsAtom); - - return ( - -
- {toasts.map(({ id, duration, message }) => ( - - {message} - - ))} -
-
- ); -}; - -export default Toast; diff --git a/src/utils/storage.tsx b/src/utils/storage.ts similarity index 100% rename from src/utils/storage.tsx rename to src/utils/storage.ts diff --git a/src/v1/base/BottomActionButton.tsx b/src/v1/base/BottomActionButton.tsx index dc030871f..89ada09a9 100644 --- a/src/v1/base/BottomActionButton.tsx +++ b/src/v1/base/BottomActionButton.tsx @@ -1,5 +1,6 @@ import { ComponentPropsWithoutRef } from 'react'; -import Button from './Button'; + +import Button from '@/v1/base/Button'; type BottomActionButtonProps = Omit< ComponentPropsWithoutRef, diff --git a/src/v1/base/Drawer.tsx b/src/v1/base/Drawer.tsx index 2ba799dcb..6953142d6 100644 --- a/src/v1/base/Drawer.tsx +++ b/src/v1/base/Drawer.tsx @@ -7,10 +7,10 @@ import { } from 'react'; import { Dialog, Transition } from '@headlessui/react'; -import { IconClose } from '@public/icons'; import useRemoveVerticalScroll from '@/hooks/useRemoveVerticalScroll'; -import Button from './Button'; +import { IconClose } from '@public/icons'; +import Button from '@/v1/base/Button'; interface DrawerProps { isOpen: boolean; diff --git a/src/v1/base/FloatingButton.tsx b/src/v1/base/FloatingButton.tsx index 541b370d2..d753f7b5d 100644 --- a/src/v1/base/FloatingButton.tsx +++ b/src/v1/base/FloatingButton.tsx @@ -2,7 +2,7 @@ import { ComponentPropsWithoutRef } from 'react'; import { IconPlus } from '@public/icons'; -import Portal from './Portal'; +import Portal from '@/v1/base/Portal'; interface FloatingButtonProps extends ComponentPropsWithoutRef<'button'> { position?: string; diff --git a/src/v1/base/LoginBottomActionButton.tsx b/src/v1/base/LoginBottomActionButton.tsx index 16f1a6ee3..2bb560c7a 100644 --- a/src/v1/base/LoginBottomActionButton.tsx +++ b/src/v1/base/LoginBottomActionButton.tsx @@ -1,7 +1,8 @@ import Link from 'next/link'; -import { KAKAO_LOGIN_URL } from '@/constants/url'; -import BottomActionButton from './BottomActionButton'; +import { KAKAO_LOGIN_URL } from '@/constants'; + +import BottomActionButton from '@/v1/base/BottomActionButton'; const LoginBottomActionButton = () => ( diff --git a/src/v1/base/Menu.tsx b/src/v1/base/Menu.tsx index 3518fb607..98c170990 100644 --- a/src/v1/base/Menu.tsx +++ b/src/v1/base/Menu.tsx @@ -12,7 +12,7 @@ import { import { IconHamburger } from '@public/icons'; import useOutsideClickRef from '@/hooks/useOutsideClickRef'; -import BottomSheet from './BottomSheet'; +import BottomSheet from '@/v1/base/BottomSheet'; type MenuContextValue = { isOpen: boolean; diff --git a/src/v1/base/ShareButton.tsx b/src/v1/base/ShareButton.tsx index b1a05bfa9..b06cd8759 100644 --- a/src/v1/base/ShareButton.tsx +++ b/src/v1/base/ShareButton.tsx @@ -1,5 +1,6 @@ +import useToast from '@/v1/base/Toast/useToast'; + import { IconShare } from '@public/icons'; -import useToast from './Toast/useToast'; const ShareButton = () => { const { show: showToast } = useToast(); diff --git a/src/v1/base/TextArea.tsx b/src/v1/base/TextArea.tsx index 78a9760d3..617b10e05 100644 --- a/src/v1/base/TextArea.tsx +++ b/src/v1/base/TextArea.tsx @@ -12,8 +12,8 @@ import { Children, } from 'react'; -import ErrorMessage from './ErrorMessage'; -import InputLength from './InputLength'; +import ErrorMessage from '@/v1/base/ErrorMessage'; +import InputLength from '@/v1/base/InputLength'; interface BaseTextAreaProps extends TextareaHTMLAttributes { diff --git a/src/v1/base/Toast/ToastItem.tsx b/src/v1/base/Toast/ToastItem.tsx index 23f40d70c..439569e0f 100644 --- a/src/v1/base/Toast/ToastItem.tsx +++ b/src/v1/base/Toast/ToastItem.tsx @@ -1,5 +1,6 @@ +import type { ToastOption } from '@/v1/base/Toast/types'; + import { IconSuccess, IconWarning, IconError } from '@public/icons'; -import { ToastOption } from './types'; const ICONS = { success: , diff --git a/src/v1/base/Toast/ToastProvider.tsx b/src/v1/base/Toast/ToastProvider.tsx index 2360d6e08..887385c48 100644 --- a/src/v1/base/Toast/ToastProvider.tsx +++ b/src/v1/base/Toast/ToastProvider.tsx @@ -1,9 +1,9 @@ import { createContext, ReactNode, useMemo, useState } from 'react'; -import Portal from '@/v1/base/Portal'; +import type { ToastController, ToastOption } from '@/v1/base/Toast/types'; -import ToastItem from './ToastItem'; -import type { ToastController, ToastOption } from './types'; +import ToastItem from '@/v1/base/Toast/ToastItem'; +import Portal from '@/v1/base/Portal'; export const ToastContext = createContext({} as ToastController); diff --git a/src/v1/base/Toast/useToast.ts b/src/v1/base/Toast/useToast.ts index 375e4575b..75589c77e 100644 --- a/src/v1/base/Toast/useToast.ts +++ b/src/v1/base/Toast/useToast.ts @@ -1,7 +1,8 @@ import { useContext } from 'react'; -import { ToastContext } from './ToastProvider'; -import type { ToastOption } from './types'; +import type { ToastOption } from '@/v1/base/Toast/types'; + +import { ToastContext } from '@/v1/base/Toast/ToastProvider'; const useToast = () => { const toastController = useContext(ToastContext); diff --git a/src/v1/book/BookCover.tsx b/src/v1/book/BookCover.tsx index b99f295eb..e19004b25 100644 --- a/src/v1/book/BookCover.tsx +++ b/src/v1/book/BookCover.tsx @@ -2,8 +2,7 @@ import { ComponentPropsWithoutRef, useState } from 'react'; import Image from 'next/image'; - -import { DATA_URL } from '@/constants/url'; +import { DATA_URL } from '@/constants'; type BookCoverSize = | 'xsmall' diff --git a/src/v1/bookGroup/DetailBookGroupCard.tsx b/src/v1/bookGroup/DetailBookGroupCard.tsx index 9951ec816..799c7a912 100644 --- a/src/v1/bookGroup/DetailBookGroupCard.tsx +++ b/src/v1/bookGroup/DetailBookGroupCard.tsx @@ -1,9 +1,10 @@ +import Link from 'next/link'; + +import { IconCalendar, IconMembers, IconComments } from '@public/icons'; +import BookGroupStatus from '@/v1/bookGroup/BookGroupStatus'; import Badge from '@/v1/base/Badge'; import Avatar from '@/v1/base/Avatar'; -import { IconCalendar, IconMembers, IconComments } from '@public/icons'; import BookCover from '@/v1/book/BookCover'; -import Link from 'next/link'; -import BookGroupStatus from './BookGroupStatus'; interface DetailBookGroupCardProps { title: string; diff --git a/src/v1/bookGroup/create/CreateBookGroupFunnel.tsx b/src/v1/bookGroup/create/CreateBookGroupFunnel.tsx index 2df059d21..3080b394e 100644 --- a/src/v1/bookGroup/create/CreateBookGroupFunnel.tsx +++ b/src/v1/bookGroup/create/CreateBookGroupFunnel.tsx @@ -3,7 +3,7 @@ import { useRouter } from 'next/navigation'; import { FormProvider, SubmitHandler, useForm } from 'react-hook-form'; -import type { CreateBookGroupFormValues } from './types'; +import type { CreateBookGroupFormValues } from '@/v1/bookGroup/create/types'; import useCreateBookGroupMutation from '@/queries/group/useCreateBookGroupMutation'; import { useFunnel } from '@/hooks/useFunnel'; @@ -20,7 +20,7 @@ import { SelectBookStep, SelectJoinTypeStep, SetUpDetailStep, -} from './steps'; +} from '@/v1/bookGroup/create/steps'; const FUNNEL_STEPS = [ 'SelectBook', diff --git a/src/v1/bookGroup/create/steps/EnterTitleStep/EnterTitleStep.tsx b/src/v1/bookGroup/create/steps/EnterTitleStep/EnterTitleStep.tsx index 1cdb5841b..25a11026e 100644 --- a/src/v1/bookGroup/create/steps/EnterTitleStep/EnterTitleStep.tsx +++ b/src/v1/bookGroup/create/steps/EnterTitleStep/EnterTitleStep.tsx @@ -1,12 +1,12 @@ import { useFormContext } from 'react-hook-form'; import type { MoveFunnelStepProps } from '@/v1/base/Funnel'; -import type { EnterTitleStepFormValues } from '../../types'; +import type { EnterTitleStepFormValues } from '@/v1/bookGroup/create/types'; import useRemoveVerticalScroll from '@/hooks/useRemoveVerticalScroll'; +import { TitleField } from '@/v1/bookGroup/create/steps/EnterTitleStep/fields'; import BottomActionButton from '@/v1/base/BottomActionButton'; -import { TitleField } from './fields'; const EnterTitleStep = ({ onNextStep }: MoveFunnelStepProps) => { const { diff --git a/src/v1/bookGroup/create/steps/SelectJoinTypeStep/SelectJoinTypeStep.tsx b/src/v1/bookGroup/create/steps/SelectJoinTypeStep/SelectJoinTypeStep.tsx index 181d367d8..b98c8926b 100644 --- a/src/v1/bookGroup/create/steps/SelectJoinTypeStep/SelectJoinTypeStep.tsx +++ b/src/v1/bookGroup/create/steps/SelectJoinTypeStep/SelectJoinTypeStep.tsx @@ -1,10 +1,13 @@ import { useFormContext } from 'react-hook-form'; import type { MoveFunnelStepProps } from '@/v1/base/Funnel'; -import type { SelectJoinTypeStepFormValues } from '../../types'; +import type { SelectJoinTypeStepFormValues } from '@/v1/bookGroup/create/types'; +import { + JoinPasswordFieldset, + JoinTypeFieldset, +} from '@/v1/bookGroup/create/steps/SelectJoinTypeStep/fields'; import BottomActionButton from '@/v1/base/BottomActionButton'; -import { JoinPasswordFieldset, JoinTypeFieldset } from './fields'; export type JoinTypeStepFieldName = keyof SelectJoinTypeStepFormValues; export type JoinTypeStepFieldProp = { name: JoinTypeStepFieldName }; diff --git a/src/v1/bookGroup/create/steps/SelectJoinTypeStep/fields/JoinTypeFieldset.tsx b/src/v1/bookGroup/create/steps/SelectJoinTypeStep/fields/JoinTypeFieldset.tsx index 2270e6927..10691ff5e 100644 --- a/src/v1/bookGroup/create/steps/SelectJoinTypeStep/fields/JoinTypeFieldset.tsx +++ b/src/v1/bookGroup/create/steps/SelectJoinTypeStep/fields/JoinTypeFieldset.tsx @@ -1,9 +1,9 @@ import { useFormContext } from 'react-hook-form'; -import type { SelectJoinTypeStepFormValues } from '../../../types'; -import type { JoinTypeStepFieldProp } from '../SelectJoinTypeStep'; +import type { SelectJoinTypeStepFormValues } from '@/v1/bookGroup/create/types'; +import type { JoinTypeStepFieldProp } from '@/v1/bookGroup/create/steps/SelectJoinTypeStep/SelectJoinTypeStep'; -import JoinTypeRadioCard from './JoinTypeRadioCard'; +import JoinTypeRadioCard from '@/v1/bookGroup/create/steps/SelectJoinTypeStep/fields/JoinTypeRadioCard'; const JoinTypeFieldset = ({ children }: { children?: React.ReactNode }) => { return
{children}
; diff --git a/src/v1/bookGroup/detail/ShortMemberInfo.tsx b/src/v1/bookGroup/detail/ShortMemberInfo.tsx index 177611f0c..a7c4e9c70 100644 --- a/src/v1/bookGroup/detail/ShortMemberInfo.tsx +++ b/src/v1/bookGroup/detail/ShortMemberInfo.tsx @@ -1,9 +1,10 @@ -import { IconArrowLeft } from '@public/icons'; -import Button from '@/v1/base/Button'; -import MemberItem from './MemberItem'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; +import { IconArrowLeft } from '@public/icons'; +import MemberItem from '@/v1/bookGroup/detail/MemberItem'; +import Button from '@/v1/base/Button'; + type Member = { id: number; profileImageSrc: string; diff --git a/src/v1/bookShelf/BookShelfCard.tsx b/src/v1/bookShelf/BookShelfCard.tsx index 88f58efa1..04683ea7d 100644 --- a/src/v1/bookShelf/BookShelfCard.tsx +++ b/src/v1/bookShelf/BookShelfCard.tsx @@ -1,5 +1,6 @@ -import { APIBookshelf } from '@/types/bookshelf'; -import BookShelf from './BookShelf'; +import type { APIBookshelf } from '@/types/bookshelf'; + +import BookShelf from '@/v1/bookShelf/BookShelf'; const BookShelfCard = ({ bookshelfName, diff --git a/src/v1/bookShelf/BookShelfRow.tsx b/src/v1/bookShelf/BookShelfRow.tsx index ad409907b..7a5903ae6 100644 --- a/src/v1/bookShelf/BookShelfRow.tsx +++ b/src/v1/bookShelf/BookShelfRow.tsx @@ -1,5 +1,6 @@ -import { APIBookshelf } from '@/types/bookshelf'; -import BookShelf from './BookShelf'; +import type { APIBookshelf } from '@/types/bookshelf'; + +import BookShelf from '@/v1/bookShelf/BookShelf'; const BookShelfRow = ({ books }: Pick) => { return ( diff --git a/src/v1/comment/BookCommentList.tsx b/src/v1/comment/BookCommentList.tsx index 212725142..25f5f4ebb 100644 --- a/src/v1/comment/BookCommentList.tsx +++ b/src/v1/comment/BookCommentList.tsx @@ -1,12 +1,13 @@ -import { APIBookComment } from '@/types/book'; -import useToast from '@/v1/base/Toast/useToast'; +import type { APIBookComment } from '@/types/book'; import { useMyProfileId } from '@/queries/user/useMyProfileQuery'; import { useBookComments } from '@/queries/book/useBookCommentsQuery'; import usePatchBookCommentMutation from '@/queries/book/usePatchBookCommentMutation'; import useDeleteBookCommentMutation from '@/queries/book/useDeleteBookCommentMutation'; + +import useToast from '@/v1/base/Toast/useToast'; import { checkAuthentication } from '@/utils/helpers'; -import CommentList from './CommentList'; +import CommentList from '@/v1/comment/CommentList'; const BookCommentList = ({ bookId }: { bookId: number }) => { const isAuthenticated = checkAuthentication(); diff --git a/src/v1/comment/BookGroupCommentList.tsx b/src/v1/comment/BookGroupCommentList.tsx index 6da08a5c6..6f8b011f1 100644 --- a/src/v1/comment/BookGroupCommentList.tsx +++ b/src/v1/comment/BookGroupCommentList.tsx @@ -1,13 +1,14 @@ import { APIGroupComment } from '@/types/group'; -import useToast from '@/v1/base/Toast/useToast'; import { useBookGroupComments } from '@/queries/group/useBookGroupCommentsQuery'; import { useMyProfileId } from '@/queries/user/useMyProfileQuery'; import { useBookGroup } from '@/queries/group/useBookGroupQuery'; import usePatchBookGroupCommentMutation from '@/queries/group/usePatchBookGroupCommentMutation'; import useDeleteBookGroupCommentMutation from '@/queries/group/useDeleteBookGroupCommentMutation'; + +import useToast from '@/v1/base/Toast/useToast'; import { checkAuthentication } from '@/utils/helpers'; -import CommentList from './CommentList'; +import CommentList from '@/v1/comment/CommentList'; const BookGroupCommentList = ({ groupId }: { groupId: number }) => { const isAuthenticated = checkAuthentication(); diff --git a/src/v1/comment/CommentList.tsx b/src/v1/comment/CommentList.tsx index 714ad86da..f1f09b878 100644 --- a/src/v1/comment/CommentList.tsx +++ b/src/v1/comment/CommentList.tsx @@ -1,13 +1,14 @@ import { useMemo, useRef } from 'react'; import type { Writer } from '@/types/user'; + import useDisclosure from '@/hooks/useDisclosure'; +import EditCommentDrawer from '@/v1/comment/CommentDrawer'; import Avatar from '@/v1/base/Avatar'; import Menu from '@/v1/base/Menu'; import Button from '@/v1/base/Button'; import Modal from '@/v1/base/Modal'; -import EditCommentDrawer from './CommentDrawer'; type Comment = { id: number; diff --git a/src/v1/profile/bookShelf/MyProfileBookshelfContainer.tsx b/src/v1/profile/bookShelf/MyProfileBookshelfContainer.tsx index 5a18c31bd..dc520279b 100644 --- a/src/v1/profile/bookShelf/MyProfileBookshelfContainer.tsx +++ b/src/v1/profile/bookShelf/MyProfileBookshelfContainer.tsx @@ -1,6 +1,7 @@ -import ProfileBookshelfPresenter from './ProfileBookshelfPresenter'; import useMySummaryBookshelfQuery from '@/queries/bookshelf/useMySummaryBookShelfQuery'; +import ProfileBookshelfPresenter from '@/v1/profile/bookShelf/ProfileBookshelfPresenter'; + const MyProfileBookshelfContainer = () => { const { data } = useMySummaryBookshelfQuery(); diff --git a/src/v1/profile/bookShelf/ProfileBookShelf.tsx b/src/v1/profile/bookShelf/ProfileBookShelf.tsx index c8ea9a60e..677f416aa 100644 --- a/src/v1/profile/bookShelf/ProfileBookShelf.tsx +++ b/src/v1/profile/bookShelf/ProfileBookShelf.tsx @@ -1,7 +1,7 @@ import type { APIUser } from '@/types/user'; -import MyProfileBookshelfContainer from './MyProfileBookshelfContainer'; -import UserProfileBookshelfContainer from './UserProfileBookshelfContainer'; +import MyProfileBookshelfContainer from '@/v1/profile/bookShelf/MyProfileBookshelfContainer'; +import UserProfileBookshelfContainer from '@/v1/profile/bookShelf/UserProfileBookshelfContainer'; const ProfileBookShelf = ({ userId }: { userId: 'me' | APIUser['userId'] }) => { return userId === 'me' ? ( diff --git a/src/v1/profile/bookShelf/UserProfileBookshelfContainer.tsx b/src/v1/profile/bookShelf/UserProfileBookshelfContainer.tsx index 1a2ef0a96..cc074e461 100644 --- a/src/v1/profile/bookShelf/UserProfileBookshelfContainer.tsx +++ b/src/v1/profile/bookShelf/UserProfileBookshelfContainer.tsx @@ -1,7 +1,8 @@ -import ProfileBookshelfPresenter from './ProfileBookshelfPresenter'; import useUserSummaryBookshelfQuery from '@/queries/bookshelf/useUserSummaryBookShelfQuery'; import type { APIUser } from '@/types/user'; +import ProfileBookshelfPresenter from '@/v1/profile/bookShelf/ProfileBookshelfPresenter'; + const UserProfileBookshelfContainer = ({ userId, }: { diff --git a/src/v1/profile/group/ProfileGroup.tsx b/src/v1/profile/group/ProfileGroup.tsx index 93efe9287..2db54d864 100644 --- a/src/v1/profile/group/ProfileGroup.tsx +++ b/src/v1/profile/group/ProfileGroup.tsx @@ -2,8 +2,8 @@ import SSRSafeSuspense from '@/components/SSRSafeSuspense'; import { APIUser } from '@/types/user'; +import ProfileGroupContainer from '@/v1/profile/group/ProfileGroupContainer'; import Skeleton from '@/v1/base/Skeleton'; -import ProfileGroupContainer from './ProfileGroupContainer'; const ProfileGroup = ({ userId }: { userId: 'me' | APIUser['userId'] }) => { return ( diff --git a/src/v1/profile/group/ProfileGroupContainer.tsx b/src/v1/profile/group/ProfileGroupContainer.tsx index cb033e864..0ddcd883c 100644 --- a/src/v1/profile/group/ProfileGroupContainer.tsx +++ b/src/v1/profile/group/ProfileGroupContainer.tsx @@ -4,7 +4,7 @@ import type { APIUser } from '@/types/user'; import { checkAuthentication } from '@/utils/helpers'; -import ProfileGroupPresenter from './ProfileGroupPresenter'; +import ProfileGroupPresenter from '@/v1/profile/group/ProfileGroupPresenter'; const ProfileGroupContainer = ({ userId, diff --git a/src/v1/profile/info/MyProfileInfoContainer.tsx b/src/v1/profile/info/MyProfileInfoContainer.tsx index cfef3cdf5..f266cc419 100644 --- a/src/v1/profile/info/MyProfileInfoContainer.tsx +++ b/src/v1/profile/info/MyProfileInfoContainer.tsx @@ -1,7 +1,9 @@ -import useMyProfileQuery from '@/queries/user/useMyProfileQuery'; -import { usePathname, useRouter } from 'next/navigation'; import { useEffect } from 'react'; -import ProfileInfoPresenter from './ProfileInfoPresenter'; +import { usePathname, useRouter } from 'next/navigation'; + +import useMyProfileQuery from '@/queries/user/useMyProfileQuery'; + +import ProfileInfoPresenter from '@/v1/profile/info/ProfileInfoPresenter'; const MyProfileContainer = () => { const { data } = useMyProfileQuery(); @@ -17,7 +19,7 @@ const MyProfileContainer = () => { if (!isSavedAdditionalInfo) replace(`${pathname}/add`); }, [data, pathname, replace]); - return ; + return ; }; export default MyProfileContainer; diff --git a/src/v1/profile/info/ProfileInfo.tsx b/src/v1/profile/info/ProfileInfo.tsx index c3107c75a..c664f6957 100644 --- a/src/v1/profile/info/ProfileInfo.tsx +++ b/src/v1/profile/info/ProfileInfo.tsx @@ -2,9 +2,9 @@ import type { APIUser } from '@/types/user'; import SSRSafeSuspense from '@/components/SSRSafeSuspense'; +import MyProfileContainer from '@/v1/profile/info/MyProfileInfoContainer'; +import UserProfileInfoContainer from '@/v1/profile/info/UserProfileInfoContainer'; import Skeleton from '@/v1/base/Skeleton'; -import MyProfileContainer from './MyProfileInfoContainer'; -import UserProfileInfoContainer from './UserProfileInfoContainer'; type ProfileInfoProps = { userId: 'me' | APIUser['userId']; diff --git a/src/v1/profile/info/UserProfileInfoContainer.tsx b/src/v1/profile/info/UserProfileInfoContainer.tsx index c92e31310..15faea504 100644 --- a/src/v1/profile/info/UserProfileInfoContainer.tsx +++ b/src/v1/profile/info/UserProfileInfoContainer.tsx @@ -1,7 +1,8 @@ import useUserProfileQuery from '@/queries/user/useUserProfileQuery'; -import ProfileInfoPresenter from './ProfileInfoPresenter'; import type { APIUser } from '@/types/user'; +import ProfileInfoPresenter from '@/v1/profile/info/ProfileInfoPresenter'; + const UserProfileInfoContainer = ({ userId, }: { @@ -9,7 +10,7 @@ const UserProfileInfoContainer = ({ }) => { const { data } = useUserProfileQuery(userId); - return ; + return ; }; export default UserProfileInfoContainer;