) => {
setInputValue(event.target.value);
};
- //메세지 전송
+ // 메시지 전송
const sendMessage = () => {
- if (stompClient.current && inputValue) {
- //현재로서는 임의의 테스트 값을 삽입
- const body = {
- id: 1,
- name: "테스트1",
- message: inputValue
+ if (inputValue) {
+ const newMessage: Message = {
+ content: inputValue,
+ sender: "나" // 닉네임이 없으면 '익명'으로 설정
};
- stompClient.current.send(
- `/pub/chat-rooms/${chatRoomId}`,
- {},
- JSON.stringify(body)
- );
- setInputValue("");
+ setMessages((prevMessages) => [...prevMessages, newMessage]); // 새 메시지 추가
+ setInputValue(""); // 입력 필드 초기화
}
};
useEffect(() => {
- connect();
- fetchMessages();
- // 컴포넌트 언마운트 시 웹소켓 연결 해제
- return () => disconnect();
- }, []);
-
- const connect = () => {
- //웹소켓 연결
- const socket = new WebSocket(
- process.env.NODE_ENV === "production"
- ? "wss://coach-coach.site/ws"
- : "ws://localhost:8080/ws"
- );
- stompClient.current = Stomp.over(socket);
- stompClient.current.connect({}, () => {
- //메시지 수신(1은 roomId를 임시로 표현)
- stompClient.current?.subscribe(
- `/sub/chat-rooms/${chatRoomId}`,
- (message) => {
- //누군가 발송했던 메시지를 리스트에 추가
- const newMessage: Message = JSON.parse(message.body);
- setMessages((prevMessages) => [...prevMessages, newMessage]);
- }
- );
- });
- };
-
- const fetchMessages = () => {
- return axios
- .get("/v1/chat-rooms/{chatRoomId}/messages")
- .then((response) => {
- setMessages(response.data);
- });
- };
-
- const disconnect = () => {
- if (stompClient.current) {
- stompClient.current.disconnect();
- }
- };
+ setMessages(initialMessages); // 기존 메시지 가져오기
+ }, [chatRoomId]);
const title = (() => {
if (activeHours.length > 0 && isMatching) return "코치님과 매칭되었습니다";
@@ -103,35 +69,63 @@ const ChatMessage = () => {
{title}
{activeHours.length > 0 && (
- <>
-
- {`${nickname}님의 채팅 가능 시간은 `}
- {activeHours}
- {` 에요`}
-
- >
+
+ {`${nickname}님의 채팅 가능 시간은 `}
+ {activeHours}
+ {` 에요`}
+
)}
-
-
+
+ {Array.isArray(messages) &&
+ messages.map((item, index) =>
+ item.sender === "나" ? (
+ {item.content}
+ ) : (
+ {item.content}
+ )
+ )}
+
+
+
+
+
);
};
-const ChatMessageStyle = styled.div``;
+const ChatMessageStyle = styled.div`
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 10px;
+ padding: 10px;
+ width: 100%;
+ max-width: 600px;
+ margin: 0 auto;
+ position: relative; /* 하단 입력 필드 위치 조정을 위해 relative 추가 */
+ height: 100vh; /* 전체 화면 높이 사용 */
+`;
+
+const ChatContainer = styled.div`
+ overflow-y: auto;
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ flex-grow: 1; /* 화면의 남은 공간을 채움 */
+`;
const ChatTitleStyle = styled.div`
position: relative;
@@ -139,6 +133,7 @@ const ChatTitleStyle = styled.div`
flex-direction: column;
align-items: center;
padding: 20px 0;
+ width: 100%;
.title {
font-size: 20px;
@@ -162,8 +157,8 @@ const ChatTitleStyle = styled.div`
`;
const AbleTimeStyle = styled.div`
- word-wrap: break-word; /* 긴 단어 자동 줄바꿈 */
- white-space: pre-wrap; /* 공백 유지 및 줄바꿈 가능 */
+ word-wrap: break-word;
+ white-space: pre-wrap;
font-size: 12px;
`;
@@ -171,4 +166,68 @@ const HighlightedText = styled.span`
color: #0075ff;
`;
+const PartnerChatStyle = styled.div`
+ align-self: flex-start; /* 부모 컨테이너 기준 왼쪽 정렬 */
+ background-color: #0075ff;
+ color: #ffffff;
+ border-radius: 20px;
+ max-width: 350px;
+ min-height: 40px;
+ padding: 10px 15px;
+ margin: 5px 0;
+ word-wrap: break-word;
+ white-space: pre-wrap;
+ display: inline-block; /* 글자 크기에 따라 넓이 조정 */
+`;
+
+const MyChatStyle = styled.div`
+ align-self: flex-end; /* 부모 컨테이너 기준 오른쪽 정렬 */
+ background-color: #3a3a3a;
+ color: #ffffff;
+ border-radius: 20px;
+ max-width: 350px;
+ min-height: 40px;
+ padding: 10px 15px;
+ margin: 5px 0;
+ word-wrap: break-word;
+ white-space: pre-wrap;
+ display: inline-block;
+ margin-left: auto; /* 오른쪽 끝으로 이동 */
+`;
+
+const ChatInputAndButtonStyle = styled.div`
+ display: flex;
+ align-items: center; /* 입력 필드와 버튼을 세로 중앙 정렬 */
+ position: absolute;
+ bottom: 150px; /* 화면 하단에서 10px 위로 */
+ left: 50%; /* 화면 중앙 정렬을 위해 왼쪽 50% 이동 */
+ transform: translateX(-50%); /* 중앙 정렬 보정 */
+ width: 100%; /* 부모 컨테이너 너비에 맞춤 */
+ max-width: 600px; /* 최대 너비 제한 */
+ padding: 10px;
+ background-color: #1e1e1e; /* 배경색 추가 (선택 사항) */
+ border-radius: 10px; /* 테두리 둥글게 */
+
+ svg {
+ margin-left: 10px;
+ }
+`;
+
+const ChatInputStyle = styled.input`
+ flex-grow: 1; /* 남은 공간을 채움 */
+ min-height: 60px;
+ border-radius: 10px;
+ background-color: #252932;
+ padding-left: 20px;
+ font-size: 18px;
+ color: #ffffff;
+ border: none; /* 테두리 제거 */
+ outline: none; /* 포커스 시 테두리 제거 */
+
+ &::placeholder {
+ color: #777c89;
+ font-size: 18px;
+ }
+`;
+
export default ChatMessage;
diff --git a/src/components/mypage/CoachProfileSection.tsx b/src/components/mypage/CoachProfileSection.tsx
index f3a6a7d..bacea00 100644
--- a/src/components/mypage/CoachProfileSection.tsx
+++ b/src/components/mypage/CoachProfileSection.tsx
@@ -34,8 +34,6 @@ const CoachProfileSection = () => {
if (userMeData?.isCoach !== undefined) {
if (userMeData?.isCoach) {
setShouldFetchCoachProfile(true);
- } else {
- openModal();
}
}
}, [userMeData, openModal]);
@@ -123,7 +121,9 @@ const CoachProfileSection = () => {
{
+ closeModal();
+ }}
>
확인
diff --git a/src/constants/apiPath.ts b/src/constants/apiPath.ts
index 79ff831..7e2ed65 100644
--- a/src/constants/apiPath.ts
+++ b/src/constants/apiPath.ts
@@ -31,5 +31,5 @@ export const API_PATH = {
recordV2: "/v2/records",
review: "/v1/coaches/reviews",
memberChat: "/v1/users/chat-rooms",
- coachChat: "v1/coaches/chat-rooms"
+ coachChat: "/v1/coaches/chat-rooms"
};
diff --git a/src/constants/assets.tsx b/src/constants/assets.tsx
index 733ffd3..ebf4dff 100644
--- a/src/constants/assets.tsx
+++ b/src/constants/assets.tsx
@@ -15,6 +15,7 @@ import Star from "@/assets/images/star.svg?react";
import Warning from "@/assets/images/warning.svg?react";
import XCircle from "@/assets/images/x-circle.svg?react";
import X from "@/assets/images/x.svg?react";
+import SendButton from "@/assets/images/SendButton.svg?react";
import { CgDetailsMore } from "react-icons/cg";
import { FaCheck, FaRegStar } from "react-icons/fa";
import { IoIosArrowBack, IoMdMore } from "react-icons/io";
@@ -70,5 +71,6 @@ export const ICONS = {
arrow: ArrowDown,
noLocation: NoLocation,
warning: Warning,
- notification: Notification
+ notification: Notification,
+ send: SendButton
};
diff --git a/src/main.tsx b/src/main.tsx
index 729da71..24ff7cd 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,21 +1,8 @@
import React from "react";
import App from "./App.tsx";
import { HelmetProvider } from "react-helmet-async";
-import * as Sentry from "@sentry/react";
import ReactDOM from "react-dom/client";
-Sentry.init({
- dsn: import.meta.env.VITE_SENTRY_DSN,
- integrations: [
- Sentry.browserTracingIntegration(),
- Sentry.replayIntegration()
- ],
- tracesSampleRate: 1.0,
- tracePropagationTargets: [import.meta.env.VITE_SENTRY_URL],
- replaysSessionSampleRate: 0.1,
- replaysOnErrorSampleRate: 1.0
-});
-
async function enableMocking() {
if (import.meta.env.MODE !== "development") {
return;