diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/chat/room/dto/ChatRoomDto.kt b/src/main/kotlin/kr/co/vividnext/sodalive/chat/room/dto/ChatRoomDto.kt index 3849ff5..aa2f930 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/chat/room/dto/ChatRoomDto.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/chat/room/dto/ChatRoomDto.kt @@ -2,6 +2,8 @@ package kr.co.vividnext.sodalive.chat.room.dto import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.annotation.JsonProperty +import kr.co.vividnext.sodalive.chat.character.CharacterType +import java.time.LocalDateTime /** * 채팅방 생성 요청 DTO @@ -24,7 +26,9 @@ data class ChatRoomListItemDto( val chatRoomId: Long, val title: String, val imageUrl: String, - val lastMessagePreview: String? + val opponentType: String, + val lastMessagePreview: String?, + val lastMessageTimeLabel: String ) /** @@ -40,10 +44,13 @@ data class ChatMessageItemDto( /** * 채팅방 목록 쿼리 DTO (레포지토리 투영용) */ + data class ChatRoomListQueryDto( val chatRoomId: Long, val title: String, - val imagePath: String? + val imagePath: String?, + val characterType: CharacterType, + val lastActivityAt: LocalDateTime? ) /** diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/chat/room/repository/ChatRoomRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/chat/room/repository/ChatRoomRepository.kt index 0b719a0..a01fe62 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/chat/room/repository/ChatRoomRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/chat/room/repository/ChatRoomRepository.kt @@ -40,7 +40,9 @@ interface ChatRoomRepository : JpaRepository { SELECT new kr.co.vividnext.sodalive.chat.room.dto.ChatRoomListQueryDto( r.id, r.title, - pc.character.imagePath + pc.character.imagePath, + pc.character.characterType, + COALESCE(MAX(m.createdAt), r.createdAt) ) FROM ChatRoom r JOIN r.participants p diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/chat/room/service/ChatRoomService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/chat/room/service/ChatRoomService.kt index e539ae2..9ecedeb 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/chat/room/service/ChatRoomService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/chat/room/service/ChatRoomService.kt @@ -199,18 +199,39 @@ class ChatRoomService( val latest = messageRepository.findTopByChatRoomAndIsActiveTrueOrderByCreatedAtDesc(room) val preview = latest?.message?.let { msg -> - if (msg.length <= 25) msg else msg.take(25) + "..." + if (msg.length <= 30) msg else msg.take(30) + "..." } + val imageUrl = "$imageHost/${q.imagePath ?: "profile/default-profile.png"}" + val opponentType = q.characterType.name // Clone or Character + val time = latest?.createdAt ?: q.lastActivityAt + val timeLabel = formatRelativeTime(time) + ChatRoomListItemDto( chatRoomId = q.chatRoomId, title = q.title, - imageUrl = "$imageHost/${q.imagePath ?: "profile/default-profile.png"}", - lastMessagePreview = preview + imageUrl = imageUrl, + opponentType = opponentType, + lastMessagePreview = preview, + lastMessageTimeLabel = timeLabel ) } } + private fun formatRelativeTime(time: java.time.LocalDateTime?): String { + if (time == null) return "" + val now = java.time.LocalDateTime.now() + val duration = java.time.Duration.between(time, now) + val seconds = duration.seconds + if (seconds <= 60) return "방금" + val minutes = duration.toMinutes() + if (minutes < 60) return "${'$'}minutes분 전" + val hours = duration.toHours() + if (hours < 24) return "${'$'}hours시간 전" + // 그 외: 날짜 (yyyy-MM-dd) + return time.toLocalDate().toString() + } + @Transactional(readOnly = true) fun isMyRoomSessionActive(member: Member, chatRoomId: Long): Boolean { val room = chatRoomRepository.findById(chatRoomId).orElseThrow {