Skip to content

Commit 6e6928f

Browse files
authored
Merge pull request #58 from pirogramming/feat-jh
Feat jh
2 parents 8affc5a + edbb64c commit 6e6928f

4 files changed

Lines changed: 43 additions & 12 deletions

File tree

backend-chat/app/api/chat.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ async def websocket_endpoint(websocket: WebSocket, room_id: str):
9696
content=data,
9797
)
9898
await chat_manager.save_message(msg_obj)
99+
await chat_manager.set_room_last_message(room_id, msg_obj)
99100

100101
await chat_manager.publish_message({
101102
"type": "TALK",

backend-chat/app/services/chat_service.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,15 @@ async def get_history(self, room_id: str):
126126
history.append(doc)
127127
return history
128128

129+
async def set_room_last_message(self, room_id: str, msg_obj: ChatMessage):
130+
"""채팅 목록용: 해당 방의 마지막 메시지를 Redis에 저장 (Django에서 조회)"""
131+
key = f"chat:room:{room_id}:last"
132+
value = {
133+
"content": (msg_obj.content or "")[:80], # 목록용으로 80자 제한
134+
"created_at": msg_obj.created_at.isoformat() if msg_obj.created_at else None,
135+
"sender_id": msg_obj.sender_id,
136+
}
137+
await redis_client.set(key, json.dumps(value, ensure_ascii=False), ex=86400 * 30)
138+
139+
129140
chat_manager = ConnectionManager()

backend-core/missions/views.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919

2020
from .forms import MissionCreateForm
2121
from .models import Mission, MissionImage, Tag, Category, ChatRoom
22-
from common.utils import publish_chat_event
22+
from common.utils import publish_chat_event, redis_client
2323
from common.utils import publish_mission_update
2424
from common.utils import acquire_lock, release_lock
25+
from collections import defaultdict
2526

2627

2728
logger = logging.getLogger(__name__)
@@ -510,27 +511,43 @@ def chat_room(request: HttpRequest, mission_id: int, room_id: int) -> HttpRespon
510511

511512
@login_required
512513
def chat_list(request: HttpRequest) -> HttpResponse:
513-
"""내가 참여한 채팅방 목록 (차단된 유저 제외)"""
514+
"""내가 참여한 채팅방을 미션별로 묶어서 보여줌"""
514515
rooms = (
515516
ChatRoom.objects
516517
.filter(models.Q(user1=request.user) | models.Q(user2=request.user))
517518
.select_related("mission", "mission__author", "user1", "user2")
518519
.order_by("-created_at")
519520
)
520-
room_list = []
521+
522+
mission_groups = defaultdict(list)
521523
for room in rooms:
522524
other = room.user2 if room.user1 == request.user else room.user1
523525
if _is_blocked_between(request.user, other):
524526
continue
525-
room_list.append({
527+
# Redis에서 이 방의 마지막 메시지 미리보기 조회
528+
last_message = None
529+
try:
530+
raw = redis_client.get(f"chat:room:{room.id}:last")
531+
if raw:
532+
data = json.loads(raw)
533+
last_message = data.get("content") or None
534+
except (json.JSONDecodeError, TypeError):
535+
pass
536+
mission_groups[room.mission].append({
526537
"room": room,
527538
"other_user": other,
528-
"mission": room.mission,
539+
"last_message": last_message,
529540
})
541+
542+
grouped_list = [
543+
{"mission": mission, "rooms": room_items}
544+
for mission, room_items in mission_groups.items()
545+
]
546+
530547
return render(
531548
request,
532549
"chat/list.html",
533-
{"room_list": room_list},
550+
{"grouped_list": grouped_list},
534551
)
535552

536553

backend-core/templates/chat/list.html

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,34 @@ <h1 class="page-title">채팅 목록</h1>
1515
</div>
1616

1717
<section class="chat-section">
18-
{% for item in room_list %}
18+
{% for group in grouped_list %}
1919
<div class="chat-toggle-group">
2020
<div class="chat-mission-header" onclick="toggleChat(this)">
2121
<div class="header-left">
22-
<div class="mission-icon">{{ item.mission.category|slice:":1"|default:"미" }}</div>
22+
<div class="mission-icon">{{ group.mission.category|slice:":1"|default:"미" }}</div>
2323
<div class="header-text">
24-
<strong class="mission-title">{{ item.mission.title }}</strong>
25-
<span class="participant-count">상대방: {{ item.other_user.get_display_name }}</span>
24+
<strong class="mission-title">{{ group.mission.title }}</strong>
25+
<span class="participant-count">채팅 {{ group.rooms|length }}</span>
2626
</div>
2727
</div>
2828
<i class="fa-solid fa-chevron-down toggle-icon"></i>
2929
</div>
3030

3131
<div class="chat-room-content">
32-
<a href="{% url 'missions:chat_room' item.mission.id item.room.id %}" class="individual-chat-link">
32+
{% for item in group.rooms %}
33+
<a href="{% url 'missions:chat_room' group.mission.id item.room.id %}" class="individual-chat-link">
3334
<div class="chat-user-avatar">
3435
{{ item.other_user.get_display_name|slice:":1" }}
3536
</div>
3637
<div class="chat-user-info">
3738
<div class="user-info-top">
3839
<span class="user-name">{{ item.other_user.get_display_name }}</span>
39-
<span class="chat-time">{{ item.room.updated_at|date:"A g:i"|default:"최근" }}</span>
40+
<span class="chat-time">{{ item.room.created_at|date:"A g:i"|default:"최근" }}</span>
4041
</div>
4142
<p class="last-preview">{{ item.last_message|default:"대화 내용이 없습니다." }}</p>
4243
</div>
4344
</a>
45+
{% endfor %}
4446
</div>
4547
</div>
4648
{% empty %}

0 commit comments

Comments
 (0)