-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'Weekly11' of https://github.com/kakao-tech-campus-2nd-s…
…tep3/Team9_FE into feat/#108-api
- Loading branch information
Showing
17 changed files
with
699 additions
and
165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,136 @@ | ||
import { Client, Stomp } from '@stomp/stompjs'; | ||
import SockJS from 'sockjs-client'; | ||
import { CompatClient } from '@stomp/stompjs'; | ||
// import { Client, CompatClient, Stomp } from '@stomp/stompjs'; | ||
// import SockJS from 'sockjs-client'; | ||
|
||
// import type { ChatMessage } from './types'; | ||
|
||
export const BASE_URL = import.meta.env.VITE_APP_BASE_URL_CHAT; | ||
|
||
export type ChatMessage = { | ||
sender: { email: string }; | ||
content: string; | ||
imageUrl?: string; | ||
}; | ||
// let stompClient: Client | null = null; | ||
|
||
// const accessToken = localStorage.getItem('accessToken'); | ||
// /** | ||
// * WebSocket과 서버와의 연결 설정 함수 | ||
// * @param onMessageReceived - 수신된 메시지를 처리할 콜백 함수 | ||
// * @param onError - 에러 시 호출될 콜백 함수 | ||
// */ | ||
// export function connectWebSocket( | ||
// chatRoomId: number, | ||
// onMessageReceived?: (message: ChatMessage) => void, | ||
// onError?: (error: string) => void, | ||
// ): void { | ||
// // WebSocket 연결, STOMP 클라이언트 설정 | ||
// const socket = new SockJS(`${BASE_URL}/ws`); | ||
// stompClient = Stomp.over(() => socket); | ||
|
||
let stompClient: Client | null = null; | ||
// // 연결이 열렸을 때 호출될 콜백 함수 | ||
// stompClient.onConnect = () => { | ||
// // SUBSCRIBE | ||
// stompClient?.subscribe(`/v1/sub/chat/rooms/${chatRoomId}`, (message) => { | ||
// console.log('received messages: ', message); | ||
|
||
/** | ||
* WebSocket과 서버와의 연결 설정 함수 | ||
* @param onMessageReceived - 수신된 메시지를 처리할 콜백 함수 | ||
* @param onError - 에러 시 호출될 콜백 함수 | ||
*/ | ||
export function connectWebSocket( | ||
chatRoomId: number, | ||
onMessageReceived?: (message: ChatMessage) => void, | ||
onError?: (error: string) => void, | ||
): void { | ||
// WebSocket 연결, STOMP 클라이언트 설정 | ||
const socket = new SockJS(`${BASE_URL}/ws`); | ||
stompClient = Stomp.over(socket); | ||
// // const parsedMessage: ChatMessage = JSON.parse(message.body); | ||
|
||
// 연결이 열렸을 때 호출될 콜백 함수 | ||
stompClient.onConnect = (frame) => { | ||
console.log('Connected: ' + frame); | ||
// // if (onMessageReceived) { | ||
// // onMessageReceived(parsedMessage); | ||
// // } | ||
// }); | ||
// }; | ||
|
||
// 토픽 구독 | ||
stompClient?.subscribe(`/sub/chat/rooms/${chatRoomId}`, (message) => { | ||
const parsedMessage: ChatMessage = JSON.parse(message.body); | ||
|
||
if (onMessageReceived) { | ||
onMessageReceived(parsedMessage); | ||
} | ||
}); | ||
// // 에러 났을 때 호출될 콜백 함수 | ||
// stompClient.onStompError = (errorFrame) => { | ||
// console.error('Broker reported error: ' + errorFrame.headers['message']); | ||
|
||
console.log('WebSocket 연결 성공'); | ||
}; | ||
// if (onError) { | ||
// onError(errorFrame.headers['message']); | ||
// } | ||
// }; | ||
|
||
// 에러 났을 때 호출될 콜백 함수 | ||
stompClient.onStompError = (errorFrame) => { | ||
console.error('Broker reported error: ' + errorFrame.headers['message']); | ||
// // CONNECT | ||
// stompClient.activate(); | ||
// } | ||
|
||
if (onError) { | ||
onError(errorFrame.headers['message']); | ||
} | ||
// 메시지(TEXT) 전송 함수 | ||
export function sendMessage( | ||
stompClient: CompatClient, | ||
chatRoomId: number, | ||
email: string, | ||
content: string, | ||
): void { | ||
const message = { | ||
sender: email, | ||
content, | ||
messageType: 'TEXT', | ||
}; | ||
|
||
stompClient.activate(); | ||
} | ||
|
||
// 메시지 전송 함수 | ||
export function sendMessage(chatRoomId: number, message: ChatMessage): void { | ||
if (stompClient && stompClient.connected) { | ||
// SEND | ||
stompClient.publish({ | ||
destination: `/pub/chat/${chatRoomId} `, | ||
destination: `/v1/pub/chat/${chatRoomId}`, | ||
body: JSON.stringify(message), | ||
// headers: { receipt: 'message-12345' }, | ||
}); | ||
} else { | ||
throw new Error('STOMP 클라이언트를 먼저 연결해주세요'); | ||
console.log('STOMP 클라이언트를 먼저 연결해주세요'); | ||
throw new Error('연결이 끊겼습니다. 새로고침 해주세요.'); | ||
} | ||
} | ||
|
||
// 파일 전송 함수 | ||
export async function sendFile( | ||
stompClient: CompatClient, | ||
chatRoomId: number, | ||
email: string, | ||
file: File, | ||
): Promise<void> { | ||
// File을 바이너리 데이터로 변환 | ||
return new Promise((resolve, reject) => { | ||
const reader = new FileReader(); | ||
reader.readAsArrayBuffer(file); | ||
|
||
reader.onload = () => { | ||
if (stompClient && stompClient.connected && reader.result) { | ||
// const fileBuffer = reader.result as ArrayBuffer; | ||
const fileBytes = new Uint8Array(reader.result as ArrayBuffer); | ||
const fileBase64 = btoa( | ||
fileBytes.reduce((data, byte) => data + String.fromCharCode(byte), ''), | ||
); | ||
|
||
const message = { | ||
chatRoomId, | ||
userEmail: email, | ||
// fileBytes: fileBuffer, | ||
// fileBytes, | ||
fileBase64: fileBase64, | ||
}; | ||
|
||
try { | ||
stompClient.publish({ | ||
destination: `/v1/pub/chat/${chatRoomId}/file`, | ||
body: JSON.stringify(message), | ||
}); | ||
resolve(); | ||
} catch (error) { | ||
console.error('Failed to send file:', error); | ||
reject(error); | ||
} | ||
} else { | ||
console.log('STOMP 클라이언트를 먼저 연결해주세요'); | ||
reject('연결이 끊겼습니다. 새로고침 해주세요.'); | ||
} | ||
}; | ||
|
||
reader.onerror = (error) => { | ||
console.error('File reading error:', error); | ||
reject(error); | ||
}; | ||
}); | ||
} | ||
|
||
// WebSocket 연결 해제 함수 | ||
export function disconnectWebSocket(): void { | ||
export function disconnectWebSocket(stompClient: CompatClient) { | ||
if (stompClient) { | ||
// DISCONNECT | ||
stompClient.deactivate(); | ||
stompClient = null; | ||
// stompClient.disconnect(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { useSuspenseQuery } from '@tanstack/react-query'; | ||
import { isAxiosError } from 'axios'; | ||
|
||
import type { ChatRoom } from '@/types/chats'; | ||
import fetchInstance from '../fetchInstance'; | ||
import QUERY_KEYS from '../queryKeys'; | ||
import { BASE_URL } from './index'; | ||
|
||
type GetChatRoomProps = { | ||
chatRoomId: number; | ||
}; | ||
|
||
type GetChatRoomData = ChatRoom; | ||
|
||
async function getChatRoom({ chatRoomId }: GetChatRoomProps): Promise<GetChatRoomData> { | ||
try { | ||
const response = await fetchInstance(BASE_URL).get(`/v1/chat/rooms/${chatRoomId}`); | ||
|
||
return response.data; | ||
} catch (error) { | ||
if (isAxiosError(error)) { | ||
if (error.response) { | ||
throw new Error(error.response.data.message || '채팅방 정보 가져오기 실패'); | ||
} else { | ||
throw new Error('네트워크 오류 또는 서버에 연결할 수 없습니다.'); | ||
} | ||
} else { | ||
throw new Error('알 수 없는 오류입니다.'); | ||
} | ||
} | ||
} | ||
|
||
const useGetChatRoom = (chatRoomId: number) => { | ||
return useSuspenseQuery<GetChatRoomData, Error>({ | ||
queryKey: [QUERY_KEYS.CHAT_ROOM, chatRoomId], | ||
queryFn: () => getChatRoom({ chatRoomId }), | ||
}); | ||
}; | ||
|
||
export default useGetChatRoom; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { useMutation } from '@tanstack/react-query'; | ||
import { isAxiosError } from 'axios'; | ||
|
||
import type { ChatRoom } from '@/types/chats'; | ||
import { getQueryParams } from '@/utils/queryParams'; | ||
import fetchInstance from '../fetchInstance'; | ||
import { BASE_URL } from './index'; | ||
|
||
type PostChatRoomProps = { | ||
userEmail1: string; | ||
userEmail2: string; | ||
}; | ||
|
||
type PostChatRoomData = ChatRoom; | ||
|
||
async function postChatRoom({ | ||
userEmail1, | ||
userEmail2, | ||
}: PostChatRoomProps): Promise<PostChatRoomData> { | ||
try { | ||
const queryParams = getQueryParams({ userEmail1: userEmail1, userEmail2: userEmail2 }); | ||
const response = await fetchInstance(BASE_URL).post(`/v1/chat/rooms?${queryParams}`); | ||
|
||
return response.data; | ||
} catch (error) { | ||
if (isAxiosError(error)) { | ||
if (error.response) { | ||
throw new Error(error.response.data.message || '채팅방 생성 실패'); | ||
} else { | ||
throw new Error('네트워크 오류 또는 서버에 연결할 수 없습니다.'); | ||
} | ||
} else { | ||
throw new Error('알 수 없는 오류입니다.'); | ||
} | ||
} | ||
} | ||
|
||
const usePostChatRoom = () => { | ||
return useMutation<PostChatRoomData, Error, PostChatRoomProps>({ | ||
mutationFn: (props: PostChatRoomProps) => postChatRoom(props), | ||
}); | ||
}; | ||
|
||
export default usePostChatRoom; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,46 @@ | ||
import { useNavigate } from 'react-router-dom'; | ||
|
||
import usePostChatRoom from '@/apis/chats/usePostChatRoom'; | ||
import CTA, { CTAContainer } from '@/components/common/CTA'; | ||
import useUserStore from '@/store/useUserStore'; | ||
import { RouterPath } from '@/routes/path'; | ||
|
||
const USER_EMAIL_1 = '[email protected]'; | ||
const USER_EMAIL_2 = '[email protected]'; | ||
|
||
const ProductDetails = () => { | ||
return <>ProductDetails</>; | ||
const { email } = useUserStore(); | ||
const userEmail1 = email || USER_EMAIL_1; // 사용자 본인 이메일 | ||
const userEmail2 = USER_EMAIL_2; // 상대방 이메일 | ||
const navigate = useNavigate(); | ||
|
||
const { mutate: postChatRoom } = usePostChatRoom(); | ||
|
||
const handleClickChat = () => { | ||
postChatRoom( | ||
{ | ||
userEmail1, | ||
userEmail2, | ||
}, | ||
{ | ||
onSuccess: (data) => { | ||
const chatRoomId = data.id; | ||
navigate(`${RouterPath.chats}/${chatRoomId}`); | ||
}, | ||
onError: (error) => { | ||
alert(error); | ||
}, | ||
}, | ||
); | ||
}; | ||
|
||
return ( | ||
<> | ||
<CTAContainer> | ||
<CTA label="채팅하기" onClick={handleClickChat}></CTA> | ||
</CTAContainer> | ||
</> | ||
); | ||
}; | ||
|
||
export default ProductDetails; |
Oops, something went wrong.