From 47a1f28fdc3ad0c254949c649943024d127d8fc1 Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:48:19 +0900 Subject: [PATCH 01/21] =?UTF-8?q?=F0=9F=90=9BFix:=20ChatInfo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/chatRoom/fetchChatRoomList.ts | 37 ++++++ src/components/Profile/index.tsx | 2 +- src/modals/ChatModal/index.tsx | 8 +- .../SocialPage/components/ChatItem/index.tsx | 19 ++- .../components/FriendChatList/index.tsx | 8 +- .../components/FriendItem/index.tsx | 2 +- src/pages/SocialPage/index.tsx | 108 +++------------ src/types/social.ts | 17 ++- vite.config.ts | 125 +++++++++--------- 9 files changed, 157 insertions(+), 169 deletions(-) create mode 100644 src/apis/chatRoom/fetchChatRoomList.ts diff --git a/src/apis/chatRoom/fetchChatRoomList.ts b/src/apis/chatRoom/fetchChatRoomList.ts new file mode 100644 index 0000000..7361508 --- /dev/null +++ b/src/apis/chatRoom/fetchChatRoomList.ts @@ -0,0 +1,37 @@ +import { AxiosError } from 'axios' +import { APIResponse, ErrorResponse } from '~types/apiResponse' +import { axiosInstance } from '~apis/axiosInstance' +import { ChatInfo } from '~types/social' + +export type FetchChatRoomListResponse = ChatInfo + +export const fetchChatRoomList = async (): Promise> => { + try { + const { data } = await axiosInstance.get>(`/chat/rooms`) + return data + } catch (error) { + if (error instanceof AxiosError) { + const { response } = error as AxiosError + + if (response) { + const { code, message } = response.data + switch (code) { + case 400: + throw new Error(message || '잘못된 요청입니다.') + case 401: + throw new Error(message || '인증에 실패했습니다.') + case 500: + throw new Error(message || '서버 오류가 발생했습니다.') + default: + throw new Error(message || '알 수 없는 오류가 발생했습니다.') + } + } else { + // 요청 자체가 실패한 경우 + throw new Error('네트워크 연결을 확인해주세요') + } + } + + console.error('예상치 못한 에러:', error) + throw new Error('다시 시도해주세요') + } +} diff --git a/src/components/Profile/index.tsx b/src/components/Profile/index.tsx index d748697..140fef0 100644 --- a/src/components/Profile/index.tsx +++ b/src/components/Profile/index.tsx @@ -5,7 +5,7 @@ import { useModalStore } from '~stores/modalStore' type ProfileProps = { $size: number $src: string - userId?: string + userId?: number } export default function Profile({ $size, $src, userId }: ProfileProps) { diff --git a/src/modals/ChatModal/index.tsx b/src/modals/ChatModal/index.tsx index 2239991..ef571c8 100644 --- a/src/modals/ChatModal/index.tsx +++ b/src/modals/ChatModal/index.tsx @@ -10,12 +10,14 @@ import * as S from './styles' import { useScrollToBottom } from '~hooks/useScrollToBottom' type ChatModalProps = { - userId: string + chatRoomId: number + userId: number } -export default function ChatModal({ userId }: ChatModalProps) { +export default function ChatModal({ chatRoomId, userId }: ChatModalProps) { const { popModal } = useModalStore() - console.log('ChatModal', userId) //todo fetch by userId + console.log('chatRoomId', chatRoomId) //todo fetch by chatRoomId + console.log('userId', userId) //todo fetch by userId const ref = useScrollToBottom() return ( diff --git a/src/pages/SocialPage/components/ChatItem/index.tsx b/src/pages/SocialPage/components/ChatItem/index.tsx index f7b762b..bd01dcd 100644 --- a/src/pages/SocialPage/components/ChatItem/index.tsx +++ b/src/pages/SocialPage/components/ChatItem/index.tsx @@ -8,12 +8,21 @@ import ChatModal from '~modals/ChatModal' type ChatItemProps = ChatInfo -export default function ChatItem({ gender, lastChat, name, profileImg, role, unreadChatCount, userId }: ChatItemProps) { +export default function ChatItem({ + gender, + lastMessage, + name, + profileImg, + role, + unreadMessageCount, + members, + chatRoomId, +}: ChatItemProps) { const { pushModal } = useModalStore() return ( - pushModal()}> - + pushModal()}> + {name} @@ -27,10 +36,10 @@ export default function ChatItem({ gender, lastChat, name, profileImg, role, unr - {lastChat} + {lastMessage} - {unreadChatCount} + {unreadMessageCount} ) diff --git a/src/pages/SocialPage/components/FriendChatList/index.tsx b/src/pages/SocialPage/components/FriendChatList/index.tsx index b725386..06cd9a1 100644 --- a/src/pages/SocialPage/components/FriendChatList/index.tsx +++ b/src/pages/SocialPage/components/FriendChatList/index.tsx @@ -2,6 +2,8 @@ import ChatItem from '~pages/SocialPage/components/ChatItem' import FriendItem from '~pages/SocialPage/components/FriendItem' import { ChatInfo, FriendInfo, SocialTabs } from '~types/social' import * as S from './styles' +import { useEffect } from 'react' +import { fetchChatRoomList } from '~apis/chatRoom/fetchChatRoomList' type FriendChatListProps = { selectedTab: SocialTabs @@ -11,12 +13,14 @@ type FriendChatListProps = { export default function FriendChatList({ selectedTab, friendList, chatList }: FriendChatListProps) { //todo fetch by userId - + useEffect(() => { + fetchChatRoomList().then(data => console.log(data)) + }, []) return ( {selectedTab === 'friendList' ? friendList.map(friendInfo => ) - : chatList.map(chatInfo => )} + : chatList.map(chatInfo => )} ) } diff --git a/src/pages/SocialPage/components/FriendItem/index.tsx b/src/pages/SocialPage/components/FriendItem/index.tsx index ac81a4c..a2d5074 100644 --- a/src/pages/SocialPage/components/FriendItem/index.tsx +++ b/src/pages/SocialPage/components/FriendItem/index.tsx @@ -25,7 +25,7 @@ export default function FriendItem({ gender, name, profileImg, role, userId }: F - pushModal()}> + pushModal()}> 메시지 diff --git a/src/pages/SocialPage/index.tsx b/src/pages/SocialPage/index.tsx index f5e8824..7b542c7 100644 --- a/src/pages/SocialPage/index.tsx +++ b/src/pages/SocialPage/index.tsx @@ -116,103 +116,35 @@ const friendList: FriendInfo[] = [ ] const chatList: ChatInfo[] = [ { - profileImg: '', - name: '감자탕수육', - gender: 'female', - userId: 'dummyUserId', - id: '1', - role: '이모', - lastChat: '마지막 채팅 텍스트입니다', - unreadChatCount: 15, - }, - { - profileImg: '', - name: '감자탕수육', - gender: 'female', - userId: 'dummyUserId', - id: '2', - role: '이모', - lastChat: '마지막 채팅 텍스트입니다', - unreadChatCount: 15, - }, - { - profileImg: '', name: '감자탕수육', - gender: 'female', - userId: 'dummyUserId', - id: '3', - role: '이모', - lastChat: '마지막 채팅 텍스트입니다', - unreadChatCount: 15, - }, - { - profileImg: '', - name: '감자탕수육', - gender: 'female', - userId: 'dummyUserId', - id: '4', - role: '이모', - lastChat: '마지막 채팅 텍스트입니다', - unreadChatCount: 15, - }, - { - profileImg: '', - name: '감자탕수육', - gender: 'female', - userId: 'dummyUserId', - id: '5', - role: '이모', - lastChat: '마지막 채팅 텍스트입니다', - unreadChatCount: 15, - }, - { + chatRoomId: 14231, + lastMessage: '마지막 채팅 텍스트입니다', + unreadMessageCount: 15, + members: [ + { + memberId: 0, + email: 'test@abc.com', + name: 'NAME', + }, + ], profileImg: '', - name: '감자탕수육', - gender: 'female', - userId: 'dummyUserId', - id: '6', role: '이모', - lastChat: '마지막 채팅 텍스트입니다', - unreadChatCount: 15, - }, - { - profileImg: '', - name: '감자탕수육', gender: 'female', - userId: 'dummyUserId', - id: '7', - role: '이모', - lastChat: '마지막 채팅 텍스트입니다', - unreadChatCount: 15, }, { - profileImg: '', name: '감자탕수육', - gender: 'female', - userId: 'dummyUserId', - id: '8', - role: '이모', - lastChat: '마지막 채팅 텍스트입니다', - unreadChatCount: 15, - }, - { + chatRoomId: 14231, + lastMessage: '마지막 채팅 텍스트입니다', + unreadMessageCount: 15, + members: [ + { + memberId: 0, + email: 'test@abc.com', + name: 'NAME', + }, + ], profileImg: '', - name: '감자탕수육', - gender: 'female', - userId: 'dummyUserId', - id: '9', role: '이모', - lastChat: '마지막 채팅 텍스트입니다', - unreadChatCount: 15, - }, - { - profileImg: '', - name: '감자탕수육', gender: 'female', - userId: 'dummyUserId', - id: '10', - role: '이모', - lastChat: '마지막 채팅 텍스트입니다', - unreadChatCount: 15, }, ] diff --git a/src/types/social.ts b/src/types/social.ts index c4290be..fbebf47 100644 --- a/src/types/social.ts +++ b/src/types/social.ts @@ -9,13 +9,20 @@ export type FriendInfo = { userId: string } +//todo 백엔드 맞춰 수정 export type ChatInfo = { - profileImg: string + chatRoomId: number name: string + lastMessage: string + profileImg: string + unreadMessageCount: number + members: [ + { + memberId: number + email: string + name: string + }, + ] gender: 'male' | 'female' role: string - lastChat: string - unreadChatCount: number - id: string - userId: string } diff --git a/vite.config.ts b/vite.config.ts index 9942bfc..a68023c 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,83 +2,80 @@ import react from '@vitejs/plugin-react' import { defineConfig } from 'vite' import { compression } from 'vite-plugin-compression2' import dts from 'vite-plugin-dts' -// import mkcert from 'vite-plugin-mkcert' +import mkcert from 'vite-plugin-mkcert' import { VitePWA } from 'vite-plugin-pwa' import svgr from 'vite-plugin-svgr' import tsconfigPaths from 'vite-tsconfig-paths' // https://vitejs.dev/config/ -export default defineConfig(() => - // { mode } - { - return { - server: { - port: 3000, - strictPort: true, - proxy: { - '^/ors/v2/directions/.*': { - target: 'http://112.162.84.70:8003', - changeOrigin: true, - secure: false, - rewrite: path => path, - configure: (proxy, options) => { - proxy.on('error', (err, req, res) => { - console.log('프록시 에러:', err) - }) - proxy.on('proxyReq', (proxyReq, req, res) => { - console.log('프록시 요청:', proxyReq.path) - }) - }, +export default defineConfig(({ mode }) => { + return { + server: { + port: 3000, + strictPort: true, + proxy: { + '^/ors/v2/directions/.*': { + target: 'http://112.162.84.70:8003', + changeOrigin: true, + secure: false, + rewrite: path => path, + configure: (proxy, options) => { + proxy.on('error', (err, req, res) => { + console.log('프록시 에러:', err) + }) + proxy.on('proxyReq', (proxyReq, req, res) => { + console.log('프록시 요청:', proxyReq.path) + }) }, }, }, - plugins: [ - react(), - tsconfigPaths(), - // ...(mode === 'development' ? [mkcert()] : []), - svgr(), - dts(), - compression(), - VitePWA({ - strategies: 'injectManifest', - srcDir: 'src', - filename: 'sw.ts', - registerType: 'prompt', - injectRegister: false, + }, + plugins: [ + react(), + tsconfigPaths(), + ...(mode === 'development' ? [mkcert()] : []), + svgr(), + dts(), + compression(), + VitePWA({ + strategies: 'injectManifest', + srcDir: 'src', + filename: 'sw.ts', + registerType: 'prompt', + injectRegister: false, - pwaAssets: { - disabled: false, - config: true, - }, + pwaAssets: { + disabled: false, + config: true, + }, - manifest: { - name: 'DDang', - short_name: 'DDang', - description: '반려견 산책 서비스', - theme_color: '#ffffff', - }, + manifest: { + name: 'DDang', + short_name: 'DDang', + description: '반려견 산책 서비스', + theme_color: '#ffffff', + }, - injectManifest: { - globPatterns: ['**/*.{js,css,html,svg,png,ico}'], - }, + injectManifest: { + globPatterns: ['**/*.{js,css,html,svg,png,ico}'], + }, - devOptions: { - enabled: true, - navigateFallback: 'index.html', - suppressWarnings: true, - type: 'module', - }, - }), - ], - build: { - rollupOptions: { - output: { - manualChunks: { - vendor: ['react', 'react-dom'], - }, + devOptions: { + enabled: true, + navigateFallback: 'index.html', + suppressWarnings: true, + type: 'module', + }, + }), + ], + build: { + rollupOptions: { + output: { + manualChunks: { + vendor: ['react', 'react-dom'], }, }, }, - } + }, } -) +}) From 058ae013631249c63480db8adc72704c7780445e Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Tue, 3 Dec 2024 22:38:21 +0900 Subject: [PATCH 02/21] =?UTF-8?q?=F0=9F=94=A8Setting:=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/typescript.code-snippets | 2 +- src/types/api.ts | 173 +++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 src/types/api.ts diff --git a/.vscode/typescript.code-snippets b/.vscode/typescript.code-snippets index 21967ca..e7e11ee 100644 --- a/.vscode/typescript.code-snippets +++ b/.vscode/typescript.code-snippets @@ -25,7 +25,7 @@ "prefix": "api-req", "body": [ "import { AxiosError } from 'axios';", - "import { APIResponse, ErrorResponse } from '~types/apiResponse';", + "import { APIResponse, ErrorResponse } from '~types/api';", "import { axiosInstance } from '~apis/axiosInstance';", "", "export type ${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}}Request = {", diff --git a/src/types/api.ts b/src/types/api.ts new file mode 100644 index 0000000..af2051b --- /dev/null +++ b/src/types/api.ts @@ -0,0 +1,173 @@ +import { ChatType, Gender, FamilyRole, DayOfWeek, Provider, BooleanString, Time } from '~types/common' + +export type APIResponse = { + code: number + status: string + message: string + data: T +} + +export type ErrorResponse = APIResponse + +export type BasicInfo = { + /** 이름 @example "홍길동" */ + name: string + /** 생년월일 @example "1990-01-01" */ + birthDate: string + /** 성별 @example "MALE" */ + gender: Gender +} + +export type Dog = BasicInfo & { + /** 강아지 ID @example 1 */ + dogId: number + /** 강아지 품종 @example "골든 리트리버" */ + breed: string + /** 강아지 체중 (kg) @example 25 */ + weight: number + /** 강아지 프로필 이미지 URL @example "https://example.com/dog_profile.jpg" */ + profileImg: string + /** 중성화 여부 @example "TRUE" */ + isNeutered: BooleanString + /** 가족 ID @example 1 */ + familyId: number + /** 코멘트 @example "활발하고 친근한 성격입니다." */ + comment: string +} + +export type OtherDog = { + /** 다른 강아지 ID @example 2 */ + otherDogId: number + /** 다른 강아지 프로필 이미지 URL @example "https://example.com/other_dog_profile.jpg" */ + otherDogProfileImg: string + /** 다른 강아지 이름 @example "초코" */ + otherDogName: string + /** 다른 강아지 품종 @example "시고르브 잡종" */ + otherDogBreed: string + /** 다른 강아지 나이 @example 3 */ + otherDogAge: number + /** 다른 강아지 성별 @example "MALE" */ + otherDogGender: Gender + /** 다른 강아지 주인의 유저 ID @example 2 */ + memberId: number +} + +export type Member = BasicInfo & { + /** 유저 ID @example 1 */ + memberId: number + /** 이메일 주소 @example "user@example.com" */ + email: string + /** 로그인 제공자 @example "GOOGLE" */ + provider: Provider + /** 주소 @example "서울시 강남구" */ + address: string + /** 가족 내 역할 @example "FATHER" */ + familyRole: FamilyRole + /** 프로필 이미지 URL @example "https://example.com/profile.jpg" */ + profileImg: string +} + +export type Position = { + /** 위도 @example 37.5665 */ + latitude: number + /** 경도 @example 126.9780 */ + longitude: number + /** 타임스탬프 @example "2024-12-03T08:23:14.753Z" */ + timeStamp: string +} + +export type Walk = { + /** 산책 시간 정보 */ + timeDuration: Time + /** 산책 일정 ID @example 1 */ + walkScheduleId: number + /** 요일 @example "MON" */ + dayOfWeek: DayOfWeek + /** 산책 시간 @example "09:30" */ + walkTime: string + /** 산책 횟수 @example 5 */ + walkCount: number + /** 날짜 @example "2024-12-03" */ + date: string + /** 총 산책 거리 (km) @example 12.5 */ + totalDistance: number + /** 총 산책 거리 (km) @example 10 */ + totalDistanceKilo: number + /** 총 소모 칼로리 @example 100 */ + totalCalorie: number + /** 총 산책 거리 (m) @example 5000 */ + totalDistanceMeter: number + /** 유저과 함께 산책한 횟수 @example 3 */ + countWalksWithMember: number + /** 총 산책 횟수 @example 10 */ + totalWalkCount: number + /** 총 산책 거리 (km) @example 5000 */ + totalDistanceInKilometers: number +} + +export type Chat = { + /** 채팅 ID @example 123 */ + chatId: number + /** 채팅방 ID @example 3 */ + chatRoomId: number + /** 채팅 타입 @example "TALK" */ + chatType: ChatType + /** 읽음 여부 @example "TRUE" */ + isRead: BooleanString + /** 메시지 내용 @example "안녕하세요!" */ + text: string + /** 마지막 메시지 @example "안녕하세요!" */ + lastMessage: string + /** 읽은 메시지 ID 목록 @example null */ + readMessageIds: null + /** 읽지 않은 메시지 수 @example 3 */ + unreadMessageCount: number + /** 생성 시간 @example "2024-12-03T08:17:04.717Z" */ + createdAt: string + /** 업데이트 시간 @example "2024-12-03T08:17:04.717Z" */ + updatedAt: string +} + +export type Family = { + /** 가족 ID @example 1 */ + familyId: number + /** 가족 이름 @example "행복한 가족" */ + familyName: string + /** 초대 코드 @example "ABC12345" */ + inviteCode: string + /** 초대 코드 만료 시간 (초) @example 300 */ + expiresInSeconds: number +} + +export type CommonAPIRequest = Member & + Dog & + Chat & { + /** 총 산책 시간 (초) @example 1800 */ + totalWalkTimeSecond: number + } + +export type CommonAPIResponse = BasicInfo & + Member & + Chat & + Family & + Walk & + Position & + Dog & + OtherDog & { + dog: Dog + dogs: Dog[] + dogWalkCount: number + dogAge: number + walkWithDogInfo: OtherDog + memberName: string + dogName: string + count: number + memberInfo: Pick + members: Pick + isMatched: BooleanString + memberGender: Gender + memberProfileImg: string + points: string + positionList: Position[] + memberEmail: string + } From 975780f4889756a27a19e2d4e5026ddf0ce50fb9 Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Tue, 3 Dec 2024 22:47:25 +0900 Subject: [PATCH 03/21] =?UTF-8?q?=E2=9C=A8Feat:=20=EC=B1=84=ED=8C=85?= =?UTF-8?q?=EB=B0=A9=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=B0=94=EC=9D=B8?= =?UTF-8?q?=EB=94=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/chatRoom/fetchChatRoomList.ts | 7 +- src/components/Profile/styles.ts | 2 +- .../SocialPage/components/ChatItem/index.tsx | 21 ++--- .../components/FriendChatList/index.tsx | 11 +-- src/pages/SocialPage/index.tsx | 84 +++++++------------ src/types/api.ts | 2 +- src/types/apiResponse.ts | 8 -- src/types/common.ts | 15 ++++ src/types/social.ts | 20 +---- 9 files changed, 60 insertions(+), 110 deletions(-) delete mode 100644 src/types/apiResponse.ts create mode 100644 src/types/common.ts diff --git a/src/apis/chatRoom/fetchChatRoomList.ts b/src/apis/chatRoom/fetchChatRoomList.ts index 7361508..03253c6 100644 --- a/src/apis/chatRoom/fetchChatRoomList.ts +++ b/src/apis/chatRoom/fetchChatRoomList.ts @@ -1,9 +1,10 @@ import { AxiosError } from 'axios' -import { APIResponse, ErrorResponse } from '~types/apiResponse' +import { APIResponse, CommonAPIResponse, ErrorResponse } from '~types/api' import { axiosInstance } from '~apis/axiosInstance' -import { ChatInfo } from '~types/social' -export type FetchChatRoomListResponse = ChatInfo +export type FetchChatRoomListResponse = Array< + Pick +> export const fetchChatRoomList = async (): Promise> => { try { diff --git a/src/components/Profile/styles.ts b/src/components/Profile/styles.ts index 37ce943..1da3c9a 100644 --- a/src/components/Profile/styles.ts +++ b/src/components/Profile/styles.ts @@ -3,7 +3,7 @@ import styled from 'styled-components' type ProfileProps = { $size: number $src: string - $userId?: string + $userId?: number } export const Profile = styled.div` diff --git a/src/pages/SocialPage/components/ChatItem/index.tsx b/src/pages/SocialPage/components/ChatItem/index.tsx index bd01dcd..381f27d 100644 --- a/src/pages/SocialPage/components/ChatItem/index.tsx +++ b/src/pages/SocialPage/components/ChatItem/index.tsx @@ -1,38 +1,29 @@ -import { ChatInfo } from '~types/social' import * as S from './styles' import { Separator } from '~components/Separator' import { Typo11, Typo13, Typo17 } from '~components/Typo' import Profile from '~components/Profile' import { useModalStore } from '~stores/modalStore' import ChatModal from '~modals/ChatModal' +import { FetchChatRoomListResponse } from '~apis/chatRoom/fetchChatRoomList' -type ChatItemProps = ChatInfo +type ChatItemProps = FetchChatRoomListResponse[number] -export default function ChatItem({ - gender, - lastMessage, - name, - profileImg, - role, - unreadMessageCount, - members, - chatRoomId, -}: ChatItemProps) { +export default function ChatItem({ chatRoomId, lastMessage, members, name, unreadMessageCount }: ChatItemProps) { const { pushModal } = useModalStore() return ( pushModal()}> - + {name} - {role} + {members[0].familyRole} - {gender === 'male' ? '남' : '여'} + {members[0].gender === 'MALE' ? '남' : '여'} diff --git a/src/pages/SocialPage/components/FriendChatList/index.tsx b/src/pages/SocialPage/components/FriendChatList/index.tsx index 06cd9a1..8b03e70 100644 --- a/src/pages/SocialPage/components/FriendChatList/index.tsx +++ b/src/pages/SocialPage/components/FriendChatList/index.tsx @@ -1,21 +1,18 @@ import ChatItem from '~pages/SocialPage/components/ChatItem' import FriendItem from '~pages/SocialPage/components/FriendItem' -import { ChatInfo, FriendInfo, SocialTabs } from '~types/social' +import { FriendInfo, SocialTabs } from '~types/social' import * as S from './styles' -import { useEffect } from 'react' -import { fetchChatRoomList } from '~apis/chatRoom/fetchChatRoomList' +import { FetchChatRoomListResponse } from '~apis/chatRoom/fetchChatRoomList' type FriendChatListProps = { selectedTab: SocialTabs friendList: FriendInfo[] - chatList: ChatInfo[] + chatList: FetchChatRoomListResponse } export default function FriendChatList({ selectedTab, friendList, chatList }: FriendChatListProps) { //todo fetch by userId - useEffect(() => { - fetchChatRoomList().then(data => console.log(data)) - }, []) + return ( {selectedTab === 'friendList' diff --git a/src/pages/SocialPage/index.tsx b/src/pages/SocialPage/index.tsx index 7b542c7..477646d 100644 --- a/src/pages/SocialPage/index.tsx +++ b/src/pages/SocialPage/index.tsx @@ -1,11 +1,17 @@ -import { useState } from 'react' +import { useEffect, useState } from 'react' import { Typo15 } from '~components/Typo' import FriendChatList from '~pages/SocialPage/components/FriendChatList' -import { ChatInfo, FriendInfo } from '~types/social' +import { FriendInfo } from '~types/social' import * as S from './styles' +import { fetchChatRoomList, FetchChatRoomListResponse } from '~apis/chatRoom/fetchChatRoomList' export default function SocialPage() { const [selectedTab, setSelectedTab] = useState<'friendList' | 'dangTalk'>('friendList') + const [chatList, setChatList] = useState([]) + + useEffect(() => { + fetchChatRoomList().then(data => setChatList(data.data)) + }, []) return ( @@ -36,115 +42,81 @@ const friendList: FriendInfo[] = [ { profileImg: '', name: '감자탕수육', - gender: 'female', + gender: 'FEMALE', userId: 'dummyUserId', id: '1', - role: '이모', + role: '', }, { profileImg: '', name: '감자탕수육', - gender: 'female', + gender: 'FEMALE', userId: 'dummyUserId', id: '2', - role: '이모', + role: '', }, { profileImg: '', name: '감자탕수육', - gender: 'female', + gender: 'FEMALE', userId: 'dummyUserId', id: '3', - role: '이모', + role: '', }, { profileImg: '', name: '감자탕수육', - gender: 'female', + gender: 'FEMALE', userId: 'dummyUserId', id: '4', - role: '이모', + role: '', }, { profileImg: '', name: '감자탕수육', - gender: 'female', + gender: 'FEMALE', userId: 'dummyUserId', id: '5', - role: '이모', + role: '', }, { profileImg: '', name: '감자탕수육', - gender: 'female', + gender: 'FEMALE', userId: 'dummyUserId', id: '6', - role: '이모', + role: '', }, { profileImg: '', name: '감자탕수육', - gender: 'female', + gender: 'FEMALE', userId: 'dummyUserId', id: '7', - role: '이모', + role: '', }, { profileImg: '', name: '감자탕수육', - gender: 'female', + gender: 'FEMALE', userId: 'dummyUserId', id: '8', - role: '이모', + role: '', }, { profileImg: '', name: '감자탕수육', - gender: 'female', + gender: 'FEMALE', userId: 'dummyUserId', id: '9', - role: '이모', + role: '', }, { profileImg: '', name: '감자탕수육', - gender: 'female', + gender: 'FEMALE', userId: 'dummyUserId', id: '10', - role: '이모', - }, -] -const chatList: ChatInfo[] = [ - { - name: '감자탕수육', - chatRoomId: 14231, - lastMessage: '마지막 채팅 텍스트입니다', - unreadMessageCount: 15, - members: [ - { - memberId: 0, - email: 'test@abc.com', - name: 'NAME', - }, - ], - profileImg: '', - role: '이모', - gender: 'female', - }, - { - name: '감자탕수육', - chatRoomId: 14231, - lastMessage: '마지막 채팅 텍스트입니다', - unreadMessageCount: 15, - members: [ - { - memberId: 0, - email: 'test@abc.com', - name: 'NAME', - }, - ], - profileImg: '', - role: '이모', - gender: 'female', + role: '', }, ] diff --git a/src/types/api.ts b/src/types/api.ts index af2051b..1ed6134 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -163,7 +163,7 @@ export type CommonAPIResponse = BasicInfo & dogName: string count: number memberInfo: Pick - members: Pick + members: Pick[] isMatched: BooleanString memberGender: Gender memberProfileImg: string diff --git a/src/types/apiResponse.ts b/src/types/apiResponse.ts deleted file mode 100644 index d4f3c2a..0000000 --- a/src/types/apiResponse.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type APIResponse = { - code: number - status: string - message: string - data: T -} - -export type ErrorResponse = APIResponse diff --git a/src/types/common.ts b/src/types/common.ts new file mode 100644 index 0000000..85325aa --- /dev/null +++ b/src/types/common.ts @@ -0,0 +1,15 @@ +export type Gender = 'MALE' | 'FEMALE' +export type FamilyRole = 'FATHER' | 'MOTHER' | 'SISTER' | 'BROTHER' +export type DayOfWeek = 'MONDAY' | 'TUESDAY' | 'WEDNESDAY' | 'THURSDAY' | 'FRIDAY' | 'SATURDAY' | 'SUNDAY' +export type NotificationType = 'WALK' | 'CHAT' | 'FRIEND' +export type Provider = 'GOOGLE' | 'NAVER' | 'KAKAO' +export type ChatType = 'TALK' | 'SYSTEM' +export type BooleanString = 'TRUE' | 'FALSE' +export type Time = { + /** 시간 @example 1 */ + hours: number + /** 분 @example 30 */ + minutes: number + /** 초 @example 45 */ + seconds: number +} diff --git a/src/types/social.ts b/src/types/social.ts index fbebf47..fbc06f9 100644 --- a/src/types/social.ts +++ b/src/types/social.ts @@ -3,26 +3,8 @@ export type SocialTabs = 'friendList' | 'dangTalk' export type FriendInfo = { profileImg: string name: string - gender: 'male' | 'female' + gender: 'MALE' | 'FEMALE' role: string id: string userId: string } - -//todo 백엔드 맞춰 수정 -export type ChatInfo = { - chatRoomId: number - name: string - lastMessage: string - profileImg: string - unreadMessageCount: number - members: [ - { - memberId: number - email: string - name: string - }, - ] - gender: 'male' | 'female' - role: string -} From e0770b8489b7e148792632452a1743e221b36e7c Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 09:21:49 +0900 Subject: [PATCH 04/21] =?UTF-8?q?=E2=9C=A8Feat:=20createChatRoom?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/chatRoom/createChatRoom.ts | 45 +++++++++++++++++++ src/components/SendMessageForm/index.tsx | 21 +++++++-- src/modals/ChatModal/index.tsx | 4 +- .../CheckDogProfileSection/index.tsx | 2 +- src/pages/FamilyDDangPage/index.tsx | 4 +- .../components/FriendItem/index.tsx | 4 +- src/pages/SocialPage/index.tsx | 20 ++++----- src/types/social.ts | 2 +- 8 files changed, 81 insertions(+), 21 deletions(-) create mode 100644 src/apis/chatRoom/createChatRoom.ts diff --git a/src/apis/chatRoom/createChatRoom.ts b/src/apis/chatRoom/createChatRoom.ts new file mode 100644 index 0000000..6e7144c --- /dev/null +++ b/src/apis/chatRoom/createChatRoom.ts @@ -0,0 +1,45 @@ +import { AxiosError } from 'axios' +import { APIResponse, CommonAPIResponse, ErrorResponse } from '~types/api' +import { axiosInstance } from '~apis/axiosInstance' + +export type CreateChatRoomRequest = { + opponentMemberId: number +} + +export type CreateChatRoomResponse = Pick< + CommonAPIResponse, + 'chatRoomId' | 'name' | 'lastMessage' | 'unreadMessageCount' | 'members' +> + +export const createChatRoom = async (req: CreateChatRoomRequest): Promise> => { + try { + const { data } = await axiosInstance.post>(`/chat/rooms`, req) + console.log(data.message || '채팅방 생성 성공') + console.log(data.data) + return data + } catch (error) { + if (error instanceof AxiosError) { + const { response } = error as AxiosError + + if (response) { + const { code, message } = response.data + switch (code) { + case 400: + throw new Error(message || '잘못된 요청입니다.') + case 401: + throw new Error(message || '인증에 실패했습니다.') + case 500: + throw new Error(message || '서버 오류가 발생했습니다.') + default: + throw new Error(message || '알 수 없는 오류가 발생했습니다.') + } + } else { + // 요청 자체가 실패한 경우 + throw new Error('네트워크 연결을 확인해주세요') + } + } + + console.error('예상치 못한 에러:', error) + throw new Error('다시 시도해주세요') + } +} diff --git a/src/components/SendMessageForm/index.tsx b/src/components/SendMessageForm/index.tsx index 4cffa82..28013fd 100644 --- a/src/components/SendMessageForm/index.tsx +++ b/src/components/SendMessageForm/index.tsx @@ -1,11 +1,26 @@ import { Typo14 } from '~components/Typo' import * as S from './styles' +import { createChatRoom } from '~apis/chatRoom/createChatRoom' +import { CommonAPIResponse } from '~types/api' -type SendMessageFormProps = React.FormHTMLAttributes +type SendMessageFormProps = React.FormHTMLAttributes & { + chatCount: number +} & Pick -export default function SendMessageForm({ ...rest }: SendMessageFormProps) { +export default function SendMessageForm({ chatCount, ...rest }: SendMessageFormProps) { + const onSubmit = async (e: React.FormEvent) => { + e.preventDefault() + if (rest.onSubmit) rest.onSubmit(e) + else { + if (chatCount === 0) { + //* 채팅방 생성 + await createChatRoom({ opponentMemberId: 123 }) + } + //* 채팅 전송 웹소켓 + } + } return ( - + 전송 diff --git a/src/modals/ChatModal/index.tsx b/src/modals/ChatModal/index.tsx index ef571c8..fee98be 100644 --- a/src/modals/ChatModal/index.tsx +++ b/src/modals/ChatModal/index.tsx @@ -5,9 +5,9 @@ import Profile from '~components/Profile' import SendMessageForm from '~components/SendMessageForm' import { Separator } from '~components/Separator' import { Typo11, Typo15 } from '~components/Typo' +import { useScrollToBottom } from '~hooks/useScrollToBottom' import { useModalStore } from '~stores/modalStore' import * as S from './styles' -import { useScrollToBottom } from '~hooks/useScrollToBottom' type ChatModalProps = { chatRoomId: number @@ -47,7 +47,7 @@ export default function ChatModal({ chatRoomId, userId }: ChatModalProps) { ) )} - + ) } diff --git a/src/modals/RegisterDogModal/CheckDogProfileSection/index.tsx b/src/modals/RegisterDogModal/CheckDogProfileSection/index.tsx index 8feb719..62df58c 100644 --- a/src/modals/RegisterDogModal/CheckDogProfileSection/index.tsx +++ b/src/modals/RegisterDogModal/CheckDogProfileSection/index.tsx @@ -32,7 +32,7 @@ export default function CheckDogProfileSection() { $src={ 'https://www.shutterstock.com/image-photo/beautiful-golden-retriever-cute-puppy-260nw-2526542701.jpg' } - userId='' + userId={0} /> diff --git a/src/pages/FamilyDDangPage/index.tsx b/src/pages/FamilyDDangPage/index.tsx index bc11ef9..07f97bb 100644 --- a/src/pages/FamilyDDangPage/index.tsx +++ b/src/pages/FamilyDDangPage/index.tsx @@ -20,7 +20,7 @@ export default function FamilyDDang() { - + {family1Info.nickName} @@ -49,7 +49,7 @@ export default function FamilyDDang() { - + {family2Info.nickName} diff --git a/src/pages/SocialPage/components/FriendItem/index.tsx b/src/pages/SocialPage/components/FriendItem/index.tsx index a2d5074..057e886 100644 --- a/src/pages/SocialPage/components/FriendItem/index.tsx +++ b/src/pages/SocialPage/components/FriendItem/index.tsx @@ -17,7 +17,7 @@ export default function FriendItem({ gender, name, profileImg, role, userId }: F {name} - {gender === 'male' ? '남자' : '여자'} + {gender === 'MALE' ? '남자' : '여자'} @@ -25,7 +25,7 @@ export default function FriendItem({ gender, name, profileImg, role, userId }: F - pushModal()}> + pushModal()}> 메시지 diff --git a/src/pages/SocialPage/index.tsx b/src/pages/SocialPage/index.tsx index 477646d..2535b6a 100644 --- a/src/pages/SocialPage/index.tsx +++ b/src/pages/SocialPage/index.tsx @@ -43,7 +43,7 @@ const friendList: FriendInfo[] = [ profileImg: '', name: '감자탕수육', gender: 'FEMALE', - userId: 'dummyUserId', + userId: 12345, id: '1', role: '', }, @@ -51,7 +51,7 @@ const friendList: FriendInfo[] = [ profileImg: '', name: '감자탕수육', gender: 'FEMALE', - userId: 'dummyUserId', + userId: 12345, id: '2', role: '', }, @@ -59,7 +59,7 @@ const friendList: FriendInfo[] = [ profileImg: '', name: '감자탕수육', gender: 'FEMALE', - userId: 'dummyUserId', + userId: 12345, id: '3', role: '', }, @@ -67,7 +67,7 @@ const friendList: FriendInfo[] = [ profileImg: '', name: '감자탕수육', gender: 'FEMALE', - userId: 'dummyUserId', + userId: 12345, id: '4', role: '', }, @@ -75,7 +75,7 @@ const friendList: FriendInfo[] = [ profileImg: '', name: '감자탕수육', gender: 'FEMALE', - userId: 'dummyUserId', + userId: 12345, id: '5', role: '', }, @@ -83,7 +83,7 @@ const friendList: FriendInfo[] = [ profileImg: '', name: '감자탕수육', gender: 'FEMALE', - userId: 'dummyUserId', + userId: 12345, id: '6', role: '', }, @@ -91,7 +91,7 @@ const friendList: FriendInfo[] = [ profileImg: '', name: '감자탕수육', gender: 'FEMALE', - userId: 'dummyUserId', + userId: 12345, id: '7', role: '', }, @@ -99,7 +99,7 @@ const friendList: FriendInfo[] = [ profileImg: '', name: '감자탕수육', gender: 'FEMALE', - userId: 'dummyUserId', + userId: 12345, id: '8', role: '', }, @@ -107,7 +107,7 @@ const friendList: FriendInfo[] = [ profileImg: '', name: '감자탕수육', gender: 'FEMALE', - userId: 'dummyUserId', + userId: 12345, id: '9', role: '', }, @@ -115,7 +115,7 @@ const friendList: FriendInfo[] = [ profileImg: '', name: '감자탕수육', gender: 'FEMALE', - userId: 'dummyUserId', + userId: 12345, id: '10', role: '', }, diff --git a/src/types/social.ts b/src/types/social.ts index fbc06f9..5a18f76 100644 --- a/src/types/social.ts +++ b/src/types/social.ts @@ -6,5 +6,5 @@ export type FriendInfo = { gender: 'MALE' | 'FEMALE' role: string id: string - userId: string + userId: number } From 784bf502bd40d4405cd89c89fb1726375b18cca3 Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 10:39:45 +0900 Subject: [PATCH 05/21] =?UTF-8?q?=E2=9C=A8Feat:=20=EC=B9=9C=EA=B5=AC?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=B0=94?= =?UTF-8?q?=EC=9D=B8=EB=94=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/friend/fetchFriendList.ts | 38 ++++++++ .../components/FriendChatList/index.tsx | 9 +- .../components/FriendItem/index.tsx | 20 +++-- src/pages/SocialPage/index.tsx | 89 +------------------ src/types/social.ts | 9 -- 5 files changed, 61 insertions(+), 104 deletions(-) create mode 100644 src/apis/friend/fetchFriendList.ts diff --git a/src/apis/friend/fetchFriendList.ts b/src/apis/friend/fetchFriendList.ts new file mode 100644 index 0000000..e17a8c4 --- /dev/null +++ b/src/apis/friend/fetchFriendList.ts @@ -0,0 +1,38 @@ +import { AxiosError } from 'axios' +import { APIResponse, CommonAPIResponse, ErrorResponse } from '~types/api' +import { axiosInstance } from '~apis/axiosInstance' + +export type FetchFriendListResponse = Array< + Pick +> + +export const fetchFriendList = async (): Promise> => { + try { + const { data } = await axiosInstance.get>(`/friend`) + return data + } catch (error) { + if (error instanceof AxiosError) { + const { response } = error as AxiosError + + if (response) { + const { code, message } = response.data + switch (code) { + case 400: + throw new Error(message || '잘못된 요청입니다.') + case 401: + throw new Error(message || '인증에 실패했습니다.') + case 500: + throw new Error(message || '서버 오류가 발생했습니다.') + default: + throw new Error(message || '알 수 없는 오류가 발생했습니다.') + } + } else { + // 요청 자체가 실패한 경우 + throw new Error('네트워크 연결을 확인해주세요') + } + } + + console.error('예상치 못한 에러:', error) + throw new Error('다시 시도해주세요') + } +} diff --git a/src/pages/SocialPage/components/FriendChatList/index.tsx b/src/pages/SocialPage/components/FriendChatList/index.tsx index 8b03e70..6099585 100644 --- a/src/pages/SocialPage/components/FriendChatList/index.tsx +++ b/src/pages/SocialPage/components/FriendChatList/index.tsx @@ -1,12 +1,13 @@ +import { FetchChatRoomListResponse } from '~apis/chatRoom/fetchChatRoomList' +import { FetchFriendListResponse } from '~apis/friend/fetchFriendList' import ChatItem from '~pages/SocialPage/components/ChatItem' import FriendItem from '~pages/SocialPage/components/FriendItem' -import { FriendInfo, SocialTabs } from '~types/social' +import { SocialTabs } from '~types/social' import * as S from './styles' -import { FetchChatRoomListResponse } from '~apis/chatRoom/fetchChatRoomList' type FriendChatListProps = { selectedTab: SocialTabs - friendList: FriendInfo[] + friendList: FetchFriendListResponse chatList: FetchChatRoomListResponse } @@ -16,7 +17,7 @@ export default function FriendChatList({ selectedTab, friendList, chatList }: Fr return ( {selectedTab === 'friendList' - ? friendList.map(friendInfo => ) + ? friendList.map(friendInfo => ) : chatList.map(chatInfo => )} ) diff --git a/src/pages/SocialPage/components/FriendItem/index.tsx b/src/pages/SocialPage/components/FriendItem/index.tsx index 057e886..10a4be6 100644 --- a/src/pages/SocialPage/components/FriendItem/index.tsx +++ b/src/pages/SocialPage/components/FriendItem/index.tsx @@ -3,16 +3,24 @@ import { Separator } from '~components/Separator' import { Typo14, Typo17 } from '~components/Typo' import ChatModal from '~modals/ChatModal' import { useModalStore } from '~stores/modalStore' -import { FriendInfo } from '~types/social' import * as S from './styles' +import { FetchFriendListResponse } from '~apis/friend/fetchFriendList' +import { createChatRoom } from '~apis/chatRoom/createChatRoom' +import { useEffect, useState } from 'react' -type FriendItemProps = FriendInfo +type FriendItemProps = FetchFriendListResponse[number] -export default function FriendItem({ gender, name, profileImg, role, userId }: FriendItemProps) { +export default function FriendItem({ gender, name, profileImg, memberId, familyRole }: FriendItemProps) { const { pushModal } = useModalStore() + const [chatRoomId, setChatRoomId] = useState(-1) + + useEffect(() => { + createChatRoom({ opponentMemberId: memberId }).then(data => setChatRoomId(data.data.chatRoomId)) + }, [memberId]) + return ( - + {name} @@ -21,11 +29,11 @@ export default function FriendItem({ gender, name, profileImg, role, userId }: F - {role} + {familyRole} - pushModal()}> + pushModal()}> 메시지 diff --git a/src/pages/SocialPage/index.tsx b/src/pages/SocialPage/index.tsx index 2535b6a..29c2f88 100644 --- a/src/pages/SocialPage/index.tsx +++ b/src/pages/SocialPage/index.tsx @@ -1,16 +1,18 @@ import { useEffect, useState } from 'react' +import { fetchChatRoomList, FetchChatRoomListResponse } from '~apis/chatRoom/fetchChatRoomList' +import { fetchFriendList, FetchFriendListResponse } from '~apis/friend/fetchFriendList' import { Typo15 } from '~components/Typo' import FriendChatList from '~pages/SocialPage/components/FriendChatList' -import { FriendInfo } from '~types/social' import * as S from './styles' -import { fetchChatRoomList, FetchChatRoomListResponse } from '~apis/chatRoom/fetchChatRoomList' export default function SocialPage() { const [selectedTab, setSelectedTab] = useState<'friendList' | 'dangTalk'>('friendList') const [chatList, setChatList] = useState([]) + const [friendList, setFriendList] = useState([]) useEffect(() => { fetchChatRoomList().then(data => setChatList(data.data)) + fetchFriendList().then(data => setFriendList(data.data)) }, []) return ( @@ -37,86 +39,3 @@ export default function SocialPage() { ) } - -const friendList: FriendInfo[] = [ - { - profileImg: '', - name: '감자탕수육', - gender: 'FEMALE', - userId: 12345, - id: '1', - role: '', - }, - { - profileImg: '', - name: '감자탕수육', - gender: 'FEMALE', - userId: 12345, - id: '2', - role: '', - }, - { - profileImg: '', - name: '감자탕수육', - gender: 'FEMALE', - userId: 12345, - id: '3', - role: '', - }, - { - profileImg: '', - name: '감자탕수육', - gender: 'FEMALE', - userId: 12345, - id: '4', - role: '', - }, - { - profileImg: '', - name: '감자탕수육', - gender: 'FEMALE', - userId: 12345, - id: '5', - role: '', - }, - { - profileImg: '', - name: '감자탕수육', - gender: 'FEMALE', - userId: 12345, - id: '6', - role: '', - }, - { - profileImg: '', - name: '감자탕수육', - gender: 'FEMALE', - userId: 12345, - id: '7', - role: '', - }, - { - profileImg: '', - name: '감자탕수육', - gender: 'FEMALE', - userId: 12345, - id: '8', - role: '', - }, - { - profileImg: '', - name: '감자탕수육', - gender: 'FEMALE', - userId: 12345, - id: '9', - role: '', - }, - { - profileImg: '', - name: '감자탕수육', - gender: 'FEMALE', - userId: 12345, - id: '10', - role: '', - }, -] diff --git a/src/types/social.ts b/src/types/social.ts index 5a18f76..bd28305 100644 --- a/src/types/social.ts +++ b/src/types/social.ts @@ -1,10 +1 @@ export type SocialTabs = 'friendList' | 'dangTalk' - -export type FriendInfo = { - profileImg: string - name: string - gender: 'MALE' | 'FEMALE' - role: string - id: string - userId: number -} From 4b8c20169dd8216dc8d678457c989579e07c087d Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 10:57:07 +0900 Subject: [PATCH 06/21] =?UTF-8?q?=E2=9C=A8Feat:=20familyRole?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/familyRole.ts | 10 ++++++++++ src/pages/SocialPage/components/FriendItem/index.tsx | 3 ++- src/types/common.ts | 4 +++- 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 src/constants/familyRole.ts diff --git a/src/constants/familyRole.ts b/src/constants/familyRole.ts new file mode 100644 index 0000000..b03254f --- /dev/null +++ b/src/constants/familyRole.ts @@ -0,0 +1,10 @@ +export const FAMILY_ROLE = { + FATHER: '아빠', + MOTHER: '엄마', + ELDER_BROTHER: '오빠', + OLDER_BROTHER: '형', + ELDER_SISTER: '언니', + OLDER_SISTER: '누나', + GRANDFATHER: '할아버지', + GRANDMOTHER: '할머니', +} diff --git a/src/pages/SocialPage/components/FriendItem/index.tsx b/src/pages/SocialPage/components/FriendItem/index.tsx index 10a4be6..d4c768a 100644 --- a/src/pages/SocialPage/components/FriendItem/index.tsx +++ b/src/pages/SocialPage/components/FriendItem/index.tsx @@ -7,6 +7,7 @@ import * as S from './styles' import { FetchFriendListResponse } from '~apis/friend/fetchFriendList' import { createChatRoom } from '~apis/chatRoom/createChatRoom' import { useEffect, useState } from 'react' +import { FAMILY_ROLE } from '~constants/familyRole' type FriendItemProps = FetchFriendListResponse[number] @@ -29,7 +30,7 @@ export default function FriendItem({ gender, name, profileImg, memberId, familyR - {familyRole} + {FAMILY_ROLE[familyRole]} diff --git a/src/types/common.ts b/src/types/common.ts index 85325aa..a7e6602 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -1,5 +1,7 @@ +import { FAMILY_ROLE } from '~constants/familyRole' + export type Gender = 'MALE' | 'FEMALE' -export type FamilyRole = 'FATHER' | 'MOTHER' | 'SISTER' | 'BROTHER' +export type FamilyRole = keyof typeof FAMILY_ROLE export type DayOfWeek = 'MONDAY' | 'TUESDAY' | 'WEDNESDAY' | 'THURSDAY' | 'FRIDAY' | 'SATURDAY' | 'SUNDAY' export type NotificationType = 'WALK' | 'CHAT' | 'FRIEND' export type Provider = 'GOOGLE' | 'NAVER' | 'KAKAO' From 3ee5a861124aa1b9802f9c4e7cae1e120e7fae66 Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 10:59:50 +0900 Subject: [PATCH 07/21] =?UTF-8?q?=F0=9F=8E=A8Design:=20ChatItem=20UnreadCh?= =?UTF-8?q?atCount?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/SocialPage/components/ChatItem/styles.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pages/SocialPage/components/ChatItem/styles.ts b/src/pages/SocialPage/components/ChatItem/styles.ts index 1a4b887..d732531 100644 --- a/src/pages/SocialPage/components/ChatItem/styles.ts +++ b/src/pages/SocialPage/components/ChatItem/styles.ts @@ -27,6 +27,12 @@ export const UnreadChatCount = styled.span` display: block; border-radius: 22px; background-color: ${({ theme }) => theme.colors.brand.sub}; + min-width: 20px; + padding: 1.5px 6px; color: ${({ theme }) => theme.colors.grayscale.gc_4}; + + display: flex; + justify-content: center; + align-items: center; ` From 5a65d1ae6767d8c033a5e7023f4e9cee9296e08f Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 11:38:10 +0900 Subject: [PATCH 08/21] =?UTF-8?q?=E2=9C=A8Feat:=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EB=B0=94=EC=9D=B8=EB=94=A9=20(=EC=9E=84=EC=8B=9C?= =?UTF-8?q?=EB=A1=9C=20=EB=A7=88=EC=9D=B4=ED=8E=98=EC=9D=B4=EC=A7=80=20API?= =?UTF-8?q?=EB=A1=9C=20=EC=9E=91=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/member/fetchProfile.ts | 48 +++++++++++++++++++++++++++ src/components/DogProfile/index.tsx | 32 +++++++----------- src/pages/ProfilePage/index.tsx | 50 ++++++++++++++++------------- src/utils/calculateAge.ts | 12 +++++++ 4 files changed, 99 insertions(+), 43 deletions(-) create mode 100644 src/apis/member/fetchProfile.ts create mode 100644 src/utils/calculateAge.ts diff --git a/src/apis/member/fetchProfile.ts b/src/apis/member/fetchProfile.ts new file mode 100644 index 0000000..81a5cc9 --- /dev/null +++ b/src/apis/member/fetchProfile.ts @@ -0,0 +1,48 @@ +import { AxiosError } from 'axios' +import { APIResponse, CommonAPIResponse, ErrorResponse } from '~types/api' +import { axiosInstance } from '~apis/axiosInstance' + +export type FetchProfileResponse = Pick< + CommonAPIResponse, + | 'memberId' + | 'name' + | 'address' + | 'gender' + | 'familyRole' + | 'profileImg' + | 'totalDistance' + | 'walkCount' + | 'countWalksWithMember' + | 'dog' +> + +export const fetchProfile = async (): Promise> => { + try { + const { data } = await axiosInstance.get>(`/member/mypage`) + return data + } catch (error) { + if (error instanceof AxiosError) { + const { response } = error as AxiosError + + if (response) { + const { code, message } = response.data + switch (code) { + case 400: + throw new Error(message || '잘못된 요청입니다.') + case 401: + throw new Error(message || '인증에 실패했습니다.') + case 500: + throw new Error(message || '서버 오류가 발생했습니다.') + default: + throw new Error(message || '알 수 없는 오류가 발생했습니다.') + } + } else { + // 요청 자체가 실패한 경우 + throw new Error('네트워크 연결을 확인해주세요') + } + } + + console.error('예상치 못한 에러:', error) + throw new Error('다시 시도해주세요') + } +} diff --git a/src/components/DogProfile/index.tsx b/src/components/DogProfile/index.tsx index 69da547..5dfdefd 100644 --- a/src/components/DogProfile/index.tsx +++ b/src/components/DogProfile/index.tsx @@ -1,21 +1,25 @@ import * as S from './styles' import { Typo13, Typo15, Typo20 } from '~components/Typo' import { Separator } from '~components/Separator' - import Profile from '~components/Profile' -export default function DogProfile() { +import { Dog } from '~types/api' +import { calculateAge } from '~utils/calculateAge' + +type DogProfileProps = Pick + +export default function DogProfile({ birthDate, breed, comment, gender, name, profileImg }: DogProfileProps) { return ( - + - {dogInfo.name} - {dogInfo.breed} + {name} + {breed} - {dogInfo.age}살 + {calculateAge(birthDate)}살 - {dogInfo.gender === 'male' ? '남' : '여'} + {gender === 'MALE' ? '남' : '여'} 중성화 X @@ -30,21 +34,9 @@ export default function DogProfile() { 우리 댕댕이를 소개해요! - {dogInfo.intro} + {comment} ) } - -const dogInfo = { - name: '밤톨이', - breed: '포메라니안', - age: 4, - gender: 'male', - neutered: false, // 중성화 여부 - weight: 3.4, - profileImg: '', - intro: `우리아이 안 물어요 착해요. - 강아지껌을 너무 좋아해요 같이 놀아요. `, -} diff --git a/src/pages/ProfilePage/index.tsx b/src/pages/ProfilePage/index.tsx index e17619b..6e48c08 100644 --- a/src/pages/ProfilePage/index.tsx +++ b/src/pages/ProfilePage/index.tsx @@ -3,56 +3,60 @@ import Profile from '~components/Profile' import { Separator } from '~components/Separator' import { Typo13, Typo15, Typo20, Typo24 } from '~components/Typo' import * as S from './styles' - import DogProfile from '~components/DogProfile' +import { useEffect, useState } from 'react' +import { fetchProfile, FetchProfileResponse } from '~apis/member/fetchProfile' +import { FAMILY_ROLE } from '~constants/familyRole' + export default function ProfilePage() { const { id } = useParams() const navigate = useNavigate() - console.log(id) //todo id 이용해 fetch + + const [data, setData] = useState() + + console.log('memberId:', id) + + useEffect(() => { + //todo 현재 마이페이지 api임. todo id 이용한 fetch 함수로 바꿔야 함 + fetchProfile().then(data => { + console.log(data.data) + setData(data.data) + }) + }, []) + return ( - navigate(-1)} title='닉네임' /> + navigate(-1)} title={data?.name} /> - - {userInfo.name} + + {data?.name} - {userInfo.location} 거주 + {data?.address} 거주 - {userInfo.gender === 'male' ? '남자' : '여자'} + {data?.gender === 'MALE' ? '남자' : '여자'} - {userInfo.role} + {data ? FAMILY_ROLE[data.familyRole] : ''} - {userInfo.walkCount}회 + {data?.walkCount}회 누적 산책 횟수 - {userInfo.walkDistance}km + {data?.totalDistance}km 총 산책 거리 - {userInfo.gangbunttaCount}회 + {data?.countWalksWithMember}회 강번따 횟수 - + {data && } ) } - -const userInfo = { - name: '이성훈', - gender: 'male', - location: '용산구 남영동', - role: '할아버지', - walkCount: 23, - walkDistance: 32, - gangbunttaCount: 16, - profileImg: '', -} diff --git a/src/utils/calculateAge.ts b/src/utils/calculateAge.ts new file mode 100644 index 0000000..53b5e67 --- /dev/null +++ b/src/utils/calculateAge.ts @@ -0,0 +1,12 @@ +export function calculateAge(birthDate: string) { + const today = new Date() + const birthDateObj = new Date(birthDate) + let age = today.getFullYear() - birthDateObj.getFullYear() + const monthDiff = today.getMonth() - birthDateObj.getMonth() + + if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDateObj.getDate())) { + age-- + } + + return age +} From 16dc6782513b9f53869ec7ea9f445f901919c972 Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:04:04 +0900 Subject: [PATCH 09/21] =?UTF-8?q?=E2=9C=A8Feat:=20useCreateChatRoom?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/chatRoom/createChatRoom.ts | 4 +++ src/apis/chatRoom/useCreateChatRoom.tsx | 31 +++++++++++++++++++ .../components/FriendItem/index.tsx | 18 ++++------- 3 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 src/apis/chatRoom/useCreateChatRoom.tsx diff --git a/src/apis/chatRoom/createChatRoom.ts b/src/apis/chatRoom/createChatRoom.ts index 6e7144c..f527849 100644 --- a/src/apis/chatRoom/createChatRoom.ts +++ b/src/apis/chatRoom/createChatRoom.ts @@ -11,6 +11,10 @@ export type CreateChatRoomResponse = Pick< 'chatRoomId' | 'name' | 'lastMessage' | 'unreadMessageCount' | 'members' > +/** + * 새로운 채팅방을 생성하고, 채팅방 정보를 반환합니다. + *? 이미 동일한 맴버와의 채팅방이 있다면, 해당 채팅방을 반환합니다. + */ export const createChatRoom = async (req: CreateChatRoomRequest): Promise> => { try { const { data } = await axiosInstance.post>(`/chat/rooms`, req) diff --git a/src/apis/chatRoom/useCreateChatRoom.tsx b/src/apis/chatRoom/useCreateChatRoom.tsx new file mode 100644 index 0000000..1a20e75 --- /dev/null +++ b/src/apis/chatRoom/useCreateChatRoom.tsx @@ -0,0 +1,31 @@ +import { useMutation, UseMutationResult } from '@tanstack/react-query' +import ChatModal from '~modals/ChatModal' +import { useModalStore } from '~stores/modalStore' +import { APIResponse } from '~types/api' +import { createChatRoom, CreateChatRoomRequest, CreateChatRoomResponse } from './createChatRoom' + +export const useCreateChatRoom = (): UseMutationResult< + APIResponse, + Error, + CreateChatRoomRequest +> & { + createRoom: (req: CreateChatRoomRequest) => void +} => { + const { pushModal } = useModalStore() + + const mutation = useMutation, Error, CreateChatRoomRequest>({ + mutationFn: createChatRoom, + onSuccess: (data, { opponentMemberId }) => { + console.log(data.message || '채팅방 생성 성공') + pushModal() + }, + onError: error => { + console.error('채팅방 생성 실패:', error.message) + }, + }) + + return { + ...mutation, + createRoom: mutation.mutate, + } +} diff --git a/src/pages/SocialPage/components/FriendItem/index.tsx b/src/pages/SocialPage/components/FriendItem/index.tsx index d4c768a..5f38a80 100644 --- a/src/pages/SocialPage/components/FriendItem/index.tsx +++ b/src/pages/SocialPage/components/FriendItem/index.tsx @@ -1,23 +1,17 @@ +import { useCreateChatRoom } from '~apis/chatRoom/useCreateChatRoom' +import { FetchFriendListResponse } from '~apis/friend/fetchFriendList' import Profile from '~components/Profile' import { Separator } from '~components/Separator' import { Typo14, Typo17 } from '~components/Typo' -import ChatModal from '~modals/ChatModal' -import { useModalStore } from '~stores/modalStore' -import * as S from './styles' -import { FetchFriendListResponse } from '~apis/friend/fetchFriendList' -import { createChatRoom } from '~apis/chatRoom/createChatRoom' -import { useEffect, useState } from 'react' import { FAMILY_ROLE } from '~constants/familyRole' +import * as S from './styles' type FriendItemProps = FetchFriendListResponse[number] export default function FriendItem({ gender, name, profileImg, memberId, familyRole }: FriendItemProps) { - const { pushModal } = useModalStore() - const [chatRoomId, setChatRoomId] = useState(-1) + const { createRoom } = useCreateChatRoom() - useEffect(() => { - createChatRoom({ opponentMemberId: memberId }).then(data => setChatRoomId(data.data.chatRoomId)) - }, [memberId]) + const onClickMessageBtn = () => createRoom({ opponentMemberId: memberId }) return ( @@ -34,7 +28,7 @@ export default function FriendItem({ gender, name, profileImg, memberId, familyR - pushModal()}> + 메시지 From f3fa97b57dcfa78faf7ea24191f7c041d0261472 Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 16:16:23 +0900 Subject: [PATCH 10/21] =?UTF-8?q?=E2=9C=A8Feat:=20useSocialData?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/chatRoom/useSocialData.tsx | 27 +++++++++++++++++++ .../components/FriendChatList/index.tsx | 8 +++--- src/pages/SocialPage/index.tsx | 13 ++------- 3 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 src/apis/chatRoom/useSocialData.tsx diff --git a/src/apis/chatRoom/useSocialData.tsx b/src/apis/chatRoom/useSocialData.tsx new file mode 100644 index 0000000..743c744 --- /dev/null +++ b/src/apis/chatRoom/useSocialData.tsx @@ -0,0 +1,27 @@ +import { useQueries } from '@tanstack/react-query' +import { fetchChatRoomList } from '~apis/chatRoom/fetchChatRoomList' +import { fetchFriendList } from '~apis/friend/fetchFriendList' + +export function useSocialData() { + const results = useQueries({ + queries: [ + { + queryKey: ['chatRoomList'], + queryFn: () => fetchChatRoomList().then(response => response.data), + }, + { + queryKey: ['friendList'], + queryFn: () => fetchFriendList().then(response => response.data), + }, + ], + }) + + const [chatListQuery, friendListQuery] = results + + return { + chatList: chatListQuery.data ?? [], + friendList: friendListQuery.data ?? [], + isLoading: chatListQuery.isLoading || friendListQuery.isLoading, + isError: chatListQuery.isError || friendListQuery.isError, + } +} diff --git a/src/pages/SocialPage/components/FriendChatList/index.tsx b/src/pages/SocialPage/components/FriendChatList/index.tsx index 6099585..5323e3a 100644 --- a/src/pages/SocialPage/components/FriendChatList/index.tsx +++ b/src/pages/SocialPage/components/FriendChatList/index.tsx @@ -1,18 +1,16 @@ -import { FetchChatRoomListResponse } from '~apis/chatRoom/fetchChatRoomList' -import { FetchFriendListResponse } from '~apis/friend/fetchFriendList' import ChatItem from '~pages/SocialPage/components/ChatItem' import FriendItem from '~pages/SocialPage/components/FriendItem' import { SocialTabs } from '~types/social' import * as S from './styles' +import { useSocialData } from '~apis/chatRoom/useSocialData' type FriendChatListProps = { selectedTab: SocialTabs - friendList: FetchFriendListResponse - chatList: FetchChatRoomListResponse } -export default function FriendChatList({ selectedTab, friendList, chatList }: FriendChatListProps) { +export default function FriendChatList({ selectedTab }: FriendChatListProps) { //todo fetch by userId + const { chatList, friendList, isError, isLoading } = useSocialData() return ( diff --git a/src/pages/SocialPage/index.tsx b/src/pages/SocialPage/index.tsx index 29c2f88..cd0b74e 100644 --- a/src/pages/SocialPage/index.tsx +++ b/src/pages/SocialPage/index.tsx @@ -1,19 +1,10 @@ -import { useEffect, useState } from 'react' -import { fetchChatRoomList, FetchChatRoomListResponse } from '~apis/chatRoom/fetchChatRoomList' -import { fetchFriendList, FetchFriendListResponse } from '~apis/friend/fetchFriendList' +import { useState } from 'react' import { Typo15 } from '~components/Typo' import FriendChatList from '~pages/SocialPage/components/FriendChatList' import * as S from './styles' export default function SocialPage() { const [selectedTab, setSelectedTab] = useState<'friendList' | 'dangTalk'>('friendList') - const [chatList, setChatList] = useState([]) - const [friendList, setFriendList] = useState([]) - - useEffect(() => { - fetchChatRoomList().then(data => setChatList(data.data)) - fetchFriendList().then(data => setFriendList(data.data)) - }, []) return ( @@ -35,7 +26,7 @@ export default function SocialPage() { - + ) } From a40d45039e1fb8b40c6e4076098a6eb1bb06bea7 Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 16:18:55 +0900 Subject: [PATCH 11/21] =?UTF-8?q?=F0=9F=90=9BFix:=20chatRoomId=20DOM=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/SendMessageForm/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/SendMessageForm/index.tsx b/src/components/SendMessageForm/index.tsx index 28013fd..5a47c8f 100644 --- a/src/components/SendMessageForm/index.tsx +++ b/src/components/SendMessageForm/index.tsx @@ -5,9 +5,9 @@ import { CommonAPIResponse } from '~types/api' type SendMessageFormProps = React.FormHTMLAttributes & { chatCount: number -} & Pick +} & Partial> -export default function SendMessageForm({ chatCount, ...rest }: SendMessageFormProps) { +export default function SendMessageForm({ chatRoomId, chatCount, ...rest }: SendMessageFormProps) { const onSubmit = async (e: React.FormEvent) => { e.preventDefault() if (rest.onSubmit) rest.onSubmit(e) @@ -19,6 +19,7 @@ export default function SendMessageForm({ chatCount, ...rest }: SendMessageFormP //* 채팅 전송 웹소켓 } } + console.log('chatRoomId:', chatRoomId) return ( From e56dc0dc795b3ba5e94f9455f9dbc445b9351c3c Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 17:11:34 +0900 Subject: [PATCH 12/21] =?UTF-8?q?=E2=9C=A8Feat:=20useFetchProfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/chatRoom/useSocialData.tsx | 4 ++-- src/apis/member/fetchProfile.ts | 8 ++++--- src/apis/member/useFetchProfile.tsx | 10 ++++++++ src/pages/ProfilePage/index.tsx | 23 +++++++------------ .../components/FriendChatList/index.tsx | 3 +++ 5 files changed, 28 insertions(+), 20 deletions(-) create mode 100644 src/apis/member/useFetchProfile.tsx diff --git a/src/apis/chatRoom/useSocialData.tsx b/src/apis/chatRoom/useSocialData.tsx index 743c744..ad69e9f 100644 --- a/src/apis/chatRoom/useSocialData.tsx +++ b/src/apis/chatRoom/useSocialData.tsx @@ -7,11 +7,11 @@ export function useSocialData() { queries: [ { queryKey: ['chatRoomList'], - queryFn: () => fetchChatRoomList().then(response => response.data), + queryFn: () => fetchChatRoomList().then(res => res.data), }, { queryKey: ['friendList'], - queryFn: () => fetchFriendList().then(response => response.data), + queryFn: () => fetchFriendList().then(res => res.data), }, ], }) diff --git a/src/apis/member/fetchProfile.ts b/src/apis/member/fetchProfile.ts index 81a5cc9..7a8382e 100644 --- a/src/apis/member/fetchProfile.ts +++ b/src/apis/member/fetchProfile.ts @@ -1,7 +1,9 @@ import { AxiosError } from 'axios' -import { APIResponse, CommonAPIResponse, ErrorResponse } from '~types/api' +import { APIResponse, CommonAPIRequest, CommonAPIResponse, ErrorResponse } from '~types/api' import { axiosInstance } from '~apis/axiosInstance' +export type FetchProfileRequest = Pick + export type FetchProfileResponse = Pick< CommonAPIResponse, | 'memberId' @@ -16,9 +18,9 @@ export type FetchProfileResponse = Pick< | 'dog' > -export const fetchProfile = async (): Promise> => { +export const fetchProfile = async ({ memberId }: FetchProfileRequest): Promise> => { try { - const { data } = await axiosInstance.get>(`/member/mypage`) + const { data } = await axiosInstance.get>(`/member/${memberId}`) return data } catch (error) { if (error instanceof AxiosError) { diff --git a/src/apis/member/useFetchProfile.tsx b/src/apis/member/useFetchProfile.tsx new file mode 100644 index 0000000..b1be787 --- /dev/null +++ b/src/apis/member/useFetchProfile.tsx @@ -0,0 +1,10 @@ +import { UseQueryResult, useQuery } from '@tanstack/react-query' +import { FetchProfileResponse, fetchProfile } from '~apis/member/fetchProfile' + +export const useFetchProfile = (memberId: number): UseQueryResult => { + return useQuery({ + queryKey: ['profile', memberId], + queryFn: () => fetchProfile({ memberId }).then(data => data.data), + enabled: !!memberId, + }) +} diff --git a/src/pages/ProfilePage/index.tsx b/src/pages/ProfilePage/index.tsx index 6e48c08..935f2ae 100644 --- a/src/pages/ProfilePage/index.tsx +++ b/src/pages/ProfilePage/index.tsx @@ -1,28 +1,21 @@ import { useNavigate, useParams } from 'react-router-dom' +import { useFetchProfile } from '~apis/member/useFetchProfile' +import DogProfile from '~components/DogProfile' +import Loader from '~components/Loader' import Profile from '~components/Profile' import { Separator } from '~components/Separator' import { Typo13, Typo15, Typo20, Typo24 } from '~components/Typo' -import * as S from './styles' -import DogProfile from '~components/DogProfile' -import { useEffect, useState } from 'react' -import { fetchProfile, FetchProfileResponse } from '~apis/member/fetchProfile' import { FAMILY_ROLE } from '~constants/familyRole' +import * as S from './styles' export default function ProfilePage() { - const { id } = useParams() + const { id = '0' } = useParams() const navigate = useNavigate() - const [data, setData] = useState() - - console.log('memberId:', id) + const { data, isLoading, isError } = useFetchProfile(+id) - useEffect(() => { - //todo 현재 마이페이지 api임. todo id 이용한 fetch 함수로 바꿔야 함 - fetchProfile().then(data => { - console.log(data.data) - setData(data.data) - }) - }, []) + if (isLoading) return + if (isError) return
Error fetching profile
return ( diff --git a/src/pages/SocialPage/components/FriendChatList/index.tsx b/src/pages/SocialPage/components/FriendChatList/index.tsx index 5323e3a..95e7477 100644 --- a/src/pages/SocialPage/components/FriendChatList/index.tsx +++ b/src/pages/SocialPage/components/FriendChatList/index.tsx @@ -3,6 +3,7 @@ import FriendItem from '~pages/SocialPage/components/FriendItem' import { SocialTabs } from '~types/social' import * as S from './styles' import { useSocialData } from '~apis/chatRoom/useSocialData' +import Loader from '~components/Loader' type FriendChatListProps = { selectedTab: SocialTabs @@ -11,6 +12,8 @@ type FriendChatListProps = { export default function FriendChatList({ selectedTab }: FriendChatListProps) { //todo fetch by userId const { chatList, friendList, isError, isLoading } = useSocialData() + if (isLoading) return + if (isError) return
Error Fetching Social Data
return ( From 0a61c61452098e84c21903b16538e19ad19cc643 Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 17:23:19 +0900 Subject: [PATCH 13/21] =?UTF-8?q?=E2=9C=A8Feat:=20ChatItem=20createRoom=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SocialPage/components/ChatItem/index.tsx | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/pages/SocialPage/components/ChatItem/index.tsx b/src/pages/SocialPage/components/ChatItem/index.tsx index 381f27d..f78b452 100644 --- a/src/pages/SocialPage/components/ChatItem/index.tsx +++ b/src/pages/SocialPage/components/ChatItem/index.tsx @@ -1,25 +1,27 @@ -import * as S from './styles' +import { FetchChatRoomListResponse } from '~apis/chatRoom/fetchChatRoomList' +import { useCreateChatRoom } from '~apis/chatRoom/useCreateChatRoom' +import Profile from '~components/Profile' import { Separator } from '~components/Separator' import { Typo11, Typo13, Typo17 } from '~components/Typo' -import Profile from '~components/Profile' -import { useModalStore } from '~stores/modalStore' -import ChatModal from '~modals/ChatModal' -import { FetchChatRoomListResponse } from '~apis/chatRoom/fetchChatRoomList' +import * as S from './styles' +import { FAMILY_ROLE } from '~constants/familyRole' type ChatItemProps = FetchChatRoomListResponse[number] -export default function ChatItem({ chatRoomId, lastMessage, members, name, unreadMessageCount }: ChatItemProps) { - const { pushModal } = useModalStore() +export default function ChatItem({ lastMessage, members, name, unreadMessageCount }: ChatItemProps) { + const { createRoom } = useCreateChatRoom() + + const onClickChatItem = () => createRoom({ opponentMemberId: members[0].memberId }) return ( - pushModal()}> + {name} - {members[0].familyRole} + {FAMILY_ROLE[members[0].familyRole]} From 25e84d587e285f36bf21097efd2f84c200c127af Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 18:01:50 +0900 Subject: [PATCH 14/21] =?UTF-8?q?=F0=9F=90=9BFix:=20ProfilePage=20?= =?UTF-8?q?=EA=B9=9C=EB=B9=A1=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/member/useFetchProfile.tsx | 1 + src/pages/ProfilePage/index.tsx | 3 ++- src/stores/modalStore.ts | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/apis/member/useFetchProfile.tsx b/src/apis/member/useFetchProfile.tsx index b1be787..6808626 100644 --- a/src/apis/member/useFetchProfile.tsx +++ b/src/apis/member/useFetchProfile.tsx @@ -6,5 +6,6 @@ export const useFetchProfile = (memberId: number): UseQueryResult fetchProfile({ memberId }).then(data => data.data), enabled: !!memberId, + staleTime: 1000 * 60 * 5, // 5분 }) } diff --git a/src/pages/ProfilePage/index.tsx b/src/pages/ProfilePage/index.tsx index 935f2ae..92d684d 100644 --- a/src/pages/ProfilePage/index.tsx +++ b/src/pages/ProfilePage/index.tsx @@ -12,8 +12,9 @@ export default function ProfilePage() { const { id = '0' } = useParams() const navigate = useNavigate() - const { data, isLoading, isError } = useFetchProfile(+id) + const { data, isLoading, isError, isFetching } = useFetchProfile(+id) + if (isFetching) return
isFetching
if (isLoading) return if (isError) return
Error fetching profile
diff --git a/src/stores/modalStore.ts b/src/stores/modalStore.ts index 7c86205..c256267 100644 --- a/src/stores/modalStore.ts +++ b/src/stores/modalStore.ts @@ -31,6 +31,7 @@ export const useModalStore = create((set, get) => ({ clearModal: () => { set({ modalList: [] }) // 모든 모달 제거 시 히스토리 초기화 - window.history.go(-get().modalList.length) + const modalCount = get().modalList.length + if (modalCount) window.history.go(-modalCount) }, })) From 9899f737a63ef18fffd61a94ebd975ed275434b6 Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 21:29:52 +0900 Subject: [PATCH 15/21] =?UTF-8?q?=F0=9F=90=9BFix:=20FamilyDDangPage=20DogP?= =?UTF-8?q?rofile=20props?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/FamilyDDangPage/index.tsx | 4 ++-- src/pages/ProfilePage/index.tsx | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pages/FamilyDDangPage/index.tsx b/src/pages/FamilyDDangPage/index.tsx index 07f97bb..4b51e13 100644 --- a/src/pages/FamilyDDangPage/index.tsx +++ b/src/pages/FamilyDDangPage/index.tsx @@ -15,8 +15,8 @@ export default function FamilyDDang() { - - + {/* 데이터 바인딩 시 props 넣어주세요 */} + diff --git a/src/pages/ProfilePage/index.tsx b/src/pages/ProfilePage/index.tsx index 92d684d..935f2ae 100644 --- a/src/pages/ProfilePage/index.tsx +++ b/src/pages/ProfilePage/index.tsx @@ -12,9 +12,8 @@ export default function ProfilePage() { const { id = '0' } = useParams() const navigate = useNavigate() - const { data, isLoading, isError, isFetching } = useFetchProfile(+id) + const { data, isLoading, isError } = useFetchProfile(+id) - if (isFetching) return
isFetching
if (isLoading) return if (isError) return
Error fetching profile
From 8d94b724820a4d9d5227f4e7baf2dc291b3a850c Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 23:15:38 +0900 Subject: [PATCH 16/21] =?UTF-8?q?=E2=9C=A8Feat:=20ProfilePage=20meta=20dat?= =?UTF-8?q?a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/ProfilePage/index.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pages/ProfilePage/index.tsx b/src/pages/ProfilePage/index.tsx index 935f2ae..e3fa0df 100644 --- a/src/pages/ProfilePage/index.tsx +++ b/src/pages/ProfilePage/index.tsx @@ -7,6 +7,7 @@ import { Separator } from '~components/Separator' import { Typo13, Typo15, Typo20, Typo24 } from '~components/Typo' import { FAMILY_ROLE } from '~constants/familyRole' import * as S from './styles' +import { Helmet } from 'react-helmet-async' export default function ProfilePage() { const { id = '0' } = useParams() @@ -19,6 +20,10 @@ export default function ProfilePage() { return ( + + DDang | {data?.name} + + navigate(-1)} title={data?.name} /> From 68aa435c6c48484ef16ce7a825b7159ca0017091 Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Wed, 4 Dec 2024 23:22:05 +0900 Subject: [PATCH 17/21] =?UTF-8?q?=E2=9C=A8Feat:=20lighthouse=EC=97=90=20pr?= =?UTF-8?q?ofile=20url=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lighthouserc.cjs | 1 + src/pages/ProfilePage/index.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lighthouserc.cjs b/lighthouserc.cjs index fb16b48..06365e2 100644 --- a/lighthouserc.cjs +++ b/lighthouserc.cjs @@ -8,6 +8,7 @@ module.exports = { // 'http://localhost:4173/walk', 'http://localhost:4173/login', 'http://localhost:4173/mypage', + 'http://localhost:4173/profile/:id', ], numberOfRuns: 2, startServerReadyPattern: 'Local', diff --git a/src/pages/ProfilePage/index.tsx b/src/pages/ProfilePage/index.tsx index e3fa0df..41c12df 100644 --- a/src/pages/ProfilePage/index.tsx +++ b/src/pages/ProfilePage/index.tsx @@ -1,3 +1,4 @@ +import { Helmet } from 'react-helmet-async' import { useNavigate, useParams } from 'react-router-dom' import { useFetchProfile } from '~apis/member/useFetchProfile' import DogProfile from '~components/DogProfile' @@ -7,7 +8,6 @@ import { Separator } from '~components/Separator' import { Typo13, Typo15, Typo20, Typo24 } from '~components/Typo' import { FAMILY_ROLE } from '~constants/familyRole' import * as S from './styles' -import { Helmet } from 'react-helmet-async' export default function ProfilePage() { const { id = '0' } = useParams() From bfffe48c38eee8b5f696c01bce98f3e1bc69d16d Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:38:46 +0900 Subject: [PATCH 18/21] =?UTF-8?q?=E2=9C=A8Feat:=20ErrorBoundary,=20Suspens?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 12 ++++++++++ package.json | 5 ++-- src/apis/chatRoom/useSocialData.tsx | 4 ++-- src/components/ErrorFallback/index.tsx | 23 +++++++++++++++++++ src/components/ErrorFallback/styles.ts | 3 +++ src/components/Loader/index.tsx | 2 +- .../components/FriendChatList/index.tsx | 8 ++----- src/pages/SocialPage/index.tsx | 16 +++++++++++-- 8 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 src/components/ErrorFallback/index.tsx create mode 100644 src/components/ErrorFallback/styles.ts diff --git a/package-lock.json b/package-lock.json index d2ae54e..325e69c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "ol": "^10.2.1", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-error-boundary": "^4.1.2", "react-helmet-async": "^2.0.5", "react-icons": "^5.3.0", "react-router-dom": "^6.28.0", @@ -9715,6 +9716,17 @@ "react": "^18.3.1" } }, + "node_modules/react-error-boundary": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.1.2.tgz", + "integrity": "sha512-GQDxZ5Jd+Aq/qUxbCm1UtzmL/s++V7zKgE8yMktJiCQXCCFZnMZh9ng+6/Ne6PjNSXH0L9CjeOEREfRnq6Duag==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, "node_modules/react-fast-compare": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", diff --git a/package.json b/package.json index da8a71e..c177f53 100644 --- a/package.json +++ b/package.json @@ -14,11 +14,11 @@ "build-and-test": "npm run build && lhci autorun" }, "dependencies": { - "@stomp/stompjs": "^7.0.0", "@emotion/react": "^11.13.5", "@emotion/styled": "^11.13.5", "@mui/material": "^6.1.9", "@mui/styled-engine-sc": "^6.1.9", + "@stomp/stompjs": "^7.0.0", "@tanstack/react-query": "^5.62.2", "@tanstack/react-query-devtools": "^5.62.2", "d3": "^7.9.0", @@ -26,6 +26,7 @@ "ol": "^10.2.1", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-error-boundary": "^4.1.2", "react-helmet-async": "^2.0.5", "react-icons": "^5.3.0", "react-router-dom": "^6.28.0", @@ -42,8 +43,8 @@ "@types/ol": "^7.0.0", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.0", - "@types/sockjs-client": "^1.5.4", "@types/react-textarea-autosize": "^8.0.0", + "@types/sockjs-client": "^1.5.4", "@types/styled-components": "^5.1.34", "@typescript-eslint/eslint-plugin": "^7.8.0", "@typescript-eslint/parser": "^7.8.0", diff --git a/src/apis/chatRoom/useSocialData.tsx b/src/apis/chatRoom/useSocialData.tsx index ad69e9f..5282461 100644 --- a/src/apis/chatRoom/useSocialData.tsx +++ b/src/apis/chatRoom/useSocialData.tsx @@ -1,9 +1,9 @@ -import { useQueries } from '@tanstack/react-query' +import { useSuspenseQueries } from '@tanstack/react-query' import { fetchChatRoomList } from '~apis/chatRoom/fetchChatRoomList' import { fetchFriendList } from '~apis/friend/fetchFriendList' export function useSocialData() { - const results = useQueries({ + const results = useSuspenseQueries({ queries: [ { queryKey: ['chatRoomList'], diff --git a/src/components/ErrorFallback/index.tsx b/src/components/ErrorFallback/index.tsx new file mode 100644 index 0000000..ce24d21 --- /dev/null +++ b/src/components/ErrorFallback/index.tsx @@ -0,0 +1,23 @@ +import { FallbackProps } from 'react-error-boundary' +import { ActionButton } from '~components/Button/ActionButton' +import { Typo15, Typo17 } from '~components/Typo' +import * as S from './styles' + +type ErrorFallbackProps = FallbackProps + +export default function ErrorFallback({ error, resetErrorBoundary }: ErrorFallbackProps) { + return ( + + {error.message}... + + 오류가 발생했네요! +
+ 아래 버튼을 통해 다시 요청해보세요! +
+ + resetErrorBoundary()}> + 다시 불러오기! + +
+ ) +} diff --git a/src/components/ErrorFallback/styles.ts b/src/components/ErrorFallback/styles.ts new file mode 100644 index 0000000..64fcf62 --- /dev/null +++ b/src/components/ErrorFallback/styles.ts @@ -0,0 +1,3 @@ +import { styled } from 'styled-components' + +export const ErrorFallback = styled.div`` diff --git a/src/components/Loader/index.tsx b/src/components/Loader/index.tsx index 6aad46e..f6c1f0d 100644 --- a/src/components/Loader/index.tsx +++ b/src/components/Loader/index.tsx @@ -1,5 +1,5 @@ import * as S from './styles' export default function Loader() { - return Loading... + return Loader... } diff --git a/src/pages/SocialPage/components/FriendChatList/index.tsx b/src/pages/SocialPage/components/FriendChatList/index.tsx index 95e7477..0ac6d9c 100644 --- a/src/pages/SocialPage/components/FriendChatList/index.tsx +++ b/src/pages/SocialPage/components/FriendChatList/index.tsx @@ -1,19 +1,15 @@ +import { useSocialData } from '~apis/chatRoom/useSocialData' import ChatItem from '~pages/SocialPage/components/ChatItem' import FriendItem from '~pages/SocialPage/components/FriendItem' import { SocialTabs } from '~types/social' import * as S from './styles' -import { useSocialData } from '~apis/chatRoom/useSocialData' -import Loader from '~components/Loader' type FriendChatListProps = { selectedTab: SocialTabs } export default function FriendChatList({ selectedTab }: FriendChatListProps) { - //todo fetch by userId - const { chatList, friendList, isError, isLoading } = useSocialData() - if (isLoading) return - if (isError) return
Error Fetching Social Data
+ const { chatList, friendList } = useSocialData() return ( diff --git a/src/pages/SocialPage/index.tsx b/src/pages/SocialPage/index.tsx index cd0b74e..494240d 100644 --- a/src/pages/SocialPage/index.tsx +++ b/src/pages/SocialPage/index.tsx @@ -1,7 +1,11 @@ -import { useState } from 'react' +import { Suspense, useState } from 'react' import { Typo15 } from '~components/Typo' import FriendChatList from '~pages/SocialPage/components/FriendChatList' import * as S from './styles' +import { ErrorBoundary } from 'react-error-boundary' +import ErrorFallback from '~components/ErrorFallback' +import { QueryErrorResetBoundary } from '@tanstack/react-query' +import Loader from '~components/Loader' export default function SocialPage() { const [selectedTab, setSelectedTab] = useState<'friendList' | 'dangTalk'>('friendList') @@ -26,7 +30,15 @@ export default function SocialPage() {
- + + {({ reset }) => ( + + }> + + + + )} + ) } From a85bed31b225aa9a6f5b360e3172f57031b2e1a0 Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:53:35 +0900 Subject: [PATCH 19/21] =?UTF-8?q?=E2=9C=A8Feat:=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=ED=8E=98=EC=9D=B4=EC=A7=80=20ErrorBoundary,=20Susp?= =?UTF-8?q?ense=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/member/useFetchProfile.tsx | 9 ++++---- src/pages/ProfilePage/index.tsx | 32 +++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/apis/member/useFetchProfile.tsx b/src/apis/member/useFetchProfile.tsx index 6808626..5796498 100644 --- a/src/apis/member/useFetchProfile.tsx +++ b/src/apis/member/useFetchProfile.tsx @@ -1,11 +1,10 @@ -import { UseQueryResult, useQuery } from '@tanstack/react-query' -import { FetchProfileResponse, fetchProfile } from '~apis/member/fetchProfile' +import { useSuspenseQuery, UseSuspenseQueryResult } from '@tanstack/react-query' +import { fetchProfile, FetchProfileResponse } from '~apis/member/fetchProfile' -export const useFetchProfile = (memberId: number): UseQueryResult => { - return useQuery({ +export const useFetchProfile = (memberId: number): UseSuspenseQueryResult => { + return useSuspenseQuery({ queryKey: ['profile', memberId], queryFn: () => fetchProfile({ memberId }).then(data => data.data), - enabled: !!memberId, staleTime: 1000 * 60 * 5, // 5분 }) } diff --git a/src/pages/ProfilePage/index.tsx b/src/pages/ProfilePage/index.tsx index 41c12df..7ab7656 100644 --- a/src/pages/ProfilePage/index.tsx +++ b/src/pages/ProfilePage/index.tsx @@ -1,7 +1,11 @@ +import { QueryErrorResetBoundary } from '@tanstack/react-query' +import { Suspense } from 'react' +import { ErrorBoundary } from 'react-error-boundary' import { Helmet } from 'react-helmet-async' import { useNavigate, useParams } from 'react-router-dom' import { useFetchProfile } from '~apis/member/useFetchProfile' import DogProfile from '~components/DogProfile' +import ErrorFallback from '~components/ErrorFallback' import Loader from '~components/Loader' import Profile from '~components/Profile' import { Separator } from '~components/Separator' @@ -9,19 +13,13 @@ import { Typo13, Typo15, Typo20, Typo24 } from '~components/Typo' import { FAMILY_ROLE } from '~constants/familyRole' import * as S from './styles' -export default function ProfilePage() { - const { id = '0' } = useParams() +function ProfileContent({ id }: { id: number }) { + const { data } = useFetchProfile(+id) const navigate = useNavigate() - - const { data, isLoading, isError } = useFetchProfile(+id) - - if (isLoading) return - if (isError) return
Error fetching profile
- return ( - DDang | {data?.name} + {`DDang | ${data?.name}`} navigate(-1)} title={data?.name} /> @@ -58,3 +56,19 @@ export default function ProfilePage() { ) } + +export default function ProfilePage() { + const { id = '0' } = useParams() + + return ( + + {({ reset }) => ( + + }> + + + + )} + + ) +} From d2d49d5607bda486fd9e708a021aaca67f6edf8b Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:23:53 +0900 Subject: [PATCH 20/21] =?UTF-8?q?=E2=99=BB=EF=B8=8FRefactor:=20else?= =?UTF-8?q?=EB=AC=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/typescript.code-snippets | 8 ++++---- src/apis/chatRoom/createChatRoom.ts | 5 ++--- src/apis/chatRoom/fetchChatRoomList.ts | 5 ++--- src/apis/friend/fetchFriendList.ts | 5 ++--- src/apis/member/fetchProfile.ts | 5 ++--- src/components/SendMessageForm/index.tsx | 19 +++++++++++-------- 6 files changed, 23 insertions(+), 24 deletions(-) diff --git a/.vscode/typescript.code-snippets b/.vscode/typescript.code-snippets index e7e11ee..4bd6c80 100644 --- a/.vscode/typescript.code-snippets +++ b/.vscode/typescript.code-snippets @@ -59,10 +59,10 @@ " default:", " throw new Error(message || '알 수 없는 오류가 발생했습니다.')", " }", - " } else {", - " // 요청 자체가 실패한 경우", - " throw new Error('네트워크 연결을 확인해주세요')", - " }", + " } ", + " // 요청 자체가 실패한 경우", + " throw new Error('네트워크 연결을 확인해주세요')", + " ", " }", "", " console.error('예상치 못한 에러:', error);", diff --git a/src/apis/chatRoom/createChatRoom.ts b/src/apis/chatRoom/createChatRoom.ts index f527849..bde5dad 100644 --- a/src/apis/chatRoom/createChatRoom.ts +++ b/src/apis/chatRoom/createChatRoom.ts @@ -37,10 +37,9 @@ export const createChatRoom = async (req: CreateChatRoomRequest): Promise & { export default function SendMessageForm({ chatRoomId, chatCount, ...rest }: SendMessageFormProps) { const onSubmit = async (e: React.FormEvent) => { e.preventDefault() - if (rest.onSubmit) rest.onSubmit(e) - else { - if (chatCount === 0) { - //* 채팅방 생성 - await createChatRoom({ opponentMemberId: 123 }) - } - //* 채팅 전송 웹소켓 + if (rest.onSubmit) { + rest.onSubmit(e) + return } + + if (chatCount === 0) { + //* 채팅방 생성 + await createChatRoom({ opponentMemberId: 123 }) + } + //* 채팅 전송 웹소켓 + console.log('chatRoomId:', chatRoomId) } - console.log('chatRoomId:', chatRoomId) + return ( From 819f3e2045ffa06b6f08b0ed96e3df73dcefad5e Mon Sep 17 00:00:00 2001 From: shlee9999 <95556588+shlee9999@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:41:07 +0900 Subject: [PATCH 21/21] =?UTF-8?q?=E2=9C=A8Feat:=20queryKey?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/chatRoom/useSocialData.tsx | 5 +++-- src/apis/member/useFetchProfile.tsx | 3 ++- src/constants/queryKey.ts | 7 +++++++ src/pages/ProfilePage/index.tsx | 1 + 4 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 src/constants/queryKey.ts diff --git a/src/apis/chatRoom/useSocialData.tsx b/src/apis/chatRoom/useSocialData.tsx index 5282461..3d45bab 100644 --- a/src/apis/chatRoom/useSocialData.tsx +++ b/src/apis/chatRoom/useSocialData.tsx @@ -1,16 +1,17 @@ import { useSuspenseQueries } from '@tanstack/react-query' import { fetchChatRoomList } from '~apis/chatRoom/fetchChatRoomList' import { fetchFriendList } from '~apis/friend/fetchFriendList' +import { queryKey } from '~constants/queryKey' export function useSocialData() { const results = useSuspenseQueries({ queries: [ { - queryKey: ['chatRoomList'], + queryKey: queryKey.social.chatRoomList(), queryFn: () => fetchChatRoomList().then(res => res.data), }, { - queryKey: ['friendList'], + queryKey: queryKey.social.friendList(), queryFn: () => fetchFriendList().then(res => res.data), }, ], diff --git a/src/apis/member/useFetchProfile.tsx b/src/apis/member/useFetchProfile.tsx index 5796498..9d7a80e 100644 --- a/src/apis/member/useFetchProfile.tsx +++ b/src/apis/member/useFetchProfile.tsx @@ -1,9 +1,10 @@ import { useSuspenseQuery, UseSuspenseQueryResult } from '@tanstack/react-query' import { fetchProfile, FetchProfileResponse } from '~apis/member/fetchProfile' +import { queryKey } from '~constants/queryKey' export const useFetchProfile = (memberId: number): UseSuspenseQueryResult => { return useSuspenseQuery({ - queryKey: ['profile', memberId], + queryKey: queryKey.profile(memberId), queryFn: () => fetchProfile({ memberId }).then(data => data.data), staleTime: 1000 * 60 * 5, // 5분 }) diff --git a/src/constants/queryKey.ts b/src/constants/queryKey.ts new file mode 100644 index 0000000..3a216be --- /dev/null +++ b/src/constants/queryKey.ts @@ -0,0 +1,7 @@ +export const queryKey = { + social: { + chatRoomList: () => ['chatRoomList'], + friendList: () => ['friendList'], + }, + profile: (memberId: number) => ['profile', memberId], +} diff --git a/src/pages/ProfilePage/index.tsx b/src/pages/ProfilePage/index.tsx index 7ab7656..c23d87a 100644 --- a/src/pages/ProfilePage/index.tsx +++ b/src/pages/ProfilePage/index.tsx @@ -16,6 +16,7 @@ import * as S from './styles' function ProfileContent({ id }: { id: number }) { const { data } = useFetchProfile(+id) const navigate = useNavigate() + return (