Skip to content

Commit 98b2558

Browse files
committed
Merge branch 'dev' into OD-197
2 parents 5a7b761 + a0d2295 commit 98b2558

46 files changed

Lines changed: 637 additions & 663 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import PostInstaFeedSelect from '@pages/Post/PostInstaFeedSelect';
2525

2626
import Chats from '@pages/Chats';
2727
import ChatRoom from '@pages/Chats/ChatRoom';
28+
import MatchingRoom from '@pages/Chats/MatchingRoom';
2829

2930
import NotFound from '@pages/NotFound';
3031

@@ -56,6 +57,7 @@ const protectedRoutes = [
5657
// 메시지/채팅
5758
{ path: '/chats', element: <Chats /> },
5859
{ path: '/chats/:chatRoomId', element: <ChatRoom /> },
60+
{ path: '/matching', element: <MatchingRoom /> },
5961
];
6062

6163
// 인증이 필요 없는 페이지 배열

src/apis/chatting/dto.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export interface LatestMessageDto {
2121
// 채팅방 전체 대화 내역 조회
2222
// 최근 메시지 수신
2323
// response
24-
export interface chatRoomMessagesData {
24+
export interface ChatRoomMessagesData {
2525
id: number;
2626
content: string;
2727
fromUser: FromUserDto;

src/apis/matching/dto.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import type { BaseSuccessResponse } from '@apis/core/dto';
22

3+
type RequestStatusEnum = 'accepted' | 'rejected' | 'pending';
4+
35
// 매칭 요청
46
// request
57
export interface CreateMatchingRequest {
@@ -18,29 +20,34 @@ export interface CreateMatchingData {
1820
targetId: number;
1921
}
2022

21-
// 매칭 리스트 조회
22-
// response
23-
export type GetMatchingListResponse = BaseSuccessResponse<GetMatchingListData>;
24-
25-
export interface GetMatchingListData {
26-
hasMatching: boolean;
27-
matchingsCount: number;
28-
matching: MatchingDto[];
23+
// 최근 매칭 조회 (채팅방 리스트에서)
24+
export interface LatestMatchingData {
25+
id?: number;
26+
requesterId?: number;
27+
targetId?: number;
28+
requestStatus?: RequestStatusEnum;
29+
createdAt: Date;
2930
}
3031

31-
export interface MatchingDto {
32-
id: number; // matchingId
32+
// 전체 매칭 리스트 조회
33+
export interface MatchingData {
34+
id: number;
35+
message: string;
36+
createdAt: string;
37+
chatRoomId: number;
38+
targetId: number;
3339
requester: RequesterDto;
40+
requestStatus: RequestStatusEnum;
3441
}
3542

3643
export interface RequesterDto {
37-
id: number; // requesterId
44+
id: number;
3845
nickname: string;
3946
profilePictureUrl: string;
40-
representativePost: RepresentativePost;
47+
representativePost: RepresentativePostDto;
4148
}
4249

43-
export interface RepresentativePost {
50+
export interface RepresentativePostDto {
4451
postImages: PostImageDto[];
4552
styleTags: string[];
4653
}

src/apis/matching/index.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { newRequest } from '@apis/core';
33
import type {
44
CreateMatchingRequest,
55
CreateMatchingResponse,
6-
GetMatchingListResponse,
76
ModifyMatchingStatusRequest,
87
ModifyMatchingStatusResponse,
98
} from './dto';
@@ -12,9 +11,6 @@ import type {
1211
export const createMatchingApi = (data: CreateMatchingRequest) =>
1312
newRequest.post<CreateMatchingResponse>('/matching', data);
1413

15-
// 매칭 리스트 조회
16-
export const getMatchingListApi = () => newRequest.get<GetMatchingListResponse>('/matching');
17-
1814
// 매칭 요청 수락 및 거절
1915
export const modifyMatchingStatusApi = (matchingId: number, data: ModifyMatchingStatusRequest) =>
2016
newRequest.patch<ModifyMatchingStatusResponse>(`/matching/${matchingId}`, data);

src/context/SocketProvider.tsx

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,55 @@ import { createContext, useContext, useEffect, useState } from 'react';
22

33
import { io, Socket } from 'socket.io-client';
44

5-
const SocketContext = createContext<Socket | null>(null);
5+
type SocketMap = { [endpoint: string]: Socket };
6+
7+
const SocketContext = createContext<SocketMap | null>(null);
68

79
export const SocketProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
8-
const [socket, setSocket] = useState<Socket | null>(null);
10+
const [socketMap, setSocketMap] = useState<SocketMap>({});
911

1012
useEffect(() => {
11-
const newSocket = io(`${import.meta.env.VITE_NEW_API_URL}/socket/chatting`, {
12-
transports: ['websocket'],
13-
});
14-
setSocket(newSocket);
15-
16-
newSocket.on('connect', () => {
17-
console.log('connection is open');
13+
const endpoints = ['chatting', 'matching']; // 필요한 엔드포인트 추가
14+
const newSockets: SocketMap = {};
15+
16+
endpoints.forEach((endpoint) => {
17+
const socket = io(`${import.meta.env.VITE_NEW_API_URL}/socket/${endpoint}`, {
18+
transports: ['websocket'],
19+
});
20+
newSockets[endpoint] = socket;
21+
22+
socket.on('connect', () => {
23+
console.log(`${endpoint} connection is open`);
24+
});
25+
26+
socket.on('disconnect', (reason) => {
27+
console.log(`${endpoint} Disconnected from server:`, reason);
28+
});
29+
30+
socket.on('connect_error', (err) => {
31+
console.log(`${endpoint} connect error:`, err.message);
32+
});
1833
});
1934

20-
newSocket.on('disconnect', (reason) => {
21-
console.log('Disconnected from server:', reason);
22-
});
23-
24-
newSocket.on('connect_error', (err) => {
25-
console.log(err.message);
26-
});
35+
setSocketMap(newSockets);
2736

2837
return () => {
29-
newSocket.disconnect();
38+
Object.values(newSockets).forEach((socket) => socket.disconnect());
3039
};
3140
}, []);
3241

33-
// 소켓 설정이 완료되지 않은 경우 렌더링 방지
34-
// 채팅방에서 새로고침했을 때 오류 방지
35-
if (!socket) {
42+
if (!Object.keys(socketMap).length) {
3643
return null;
3744
}
3845

39-
return <SocketContext.Provider value={socket}>{children}</SocketContext.Provider>;
46+
return <SocketContext.Provider value={socketMap}>{children}</SocketContext.Provider>;
4047
};
4148

42-
export const useSocket = () => {
43-
const context = useContext(SocketContext);
44-
if (context === null) {
45-
throw new Error('useSocket must be used within a SocketProvider');
49+
// 엔드포인트를 인자로 받아 해당 소켓을 반환하는 훅
50+
export const useSocket = (endpoint = 'chatting') => {
51+
const socketMap = useContext(SocketContext);
52+
if (!socketMap || !socketMap[endpoint]) {
53+
throw new Error(`useSocket must be used within a SocketProvider with a valid endpoint (${endpoint})`);
4654
}
47-
return context;
55+
return socketMap[endpoint];
4856
};

src/pages/Chats/ChatRoom/ChatBox/index.tsx renamed to src/pages/Chats/ChatBox/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import SendIcon from '@assets/default/send-message.svg';
1111

1212
import { ChatBoxContainer, Textarea, SendButton } from './styles';
1313

14-
const ChatBox: React.FC = () => {
14+
const ChatBox: React.FC<{ disabled?: boolean }> = ({ disabled = false }) => {
1515
const [newMessage, setNewMessage] = useState('');
1616
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
1717
const socket = useSocket();
@@ -22,9 +22,9 @@ const ChatBox: React.FC = () => {
2222
const isOtherUserValid = !!(otherUser && otherUser.id);
2323

2424
useEffect(() => {
25-
if (textareaRef.current && !isOtherUserValid) {
25+
if (textareaRef.current && (!isOtherUserValid || disabled)) {
2626
textareaRef.current.disabled = true;
27-
textareaRef.current.placeholder = '메시지를 보낼 수 없습니다.';
27+
textareaRef.current.placeholder = '메시지를 보낼 수 없는 채팅방입니다.';
2828
}
2929
}, []);
3030

File renamed without changes.

src/pages/Chats/ChatRoom/createExtendedMessages.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ import 'dayjs/locale/ko';
33

44
import defaultProfile from '@assets/default/defaultProfile.svg';
55

6-
import type { OtherUserDto, chatRoomMessagesData } from '@apis/chatting/dto';
6+
import type { OtherUserDto, ChatRoomMessagesData } from '@apis/chatting/dto';
77

8-
import type { ExtendedMessageDto, RcvdMessageProps, SentMessageProps } from './dto';
8+
import { RcvdMessageProps } from '../RcvdMessage/dto';
9+
import { SentMessageProps } from '../SentMessage/dto';
10+
11+
import type { ExtendedMessageDto } from './dto';
912

1013
export const createExtendedMessages = (
11-
allMessages: chatRoomMessagesData[],
14+
allMessages: ChatRoomMessagesData[],
1215
userId: number,
1316
otherUser: OtherUserDto | null,
1417
) => {
@@ -21,7 +24,7 @@ export const createExtendedMessages = (
2124
};
2225

2326
// 렌더링에 필요한 요소를 추가한 메시지 배열
24-
const temp: ExtendedMessageDto[] = allMessages.map((message: chatRoomMessagesData, index) => {
27+
const temp: ExtendedMessageDto[] = allMessages.map((message: ChatRoomMessagesData, index) => {
2528
const prevMessage = index !== 0 ? allMessages[index - 1] : null;
2629
const nextMessage = index !== allMessages.length - 1 ? allMessages[index + 1] : null;
2730
const formattedTime = dayjs(message.createdAt).format('HH:mm');

src/pages/Chats/ChatRoom/dto.ts

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,10 @@
1-
import type { chatRoomMessagesData } from '@apis/chatting/dto';
1+
import type { ChatRoomMessagesData } from '@apis/chatting/dto';
22

3-
export interface ExtendedMessageDto extends chatRoomMessagesData {
3+
import { RcvdMessageProps } from '../RcvdMessage/dto';
4+
import { SentMessageProps } from '../SentMessage/dto';
5+
6+
export interface ExtendedMessageDto extends ChatRoomMessagesData {
47
isDateBarVisible: boolean;
58
sentMessage?: SentMessageProps;
69
rcvdMessage?: RcvdMessageProps;
710
}
8-
9-
export interface SentMessageProps {
10-
content: string;
11-
isSenderChanged: boolean; // 상단 마진 추가 여부
12-
isTimeVisible: boolean; // 메시지 옆 시간 표시 여부
13-
formattedTime: string; // 타임스탬프를 HH:MM 형태로 변환한 값
14-
}
15-
16-
export interface RcvdMessageProps {
17-
fromUserNickname: string;
18-
profilePictureUrl: string;
19-
content: string;
20-
isSenderChanged: boolean; // 상단 마진 추가 여부
21-
isProfileImageVisible: boolean; // 사용자 프로필 표시 여부
22-
isTimeVisible: boolean; // 메시지 옆 시간 표시 여부
23-
formattedTime: string; // 타임스탬프를 HH:MM 형태로 변환한 값
24-
}

src/pages/Chats/ChatRoom/index.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,18 @@ import Loading from '@components/Loading';
2424
import Modal from '@components/Modal';
2525
import TopBar from '@components/TopBar';
2626

27-
import type { chatRoomMessagesData } from '@apis/chatting/dto';
27+
import type { ChatRoomMessagesData } from '@apis/chatting/dto';
2828
import type { PostUserBlockRequest } from '@apis/user-block/dto';
2929
import type { BottomSheetMenuProps } from '@components/BottomSheet/BottomSheetMenu/dto';
3030
import type { BottomSheetProps } from '@components/BottomSheet/dto';
3131
import type { ModalProps } from '@components/Modal/dto';
3232

3333
import type { ExtendedMessageDto } from './dto';
3434

35-
import ChatBox from './ChatBox/index';
36-
import DateBar from './DateBar/index';
37-
import RcvdMessage from './RcvdMessage/index';
38-
import SentMessage from './SentMessage/index';
35+
import ChatBox from '../ChatBox/index';
36+
import DateBar from '../DateBar/index';
37+
import RcvdMessage from '../RcvdMessage/index';
38+
import SentMessage from '../SentMessage/index';
3939

4040
import { createExtendedMessages } from './createExtendedMessages';
4141
import { MessagesContainer } from './styles';
@@ -114,7 +114,7 @@ const ChatRoom: React.FC = () => {
114114
};
115115

116116
// 전체 메시지 조회 socket api
117-
const getChatRoomMessages = (data: chatRoomMessagesData[]) => {
117+
const getChatRoomMessages = (data: ChatRoomMessagesData[]) => {
118118
setAllMessages(data);
119119
if (data.length > messageLengthRef.current) {
120120
setIsScroll((prev) => !prev);
@@ -123,7 +123,7 @@ const ChatRoom: React.FC = () => {
123123
};
124124

125125
// 새 메시지 수신 socket api
126-
const getNewMessage = (data: chatRoomMessagesData) => {
126+
const getNewMessage = (data: ChatRoomMessagesData) => {
127127
setAllMessages((prevMessages) => [...prevMessages, data]);
128128
setIsScroll((prev) => !prev);
129129
};

0 commit comments

Comments
 (0)