Skip to content

Commit ff93eec

Browse files
authored
Merge pull request #73 from CommitField/dev
merge
2 parents fbfc607 + 7e65d87 commit ff93eec

File tree

10 files changed

+330
-65
lines changed

10 files changed

+330
-65
lines changed

package-lock.json

Lines changed: 49 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"@stomp/stompjs": "^7.0.0",
1515
"axios": "^1.8.1",
1616
"chart.js": "^4.4.8",
17+
"framer-motion": "^12.4.11",
1718
"lucide-react": "^0.475.0",
1819
"react": "^19.0.0",
1920
"react-chartjs-2": "^5.3.0",

src/App.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { BrowserRouter as Router, Route, Routes, useNavigate } from "react-router-dom";
33
import { useEffect, useState } from "react";
44
import Home from "./pages/Home";
5+
import Pets from "./pages/Pets";
56
import ErrorPage from "./error/ErrorPage";
67
import TestAPI from "./pages/TestAPI";
78
import GithubLogin from "./components/GithubLogin";
@@ -23,6 +24,7 @@ function App() {
2324
<Routes>
2425
<Route path="/" element={<GithubLogin />} />
2526
<Route path="/home" element={<Home />} />
27+
<Route path="/pets" element={<Pets />} />
2628
<Route path="/error" element={<ErrorPage />} />
2729
<Route path="/testapi" element={<TestAPI />} />
2830
<Route path="/protected" element={

src/components/ChatRoom.jsx

Lines changed: 43 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -166,15 +166,17 @@ const ChatRoom = ({ roomId: propRoomId, onLeaveRoom, refreshRooms }) => {
166166
});
167167
const userData = await userResponse.json();
168168

169-
if (!userData || !userData.username) {
169+
if (!userData || !userData.id) {
170170
throw new Error('사용자 정보를 가져올 수 없습니다.');
171171
}
172172

173173
// 새 메시지 객체 생성
174174
const newMsg = {
175175
chatMsgId: `local-${Date.now()}`,
176-
userId: userData.username,
176+
userId: userData.id,
177+
username: userData.username,
177178
nickname: userData.nickname || userData.username,
179+
avatarUrl: userData.avatarUrl, // 프로필 이미지 URL 추가
178180
message: messageText,
179181
sendAt: new Date().toISOString()
180182
};
@@ -186,6 +188,7 @@ const ChatRoom = ({ roomId: propRoomId, onLeaveRoom, refreshRooms }) => {
186188
const wsSuccess = await webSocketService.sendMessage(
187189
roomIdInt,
188190
messageText,
191+
userData.id,
189192
userData.username,
190193
userData.nickname || userData.username
191194
);
@@ -289,12 +292,12 @@ const ChatRoom = ({ roomId: propRoomId, onLeaveRoom, refreshRooms }) => {
289292
});
290293
const userData = await response.json();
291294

292-
if (!userData || !userData.username) {
295+
if (!userData || !userData.id) {
293296
throw new Error('사용자 정보를 가져올 수 없습니다.');
294297
}
295298

296299
setUserInfo({
297-
id: userData.username,
300+
id: userData.id,
298301
nickname: userData.nickname || userData.username
299302
});
300303
} catch (err) {
@@ -304,73 +307,54 @@ const ChatRoom = ({ roomId: propRoomId, onLeaveRoom, refreshRooms }) => {
304307
}
305308
};
306309

307-
// 웹소켓 메시지 핸들러 - 일반 웹소켓용
310+
// 웹소켓 메시지 핸들러 수정
308311
const handleWebSocketMessage = (message) => {
309312
console.log('WebSocket message received:', message);
310313

311-
// 시스템 메시지 처리
312314
if (message.type === 'SYSTEM' || message.type === 'SUBSCRIBE_ACK' || message.type === 'UNSUBSCRIBE_ACK') {
313-
// 시스템 메시지는 상태 표시만 하고 채팅에 추가하지 않음
314-
console.log('System/Control message:', message.message);
315315
return;
316316
}
317317

318-
// 에러 메시지 처리
319318
if (message.type === 'ERROR') {
320-
console.error('WebSocket error message:', message.message);
321-
// alert(message.message || '채팅 오류가 발생했습니다.');
322319
return;
323320
}
324321

325-
// 채팅방 ID 확인
326-
const messageRoomId = message.roomId ? parseInt(message.roomId) : null;
327-
if (messageRoomId && messageRoomId !== roomIdInt) {
328-
console.log('Message for different room ignored:', messageRoomId);
322+
const messageRoomId = parseInt(message.roomId);
323+
if (messageRoomId !== roomIdInt) {
329324
return;
330325
}
331326

332-
// 메시지 형식 처리
333-
const newMessage = {
334-
chatMsgId: message.id || message.chatMsgId || Date.now(),
335-
userId: message.userId,
336-
nickname: message.from || message.nickname || '알 수 없는 사용자',
337-
message: message.message || message.content || '',
338-
sendAt: message.sendAt || new Date().toISOString()
339-
};
327+
// 현재 사용자가 보낸 메시지인지 확인
328+
if (message.isLocalMessage || parseInt(message.userId) === parseInt(userInfo.id)) {
329+
console.log('Ignoring own message:', message);
330+
return;
331+
}
340332

341-
// 중복 메시지 방지
342333
setMessages(prevMessages => {
343-
// 로컬 메시지 ID (local-*)로 시작하는 임시 메시지 대체
344-
const isLocalMessage = prevMessages.some(msg =>
345-
msg.chatMsgId?.toString().startsWith('local-') &&
346-
msg.message === newMessage.message &&
347-
msg.userId === newMessage.userId
334+
// 중복 메시지 확인
335+
const isDuplicate = prevMessages.some(msg =>
336+
msg.chatMsgId === message.id ||
337+
(msg.message === message.message &&
338+
parseInt(msg.userId) === parseInt(message.userId) &&
339+
Math.abs(new Date(msg.sendAt) - new Date(message.sendAt)) < 1000)
348340
);
349341

350-
let updatedMessages;
351-
if (isLocalMessage) {
352-
// 임시 메시지를 서버 메시지로 대체
353-
updatedMessages = prevMessages.map(msg =>
354-
(msg.chatMsgId?.toString().startsWith('local-') &&
355-
msg.message === newMessage.message &&
356-
msg.userId === newMessage.userId)
357-
? newMessage
358-
: msg
359-
);
360-
} else {
361-
// 이미 동일한 ID의 메시지가 있는지 확인
362-
const exists = prevMessages.some(msg =>
363-
msg.chatMsgId === newMessage.chatMsgId &&
364-
!msg.chatMsgId?.toString().startsWith('local-')
365-
);
366-
367-
if (exists) return prevMessages;
368-
updatedMessages = [...prevMessages, newMessage];
342+
if (isDuplicate) {
343+
console.log('Duplicate message ignored:', message);
344+
return prevMessages;
369345
}
370346

371-
// 로컬 스토리지에 업데이트된 메시지 저장
372-
saveChatMessages(roomId, updatedMessages);
347+
const newMessage = {
348+
chatMsgId: message.id || Date.now(),
349+
userId: parseInt(message.userId),
350+
nickname: message.nickname || message.from || '알 수 없는 사용자',
351+
avatarUrl: message.avatarUrl, // avatarUrl 추가
352+
message: message.message,
353+
sendAt: message.sendAt || new Date().toISOString()
354+
};
373355

356+
const updatedMessages = [...prevMessages, newMessage];
357+
saveChatMessages(roomId, updatedMessages);
374358
return updatedMessages;
375359
});
376360
};
@@ -655,7 +639,15 @@ const ChatRoom = ({ roomId: propRoomId, onLeaveRoom, refreshRooms }) => {
655639
className={`message ${msg.userId === userInfo.id ? 'sent' : 'received'} ${msg.failed ? 'failed' : ''}`}
656640
>
657641
<div className="avatar">
658-
{/* 실제 사용자 아바타가 있으면 추가 */}
642+
{msg.avatarUrl ? (
643+
<img
644+
src={msg.avatarUrl}
645+
alt={msg.nickname}
646+
className="user-avatar"
647+
/>
648+
) : (
649+
<i className="fas fa-user"></i>
650+
)}
659651
</div>
660652
<div className="content">
661653
<div className="sender">{msg.nickname}</div>

src/components/ChatStyles.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,17 @@
603603
overflow: hidden;
604604
}
605605

606+
.message .avatar img.user-avatar {
607+
width: 100%;
608+
height: 100%;
609+
object-fit: cover;
610+
}
611+
612+
.message .avatar i.fa-user {
613+
font-size: 20px;
614+
color: #fff;
615+
}
616+
606617
.message.sent .avatar {
607618
display: none;
608619
}

src/pages/Pets.css

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/* 전체 배경 설정 */
2+
body {
3+
background-color: rgb(63, 178, 127);
4+
margin: 0;
5+
display: flex;
6+
justify-content: center;
7+
align-items: center;
8+
height: 100vh;
9+
}
10+
11+
/* 펫이 움직이는 공간 */
12+
.pets-wrapper {
13+
display: flex;
14+
justify-content: center;
15+
align-items: center;
16+
width: 100vw;
17+
height: 100vh;
18+
}
19+
20+
.pets-container {
21+
position: relative;
22+
width: 800px;
23+
height: 500px;
24+
background-color: white;
25+
border-radius: 10px;
26+
overflow: hidden;
27+
}
28+
29+
/* 펫을 감싸는 div */
30+
.pet-wrapper {
31+
position: absolute;
32+
width: 100px;
33+
height: 100px;
34+
}
35+
36+
/* 알이 0.8배~1배로 커졌다 작아지는 효과 */
37+
.pet-egg {
38+
width: 100px;
39+
height: 100px;
40+
animation: egg-bounce 1.5s infinite ease-in-out alternate;
41+
}
42+
43+
@keyframes egg-bounce {
44+
0% {
45+
transform: scaleY(0.7);
46+
}
47+
100% {
48+
transform: scaleY(1);
49+
}
50+
}
51+
52+
.pets-wrapper {
53+
position: relative; /* 하위 요소들이 절대적으로 위치할 수 있도록 설정 */
54+
}
55+
56+
.pets-container {
57+
position: relative;
58+
}
59+
60+
.home-button-container {
61+
display: flex;
62+
justify-content: center;
63+
margin-top: 20px; /* 위쪽에 간격 추가 */
64+
position: absolute;
65+
bottom: 10px; /* 버튼을 하단에 고정 */
66+
width: 100%; /* 버튼이 가로로 꽉 차도록 설정 */
67+
}
68+
69+
.home-button {
70+
padding: 10px 20px;
71+
font-size: 16px;
72+
cursor: pointer;
73+
background-color: white;
74+
border: 1px solid #ccc;
75+
border-radius: 5px;
76+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
77+
transition: background-color 0.3s;
78+
color:#111111;
79+
}
80+
81+
.home-button:hover {
82+
background-color: #f0f0f0;
83+
}

0 commit comments

Comments
 (0)