From 23a9253e4915e059b927a86e7e9c8f3dd1237ba2 Mon Sep 17 00:00:00 2001 From: Seheon Yu Date: Tue, 2 Jul 2024 04:43:04 +0900 Subject: [PATCH 1/7] refactor: Remove chat store and Add useSubscription for new message --- src/components/molecules/ChatBubbles.tsx | 112 ++++++++++-------- src/components/molecules/ChatToolbox.tsx | 21 ++-- src/components/molecules/NoticeBubble.tsx | 23 +--- src/components/organisms/Chat.tsx | 10 +- src/components/organisms/ChatParticipants.tsx | 34 +++--- src/components/organisms/ChatRoom.tsx | 36 +----- src/hooks/index.ts | 16 +++ src/hooks/use-chat-id.ts | 23 ++++ src/hooks/use-chat-users.ts | 23 ++++ src/hooks/use-chat.ts | 50 +++++++- src/stores/chat.ts | 73 ------------ src/stores/index.ts | 1 - src/types/message.ts | 8 +- src/utilities/message.ts | 8 +- 14 files changed, 216 insertions(+), 222 deletions(-) create mode 100644 src/hooks/index.ts create mode 100644 src/hooks/use-chat-id.ts create mode 100644 src/hooks/use-chat-users.ts delete mode 100644 src/stores/chat.ts diff --git a/src/components/molecules/ChatBubbles.tsx b/src/components/molecules/ChatBubbles.tsx index dee29887..ce47a990 100644 --- a/src/components/molecules/ChatBubbles.tsx +++ b/src/components/molecules/ChatBubbles.tsx @@ -1,61 +1,69 @@ -import { useEffect, useRef, useState } from 'react'; +import { useEffect, useRef } from 'react'; +import { useRouter } from 'next/navigation'; import styled from '@emotion/styled'; -import _ from 'lodash'; -import { useShallow } from 'zustand/react/shallow'; - import { Loading } from '#/components/atoms'; import { nullUser } from '#/entities'; -import { useChatMessagesQuery } from '#/hooks/use-chat'; -import { useMeQuery } from '#/hooks/use-user'; -import { useChatStore } from '#/stores'; -import { Chat } from '#/types'; +import { + useChatId, + useChatUsers, + useChatMessagesQuery, + useChatSubscription, + useMeQuery, + useMatchingRoomQuery, + useProjectsQuery, + useMatchingQuery, +} from '#/hooks'; +import { MatchingRoom, Project } from '#/types'; import { isImageMessage, isNoticeMessage, isTextMessage } from '#/utilities'; -import { convertDtoToMessage } from '#/utilities/message'; import { ChatBubble } from './ChatBubble'; import { NoticeBubble } from './NoticeBubble'; interface ChatBubblesProps { - chatId: Chat['id']; + projectId?: Project['id']; + matchingId?: MatchingRoom['id']; } -export const ChatBubbles = ({ chatId }: ChatBubblesProps) => { +export const ChatBubbles = ({ projectId, matchingId }: ChatBubblesProps) => { + const router = useRouter(); const topRef = useRef(null); - const [hasNext, setHasNext] = useState(true); - const [pageCursor, setPageCursor] = useState(0); + const { mutate: mutateCachedMatching } = useMatchingQuery(); + const { mutate: mutateCachedRoom } = useMatchingRoomQuery(matchingId); + const { mutate: mutateCachedProjects } = useProjectsQuery(); - const { participants, socket, messages, unshiftMessage, appendMessages } = useChatStore( - useShallow(({ chats, unshiftMessage, appendMessages }) => ({ - participants: chats[chatId].users, - socket: chats[chatId].socket, - messages: chats[chatId].messages, - unshiftMessage, - appendMessages, - })) - ); + const participants = useChatUsers({ projectId, matchingId }); + const chatId = useChatId({ projectId, matchingId }); const { data: me } = useMeQuery(); - - const { data: pages, size, setSize } = useChatMessagesQuery(chatId); + const { data: messages, setSize, append: appendMessage } = useChatMessagesQuery(chatId); + const { data: recentMessage } = useChatSubscription(chatId); useEffect(() => { - socket.on('get_message', (data: string) => { - const message = convertDtoToMessage(JSON.parse(data)); - unshiftMessage(chatId, message); - }); - return () => socket.off('get_message'); - }, [chatId, socket, unshiftMessage]); - - useEffect(() => { - if (pages && pages.length > pageCursor) { - const page = pages[pageCursor]; - appendMessages(chatId, page.messages); - setHasNext(page.hasNext); - setPageCursor((c) => c + 1); + if (recentMessage) { + if (isNoticeMessage(recentMessage)) { + mutateCachedRoom(); + if (recentMessage.type === 'COMPLETE' && matchingId) { + mutateCachedMatching(); + router.replace(`/projects/${recentMessage.notice}`); + } + if (recentMessage.type === 'COMPLETE' && projectId) { + mutateCachedProjects(); + } + } + appendMessage(recentMessage); } - }, [appendMessages, chatId, pageCursor, pages, size]); + }, [ + appendMessage, + matchingId, + mutateCachedMatching, + mutateCachedProjects, + mutateCachedRoom, + projectId, + recentMessage, + router, + ]); useEffect(() => { const observer = new IntersectionObserver((entries) => { @@ -74,19 +82,21 @@ export const ChatBubbles = ({ chatId }: ChatBubblesProps) => {
- {messages?.map((message, index) => - isNoticeMessage(message) ? ( - - ) : isTextMessage(message) || isImageMessage(message) ? ( - p.id === message.userId) ?? nullUser} - message={message} - myBubble={me?.id === message.userId} - /> - ) : null - )} - {hasNext && } + {messages + ?.flatMap((m) => m.messages) + ?.map((message) => + isNoticeMessage(message) ? ( + + ) : isTextMessage(message) || isImageMessage(message) ? ( + p.id === message.userId) ?? nullUser} + message={message} + myBubble={me?.id === message.userId} + /> + ) : null + )} + {messages?.at(-1)?.hasNext && } ); }; diff --git a/src/components/molecules/ChatToolbox.tsx b/src/components/molecules/ChatToolbox.tsx index 2ba72e36..17f3b28d 100644 --- a/src/components/molecules/ChatToolbox.tsx +++ b/src/components/molecules/ChatToolbox.tsx @@ -3,29 +3,30 @@ import React, { useCallback, useRef, useState } from 'react'; import styled from '@emotion/styled'; import { Icons, Input, Loading } from '#/components/atoms'; +import { useChatId, useChatMessageEmitter } from '#/hooks'; import { usePresignedUrlLazyQuery } from '#/hooks/use-file'; import { useMeQuery } from '#/hooks/use-user'; -import { useChatStore } from '#/stores'; -import { Chat } from '#/types'; -import { getStorageUrl } from '#/utilities'; -import { uploadFile } from '#/utilities/storage'; +import { Matching, Project } from '#/types'; +import { getStorageUrl, uploadFile } from '#/utilities'; import { RemovableImage } from './RemovableImage'; interface ChatToolboxProps { - chatId: Chat['id']; + projectId?: Project['id']; + matchingId?: Matching['id']; } -export const ChatToolbox = ({ chatId }: ChatToolboxProps) => { +export const ChatToolbox = ({ projectId, matchingId }: ChatToolboxProps) => { const imageInputRef = useRef(null); const [message, setMessage] = useState(''); const [imageUrls, setImageUrls] = useState([]); - const socket = useChatStore((state) => state.chats[chatId].socket); - const { data: user } = useMeQuery(); const { trigger: getPresignedUrl } = usePresignedUrlLazyQuery(); + const chatId = useChatId({ projectId, matchingId }); + const { emitText, emitImage } = useChatMessageEmitter(chatId); + const onUploadImage = useCallback>( async (e) => { const files = e.target.files; @@ -64,11 +65,11 @@ export const ChatToolbox = ({ chatId }: ChatToolboxProps) => {
{ if (imageUrls.length > 0) { - imageUrls.map((url) => socket.emit('/chat/image', { content: url })); + imageUrls.map((url) => emitImage(url)); setImageUrls([]); } if (message) { - socket.emit('/chat/text', { content: message }); + emitText(message); setMessage(''); } }} diff --git a/src/components/molecules/NoticeBubble.tsx b/src/components/molecules/NoticeBubble.tsx index f708c9a5..7f2dc820 100644 --- a/src/components/molecules/NoticeBubble.tsx +++ b/src/components/molecules/NoticeBubble.tsx @@ -1,10 +1,6 @@ -import { useRouter } from 'next/navigation'; - import styled from '@emotion/styled'; import { Txt } from '#/components/atoms'; -import { useMatchingQuery } from '#/hooks/use-matching'; -import { useMatchingRoomQuery } from '#/hooks/use-matching-room'; import { NoticeMessage } from '#/types'; interface NoticeBubbleProps extends React.HTMLAttributes { @@ -12,24 +8,7 @@ interface NoticeBubbleProps extends React.HTMLAttributes { } export const NoticeBubble = ({ message }: NoticeBubbleProps) => { - const router = useRouter(); - - const { data: matching, mutate: mutateCachedMatching } = useMatchingQuery(); - const { mutate: mutateCachedRoom } = useMatchingRoomQuery(matching?.id); - - switch (message.messageType) { - case 'JOIN': - case 'EXIT': - case 'READY': - mutateCachedRoom(); - break; - case 'COMPLETE': - mutateCachedRoom(); - mutateCachedMatching(); - router.replace('/projects'); - } - - return ( + return message.type === 'COMPLETE' ? null : ( {message.notice} diff --git a/src/components/organisms/Chat.tsx b/src/components/organisms/Chat.tsx index 4af8ec06..5b4c1cba 100644 --- a/src/components/organisms/Chat.tsx +++ b/src/components/organisms/Chat.tsx @@ -3,12 +3,14 @@ import styled from '@emotion/styled'; import { Txt } from '#/components/atoms'; import { ChatBubbles } from '#/components/molecules/ChatBubbles'; import { ChatToolbox } from '#/components/molecules/ChatToolbox'; +import { MatchingRoom, Project } from '#/types'; interface ChatProps { - chatId: number; + projectId?: Project['id']; + matchingId?: MatchingRoom['id']; } -export const Chat = ({ chatId }: ChatProps) => { +export const Chat = ({ projectId, matchingId }: ChatProps) => { return (
@@ -16,9 +18,9 @@ export const Chat = ({ chatId }: ChatProps) => { 채팅방
- + - +
); diff --git a/src/components/organisms/ChatParticipants.tsx b/src/components/organisms/ChatParticipants.tsx index 63ca7c9f..d8e63962 100644 --- a/src/components/organisms/ChatParticipants.tsx +++ b/src/components/organisms/ChatParticipants.tsx @@ -1,7 +1,6 @@ import styled from '@emotion/styled'; import { mutate } from 'swr'; -import { useShallow } from 'zustand/react/shallow'; import { MatchingChatPositionGroup, @@ -11,34 +10,33 @@ import { MatchingChatHeader } from '#/components/molecules/MatchingChatHeader'; import { ProjectChatHeader } from '#/components/molecules/ProjectChatHeader'; import { MATCHING_ROOM_QUERY_KEY, + useChatUsers, useMatchingRoomForceOutMutation, -} from '#/hooks/use-matching-room'; -import { usePositionsQuery } from '#/hooks/use-positions'; -import { useReportUserMutator } from '#/hooks/use-projects'; -import { useMeQuery } from '#/hooks/use-user'; -import { useChatStore } from '#/stores'; -import type { Chat } from '#/types'; + useMeQuery, + usePositionsQuery, + useReportUserMutator, +} from '#/hooks'; +import type { Matching, Project } from '#/types'; interface ChatParticipantsProps { - chatId: Chat['id']; + matchingId?: Matching['id']; + projectId?: Project['id']; onClickHeader?: React.MouseEventHandler; } -export const ChatParticipants: React.FC = ({ chatId, onClickHeader }) => { - const { participants, projectId, matchingId } = useChatStore( - useShallow(({ chats }) => ({ - participants: chats[chatId].users, - projectId: chats[chatId].projectId, - matchingId: chats[chatId].matchingId, - })) - ); - +export const ChatParticipants: React.FC = ({ + matchingId, + projectId, + onClickHeader, +}) => { const { data: me } = useMeQuery(); const { data: positions } = usePositionsQuery(); const { trigger: kickUser } = useMatchingRoomForceOutMutation(matchingId ?? undefined); const { trigger: reportUser } = useReportUserMutator(projectId); + const participants = useChatUsers({ projectId, matchingId }); + return ( @@ -62,7 +60,7 @@ export const ChatParticipants: React.FC = ({ chatId, onCl name={position.displayName} participants={participants.filter((p) => p.positionId === position.id) ?? []} onKickUser={ - participants.some((p) => p.isHost && p.id === me?.id) + participants.some((p) => p.id === me?.id && p.isHost) ? async (userId) => { await kickUser({ userId }); mutate(MATCHING_ROOM_QUERY_KEY(matchingId)); diff --git a/src/components/organisms/ChatRoom.tsx b/src/components/organisms/ChatRoom.tsx index 426d0821..9a9200c8 100644 --- a/src/components/organisms/ChatRoom.tsx +++ b/src/components/organisms/ChatRoom.tsx @@ -1,12 +1,7 @@ -import { useEffect, useMemo, useRef, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import styled from '@emotion/styled'; -import { Loading } from '#/components/atoms'; -import { useMatchingRoomQuery } from '#/hooks/use-matching-room'; -import { useProjectsQuery } from '#/hooks/use-projects'; -import { useChatStore } from '#/stores'; -import { Chat } from '#/types'; import { Chat as ChatBox } from './Chat'; import { ChatParticipants } from './ChatParticipants'; @@ -19,13 +14,6 @@ export const ChatRoom = ({ projectId, matchingId }: ChatRoomProps) => { const participantsContainerRef = useRef(null); const [height, setHeight] = useState(null); - const [chatId, setChatId] = useState(null); - - const { data: matchingRoom } = useMatchingRoomQuery(matchingId); - const { data: projects } = useProjectsQuery(); - const project = useMemo(() => projects?.find((p) => p.id === projectId), [projects, projectId]); - - const createChat = useChatStore((state) => state.createChat); useEffect(() => { if (participantsContainerRef.current) { @@ -34,28 +22,14 @@ export const ChatRoom = ({ projectId, matchingId }: ChatRoomProps) => { } }, [participantsContainerRef.current?.offsetHeight]); - useEffect(() => { - if (matchingRoom) { - const { id, chatId, matchingUsers } = matchingRoom; - createChat({ id: chatId, matchingId: id, users: matchingUsers }); - setChatId(chatId); - } - }, [createChat, matchingRoom]); - - useEffect(() => { - if (project) { - const { id, chatId, members } = project; - createChat({ id: chatId, projectId: id, users: members }); - setChatId(chatId); - } - }, [createChat, project]); - return ( - {chatId ? : } + - {chatId && } + + + ); }; diff --git a/src/hooks/index.ts b/src/hooks/index.ts new file mode 100644 index 00000000..ba9b09d5 --- /dev/null +++ b/src/hooks/index.ts @@ -0,0 +1,16 @@ +export * from './use-alarm'; +export * from './use-chat-id'; +export * from './use-chat-users'; +export * from './use-chat'; +export * from './use-file'; +export * from './use-login-page'; +export * from './use-matching-room'; +export * from './use-matching'; +export * from './use-policy-agrees'; +export * from './use-positions'; +export * from './use-presigned-url'; +export * from './use-projects'; +export * from './use-recommend'; +export * from './use-regions'; +export * from './use-skills'; +export * from './use-user'; diff --git a/src/hooks/use-chat-id.ts b/src/hooks/use-chat-id.ts new file mode 100644 index 00000000..207e751e --- /dev/null +++ b/src/hooks/use-chat-id.ts @@ -0,0 +1,23 @@ +import { useMemo } from 'react'; + +import { Matching, Project } from '#/types'; +import { useMatchingRoomQuery, useProjectsQuery } from '.'; + +export function useChatId({ + projectId, + matchingId, +}: { + projectId?: Project['id']; + matchingId?: Matching['id']; +}) { + const { data: matching } = useMatchingRoomQuery(matchingId); + const { data: projects } = useProjectsQuery(); + + const project = useMemo(() => projects?.find((p) => p.id === projectId), [projects, projectId]); + const chatId = useMemo( + () => project?.chatId ?? matching?.chatId, + [matching?.chatId, project?.chatId] + ); + + return chatId; +} diff --git a/src/hooks/use-chat-users.ts b/src/hooks/use-chat-users.ts new file mode 100644 index 00000000..4930c12d --- /dev/null +++ b/src/hooks/use-chat-users.ts @@ -0,0 +1,23 @@ +import { useMemo } from 'react'; + +import { ChatUser, Matching, Project } from '#/types'; +import { useMatchingRoomQuery, useProjectsQuery } from '.'; + +export function useChatUsers({ + projectId, + matchingId, +}: { + projectId?: Project['id']; + matchingId?: Matching['id']; +}) { + const { data: matching } = useMatchingRoomQuery(matchingId); + const { data: projects } = useProjectsQuery(); + + const project = useMemo(() => projects?.find((p) => p.id === projectId), [projects, projectId]); + const users: ChatUser[] = useMemo( + () => project?.members ?? matching?.matchingUsers ?? [], + [matching?.matchingUsers, project?.members] + ); + + return users; +} diff --git a/src/hooks/use-chat.ts b/src/hooks/use-chat.ts index faf5310e..dd31067e 100644 --- a/src/hooks/use-chat.ts +++ b/src/hooks/use-chat.ts @@ -1,13 +1,20 @@ +import { useEffect, useMemo, useState } from 'react'; + import _ from 'lodash'; import useSWR from 'swr'; import useSWRInfinite from 'swr/infinite'; +import useSWRSubscription, { SWRSubscriptionOptions } from 'swr/subscription'; import { Chat, Message } from '#/types'; -import { fitFetcher } from '#/utilities'; +import { fitFetcher, fitSocket } from '#/utilities'; import { convertDtoToMessage } from '#/utilities/message'; const CHAT_MESSAGES_QUERY_KEY = - (id: Chat['id']) => (index: number, previousPageData: ChatMessagesPage | null) => { + (id?: Chat['id']) => (index: number, previousPageData: ChatMessagesPage | null) => { + if (id === undefined) { + return null; + } + if (previousPageData && !previousPageData.hasNext) { return null; } @@ -21,6 +28,19 @@ const CHAT_MESSAGES_QUERY_KEY = const CHAT_RECENT_MESSAGE_QUERY_KEY = (id: Chat['id']) => `/v1/chat/room/${id}/recent`; +export function useChatSubscription(id?: Chat['id']) { + return useSWRSubscription( + id !== undefined ? [id] : null, + ([id], { next }: SWRSubscriptionOptions) => { + const socket = fitSocket({ roomId: id }); + socket.on('get_message', (message: string) => + next(null, convertDtoToMessage(JSON.parse(message))) + ); + return () => socket.disconnect(); + } + ); +} + interface ChatMessagesResponse { pageResult: { values: { @@ -41,14 +61,20 @@ interface ChatMessagesPage { hasNext: boolean; } -export function useChatMessagesQuery(id: Chat['id']) { - return useSWRInfinite(CHAT_MESSAGES_QUERY_KEY(id), async (url) => { +export function useChatMessagesQuery(id?: Chat['id']) { + const { mutate, ...props } = useSWRInfinite(CHAT_MESSAGES_QUERY_KEY(id), async (url) => { const json = await fitFetcher(url); return { messages: json.pageResult.values.map((v) => convertDtoToMessage(v)), hasNext: json.pageResult.hasNext, } as { messages: Message[]; hasNext: boolean }; }); + const append = useMemo( + () => (message: Message) => + mutate((prev) => [{ messages: [message], hasNext: true }, ...(prev ?? [])]), + [mutate] + ); + return { append, mutate, ...props }; } interface ChatRecentMessageResponse { @@ -61,3 +87,19 @@ export function useChatRecentMessageQuery(id: Chat['id']) { return json.messageId; }); } + +export function useChatMessageEmitter(id?: Chat['id']) { + const [socket, setSocket] = useState>(); + + useEffect(() => { + if (!socket) { + setSocket(fitSocket({ roomId: id })); + } + return () => socket?.disconnect(); + }, [id, socket]); + + return { + emitText: (content: string) => socket?.emit('/chat/text', { content }), + emitImage: (content: string) => socket?.emit('/chat/image', { content }), + }; +} diff --git a/src/stores/chat.ts b/src/stores/chat.ts deleted file mode 100644 index e8b16154..00000000 --- a/src/stores/chat.ts +++ /dev/null @@ -1,73 +0,0 @@ -import _ from 'lodash'; -import { create } from 'zustand'; -import { immer } from 'zustand/middleware/immer'; - -import { Chat, Message } from '#/types'; -import { fitSocket } from '#/utilities/socket'; - -interface ChatState { - chats: Record; -} - -interface ChatAction { - createChat: (chat: Pick) => void; - setParticipants: (id: Chat['id'], participants: Chat['users']) => void; - setMessages: (id: Chat['id'], messages: Message[]) => void; - unshiftMessage: (id: Chat['id'], message: Message) => void; - appendMessages: (id: Chat['id'], messages: Message[]) => void; -} - -export const useChatStore = create()( - immer((set) => ({ - chats: {}, - - createChat: (chat) => { - set((state) => { - if (state.chats[chat.id]) { - return; - } - state.chats[chat.id] = { - ...chat, - messages: [], - socket: fitSocket({ roomId: chat.id }), - } as Chat; - }); - }, - setParticipants: (id, participants) => { - set((state) => { - const chat = state.chats[id]; - if (!chat) { - return; - } - chat.users = participants; - }); - }, - setMessages: (id, messages) => { - set((state) => { - const chat = state.chats[id]; - if (!chat) { - return; - } - chat.messages = messages; - }); - }, - unshiftMessage: (id, message) => { - set((state) => { - const chat = state.chats[id]; - if (!chat) { - return; - } - chat.messages.unshift(message); - }); - }, - appendMessages: (id, messages) => { - set((state) => { - const chat = state.chats[id]; - if (!chat) { - return; - } - chat.messages = [...chat.messages, ...messages]; - }); - }, - })) -); diff --git a/src/stores/index.ts b/src/stores/index.ts index 21338631..e734d0ce 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -1,2 +1 @@ -export { useChatStore } from './chat'; export { useLoginGuardStore } from './login-guard'; diff --git a/src/types/message.ts b/src/types/message.ts index 5760a7bb..48d6679e 100644 --- a/src/types/message.ts +++ b/src/types/message.ts @@ -2,7 +2,7 @@ import { User } from '.'; export interface Message { id: number; - messageType: 'TEXT' | 'IMAGE' | 'NOTICE' | 'JOIN' | 'EXIT' | 'COMPLETE' | 'READY'; + type: 'TEXT' | 'IMAGE' | 'NOTICE' | 'JOIN' | 'EXIT' | 'COMPLETE' | 'READY'; createdAt: string; userId?: User['id']; content?: string; @@ -11,21 +11,21 @@ export interface Message { } export interface TextMessage extends Message { - messageType: 'TEXT'; + type: 'TEXT'; content: string; imageUrl: undefined; notice: undefined; } export interface ImageMessage extends Message { - messageType: 'IMAGE'; + type: 'IMAGE'; content: undefined; imageUrl: string; notice: undefined; } export interface NoticeMessage extends Message { - messageType: 'NOTICE' | 'JOIN' | 'EXIT' | 'COMPLETE' | 'READY'; + type: 'NOTICE' | 'JOIN' | 'EXIT' | 'COMPLETE' | 'READY'; content: undefined; imageUrl: undefined; notice: string; diff --git a/src/utilities/message.ts b/src/utilities/message.ts index 21bde5da..d24d30b1 100644 --- a/src/utilities/message.ts +++ b/src/utilities/message.ts @@ -1,16 +1,16 @@ import { ImageMessage, Message, NoticeMessage, TextMessage, User } from '#/types'; export function isTextMessage(message: Message): message is TextMessage { - return message.messageType === 'TEXT'; + return message.type === 'TEXT'; } export function isImageMessage(message: Message): message is ImageMessage { - return message.messageType === 'IMAGE'; + return message.type === 'IMAGE'; } export function isNoticeMessage(message: Message): message is NoticeMessage { const noticeMessageTypes = ['NOTICE', 'JOIN', 'EXIT', 'COMPLETE', 'READY']; - return noticeMessageTypes.includes(message.messageType); + return noticeMessageTypes.includes(message.type); } interface MessageDto { @@ -28,6 +28,6 @@ export function convertDtoToMessage(messageDto: MessageDto): Message { return { ...message, id: messageId, - messageType: messageType as Message['messageType'], + type: messageType as Message['type'], }; } From 2c633d00743f224c76bed103ed3c6b6205e25e63 Mon Sep 17 00:00:00 2001 From: Seheon Yu Date: Tue, 2 Jul 2024 05:15:00 +0900 Subject: [PATCH 2/7] dependency: Add eslint:recommend extends for eslint --- .eslintrc.json | 11 +- .pnp.cjs | 418 +++++++++++++++++- package.json | 14 +- src/app/signup-guard.tsx | 2 +- src/components/atoms/Icons.tsx | 8 +- src/components/atoms/Label.tsx | 4 +- src/components/atoms/Loading.tsx | 2 +- src/components/atoms/MouseDetector.tsx | 2 +- .../atoms/MyPage/PortfolioTicket.tsx | 1 - src/components/atoms/SocialLoginButton.tsx | 1 - src/components/atoms/Text.tsx | 2 +- src/components/molecules/ChatToolbox.tsx | 3 +- .../molecules/MyPage/TechSelectBlock.tsx | 1 - src/components/molecules/PositionCard.tsx | 4 +- .../molecules/TeamRecommend/TechSelect.tsx | 2 +- .../MatchingInfo/MatchingSequenceSwiper.tsx | 2 +- src/components/organisms/MatchingRegister.tsx | 2 - .../organisms/MyPage/ActivityEdit.tsx | 4 +- .../organisms/MyPage/MemberInfoEdit.tsx | 4 +- .../organisms/MyPage/PortfolioInformation.tsx | 17 - src/components/organisms/ProjectChatRoom.tsx | 2 - src/components/organisms/SignUpTermsPopup.tsx | 6 +- .../TeamRecommend/RecommendFilterBlock.tsx | 5 +- .../sign-up/ProfileDetailsSubmission.tsx | 2 +- src/entities/policy.ts | 2 +- src/hooks/use-matching.ts | 7 +- src/hooks/use-presigned-url.ts | 2 +- src/types/api-error.ts | 9 +- src/types/matching.ts | 2 +- src/utilities/index.ts | 18 +- src/utilities/matching.ts | 11 +- src/utilities/socket.ts | 1 + svgr.d.ts | 10 + tsconfig.json | 48 +- yarn.lock | 171 ++++++- 35 files changed, 695 insertions(+), 105 deletions(-) create mode 100644 svgr.d.ts diff --git a/.eslintrc.json b/.eslintrc.json index faae563d..7e0b4fad 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,17 +1,26 @@ { "extends": [ "next/core-web-vitals", + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", "plugin:import/typescript", "plugin:storybook/recommended" ], + "parser": "@typescript-eslint/parser", "settings": { + "import/parsers": { + "@typescript-eslint/parser": [ + ".ts", + ".tsx" + ] + }, "import/resolver": { "typescript": true, "node": true } }, "rules": { - "import/no-unused-modules": "error", "import/order": [ "error", { diff --git a/.pnp.cjs b/.pnp.cjs index 479122f4..00595279 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -46,7 +46,8 @@ const RAW_RUNTIME_STATE = ["@types/node", "npm:20.11.27"],\ ["@types/react", "npm:18.2.65"],\ ["@types/react-dom", "npm:18.2.22"],\ - ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:6.21.0"],\ + ["@typescript-eslint/eslint-plugin", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ + ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ ["eslint", "npm:8.57.0"],\ ["eslint-config-next", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:14.0.2"],\ ["eslint-import-resolver-typescript", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:3.6.1"],\ @@ -75,6 +76,7 @@ const RAW_RUNTIME_STATE = ["swiper", "npm:11.0.7"],\ ["swr", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:2.2.5"],\ ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"],\ + ["typescript-eslint", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ ["webpack", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:5.90.3"],\ ["zustand", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:4.5.2"]\ ],\ @@ -3525,6 +3527,13 @@ const RAW_RUNTIME_STATE = ["@eslint-community/regexpp", "npm:4.10.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.11.0", {\ + "packageLocation": "./.yarn/cache/@eslint-community-regexpp-npm-4.11.0-dd7ae18a6d-0f6328869b.zip/node_modules/@eslint-community/regexpp/",\ + "packageDependencies": [\ + ["@eslint-community/regexpp", "npm:4.11.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@eslint/eslintrc", [\ @@ -6428,6 +6437,45 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@typescript-eslint/eslint-plugin", [\ + ["npm:7.15.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-eslint-plugin-npm-7.15.0-546a66c6ca-7ed4ef8355.zip/node_modules/@typescript-eslint/eslint-plugin/",\ + "packageDependencies": [\ + ["@typescript-eslint/eslint-plugin", "npm:7.15.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-eslint-plugin-virtual-b459dd3718/0/cache/@typescript-eslint-eslint-plugin-npm-7.15.0-546a66c6ca-7ed4ef8355.zip/node_modules/@typescript-eslint/eslint-plugin/",\ + "packageDependencies": [\ + ["@typescript-eslint/eslint-plugin", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ + ["@eslint-community/regexpp", "npm:4.11.0"],\ + ["@types/eslint", null],\ + ["@types/typescript", null],\ + ["@types/typescript-eslint__parser", null],\ + ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ + ["@typescript-eslint/scope-manager", "npm:7.15.0"],\ + ["@typescript-eslint/type-utils", "virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:7.15.0"],\ + ["@typescript-eslint/utils", "virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:7.15.0"],\ + ["@typescript-eslint/visitor-keys", "npm:7.15.0"],\ + ["eslint", "npm:8.57.0"],\ + ["graphemer", "npm:1.4.0"],\ + ["ignore", "npm:5.3.1"],\ + ["natural-compare", "npm:1.4.0"],\ + ["ts-api-utils", "virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:1.3.0"],\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "@types/typescript-eslint__parser",\ + "@types/typescript",\ + "@typescript-eslint/parser",\ + "eslint",\ + "typescript"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@typescript-eslint/parser", [\ ["npm:6.21.0", {\ "packageLocation": "./.yarn/cache/@typescript-eslint-parser-npm-6.21.0-d7ff8425ee-a8f9982067.zip/node_modules/@typescript-eslint/parser/",\ @@ -6436,15 +6484,22 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ - ["virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:6.21.0", {\ - "packageLocation": "./.yarn/__virtual__/@typescript-eslint-parser-virtual-2c15a16a95/0/cache/@typescript-eslint-parser-npm-6.21.0-d7ff8425ee-a8f9982067.zip/node_modules/@typescript-eslint/parser/",\ + ["npm:7.15.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-parser-npm-7.15.0-3593910f08-8dcad9b84e.zip/node_modules/@typescript-eslint/parser/",\ + "packageDependencies": [\ + ["@typescript-eslint/parser", "npm:7.15.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:6.21.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-parser-virtual-248cf40f49/0/cache/@typescript-eslint-parser-npm-6.21.0-d7ff8425ee-a8f9982067.zip/node_modules/@typescript-eslint/parser/",\ "packageDependencies": [\ - ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:6.21.0"],\ + ["@typescript-eslint/parser", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:6.21.0"],\ ["@types/eslint", null],\ ["@types/typescript", null],\ ["@typescript-eslint/scope-manager", "npm:6.21.0"],\ ["@typescript-eslint/types", "npm:6.21.0"],\ - ["@typescript-eslint/typescript-estree", "virtual:2c15a16a95951ee0f85f94e2126f5ab6815c77305a68397228634433a123c0c4b481f9241d60b5436f83b37158ee8835bed308dea5e5efb6f32877adabbbd2cc#npm:6.21.0"],\ + ["@typescript-eslint/typescript-estree", "virtual:248cf40f49d0471bd7d34206af9fd390a4f900cc7c44d3a18c4fc041b2e0669577f1919617758d059ad29591e0f0066d11d784208fcfc2fb3456dd7966c326bd#npm:6.21.0"],\ ["@typescript-eslint/visitor-keys", "npm:6.21.0"],\ ["debug", "virtual:52cc1f08fdfa0ce0882bedf10264a24f906e33f7892b3412b78b3e749d6e4b50a5c4d47e46903c21fe956663d3ab6f4d2b4677d28abd53464b00761501f37601#npm:4.3.4"],\ ["eslint", "npm:8.57.0"],\ @@ -6457,6 +6512,28 @@ const RAW_RUNTIME_STATE = "typescript"\ ],\ "linkType": "HARD"\ + }],\ + ["virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-parser-virtual-bc1959a301/0/cache/@typescript-eslint-parser-npm-7.15.0-3593910f08-8dcad9b84e.zip/node_modules/@typescript-eslint/parser/",\ + "packageDependencies": [\ + ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ + ["@types/eslint", null],\ + ["@types/typescript", null],\ + ["@typescript-eslint/scope-manager", "npm:7.15.0"],\ + ["@typescript-eslint/types", "npm:7.15.0"],\ + ["@typescript-eslint/typescript-estree", "virtual:61dad79ad31ee3d210b36101f263d75ed4b62508ee7d8ad5472508926411ddf38cd7dcc600e317208007c9394b171eb8d58c088e7948c8e58c008da50b64a5a0#npm:7.15.0"],\ + ["@typescript-eslint/visitor-keys", "npm:7.15.0"],\ + ["debug", "virtual:52cc1f08fdfa0ce0882bedf10264a24f906e33f7892b3412b78b3e749d6e4b50a5c4d47e46903c21fe956663d3ab6f4d2b4677d28abd53464b00761501f37601#npm:4.3.4"],\ + ["eslint", "npm:8.57.0"],\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "@types/typescript",\ + "eslint",\ + "typescript"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@typescript-eslint/scope-manager", [\ @@ -6477,6 +6554,45 @@ const RAW_RUNTIME_STATE = ["@typescript-eslint/visitor-keys", "npm:6.21.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.15.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-scope-manager-npm-7.15.0-6cd6663c93-781ec31a07.zip/node_modules/@typescript-eslint/scope-manager/",\ + "packageDependencies": [\ + ["@typescript-eslint/scope-manager", "npm:7.15.0"],\ + ["@typescript-eslint/types", "npm:7.15.0"],\ + ["@typescript-eslint/visitor-keys", "npm:7.15.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@typescript-eslint/type-utils", [\ + ["npm:7.15.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-type-utils-npm-7.15.0-f8293abccb-06189eb05d.zip/node_modules/@typescript-eslint/type-utils/",\ + "packageDependencies": [\ + ["@typescript-eslint/type-utils", "npm:7.15.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:7.15.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-type-utils-virtual-61dad79ad3/0/cache/@typescript-eslint-type-utils-npm-7.15.0-f8293abccb-06189eb05d.zip/node_modules/@typescript-eslint/type-utils/",\ + "packageDependencies": [\ + ["@typescript-eslint/type-utils", "virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:7.15.0"],\ + ["@types/eslint", null],\ + ["@types/typescript", null],\ + ["@typescript-eslint/typescript-estree", "virtual:61dad79ad31ee3d210b36101f263d75ed4b62508ee7d8ad5472508926411ddf38cd7dcc600e317208007c9394b171eb8d58c088e7948c8e58c008da50b64a5a0#npm:7.15.0"],\ + ["@typescript-eslint/utils", "virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:7.15.0"],\ + ["debug", "virtual:52cc1f08fdfa0ce0882bedf10264a24f906e33f7892b3412b78b3e749d6e4b50a5c4d47e46903c21fe956663d3ab6f4d2b4677d28abd53464b00761501f37601#npm:4.3.4"],\ + ["eslint", "npm:8.57.0"],\ + ["ts-api-utils", "virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:1.3.0"],\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "@types/typescript",\ + "eslint",\ + "typescript"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@typescript-eslint/types", [\ @@ -6493,6 +6609,13 @@ const RAW_RUNTIME_STATE = ["@typescript-eslint/types", "npm:6.21.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.15.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-types-npm-7.15.0-f8bd99bde7-935387b21d.zip/node_modules/@typescript-eslint/types/",\ + "packageDependencies": [\ + ["@typescript-eslint/types", "npm:7.15.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@typescript-eslint/typescript-estree", [\ @@ -6510,6 +6633,13 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["npm:7.15.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-typescript-estree-npm-7.15.0-53b406f82c-0d6e61cb36.zip/node_modules/@typescript-eslint/typescript-estree/",\ + "packageDependencies": [\ + ["@typescript-eslint/typescript-estree", "npm:7.15.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ ["virtual:0407010d0b41f57079c3e0b1c581c7464df63fc814e3e600a185d19bf80eb4ae6cfa990ddd012d99f7489e4ec15e5104eeb69bc407444622b5e315e7bfcaff3c#npm:5.62.0", {\ "packageLocation": "./.yarn/__virtual__/@typescript-eslint-typescript-estree-virtual-abed2b0041/0/cache/@typescript-eslint-typescript-estree-npm-5.62.0-5d1ea132a9-d7984a3e9d.zip/node_modules/@typescript-eslint/typescript-estree/",\ "packageDependencies": [\ @@ -6530,10 +6660,10 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:2c15a16a95951ee0f85f94e2126f5ab6815c77305a68397228634433a123c0c4b481f9241d60b5436f83b37158ee8835bed308dea5e5efb6f32877adabbbd2cc#npm:6.21.0", {\ - "packageLocation": "./.yarn/__virtual__/@typescript-eslint-typescript-estree-virtual-91cec3001b/0/cache/@typescript-eslint-typescript-estree-npm-6.21.0-04a199adba-af1438c60f.zip/node_modules/@typescript-eslint/typescript-estree/",\ + ["virtual:248cf40f49d0471bd7d34206af9fd390a4f900cc7c44d3a18c4fc041b2e0669577f1919617758d059ad29591e0f0066d11d784208fcfc2fb3456dd7966c326bd#npm:6.21.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-typescript-estree-virtual-c5d46b5797/0/cache/@typescript-eslint-typescript-estree-npm-6.21.0-04a199adba-af1438c60f.zip/node_modules/@typescript-eslint/typescript-estree/",\ "packageDependencies": [\ - ["@typescript-eslint/typescript-estree", "virtual:2c15a16a95951ee0f85f94e2126f5ab6815c77305a68397228634433a123c0c4b481f9241d60b5436f83b37158ee8835bed308dea5e5efb6f32877adabbbd2cc#npm:6.21.0"],\ + ["@typescript-eslint/typescript-estree", "virtual:248cf40f49d0471bd7d34206af9fd390a4f900cc7c44d3a18c4fc041b2e0669577f1919617758d059ad29591e0f0066d11d784208fcfc2fb3456dd7966c326bd#npm:6.21.0"],\ ["@types/typescript", null],\ ["@typescript-eslint/types", "npm:6.21.0"],\ ["@typescript-eslint/visitor-keys", "npm:6.21.0"],\ @@ -6542,7 +6672,28 @@ const RAW_RUNTIME_STATE = ["is-glob", "npm:4.0.3"],\ ["minimatch", "npm:9.0.3"],\ ["semver", "npm:7.6.0"],\ - ["ts-api-utils", "virtual:91cec3001b898073c23dd87c125639536749704c79541ef0d14a1f1a612a3b8aa88ec9391cd5bbfc506d987d8818034bf8cb8082dc3ebad073a1dcd62162fd04#npm:1.3.0"],\ + ["ts-api-utils", "virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:1.3.0"],\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ + ],\ + "packagePeers": [\ + "@types/typescript",\ + "typescript"\ + ],\ + "linkType": "HARD"\ + }],\ + ["virtual:61dad79ad31ee3d210b36101f263d75ed4b62508ee7d8ad5472508926411ddf38cd7dcc600e317208007c9394b171eb8d58c088e7948c8e58c008da50b64a5a0#npm:7.15.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-typescript-estree-virtual-c0ecddf7d6/0/cache/@typescript-eslint-typescript-estree-npm-7.15.0-53b406f82c-0d6e61cb36.zip/node_modules/@typescript-eslint/typescript-estree/",\ + "packageDependencies": [\ + ["@typescript-eslint/typescript-estree", "virtual:61dad79ad31ee3d210b36101f263d75ed4b62508ee7d8ad5472508926411ddf38cd7dcc600e317208007c9394b171eb8d58c088e7948c8e58c008da50b64a5a0#npm:7.15.0"],\ + ["@types/typescript", null],\ + ["@typescript-eslint/types", "npm:7.15.0"],\ + ["@typescript-eslint/visitor-keys", "npm:7.15.0"],\ + ["debug", "virtual:52cc1f08fdfa0ce0882bedf10264a24f906e33f7892b3412b78b3e749d6e4b50a5c4d47e46903c21fe956663d3ab6f4d2b4677d28abd53464b00761501f37601#npm:4.3.4"],\ + ["globby", "npm:11.1.0"],\ + ["is-glob", "npm:4.0.3"],\ + ["minimatch", "npm:9.0.5"],\ + ["semver", "npm:7.6.2"],\ + ["ts-api-utils", "virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:1.3.0"],\ ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ ],\ "packagePeers": [\ @@ -6550,6 +6701,27 @@ const RAW_RUNTIME_STATE = "typescript"\ ],\ "linkType": "HARD"\ + }],\ + ["virtual:6473a2b2b3158919c1adaf21e919d3d15c307f2ecccd0492f5761b4792c1785feb653fa1db92bde4fdc7e9f5ada871f09678f28dd2e8837c7d52db3816fbb0bd#npm:7.15.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-typescript-estree-virtual-771b6bc247/0/cache/@typescript-eslint-typescript-estree-npm-7.15.0-53b406f82c-0d6e61cb36.zip/node_modules/@typescript-eslint/typescript-estree/",\ + "packageDependencies": [\ + ["@typescript-eslint/typescript-estree", "virtual:6473a2b2b3158919c1adaf21e919d3d15c307f2ecccd0492f5761b4792c1785feb653fa1db92bde4fdc7e9f5ada871f09678f28dd2e8837c7d52db3816fbb0bd#npm:7.15.0"],\ + ["@types/typescript", null],\ + ["@typescript-eslint/types", "npm:7.15.0"],\ + ["@typescript-eslint/visitor-keys", "npm:7.15.0"],\ + ["debug", "virtual:52cc1f08fdfa0ce0882bedf10264a24f906e33f7892b3412b78b3e749d6e4b50a5c4d47e46903c21fe956663d3ab6f4d2b4677d28abd53464b00761501f37601#npm:4.3.4"],\ + ["globby", "npm:11.1.0"],\ + ["is-glob", "npm:4.0.3"],\ + ["minimatch", "npm:9.0.5"],\ + ["semver", "npm:7.6.2"],\ + ["ts-api-utils", "virtual:771b6bc24730ab0421bf193947d472f40d187d144f370034918af6e92427abf255f59411a17788fa47ed9d81de6242753f38ee2df63c10fd2363a2da0136a850#npm:1.3.0"],\ + ["typescript", null]\ + ],\ + "packagePeers": [\ + "@types/typescript",\ + "typescript"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@typescript-eslint/utils", [\ @@ -6560,6 +6732,13 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["npm:7.15.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-utils-npm-7.15.0-62466ad6b7-26aced1797.zip/node_modules/@typescript-eslint/utils/",\ + "packageDependencies": [\ + ["@typescript-eslint/utils", "npm:7.15.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ ["virtual:3df8c63f258f17ad6727dfd6217bf0775b2248640731bb9b119885049f7608d9dab85b4ea31a40ffba95d15df8e01e66fcad2e98c2b81f6ec7340958cc6a7ec9#npm:5.62.0", {\ "packageLocation": "./.yarn/__virtual__/@typescript-eslint-utils-virtual-0407010d0b/0/cache/@typescript-eslint-utils-npm-5.62.0-907f2d579e-f09b7d9952.zip/node_modules/@typescript-eslint/utils/",\ "packageDependencies": [\ @@ -6580,6 +6759,23 @@ const RAW_RUNTIME_STATE = "eslint"\ ],\ "linkType": "HARD"\ + }],\ + ["virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:7.15.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-utils-virtual-6473a2b2b3/0/cache/@typescript-eslint-utils-npm-7.15.0-62466ad6b7-26aced1797.zip/node_modules/@typescript-eslint/utils/",\ + "packageDependencies": [\ + ["@typescript-eslint/utils", "virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:7.15.0"],\ + ["@eslint-community/eslint-utils", "virtual:4286e12a3a0f74af013bc8f16c6d8fdde823cfbf6389660266b171e551f576c805b0a7a8eb2a7087a5cee7dfe6ebb6e1ea3808d93daf915edc95656907a381bb#npm:4.4.0"],\ + ["@types/eslint", null],\ + ["@typescript-eslint/scope-manager", "npm:7.15.0"],\ + ["@typescript-eslint/types", "npm:7.15.0"],\ + ["@typescript-eslint/typescript-estree", "virtual:6473a2b2b3158919c1adaf21e919d3d15c307f2ecccd0492f5761b4792c1785feb653fa1db92bde4fdc7e9f5ada871f09678f28dd2e8837c7d52db3816fbb0bd#npm:7.15.0"],\ + ["eslint", "npm:8.57.0"]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "eslint"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@typescript-eslint/visitor-keys", [\ @@ -6600,6 +6796,15 @@ const RAW_RUNTIME_STATE = ["eslint-visitor-keys", "npm:3.4.3"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.15.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-visitor-keys-npm-7.15.0-32c639de86-7509f01c8c.zip/node_modules/@typescript-eslint/visitor-keys/",\ + "packageDependencies": [\ + ["@typescript-eslint/visitor-keys", "npm:7.15.0"],\ + ["@typescript-eslint/types", "npm:7.15.0"],\ + ["eslint-visitor-keys", "npm:3.4.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@ungap/structured-clone", [\ @@ -10234,11 +10439,11 @@ const RAW_RUNTIME_STATE = ["@rushstack/eslint-patch", "npm:1.7.2"],\ ["@types/eslint", null],\ ["@types/typescript", null],\ - ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:6.21.0"],\ + ["@typescript-eslint/parser", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:6.21.0"],\ ["eslint", "npm:8.57.0"],\ ["eslint-import-resolver-node", "npm:0.3.9"],\ - ["eslint-import-resolver-typescript", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:3.6.1"],\ - ["eslint-plugin-import", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:2.29.1"],\ + ["eslint-import-resolver-typescript", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:3.6.1"],\ + ["eslint-plugin-import", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:2.29.1"],\ ["eslint-plugin-jsx-a11y", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:6.8.0"],\ ["eslint-plugin-react", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:7.34.0"],\ ["eslint-plugin-react-hooks", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:5.0.0-canary-7118f5dd7-20230705"],\ @@ -10273,6 +10478,30 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:3.6.1", {\ + "packageLocation": "./.yarn/__virtual__/eslint-import-resolver-typescript-virtual-3ee2336688/0/cache/eslint-import-resolver-typescript-npm-3.6.1-994bbf65fc-cb1cb43899.zip/node_modules/eslint-import-resolver-typescript/",\ + "packageDependencies": [\ + ["eslint-import-resolver-typescript", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:3.6.1"],\ + ["@types/eslint", null],\ + ["@types/eslint-plugin-import", null],\ + ["debug", "virtual:52cc1f08fdfa0ce0882bedf10264a24f906e33f7892b3412b78b3e749d6e4b50a5c4d47e46903c21fe956663d3ab6f4d2b4677d28abd53464b00761501f37601#npm:4.3.4"],\ + ["enhanced-resolve", "npm:5.16.0"],\ + ["eslint", "npm:8.57.0"],\ + ["eslint-module-utils", "virtual:3ee233668871e97abf55b7a69893a21f6a8b0cf445880477535ff69bfad30b2bf8e30bdd930f9afc699a64686b8bf94845d6d38ea4ddef7a6535ad51a8fcd593#npm:2.8.1"],\ + ["eslint-plugin-import", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:2.29.1"],\ + ["fast-glob", "npm:3.3.2"],\ + ["get-tsconfig", "npm:4.7.3"],\ + ["is-core-module", "npm:2.13.1"],\ + ["is-glob", "npm:4.0.3"]\ + ],\ + "packagePeers": [\ + "@types/eslint-plugin-import",\ + "@types/eslint",\ + "eslint-plugin-import",\ + "eslint"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:3.6.1", {\ "packageLocation": "./.yarn/__virtual__/eslint-import-resolver-typescript-virtual-73c7971360/0/cache/eslint-import-resolver-typescript-npm-3.6.1-994bbf65fc-cb1cb43899.zip/node_modules/eslint-import-resolver-typescript/",\ "packageDependencies": [\ @@ -10306,6 +10535,66 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["virtual:1299be19c2f00cb22779c555bfbdf007638b200789a4aee25b6a50499a42878490b2bfc681122816d578f2c7ccb50cb799727e290ad864c9ca0c9ca9265eac49#npm:2.8.1", {\ + "packageLocation": "./.yarn/__virtual__/eslint-module-utils-virtual-d7830846ac/0/cache/eslint-module-utils-npm-2.8.1-c9aeb3ec2c-1aeeb97bf4.zip/node_modules/eslint-module-utils/",\ + "packageDependencies": [\ + ["eslint-module-utils", "virtual:1299be19c2f00cb22779c555bfbdf007638b200789a4aee25b6a50499a42878490b2bfc681122816d578f2c7ccb50cb799727e290ad864c9ca0c9ca9265eac49#npm:2.8.1"],\ + ["@types/eslint", null],\ + ["@types/eslint-import-resolver-node", null],\ + ["@types/eslint-import-resolver-typescript", null],\ + ["@types/eslint-import-resolver-webpack", null],\ + ["@types/typescript-eslint__parser", null],\ + ["@typescript-eslint/parser", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:6.21.0"],\ + ["debug", "virtual:2a426afc4b2eef43db12a540d29c2b5476640459bfcd5c24f86bb401cf8cce97e63bd81794d206a5643057e7f662643afd5ce3dfc4d4bfd8e706006c6309c5fa#npm:3.2.7"],\ + ["eslint", "npm:8.57.0"],\ + ["eslint-import-resolver-node", "npm:0.3.9"],\ + ["eslint-import-resolver-typescript", null],\ + ["eslint-import-resolver-webpack", null]\ + ],\ + "packagePeers": [\ + "@types/eslint-import-resolver-node",\ + "@types/eslint-import-resolver-typescript",\ + "@types/eslint-import-resolver-webpack",\ + "@types/eslint",\ + "@types/typescript-eslint__parser",\ + "@typescript-eslint/parser",\ + "eslint-import-resolver-node",\ + "eslint-import-resolver-typescript",\ + "eslint-import-resolver-webpack",\ + "eslint"\ + ],\ + "linkType": "HARD"\ + }],\ + ["virtual:3ee233668871e97abf55b7a69893a21f6a8b0cf445880477535ff69bfad30b2bf8e30bdd930f9afc699a64686b8bf94845d6d38ea4ddef7a6535ad51a8fcd593#npm:2.8.1", {\ + "packageLocation": "./.yarn/__virtual__/eslint-module-utils-virtual-30885aac8b/0/cache/eslint-module-utils-npm-2.8.1-c9aeb3ec2c-1aeeb97bf4.zip/node_modules/eslint-module-utils/",\ + "packageDependencies": [\ + ["eslint-module-utils", "virtual:3ee233668871e97abf55b7a69893a21f6a8b0cf445880477535ff69bfad30b2bf8e30bdd930f9afc699a64686b8bf94845d6d38ea4ddef7a6535ad51a8fcd593#npm:2.8.1"],\ + ["@types/eslint", null],\ + ["@types/eslint-import-resolver-node", null],\ + ["@types/eslint-import-resolver-typescript", null],\ + ["@types/eslint-import-resolver-webpack", null],\ + ["@types/typescript-eslint__parser", null],\ + ["@typescript-eslint/parser", null],\ + ["debug", "virtual:2a426afc4b2eef43db12a540d29c2b5476640459bfcd5c24f86bb401cf8cce97e63bd81794d206a5643057e7f662643afd5ce3dfc4d4bfd8e706006c6309c5fa#npm:3.2.7"],\ + ["eslint", "npm:8.57.0"],\ + ["eslint-import-resolver-node", null],\ + ["eslint-import-resolver-typescript", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:3.6.1"],\ + ["eslint-import-resolver-webpack", null]\ + ],\ + "packagePeers": [\ + "@types/eslint-import-resolver-node",\ + "@types/eslint-import-resolver-typescript",\ + "@types/eslint-import-resolver-webpack",\ + "@types/eslint",\ + "@types/typescript-eslint__parser",\ + "@typescript-eslint/parser",\ + "eslint-import-resolver-node",\ + "eslint-import-resolver-typescript",\ + "eslint-import-resolver-webpack",\ + "eslint"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:73c7971360daa62e2a2e27ecd41dfa00a3a85d149290692e7f6c1cb0745c52000e3c9e1df1aa63e6774da190928a0efd78bd0ea7db4fad30ee0c671886e62d95#npm:2.8.1", {\ "packageLocation": "./.yarn/__virtual__/eslint-module-utils-virtual-d466aeb345/0/cache/eslint-module-utils-npm-2.8.1-c9aeb3ec2c-1aeeb97bf4.zip/node_modules/eslint-module-utils/",\ "packageDependencies": [\ @@ -10345,7 +10634,7 @@ const RAW_RUNTIME_STATE = ["@types/eslint-import-resolver-typescript", null],\ ["@types/eslint-import-resolver-webpack", null],\ ["@types/typescript-eslint__parser", null],\ - ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:6.21.0"],\ + ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ ["debug", "virtual:2a426afc4b2eef43db12a540d29c2b5476640459bfcd5c24f86bb401cf8cce97e63bd81794d206a5643057e7f662643afd5ce3dfc4d4bfd8e706006c6309c5fa#npm:3.2.7"],\ ["eslint", "npm:8.57.0"],\ ["eslint-import-resolver-node", "npm:0.3.9"],\ @@ -10375,13 +10664,47 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:2.29.1", {\ + "packageLocation": "./.yarn/__virtual__/eslint-plugin-import-virtual-1299be19c2/0/cache/eslint-plugin-import-npm-2.29.1-b94305f7dc-5f35dfbf4e.zip/node_modules/eslint-plugin-import/",\ + "packageDependencies": [\ + ["eslint-plugin-import", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:2.29.1"],\ + ["@types/eslint", null],\ + ["@types/typescript-eslint__parser", null],\ + ["@typescript-eslint/parser", "virtual:5c22de88e9b3f6d5ff9cb524d3419e5f8689422b1b5618bbdf844ae02a2c38f696d64058a36607d1388eea20e72dbd969852b10b559f35d5d7ba886ea745abc4#npm:6.21.0"],\ + ["array-includes", "npm:3.1.7"],\ + ["array.prototype.findlastindex", "npm:1.2.4"],\ + ["array.prototype.flat", "npm:1.3.2"],\ + ["array.prototype.flatmap", "npm:1.3.2"],\ + ["debug", "virtual:2a426afc4b2eef43db12a540d29c2b5476640459bfcd5c24f86bb401cf8cce97e63bd81794d206a5643057e7f662643afd5ce3dfc4d4bfd8e706006c6309c5fa#npm:3.2.7"],\ + ["doctrine", "npm:2.1.0"],\ + ["eslint", "npm:8.57.0"],\ + ["eslint-import-resolver-node", "npm:0.3.9"],\ + ["eslint-module-utils", "virtual:1299be19c2f00cb22779c555bfbdf007638b200789a4aee25b6a50499a42878490b2bfc681122816d578f2c7ccb50cb799727e290ad864c9ca0c9ca9265eac49#npm:2.8.1"],\ + ["hasown", "npm:2.0.2"],\ + ["is-core-module", "npm:2.13.1"],\ + ["is-glob", "npm:4.0.3"],\ + ["minimatch", "npm:3.1.2"],\ + ["object.fromentries", "npm:2.0.7"],\ + ["object.groupby", "npm:1.0.2"],\ + ["object.values", "npm:1.1.7"],\ + ["semver", "npm:6.3.1"],\ + ["tsconfig-paths", "npm:3.15.0"]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "@types/typescript-eslint__parser",\ + "@typescript-eslint/parser",\ + "eslint"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:2.29.1", {\ "packageLocation": "./.yarn/__virtual__/eslint-plugin-import-virtual-7e8ce765d0/0/cache/eslint-plugin-import-npm-2.29.1-b94305f7dc-5f35dfbf4e.zip/node_modules/eslint-plugin-import/",\ "packageDependencies": [\ ["eslint-plugin-import", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:2.29.1"],\ ["@types/eslint", null],\ ["@types/typescript-eslint__parser", null],\ - ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:6.21.0"],\ + ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ ["array-includes", "npm:3.1.7"],\ ["array.prototype.findlastindex", "npm:1.2.4"],\ ["array.prototype.flat", "npm:1.3.2"],\ @@ -11044,7 +11367,8 @@ const RAW_RUNTIME_STATE = ["@types/node", "npm:20.11.27"],\ ["@types/react", "npm:18.2.65"],\ ["@types/react-dom", "npm:18.2.22"],\ - ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:6.21.0"],\ + ["@typescript-eslint/eslint-plugin", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ + ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ ["eslint", "npm:8.57.0"],\ ["eslint-config-next", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:14.0.2"],\ ["eslint-import-resolver-typescript", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:3.6.1"],\ @@ -11073,6 +11397,7 @@ const RAW_RUNTIME_STATE = ["swiper", "npm:11.0.7"],\ ["swr", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:2.2.5"],\ ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"],\ + ["typescript-eslint", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ ["webpack", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:5.90.3"],\ ["zustand", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:4.5.2"]\ ],\ @@ -13726,6 +14051,14 @@ const RAW_RUNTIME_STATE = ["brace-expansion", "npm:2.0.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:9.0.5", {\ + "packageLocation": "./.yarn/cache/minimatch-npm-9.0.5-9aa93d97fa-de96cf5e35.zip/node_modules/minimatch/",\ + "packageDependencies": [\ + ["minimatch", "npm:9.0.5"],\ + ["brace-expansion", "npm:2.0.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["minimist", [\ @@ -16261,6 +16594,13 @@ const RAW_RUNTIME_STATE = ["lru-cache", "npm:6.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.6.2", {\ + "packageLocation": "./.yarn/cache/semver-npm-7.6.2-0fec6944bb-97d3441e97.zip/node_modules/semver/",\ + "packageDependencies": [\ + ["semver", "npm:7.6.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["send", [\ @@ -17639,10 +17979,23 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ - ["virtual:91cec3001b898073c23dd87c125639536749704c79541ef0d14a1f1a612a3b8aa88ec9391cd5bbfc506d987d8818034bf8cb8082dc3ebad073a1dcd62162fd04#npm:1.3.0", {\ - "packageLocation": "./.yarn/__virtual__/ts-api-utils-virtual-368e1fa1d4/0/cache/ts-api-utils-npm-1.3.0-33457908f8-f54a0ba9ed.zip/node_modules/ts-api-utils/",\ + ["virtual:771b6bc24730ab0421bf193947d472f40d187d144f370034918af6e92427abf255f59411a17788fa47ed9d81de6242753f38ee2df63c10fd2363a2da0136a850#npm:1.3.0", {\ + "packageLocation": "./.yarn/__virtual__/ts-api-utils-virtual-25a16c1a0e/0/cache/ts-api-utils-npm-1.3.0-33457908f8-f54a0ba9ed.zip/node_modules/ts-api-utils/",\ "packageDependencies": [\ - ["ts-api-utils", "virtual:91cec3001b898073c23dd87c125639536749704c79541ef0d14a1f1a612a3b8aa88ec9391cd5bbfc506d987d8818034bf8cb8082dc3ebad073a1dcd62162fd04#npm:1.3.0"],\ + ["ts-api-utils", "virtual:771b6bc24730ab0421bf193947d472f40d187d144f370034918af6e92427abf255f59411a17788fa47ed9d81de6242753f38ee2df63c10fd2363a2da0136a850#npm:1.3.0"],\ + ["@types/typescript", null],\ + ["typescript", null]\ + ],\ + "packagePeers": [\ + "@types/typescript",\ + "typescript"\ + ],\ + "linkType": "HARD"\ + }],\ + ["virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:1.3.0", {\ + "packageLocation": "./.yarn/__virtual__/ts-api-utils-virtual-c3549691b5/0/cache/ts-api-utils-npm-1.3.0-33457908f8-f54a0ba9ed.zip/node_modules/ts-api-utils/",\ + "packageDependencies": [\ + ["ts-api-utils", "virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:1.3.0"],\ ["@types/typescript", null],\ ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ ],\ @@ -17932,6 +18285,35 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["typescript-eslint", [\ + ["npm:7.15.0", {\ + "packageLocation": "./.yarn/cache/typescript-eslint-npm-7.15.0-80f0945dec-98293831f7.zip/node_modules/typescript-eslint/",\ + "packageDependencies": [\ + ["typescript-eslint", "npm:7.15.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0", {\ + "packageLocation": "./.yarn/__virtual__/typescript-eslint-virtual-c50595ad56/0/cache/typescript-eslint-npm-7.15.0-80f0945dec-98293831f7.zip/node_modules/typescript-eslint/",\ + "packageDependencies": [\ + ["typescript-eslint", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ + ["@types/eslint", null],\ + ["@types/typescript", null],\ + ["@typescript-eslint/eslint-plugin", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ + ["@typescript-eslint/parser", "virtual:67a01b8379dbfa206d4ad50c4ea9820edff287ac6e8e45e1c251d66e9a321bdbb9d5b5cf53117f97ad8d35663c2e78c57d82e9a46aa615d46102bbc530488947#npm:7.15.0"],\ + ["@typescript-eslint/utils", "virtual:b459dd3718d70f592fed8047d38e30ab5428c35517065f4f7fefd6d0f64a24b0d0ad9d0da4ec2662e2c5faa44a123a5b0e5c6dc5142947bb09db9f4ecafd7c91#npm:7.15.0"],\ + ["eslint", "npm:8.57.0"],\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "@types/typescript",\ + "eslint",\ + "typescript"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["ufo", [\ ["npm:1.4.0", {\ "packageLocation": "./.yarn/cache/ufo-npm-1.4.0-ca057b1d71-d9a3cb8c5f.zip/node_modules/ufo/",\ diff --git a/package.json b/package.json index 7f0bb47f..f31535eb 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,8 @@ "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", - "@typescript-eslint/parser": "^6.19.1", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7", "eslint": "^8", "eslint-config-next": "14.0.2", "eslint-import-resolver-typescript": "^3.6.1", @@ -65,14 +66,15 @@ "stylelint-order": "^6.0.4", "supports-color": "^9.4.0", "typescript": "5.3.2", + "typescript-eslint": "^7.15.0", "webpack": "^5.89.0" }, "packageManager": "yarn@4.1.1", "lint-staged": { - "*.{ts,tsx}": [ - "eslint --fix", - "stylelint --fix", - "prettier --write" + "*.{js,jsx,ts,tsx}": [ + "yarn eslint --fix", + "yarn stylelint --fix", + "yarn prettier --write" ] } -} +} \ No newline at end of file diff --git a/src/app/signup-guard.tsx b/src/app/signup-guard.tsx index fa6f93a5..0ff6ce25 100644 --- a/src/app/signup-guard.tsx +++ b/src/app/signup-guard.tsx @@ -37,7 +37,7 @@ export const SignupGuard = () => { const popupComponent = useMemo(() => { switch (step) { case SignUpStep.TERMS_AGREEMENT: - return setNextStep()} />; + return ; case SignUpStep.PROFILE_CREATION: return setNextStep()} />; case SignUpStep.POSITION_SELECTION: diff --git a/src/components/atoms/Icons.tsx b/src/components/atoms/Icons.tsx index a71bde6a..d0e7727f 100644 --- a/src/components/atoms/Icons.tsx +++ b/src/components/atoms/Icons.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import Image from 'next/image'; +import { SVGProps } from 'react'; +import Image, { StaticImageData } from 'next/image'; import { AccountIcon, @@ -95,7 +95,7 @@ export type IconName = | 'velog'; interface Icon { - SVGR: any; + SVGR: React.FC> | StaticImageData; color?: string; style?: React.CSSProperties; } @@ -281,7 +281,7 @@ const icons: Record = { }, }; -interface IconsProps extends React.HTMLAttributes { +interface IconsProps extends SVGProps { icon: IconName; useCSSColor?: boolean; diff --git a/src/components/atoms/Label.tsx b/src/components/atoms/Label.tsx index 13a2c36b..9e11f36e 100644 --- a/src/components/atoms/Label.tsx +++ b/src/components/atoms/Label.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import { HTMLAttributes } from 'react'; import styled from '@emotion/styled'; @@ -18,7 +18,7 @@ const LabelText = styled(Txt)` white-space: nowrap; `; -interface LabelProps extends React.HTMLAttributes { +interface LabelProps extends HTMLAttributes { text: string; position?: 'top' | 'left'; gap?: React.CSSProperties['gap']; diff --git a/src/components/atoms/Loading.tsx b/src/components/atoms/Loading.tsx index d0762472..62b9e127 100644 --- a/src/components/atoms/Loading.tsx +++ b/src/components/atoms/Loading.tsx @@ -4,7 +4,7 @@ import styled from '@emotion/styled'; import { FitLogo } from '.'; -export const Loading = forwardRef(({}, ref) => { +export const Loading = forwardRef((_, ref) => { return ( diff --git a/src/components/atoms/MouseDetector.tsx b/src/components/atoms/MouseDetector.tsx index c38e0d59..405ad0f6 100644 --- a/src/components/atoms/MouseDetector.tsx +++ b/src/components/atoms/MouseDetector.tsx @@ -1,4 +1,4 @@ -import { MouseEventHandler, useEffect, useRef } from 'react'; +import { useEffect, useRef } from 'react'; interface MouseDetectorProps extends React.HTMLAttributes { onClickOutside?: () => void; diff --git a/src/components/atoms/MyPage/PortfolioTicket.tsx b/src/components/atoms/MyPage/PortfolioTicket.tsx index ab8b5b48..b80eb292 100644 --- a/src/components/atoms/MyPage/PortfolioTicket.tsx +++ b/src/components/atoms/MyPage/PortfolioTicket.tsx @@ -3,7 +3,6 @@ import { useCallback } from 'react'; import styled from '@emotion/styled'; import { useTempAuthStore } from '#/stores/tempAuth'; -import { User } from '#/types'; import { IconName, Icons } from '#atoms/Icons'; import { Txt } from '#atoms/Text'; diff --git a/src/components/atoms/SocialLoginButton.tsx b/src/components/atoms/SocialLoginButton.tsx index a2d22d73..9b04117b 100644 --- a/src/components/atoms/SocialLoginButton.tsx +++ b/src/components/atoms/SocialLoginButton.tsx @@ -1,6 +1,5 @@ 'use client'; -import { useEffect, useState } from 'react'; import Link from 'next/link'; import { css } from '@emotion/react'; diff --git a/src/components/atoms/Text.tsx b/src/components/atoms/Text.tsx index e92d20f7..5aaf5c9a 100644 --- a/src/components/atoms/Text.tsx +++ b/src/components/atoms/Text.tsx @@ -1,4 +1,4 @@ -import { CSSProperties, HTMLAttributes } from 'react'; +import { CSSProperties } from 'react'; import { css } from '@emotion/react'; import styled from '@emotion/styled'; diff --git a/src/components/molecules/ChatToolbox.tsx b/src/components/molecules/ChatToolbox.tsx index 17f3b28d..ce704068 100644 --- a/src/components/molecules/ChatToolbox.tsx +++ b/src/components/molecules/ChatToolbox.tsx @@ -63,7 +63,8 @@ export const ChatToolbox = ({ projectId, matchingId }: ChatToolboxProps) => { ))} { + onSubmit={(e) => { + e.preventDefault(); if (imageUrls.length > 0) { imageUrls.map((url) => emitImage(url)); setImageUrls([]); diff --git a/src/components/molecules/MyPage/TechSelectBlock.tsx b/src/components/molecules/MyPage/TechSelectBlock.tsx index 3fc21b66..b35c7ff0 100644 --- a/src/components/molecules/MyPage/TechSelectBlock.tsx +++ b/src/components/molecules/MyPage/TechSelectBlock.tsx @@ -3,7 +3,6 @@ import { useCallback, useEffect, useState } from 'react'; import styled from '@emotion/styled'; import { usePositionsQuery } from '#/hooks/use-positions'; -import { useTempAuthStore } from '#/stores/tempAuth'; import { Position, Skill } from '#/types'; import { Txt } from '#atoms/Text'; import { PositionBadge } from './PositionBadge'; diff --git a/src/components/molecules/PositionCard.tsx b/src/components/molecules/PositionCard.tsx index 9f18a8cf..582fb64e 100644 --- a/src/components/molecules/PositionCard.tsx +++ b/src/components/molecules/PositionCard.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import { HTMLAttributes } from 'react'; import Image from 'next/image'; import styled from '@emotion/styled'; @@ -6,7 +6,7 @@ import styled from '@emotion/styled'; import { Txt } from '#/components/atoms'; import { media } from '#/utilities'; -interface PositionCardProps extends React.HTMLAttributes { +interface PositionCardProps extends HTMLAttributes { name: string; imageUrl: string; selected: boolean; diff --git a/src/components/molecules/TeamRecommend/TechSelect.tsx b/src/components/molecules/TeamRecommend/TechSelect.tsx index e0e88b11..4fedd211 100644 --- a/src/components/molecules/TeamRecommend/TechSelect.tsx +++ b/src/components/molecules/TeamRecommend/TechSelect.tsx @@ -1,4 +1,4 @@ -import { Dispatch, SetStateAction, useCallback, useState } from 'react'; +import { Dispatch, SetStateAction, useState } from 'react'; import styled from '@emotion/styled'; diff --git a/src/components/organisms/MatchingInfo/MatchingSequenceSwiper.tsx b/src/components/organisms/MatchingInfo/MatchingSequenceSwiper.tsx index 54cb9b74..a92f4158 100644 --- a/src/components/organisms/MatchingInfo/MatchingSequenceSwiper.tsx +++ b/src/components/organisms/MatchingInfo/MatchingSequenceSwiper.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import styled from '@emotion/styled'; diff --git a/src/components/organisms/MatchingRegister.tsx b/src/components/organisms/MatchingRegister.tsx index cb49e83a..1457749e 100644 --- a/src/components/organisms/MatchingRegister.tsx +++ b/src/components/organisms/MatchingRegister.tsx @@ -2,8 +2,6 @@ import styled from '@emotion/styled'; -import _ from 'lodash'; - import { MatchingButtons } from '#/components/molecules/MatchingButtons'; import { useMeQuery } from '#/hooks/use-user'; import { UserDetails } from './UserDetails'; diff --git a/src/components/organisms/MyPage/ActivityEdit.tsx b/src/components/organisms/MyPage/ActivityEdit.tsx index 23b2f8bc..1494125a 100644 --- a/src/components/organisms/MyPage/ActivityEdit.tsx +++ b/src/components/organisms/MyPage/ActivityEdit.tsx @@ -1,4 +1,4 @@ -import { useCallback, useState } from 'react'; +import { useCallback } from 'react'; import styled from '@emotion/styled'; @@ -41,7 +41,7 @@ export const ActivityEdit = () => { ); const handleUpdateTempUser = useCallback( - (key: string, value: any) => { + (key: string, value: unknown) => { if (tempUser !== null) setTempUser({ ...tempUser, [key]: value }); }, [tempUser, setTempUser] diff --git a/src/components/organisms/MyPage/MemberInfoEdit.tsx b/src/components/organisms/MyPage/MemberInfoEdit.tsx index 64794f05..4bb77191 100644 --- a/src/components/organisms/MyPage/MemberInfoEdit.tsx +++ b/src/components/organisms/MyPage/MemberInfoEdit.tsx @@ -72,8 +72,8 @@ export const MemberInfoEdit = () => { const setTempUser = useTempAuthStore((state) => state.setTempUser); const handleUpdateTempUser = useCallback( - (key: string, value: any, maxLength?: number) => { - if (maxLength && value.length > maxLength) { + (key: string, value: string | boolean, maxLength?: number) => { + if (maxLength && (value as string).length > maxLength) { alert('최대 글자수를 초과하였습니다.'); return; } diff --git a/src/components/organisms/MyPage/PortfolioInformation.tsx b/src/components/organisms/MyPage/PortfolioInformation.tsx index 9808039d..db93b2f2 100644 --- a/src/components/organisms/MyPage/PortfolioInformation.tsx +++ b/src/components/organisms/MyPage/PortfolioInformation.tsx @@ -35,23 +35,6 @@ const PortfolioContent = styled.div` display: flex; gap: 18px; `; -const ClipBlock = styled.div` - display: flex; - flex-direction: column; - gap: 12px; - align-items: center; - justify-content: center; - - width: 92px; - height: 98px; - padding: 0 10px; - - text-align: center; - word-break: keep-all; - - border: 1px solid #e0e0e0; - border-radius: 5px; -`; const PortfolioList = styled.div` display: flex; flex-direction: column; diff --git a/src/components/organisms/ProjectChatRoom.tsx b/src/components/organisms/ProjectChatRoom.tsx index caba40e6..4ac3b663 100644 --- a/src/components/organisms/ProjectChatRoom.tsx +++ b/src/components/organisms/ProjectChatRoom.tsx @@ -1,5 +1,3 @@ -import { useState } from 'react'; - import styled from '@emotion/styled'; import { Icons } from '#/components/atoms'; diff --git a/src/components/organisms/SignUpTermsPopup.tsx b/src/components/organisms/SignUpTermsPopup.tsx index 3527c08c..9861b7d6 100644 --- a/src/components/organisms/SignUpTermsPopup.tsx +++ b/src/components/organisms/SignUpTermsPopup.tsx @@ -11,11 +11,7 @@ import { policies } from '#/entities'; import { usePolicyAgreesMutation, usePolicyAgreesQuery } from '#/hooks/use-policy-agrees'; import { PolicyAgreement, PolicyType } from '#/types'; -interface SignUpTermsPopupProps { - onSuccess: () => void; -} - -export const SignUpTermsPopup: React.FC = ({ onSuccess }) => { +export const SignUpTermsPopup = () => { const [policyAgrees, setPolicyAgrees] = useState>( Object.values(policies).reduce( (acc, { type }) => ({ ...acc, [type]: { type, version: '', isAgreed: false } }), diff --git a/src/components/organisms/TeamRecommend/RecommendFilterBlock.tsx b/src/components/organisms/TeamRecommend/RecommendFilterBlock.tsx index 340c8330..84a51ec8 100644 --- a/src/components/organisms/TeamRecommend/RecommendFilterBlock.tsx +++ b/src/components/organisms/TeamRecommend/RecommendFilterBlock.tsx @@ -1,4 +1,4 @@ -import { Dispatch, SetStateAction, useCallback, useState } from 'react'; +import { Dispatch, SetStateAction, useCallback } from 'react'; import { css } from '@emotion/react'; import styled from '@emotion/styled'; @@ -37,6 +37,8 @@ const DibsFilter = styled.div` border-bottom: 2px solid #eee; `; const DibsBlock = styled(Txt)<{ selected: boolean }>` + cursor: pointer; + position: relative; bottom: -2px; @@ -46,7 +48,6 @@ const DibsBlock = styled(Txt)<{ selected: boolean }>` border-bottom: 2px solid transparent; - cursor: pointer; ${({ selected }) => selected && css` diff --git a/src/components/organisms/sign-up/ProfileDetailsSubmission.tsx b/src/components/organisms/sign-up/ProfileDetailsSubmission.tsx index 8ca8fc6e..65d7a0ed 100644 --- a/src/components/organisms/sign-up/ProfileDetailsSubmission.tsx +++ b/src/components/organisms/sign-up/ProfileDetailsSubmission.tsx @@ -3,7 +3,7 @@ import styled from '@emotion/styled'; import { Input, Label, Txt } from '#/components/atoms'; import { CareerSelect } from '#/components/molecules/CareerSelect'; import { Me, UserBackgroundStatus } from '#/types'; -import { isUserStudent, isUserWorker, media } from '#/utilities'; +import { isUserStudent, isUserWorker } from '#/utilities'; const Container = styled.div` display: flex; diff --git a/src/entities/policy.ts b/src/entities/policy.ts index 11009a5b..a352936a 100644 --- a/src/entities/policy.ts +++ b/src/entities/policy.ts @@ -175,7 +175,7 @@ export const policies: Record = { }, { article: '4. 처리하는 개인정보의 항목 작성', - clause: `‘핏’은 다음의 개인정보 항목을 처리하고 있습니다.\n\n<‘핏’에서 수집하는 개인정보 항목>\n'핏’ 회원 가입 및 고객 문의 시, 제공 동의를 해주시는 개인정보 수집 항목입니다. \n\n ㅁ 서비스 사용 시(회원)\n • 필수항목 : 이름, 닉네임, 이메일, 학력/경력, 프로젝트 관련 개인 정보\n • 선택항목 : 전화번호, 포트폴리오\n • 수집목적 : 핏 서비스 사용, 회원관리 및 마케팅 이용\n • 보유기간 : 회원 탈퇴 또는 동의 철회 시 지체없이 파기\n\n ㅁ 고객 문의 시(비회원)\n • 필수항목 : 문의종류, 이름, 휴대폰번호, 이메일, 문의사항\n • 수집목적 : 고객문의 및 상담요청에 대한 회신, 상담을 위한 서비스 이용기록 조회\n • 보유기간 : 문의 접수 후 2년 간 보관 (단, 관계 법령이 정한 시점까지 보존)\n\n<카카오 개인정보 제3자 제공 동의>\n아래는 ‘핏’ 회원 가입 시(카카오 계정을 통한 간편 가입시) 제공 동의를 해주시는 자동 수집 항목입니다.\n • 필수항목 : 프로필 정보(닉네임/프로필 사진)\n • 수집목적 : 핏 서비스 사용, 회원관리 및 마케팅 이용\n • 보유기간 : 회원 탈퇴, 카카오 탈퇴 또는 동의 철회 시 지체없이 파기\n\n<구글 개인정보 제3자 제공 동의>\n아래는 ‘핏’ 회원 가입 시(구글 계정을 통한 간편 가입시) 제공 동의를 해주시는 자동 수집 항목입니다.\n • 필수항목 : 구글 이메일, 구글에 등록된 개인정보(공개로 설정한 개인정보 포함)\n • 수집목적 : 핏\n서비스 사용, 회원관리 및 마케팅 이용\n • 보유기간 : 회원 탈퇴, 구글 탈퇴 또는 동의 철회 시 지체없이 파기\n\n‘핏’은 만 14세 미만 아동의 개인정보를 보호하기 위하여 회원가입은 만14세 이상만 가능하도록 함으로써 아동의 개인정보를 수집하지 않습니다.`, + clause: `‘핏’은 다음의 개인정보 항목을 처리하고 있습니다.\n\n<‘핏’에서 수집하는 개인정보 항목>\n'핏’ 회원 가입 및 고객 문의 시, 제공 동의를 해주시는 개인정보 수집 항목입니다. \n\n ㅁ 서비스 사용 시(회원)\n • 필수항목 : 이름, 닉네임, 이메일, 학력/경력, 프로젝트 관련 개인 정보\n • 선택항목 : 전화번호, 포트폴리오\n • 수집목적 : 핏 서비스 사용, 회원관리 및 마케팅 이용\n • 보유기간 : 회원 탈퇴 또는 동의 철회 시 지체없이 파기\n\n ㅁ 고객 문의 시(비회원)\n • 필수항목 : 문의종류, 이름, 휴대폰번호, 이메일, 문의사항\n • 수집목적 : 고객문의 및 상담요청에 대한 회신, 상담을 위한 서비스 이용기록 조회\n • 보유기간 : 문의 접수 후 2년 간 보관 (단, 관계 법령이 정한 시점까지 보존)\n\n<카카오 개인정보 제3자 제공 동의>\n아래는 ‘핏’ 회원 가입 시(카카오 계정을 통한 간편 가입시) 제공 동의를 해주시는 자동 수집 항목입니다.\n • 필수항목 : 프로필 정보(닉네임/프로필 사진)\n • 수집목적 : 핏 서비스 사용, 회원관리 및 마케팅 이용\n • 보유기간 : 회원 탈퇴, 카카오 탈퇴 또는 동의 철회 시 지체없이 파기\n\n<구글 개인정보 제3자 제공 동의>\n아래는 ‘핏’ 회원 가입 시(구글 계정을 통한 간편 가입시) 제공 동의를 해주시는 자동 수집 항목입니다.\n • 필수항목 : 구글 이메일, 구글에 등록된 개인정보(공개로 설정한 개인정보 포함)\n • 수집목적 : 핏\n서비스 사용, 회원관리 및 마케팅 이용\n • 보유기간 : 회원 탈퇴, 구글 탈퇴 또는 동의 철회 시 지체없이 파기\n\n'핏’은 만 14세 미만 아동의 개인정보를 보호하기 위하여 회원가입은 만14세 이상만 가능하도록 함으로써 아동의 개인정보를 수집하지 않습니다.`, }, { article: '5. 개인정보의 파기', diff --git a/src/hooks/use-matching.ts b/src/hooks/use-matching.ts index aff83b32..91640bd5 100644 --- a/src/hooks/use-matching.ts +++ b/src/hooks/use-matching.ts @@ -1,3 +1,4 @@ +import _ from 'lodash'; import useSWR from 'swr'; import useSWRMutation from 'swr/mutation'; @@ -32,7 +33,11 @@ export function useMatchingQuery() { createdAt: json.createdAt, } as Matching; } catch (error) { - if (ApiError.isApiError(error) && error.code === ApiError.MATCHING_NOT_FOUND_CODE) { + if ( + _.isObject(error) && + ApiError.isApiError(error) && + error.code === ApiError.MATCHING_NOT_FOUND_CODE + ) { return { id: null, status: MatchingStatus.REGISTER }; } throw error; diff --git a/src/hooks/use-presigned-url.ts b/src/hooks/use-presigned-url.ts index 6736c8b4..a88dccdc 100644 --- a/src/hooks/use-presigned-url.ts +++ b/src/hooks/use-presigned-url.ts @@ -1,6 +1,6 @@ import useSWRMutation from 'swr/mutation'; -import type { PresignedUrl, FileDomain } from '#/types'; +import type { PresignedUrl } from '#/types'; import { fitFetcher } from '#/utilities'; const PRESIGNED_URL_QUERY_KEY = '/v1/file/pre-signed-url'; diff --git a/src/types/api-error.ts b/src/types/api-error.ts index 1fba7e09..9cad2bc8 100644 --- a/src/types/api-error.ts +++ b/src/types/api-error.ts @@ -12,10 +12,15 @@ export class ApiError { this.message = message; } - static isApiError(error: any): error is ApiError { + static isApiError(error: object): error is ApiError { if (!error) { return false; } - return typeof error.code === 'string' && typeof error.message === 'string'; + return ( + 'code' in error && + typeof error.code === 'string' && + 'message' in error && + typeof error.message === 'string' + ); } } diff --git a/src/types/matching.ts b/src/types/matching.ts index cb346765..bb3eba37 100644 --- a/src/types/matching.ts +++ b/src/types/matching.ts @@ -23,7 +23,7 @@ export interface Matching { } export interface MatchingRoom { - id: number; + id: NonNullable; hostId: User['id']; chatId: number; diff --git a/src/utilities/index.ts b/src/utilities/index.ts index a83ea969..8d758563 100644 --- a/src/utilities/index.ts +++ b/src/utilities/index.ts @@ -1,7 +1,13 @@ -export { checkSignUpStep } from './check-sign-up-step'; -export { fitFetch, fitFetcher } from './fetch'; -export { isTextMessage, isImageMessage, isNoticeMessage } from './message'; -export { getTokens, setTokens } from './session'; -export { getStorageUrl } from './storage'; +export * from './alarm-replace-text'; +export * from './check-sign-up-step'; +export * from './fetch'; +export * from './icon'; +export * from './matching'; +export * from './message'; +export * from './policy'; +export * from './session'; +export * from './socket'; +export * from './storage'; export * from './styles'; -export { isBackgroundStatus, isUserStudent, isUserWorker, getBackgroundStatusText } from './user'; +export * from './transient-styled'; +export * from './user'; diff --git a/src/utilities/matching.ts b/src/utilities/matching.ts index d5bd5330..c0bfa321 100644 --- a/src/utilities/matching.ts +++ b/src/utilities/matching.ts @@ -1,12 +1,21 @@ +import _ from 'lodash'; + import { Matching } from '#/types'; -export function isMatching(object: any): object is Matching { +export function isMatching(object: object | null | undefined): object is Matching { return ( + !_.isNil(object) && + 'id' in object && (typeof object.id === 'number' || object.id === null) && + 'userId' in object && typeof object.userId === 'number' && + 'positionId' in object && typeof object.positionId === 'number' && + 'status' in object && typeof object.status === 'string' && + 'expiredAt' in object && typeof object.expiredAt === 'string' && + 'createdAt' in object && typeof object.createdAt === 'string' ); } diff --git a/src/utilities/socket.ts b/src/utilities/socket.ts index fa2b5a40..e41984b6 100644 --- a/src/utilities/socket.ts +++ b/src/utilities/socket.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error import io from 'socket.io-client'; diff --git a/svgr.d.ts b/svgr.d.ts new file mode 100644 index 00000000..f54954ce --- /dev/null +++ b/svgr.d.ts @@ -0,0 +1,10 @@ +declare module '*.svg' { + import { FC, SVGProps } from 'react'; + const content: FC>; + export default content; +} + +declare module '*.svg?url' { + const content: unknown; + export default content; +} diff --git a/tsconfig.json b/tsconfig.json index fde77d15..bd4e1640 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,11 @@ "compilerOptions": { "baseUrl": ".", "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -20,15 +24,37 @@ } ], "paths": { - "#/*": ["./src/*"], - "#app/*": ["./src/app/*"], - "#atoms/*": ["./src/components/atoms/*"], - "#molecules/*": ["./src/components/molecules/*"], - "#organisms/*": ["./src/components/organisms/*"], - "#templates/*": ["./src/components/templates/*"], - "#utilities/*": ["./src/utilities/*"] + "#/*": [ + "./src/*" + ], + "#app/*": [ + "./src/app/*" + ], + "#atoms/*": [ + "./src/components/atoms/*" + ], + "#molecules/*": [ + "./src/components/molecules/*" + ], + "#organisms/*": [ + "./src/components/organisms/*" + ], + "#templates/*": [ + "./src/components/templates/*" + ], + "#utilities/*": [ + "./src/utilities/*" + ] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] -} + "include": [ + "svgr.d.ts", + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 776e913e..69b4ed44 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2081,7 +2081,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.2.0": +"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" dependencies: @@ -2092,6 +2092,13 @@ __metadata: languageName: node linkType: hard +"@eslint-community/regexpp@npm:^4.10.0": + version: 4.11.0 + resolution: "@eslint-community/regexpp@npm:4.11.0" + checksum: 10c0/0f6328869b2741e2794da4ad80beac55cba7de2d3b44f796a60955b0586212ec75e6b0253291fd4aad2100ad471d1480d8895f2b54f1605439ba4c875e05e523 + languageName: node + linkType: hard + "@eslint-community/regexpp@npm:^4.6.1": version: 4.10.0 resolution: "@eslint-community/regexpp@npm:4.10.0" @@ -4191,7 +4198,48 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/parser@npm:^5.4.2 || ^6.0.0, @typescript-eslint/parser@npm:^6.19.1": +"@typescript-eslint/eslint-plugin@npm:7.15.0, @typescript-eslint/eslint-plugin@npm:^7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/eslint-plugin@npm:7.15.0" + dependencies: + "@eslint-community/regexpp": "npm:^4.10.0" + "@typescript-eslint/scope-manager": "npm:7.15.0" + "@typescript-eslint/type-utils": "npm:7.15.0" + "@typescript-eslint/utils": "npm:7.15.0" + "@typescript-eslint/visitor-keys": "npm:7.15.0" + graphemer: "npm:^1.4.0" + ignore: "npm:^5.3.1" + natural-compare: "npm:^1.4.0" + ts-api-utils: "npm:^1.3.0" + peerDependencies: + "@typescript-eslint/parser": ^7.0.0 + eslint: ^8.56.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/7ed4ef8355cb60f02ed603673ef749928a001931c534960d1f3f9f9b8092f4abd7ec1e80a33b4c38efb6e8e66c902583bd56a4c4d6ccbd870677a40680a7d1f5 + languageName: node + linkType: hard + +"@typescript-eslint/parser@npm:7.15.0, @typescript-eslint/parser@npm:^7": + version: 7.15.0 + resolution: "@typescript-eslint/parser@npm:7.15.0" + dependencies: + "@typescript-eslint/scope-manager": "npm:7.15.0" + "@typescript-eslint/types": "npm:7.15.0" + "@typescript-eslint/typescript-estree": "npm:7.15.0" + "@typescript-eslint/visitor-keys": "npm:7.15.0" + debug: "npm:^4.3.4" + peerDependencies: + eslint: ^8.56.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/8dcad9b84e2cbf89afea97ee7f690f91b487eed21d01997126f98cb7dd56d3b6c98c7ecbdbeda35904af521c4ed746c47887e908f8a1e2148d47c05b491d7b9d + languageName: node + linkType: hard + +"@typescript-eslint/parser@npm:^5.4.2 || ^6.0.0": version: 6.21.0 resolution: "@typescript-eslint/parser@npm:6.21.0" dependencies: @@ -4229,6 +4277,33 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/scope-manager@npm:7.15.0" + dependencies: + "@typescript-eslint/types": "npm:7.15.0" + "@typescript-eslint/visitor-keys": "npm:7.15.0" + checksum: 10c0/781ec31a07ab7f0bdfb07dd271ef6553aa98f8492f1b3a67c65d178c94d590f4fd2e0916450f2446f1da2fbe007f3454c360ccb25f4d69612f782eb499f400ab + languageName: node + linkType: hard + +"@typescript-eslint/type-utils@npm:7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/type-utils@npm:7.15.0" + dependencies: + "@typescript-eslint/typescript-estree": "npm:7.15.0" + "@typescript-eslint/utils": "npm:7.15.0" + debug: "npm:^4.3.4" + ts-api-utils: "npm:^1.3.0" + peerDependencies: + eslint: ^8.56.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/06189eb05d741f05977bbc029c6ac46edd566e0136f2f2c22429fd5f2be1224e2d9135b7021bc686871bfaec9c05a5c9990a321762d3abd06e457486956326ba + languageName: node + linkType: hard + "@typescript-eslint/types@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/types@npm:5.62.0" @@ -4243,6 +4318,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/types@npm:7.15.0" + checksum: 10c0/935387b21d9fdff65de86f6350cdda1f0614e269324f3a4f0a2ca1b0d72ef4b1d40c7de2f3a20a6f8c83edca6507bfbac3168c860625859e59fc455c80392bed + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/typescript-estree@npm:5.62.0" @@ -4280,6 +4362,39 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.15.0" + dependencies: + "@typescript-eslint/types": "npm:7.15.0" + "@typescript-eslint/visitor-keys": "npm:7.15.0" + debug: "npm:^4.3.4" + globby: "npm:^11.1.0" + is-glob: "npm:^4.0.3" + minimatch: "npm:^9.0.4" + semver: "npm:^7.6.0" + ts-api-utils: "npm:^1.3.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/0d6e61cb36c4612147ceea796c2bdbb65fca59170d9d768cff314146c5564253a058cbcb9e251722cd76c92a90c257e1210a69f8d4377c8002f211c574d18d24 + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/utils@npm:7.15.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.4.0" + "@typescript-eslint/scope-manager": "npm:7.15.0" + "@typescript-eslint/types": "npm:7.15.0" + "@typescript-eslint/typescript-estree": "npm:7.15.0" + peerDependencies: + eslint: ^8.56.0 + checksum: 10c0/26aced17976cee0aa39a79201f68b384bbce1dc96e1c70d0e5f790e1e5655b1b1ddb2afd9eaf3fce9a48c0fb69daecd37a99fdbcdbf1cb58c65ae89ecac88a2c + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:^5.45.0": version: 5.62.0 resolution: "@typescript-eslint/utils@npm:5.62.0" @@ -4318,6 +4433,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/visitor-keys@npm:7.15.0" + dependencies: + "@typescript-eslint/types": "npm:7.15.0" + eslint-visitor-keys: "npm:^3.4.3" + checksum: 10c0/7509f01c8cd2126a38213bc735a77aa7e976340af0d664be5b2ccd01b8211724b2ea129e33bfd32fe5feac848b7b68ca55bb533f6ccfeec1d2f26a91240489b9 + languageName: node + linkType: hard + "@ungap/structured-clone@npm:^1.0.0, @ungap/structured-clone@npm:^1.2.0": version: 1.2.0 resolution: "@ungap/structured-clone@npm:1.2.0" @@ -8096,7 +8221,8 @@ __metadata: "@types/node": "npm:^20" "@types/react": "npm:^18" "@types/react-dom": "npm:^18" - "@typescript-eslint/parser": "npm:^6.19.1" + "@typescript-eslint/eslint-plugin": "npm:^7.15.0" + "@typescript-eslint/parser": "npm:^7" eslint: "npm:^8" eslint-config-next: "npm:14.0.2" eslint-import-resolver-typescript: "npm:^3.6.1" @@ -8125,6 +8251,7 @@ __metadata: swiper: "npm:^11.0.5" swr: "npm:^2.2.5" typescript: "npm:5.3.2" + typescript-eslint: "npm:^7.15.0" webpack: "npm:^5.89.0" zustand: "npm:^4.5.2" languageName: unknown @@ -8987,7 +9114,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.2.0, ignore@npm:^5.3.0": +"ignore@npm:^5.2.0, ignore@npm:^5.3.0, ignore@npm:^5.3.1": version: 5.3.1 resolution: "ignore@npm:5.3.1" checksum: 10c0/703f7f45ffb2a27fb2c5a8db0c32e7dee66b33a225d28e8db4e1be6474795f606686a6e3bcc50e1aa12f2042db4c9d4a7d60af3250511de74620fbed052ea4cd @@ -10428,6 +10555,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^9.0.4": + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed + languageName: node + linkType: hard + "minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6": version: 1.2.8 resolution: "minimist@npm:1.2.8" @@ -12567,6 +12703,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.6.0": + version: 7.6.2 + resolution: "semver@npm:7.6.2" + bin: + semver: bin/semver.js + checksum: 10c0/97d3441e97ace8be4b1976433d1c32658f6afaff09f143e52c593bae7eef33de19e3e369c88bd985ce1042c6f441c80c6803078d1de2a9988080b66684cbb30c + languageName: node + linkType: hard + "send@npm:0.18.0": version: 0.18.0 resolution: "send@npm:0.18.0" @@ -13711,7 +13856,7 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^1.0.1": +"ts-api-utils@npm:^1.0.1, ts-api-utils@npm:^1.3.0": version: 1.3.0 resolution: "ts-api-utils@npm:1.3.0" peerDependencies: @@ -13939,6 +14084,22 @@ __metadata: languageName: node linkType: hard +"typescript-eslint@npm:^7.15.0": + version: 7.15.0 + resolution: "typescript-eslint@npm:7.15.0" + dependencies: + "@typescript-eslint/eslint-plugin": "npm:7.15.0" + "@typescript-eslint/parser": "npm:7.15.0" + "@typescript-eslint/utils": "npm:7.15.0" + peerDependencies: + eslint: ^8.56.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/98293831f7557831b80143b0e717d2a61dca289d637ef464da524880fab2ea62fb61dd952707c571719914c1565942504db2b4ccfe7178a48971e69f270c1abc + languageName: node + linkType: hard + "typescript@npm:5.3.2": version: 5.3.2 resolution: "typescript@npm:5.3.2" From ad467b97605319d7c71751963c032fa4219c5d9a Mon Sep 17 00:00:00 2001 From: Seheon Yu Date: Tue, 2 Jul 2024 21:30:40 +0900 Subject: [PATCH 3/7] fix: Update message types to use 'type' instead of 'messageType' --- src/types/message.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/types/message.ts b/src/types/message.ts index 418b352f..b4f814fc 100644 --- a/src/types/message.ts +++ b/src/types/message.ts @@ -2,15 +2,7 @@ import { User } from '.'; export interface Message { id: number; - messageType: - | 'TEXT' - | 'IMAGE' - | 'NOTICE' - | 'JOIN' - | 'EXIT' - | 'COMPLETE' - | 'READY' - | 'CANCEL_READY'; + type: 'TEXT' | 'IMAGE' | 'NOTICE' | 'JOIN' | 'EXIT' | 'COMPLETE' | 'READY' | 'CANCEL_READY'; createdAt: string; userId?: User['id']; content?: string; @@ -33,7 +25,7 @@ export interface ImageMessage extends Message { } export interface NoticeMessage extends Message { - messageType: 'NOTICE' | 'JOIN' | 'EXIT' | 'COMPLETE' | 'READY' | 'CANCEL_READY'; + type: 'NOTICE' | 'JOIN' | 'EXIT' | 'COMPLETE' | 'READY' | 'CANCEL_READY'; content: undefined; imageUrl: undefined; notice: string; From a2f819c88f634f68ecfa0fe9ce020543eb934438 Mon Sep 17 00:00:00 2001 From: Seheon Yu Date: Tue, 2 Jul 2024 21:50:57 +0900 Subject: [PATCH 4/7] refactor: Add ControlMessage type and Add notice/control message handler hooks --- src/components/molecules/ChatBubbles.tsx | 37 ++++++----------------- src/components/molecules/NoticeBubble.tsx | 2 +- src/hooks/use-control-message-handler.ts | 26 ++++++++++++++++ src/hooks/use-notice-message-handler.ts | 26 ++++++++++++++++ src/hooks/use-projects.ts | 2 +- src/types/message.ts | 11 +++++-- src/utilities/message.ts | 10 ++++-- 7 files changed, 81 insertions(+), 33 deletions(-) create mode 100644 src/hooks/use-control-message-handler.ts create mode 100644 src/hooks/use-notice-message-handler.ts diff --git a/src/components/molecules/ChatBubbles.tsx b/src/components/molecules/ChatBubbles.tsx index ce47a990..4da4a28e 100644 --- a/src/components/molecules/ChatBubbles.tsx +++ b/src/components/molecules/ChatBubbles.tsx @@ -1,5 +1,4 @@ import { useEffect, useRef } from 'react'; -import { useRouter } from 'next/navigation'; import styled from '@emotion/styled'; @@ -11,12 +10,11 @@ import { useChatMessagesQuery, useChatSubscription, useMeQuery, - useMatchingRoomQuery, - useProjectsQuery, - useMatchingQuery, } from '#/hooks'; +import { useControlMessageHandler } from '#/hooks/use-control-message-handler'; +import { useNoticeMessageHandler } from '#/hooks/use-notice-message-handler'; import { MatchingRoom, Project } from '#/types'; -import { isImageMessage, isNoticeMessage, isTextMessage } from '#/utilities'; +import { isControlMessage, isImageMessage, isNoticeMessage, isTextMessage } from '#/utilities'; import { ChatBubble } from './ChatBubble'; import { NoticeBubble } from './NoticeBubble'; @@ -26,12 +24,10 @@ interface ChatBubblesProps { } export const ChatBubbles = ({ projectId, matchingId }: ChatBubblesProps) => { - const router = useRouter(); const topRef = useRef(null); - const { mutate: mutateCachedMatching } = useMatchingQuery(); - const { mutate: mutateCachedRoom } = useMatchingRoomQuery(matchingId); - const { mutate: mutateCachedProjects } = useProjectsQuery(); + const noticeMessageHandler = useNoticeMessageHandler(matchingId); + const controlMessageHandler = useControlMessageHandler({ projectId, matchingId }); const participants = useChatUsers({ projectId, matchingId }); const chatId = useChatId({ projectId, matchingId }); @@ -43,27 +39,14 @@ export const ChatBubbles = ({ projectId, matchingId }: ChatBubblesProps) => { useEffect(() => { if (recentMessage) { if (isNoticeMessage(recentMessage)) { - mutateCachedRoom(); - if (recentMessage.type === 'COMPLETE' && matchingId) { - mutateCachedMatching(); - router.replace(`/projects/${recentMessage.notice}`); - } - if (recentMessage.type === 'COMPLETE' && projectId) { - mutateCachedProjects(); - } + noticeMessageHandler(recentMessage); + } + if (isControlMessage(recentMessage)) { + controlMessageHandler(recentMessage); } appendMessage(recentMessage); } - }, [ - appendMessage, - matchingId, - mutateCachedMatching, - mutateCachedProjects, - mutateCachedRoom, - projectId, - recentMessage, - router, - ]); + }, [appendMessage, controlMessageHandler, noticeMessageHandler, recentMessage]); useEffect(() => { const observer = new IntersectionObserver((entries) => { diff --git a/src/components/molecules/NoticeBubble.tsx b/src/components/molecules/NoticeBubble.tsx index 7f2dc820..d4f5cffc 100644 --- a/src/components/molecules/NoticeBubble.tsx +++ b/src/components/molecules/NoticeBubble.tsx @@ -8,7 +8,7 @@ interface NoticeBubbleProps extends React.HTMLAttributes { } export const NoticeBubble = ({ message }: NoticeBubbleProps) => { - return message.type === 'COMPLETE' ? null : ( + return ( {message.notice} diff --git a/src/hooks/use-control-message-handler.ts b/src/hooks/use-control-message-handler.ts new file mode 100644 index 00000000..5b4edf99 --- /dev/null +++ b/src/hooks/use-control-message-handler.ts @@ -0,0 +1,26 @@ +import { useRouter } from 'next/navigation'; + +import { mutate } from 'swr'; + +import { MatchingRoom, Project } from '#/types'; +import { ControlMessage } from '#/types/message'; +import { MATCHING_QUERY_KEY, PROJECTS_QUERY_KEY } from '.'; + +export function useControlMessageHandler({ + projectId, + matchingId, +}: { + projectId?: Project['id']; + matchingId?: MatchingRoom['id']; +}) { + const router = useRouter(); + return (message: ControlMessage) => { + if (message.type === 'COMPLETE' && matchingId) { + mutate(MATCHING_QUERY_KEY); + router.replace(`/projects/${message.notice}`); + } + if (message.type === 'COMPLETE' && projectId) { + mutate(PROJECTS_QUERY_KEY); + } + }; +} diff --git a/src/hooks/use-notice-message-handler.ts b/src/hooks/use-notice-message-handler.ts new file mode 100644 index 00000000..3f185385 --- /dev/null +++ b/src/hooks/use-notice-message-handler.ts @@ -0,0 +1,26 @@ +import { useMemo } from 'react'; + +import _ from 'lodash'; +import { mutate } from 'swr'; + +import { Matching, NoticeMessage } from '#/types'; +import { MATCHING_ROOM_QUERY_KEY } from '.'; + +export function useNoticeMessageHandler(matchingId?: Matching['id']) { + const mutateMatchingRoom = useMemo(() => { + if (_.isNil(matchingId)) { + return null; + } + return () => mutate(MATCHING_ROOM_QUERY_KEY(matchingId)); + }, [matchingId]); + + return (message: NoticeMessage) => { + switch (message.type) { + case 'JOIN': + case 'READY': + case 'CANCEL_READY': + case 'EXIT': + mutateMatchingRoom?.(); + } + }; +} diff --git a/src/hooks/use-projects.ts b/src/hooks/use-projects.ts index 0f2c0c6f..848f1725 100644 --- a/src/hooks/use-projects.ts +++ b/src/hooks/use-projects.ts @@ -4,7 +4,7 @@ import useSWRMutation from 'swr/mutation'; import { Project, ProjectStatus, type ReportType } from '#/types'; import { fitFetcher } from '#/utilities'; -const PROJECTS_QUERY_KEY = '/v1/project'; +export const PROJECTS_QUERY_KEY = '/v1/project'; const PROJECTS_MUTATION_KEY = (id: Project['id']) => `/v1/project/${id}`; const PROJECTS_REPORT_USER_MUTATION_KEY = (id: Project['id']) => `/v1/project/${id}/report`; diff --git a/src/types/message.ts b/src/types/message.ts index b4f814fc..436699df 100644 --- a/src/types/message.ts +++ b/src/types/message.ts @@ -2,7 +2,7 @@ import { User } from '.'; export interface Message { id: number; - type: 'TEXT' | 'IMAGE' | 'NOTICE' | 'JOIN' | 'EXIT' | 'COMPLETE' | 'READY' | 'CANCEL_READY'; + type: 'TEXT' | 'IMAGE' | 'NOTICE' | 'JOIN' | 'EXIT' | 'READY' | 'CANCEL_READY' | 'COMPLETE'; createdAt: string; userId?: User['id']; content?: string; @@ -25,7 +25,14 @@ export interface ImageMessage extends Message { } export interface NoticeMessage extends Message { - type: 'NOTICE' | 'JOIN' | 'EXIT' | 'COMPLETE' | 'READY' | 'CANCEL_READY'; + type: 'NOTICE' | 'JOIN' | 'EXIT' | 'READY' | 'CANCEL_READY'; + content: undefined; + imageUrl: undefined; + notice: string; +} + +export interface ControlMessage extends Message { + type: 'COMPLETE'; content: undefined; imageUrl: undefined; notice: string; diff --git a/src/utilities/message.ts b/src/utilities/message.ts index d24d30b1..08d56ff4 100644 --- a/src/utilities/message.ts +++ b/src/utilities/message.ts @@ -1,4 +1,5 @@ import { ImageMessage, Message, NoticeMessage, TextMessage, User } from '#/types'; +import { ControlMessage } from '#/types/message'; export function isTextMessage(message: Message): message is TextMessage { return message.type === 'TEXT'; @@ -9,13 +10,18 @@ export function isImageMessage(message: Message): message is ImageMessage { } export function isNoticeMessage(message: Message): message is NoticeMessage { - const noticeMessageTypes = ['NOTICE', 'JOIN', 'EXIT', 'COMPLETE', 'READY']; + const noticeMessageTypes = ['NOTICE', 'JOIN', 'EXIT', 'READY', 'CANCEL_READY']; return noticeMessageTypes.includes(message.type); } +export function isControlMessage(message: Message): message is ControlMessage { + const controlMessageTypes = ['COMPLETE']; + return controlMessageTypes.includes(message.type); +} + interface MessageDto { messageId: number; - messageType: 'TEXT' | 'IMAGE' | 'NOTICE' | 'JOIN' | 'EXIT' | 'COMPLETE' | 'READY'; + messageType: Message['type']; createdAt: string; userId?: User['id']; content?: string; From bcc75af4d904e65856fcebf9d21506de111ee096 Mon Sep 17 00:00:00 2001 From: Seheon Yu Date: Tue, 2 Jul 2024 22:28:30 +0900 Subject: [PATCH 5/7] fix: Attach ref to Loading component correctly --- src/components/atoms/Loading.tsx | 9 +++++++-- src/components/molecules/ChatBubbles.tsx | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/atoms/Loading.tsx b/src/components/atoms/Loading.tsx index 62b9e127..3f36e166 100644 --- a/src/components/atoms/Loading.tsx +++ b/src/components/atoms/Loading.tsx @@ -1,12 +1,13 @@ import { forwardRef } from 'react'; +import type { HTMLAttributes } from 'react'; import styled from '@emotion/styled'; import { FitLogo } from '.'; -export const Loading = forwardRef((_, ref) => { +export const Loading = forwardRef>((props, ref) => { return ( - + @@ -19,6 +20,10 @@ Loading.displayName = 'Loading'; const Container = styled.div` display: flex; justify-content: center; + + &[hidden] { + display: none; + } `; const Spinner = styled.div` diff --git a/src/components/molecules/ChatBubbles.tsx b/src/components/molecules/ChatBubbles.tsx index 4da4a28e..b289a488 100644 --- a/src/components/molecules/ChatBubbles.tsx +++ b/src/components/molecules/ChatBubbles.tsx @@ -79,7 +79,7 @@ export const ChatBubbles = ({ projectId, matchingId }: ChatBubblesProps) => { /> ) : null )} - {messages?.at(-1)?.hasNext && } + ); }; From 8bb5b4b3d890494ca7450e3dc79af5718a1a0454 Mon Sep 17 00:00:00 2001 From: Seheon Yu Date: Tue, 2 Jul 2024 22:33:39 +0900 Subject: [PATCH 6/7] refactor: Add message handler hooks in index.ts --- src/components/molecules/ChatBubbles.tsx | 6 +++--- src/hooks/index.ts | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/molecules/ChatBubbles.tsx b/src/components/molecules/ChatBubbles.tsx index b289a488..8817b279 100644 --- a/src/components/molecules/ChatBubbles.tsx +++ b/src/components/molecules/ChatBubbles.tsx @@ -6,13 +6,13 @@ import { Loading } from '#/components/atoms'; import { nullUser } from '#/entities'; import { useChatId, - useChatUsers, useChatMessagesQuery, useChatSubscription, + useChatUsers, + useControlMessageHandler, useMeQuery, + useNoticeMessageHandler, } from '#/hooks'; -import { useControlMessageHandler } from '#/hooks/use-control-message-handler'; -import { useNoticeMessageHandler } from '#/hooks/use-notice-message-handler'; import { MatchingRoom, Project } from '#/types'; import { isControlMessage, isImageMessage, isNoticeMessage, isTextMessage } from '#/utilities'; import { ChatBubble } from './ChatBubble'; diff --git a/src/hooks/index.ts b/src/hooks/index.ts index ba9b09d5..2d798932 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -2,10 +2,12 @@ export * from './use-alarm'; export * from './use-chat-id'; export * from './use-chat-users'; export * from './use-chat'; +export * from './use-control-message-handler'; export * from './use-file'; export * from './use-login-page'; export * from './use-matching-room'; export * from './use-matching'; +export * from './use-notice-message-handler'; export * from './use-policy-agrees'; export * from './use-positions'; export * from './use-presigned-url'; From d38625e53edc92daaf6e4a998d893f502f2d72bd Mon Sep 17 00:00:00 2001 From: Seheon Yu Date: Tue, 2 Jul 2024 22:34:21 +0900 Subject: [PATCH 7/7] refactor: Reorder imports and ignore declaration sort in sort-imports rule --- .eslintrc.json | 6 +++++ src/components/atoms/CheckBox.tsx | 2 +- src/components/atoms/FitLogo.tsx | 2 +- src/components/atoms/Icons.tsx | 24 +++++++++---------- src/components/molecules/HeaderAlarmBlock.tsx | 2 +- src/components/organisms/ProjectChatRoom.tsx | 2 +- .../organisms/SignUpCompletePopup.tsx | 2 +- .../organisms/SignUpProfileUpdatePopup.tsx | 2 +- src/components/templates/LoginCallback.tsx | 2 +- 9 files changed, 25 insertions(+), 19 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 7e0b4fad..f6cdc294 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -21,6 +21,12 @@ } }, "rules": { + "sort-imports": [ + "error", + { + "ignoreDeclarationSort": true + } + ], "import/order": [ "error", { diff --git a/src/components/atoms/CheckBox.tsx b/src/components/atoms/CheckBox.tsx index b9483d5f..08c112b0 100644 --- a/src/components/atoms/CheckBox.tsx +++ b/src/components/atoms/CheckBox.tsx @@ -1,4 +1,4 @@ -import { forwardRef, type InputHTMLAttributes } from 'react'; +import { type InputHTMLAttributes, forwardRef } from 'react'; import { css } from '@emotion/react'; import styled from '@emotion/styled'; diff --git a/src/components/atoms/FitLogo.tsx b/src/components/atoms/FitLogo.tsx index d8636dc5..33c7d515 100644 --- a/src/components/atoms/FitLogo.tsx +++ b/src/components/atoms/FitLogo.tsx @@ -1,4 +1,4 @@ -import { SignatureLogo, MonochromeSignatureLogo, SymbolLogo } from '#/assets/logos'; +import { MonochromeSignatureLogo, SignatureLogo, SymbolLogo } from '#/assets/logos'; interface LogoProps { variant?: 'signature' | 'symbol'; diff --git a/src/components/atoms/Icons.tsx b/src/components/atoms/Icons.tsx index d0e7727f..b1bd7476 100644 --- a/src/components/atoms/Icons.tsx +++ b/src/components/atoms/Icons.tsx @@ -12,39 +12,39 @@ import { CameraIcon, CheckIcon, ClickIcon, + ClipBoldIcon, ClipIcon, CrossIcon, CrownIcon, + EmailIcon, EmojiFire, EmojiHoldingBackTears, EmojiPartyingFace, + EmojiPoliceCarLight, EmojiWinkingFace, + FacebookIcon, + GithubIcon, GoogleIcon, + HeartFilledIcon, + HeartIcon, ImageIcon, InfoIcon, InstagramIcon, KakaoIcon, LinkIcon, + LinkedInIcon, + LogoutIcon, MegaphoneIcon, PencilIcon, + PhoneFillIcon, PlusIcon, ProgressIcon, RunIcon, + TistoryIcon, Upload, UserIcon, - HeartIcon, - HeartFilledIcon, - EmailIcon, - PhoneFillIcon, - GithubIcon, - FacebookIcon, - LinkedInIcon, - TistoryIcon, - VelogIcon, - ClipBoldIcon, UserLineIcon, - LogoutIcon, - EmojiPoliceCarLight, + VelogIcon, } from '#/assets/icons'; export type IconName = diff --git a/src/components/molecules/HeaderAlarmBlock.tsx b/src/components/molecules/HeaderAlarmBlock.tsx index 68e5e296..d1e5ea9f 100644 --- a/src/components/molecules/HeaderAlarmBlock.tsx +++ b/src/components/molecules/HeaderAlarmBlock.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useCallback } from 'react'; +import { useCallback, useEffect, useRef } from 'react'; import styled from '@emotion/styled'; diff --git a/src/components/organisms/ProjectChatRoom.tsx b/src/components/organisms/ProjectChatRoom.tsx index 4ac3b663..3e138876 100644 --- a/src/components/organisms/ProjectChatRoom.tsx +++ b/src/components/organisms/ProjectChatRoom.tsx @@ -3,7 +3,7 @@ import styled from '@emotion/styled'; import { Icons } from '#/components/atoms'; import { ProjectSummary } from '#/components/molecules/ProjectSummary'; import { Project } from '#/types'; -import { transientStyled, transientOptions } from '#/utilities/transient-styled'; +import { transientOptions, transientStyled } from '#/utilities/transient-styled'; import { ChatRoom } from './ChatRoom'; interface ProjectChatRoomProps { diff --git a/src/components/organisms/SignUpCompletePopup.tsx b/src/components/organisms/SignUpCompletePopup.tsx index 931cc018..caf38ba8 100644 --- a/src/components/organisms/SignUpCompletePopup.tsx +++ b/src/components/organisms/SignUpCompletePopup.tsx @@ -2,7 +2,7 @@ import Link from 'next/link'; import styled from '@emotion/styled'; -import { Txt, Icons, Toggle, Button, Tooltip } from '#/components/atoms'; +import { Button, Icons, Toggle, Tooltip, Txt } from '#/components/atoms'; import { useMeMutation, useMeQuery } from '#/hooks/use-user'; import { media } from '#/utilities'; diff --git a/src/components/organisms/SignUpProfileUpdatePopup.tsx b/src/components/organisms/SignUpProfileUpdatePopup.tsx index e3301482..f87e5c01 100644 --- a/src/components/organisms/SignUpProfileUpdatePopup.tsx +++ b/src/components/organisms/SignUpProfileUpdatePopup.tsx @@ -3,7 +3,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import styled from '@emotion/styled'; import { useMeMutation, useMeQuery } from '#/hooks/use-user'; -import { SignUpStep, Me } from '#/types'; +import { Me, SignUpStep } from '#/types'; import { checkSignUpStep, media } from '#/utilities'; import { PositionSelection } from './sign-up/PositionSelection'; import { ProfileDetailsSubmission } from './sign-up/ProfileDetailsSubmission'; diff --git a/src/components/templates/LoginCallback.tsx b/src/components/templates/LoginCallback.tsx index 31de20d3..0408a51c 100644 --- a/src/components/templates/LoginCallback.tsx +++ b/src/components/templates/LoginCallback.tsx @@ -1,7 +1,7 @@ 'use client'; import { useEffect } from 'react'; -import { useSearchParams, useRouter, notFound } from 'next/navigation'; +import { notFound, useRouter, useSearchParams } from 'next/navigation'; import styled from '@emotion/styled';