Skip to content

Commit 998f5d0

Browse files
committed
#17 Feat: 채팅 좋아요 기능 추가
1 parent 8906221 commit 998f5d0

File tree

5 files changed

+70
-6
lines changed

5 files changed

+70
-6
lines changed

src/main/java/com/memesphere/domain/chat/controller/ChatController.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515
import org.springframework.messaging.handler.annotation.Payload;
1616
import org.springframework.messaging.handler.annotation.SendTo;
1717
import org.springframework.security.core.annotation.AuthenticationPrincipal;
18-
import org.springframework.web.bind.annotation.GetMapping;
19-
import org.springframework.web.bind.annotation.PathVariable;
20-
import org.springframework.web.bind.annotation.RestController;
18+
import org.springframework.web.bind.annotation.*;
2119

2220
@Tag(name = "실시간 채팅", description = "실시간 채팅 관련 API")
2321
@RestController
@@ -34,7 +32,7 @@ public ChatResponse chat(@DestinationVariable("coin_id") Long coin_id,
3432
return chatService.saveMessage(coin_id, chatRequest);
3533
}
3634

37-
@GetMapping("/chat/list/{coin_id}")
35+
@GetMapping("/chat/{coin_id}/list/")
3836
@Operation(summary = "코인별 채팅 전체 메시지 조회 API",
3937
description = "특정 코인의 채팅방의 전체 메시지를 보여줍니다.")
4038
public ApiResponse<ChatListResponse> getChatList(@PathVariable("coin_id") Long coin_id) {
@@ -44,7 +42,7 @@ public ApiResponse<ChatListResponse> getChatList(@PathVariable("coin_id") Long c
4442
}
4543

4644
//최신 댓글 조회 Api
47-
@GetMapping("/chat/latest/{coin_id}")
45+
@GetMapping("/chat/{coin_id}/latest/")
4846
@Operation(summary = "코인별 최신 댓글 조회 API",
4947
description = "특정 코인에 대한 최신 댓글을 반환합니다. 요청 시 최신 댓글 하나만 가져옵니다.")
5048
public ApiResponse<ChatResponse> getLatestMessages(
@@ -55,4 +53,16 @@ public ApiResponse<ChatResponse> getLatestMessages(
5553

5654
return ApiResponse.onSuccess(latestMessage);
5755
}
56+
57+
@PostMapping("/chat/{coin_id}/like")
58+
@Operation(summary = "채팅 좋아요 관련 API",
59+
description = "채팅에서 하트를 클릭 시 하트가 채워지고, 좋아요 누른 사람의 숫자에 반영됩니다.")
60+
public ApiResponse<String> postChatLike(@PathVariable("coin_id") Long coin_id,
61+
@RequestParam(value = "chat_id", required = true) Long chat_id,
62+
@AuthenticationPrincipal CustomUserDetails customUserDetails) {
63+
64+
Long userId = customUserDetails.getUser().getId();
65+
66+
return ApiResponse.onSuccess(chatService.postChatLike(chat_id, userId));
67+
}
5868
}

src/main/java/com/memesphere/domain/chat/converter/ChatConverter.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.memesphere.domain.chat.dto.response.ChatListResponse;
44
import com.memesphere.domain.chat.entity.Chat;
5+
import com.memesphere.domain.chat.entity.ChatLike;
56
import com.memesphere.domain.memecoin.entity.MemeCoin;
67
import com.memesphere.domain.chat.dto.request.ChatRequest;
78
import com.memesphere.domain.chat.dto.response.ChatResponse;
@@ -37,4 +38,11 @@ public static ChatListResponse toChatListResponse(List<ChatResponse> chatRespons
3738
.chats(chatResponses)
3839
.build();
3940
}
41+
42+
public static ChatLike toChatLike(Chat chat, User user) {
43+
return ChatLike.builder()
44+
.user(user)
45+
.chat(chat)
46+
.build();
47+
}
4048
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.memesphere.domain.chat.repository;
2+
3+
import com.memesphere.domain.chat.entity.Chat;
4+
import com.memesphere.domain.chat.entity.ChatLike;
5+
import com.memesphere.domain.user.entity.User;
6+
import org.springframework.data.jpa.repository.JpaRepository;
7+
8+
import java.util.Optional;
9+
10+
public interface ChatLikeRepository extends JpaRepository<ChatLike, Long> {
11+
12+
Optional<ChatLike> findByChatAndUser(Chat chat, User user);
13+
}

src/main/java/com/memesphere/domain/chat/service/ChatService.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import com.memesphere.domain.chat.converter.ChatConverter;
44
import com.memesphere.domain.chat.dto.response.ChatListResponse;
55
import com.memesphere.domain.chat.entity.Chat;
6+
import com.memesphere.domain.chat.entity.ChatLike;
7+
import com.memesphere.domain.chat.repository.ChatLikeRepository;
68
import com.memesphere.domain.user.entity.User;
79
import com.memesphere.domain.user.repository.UserRepository;
810
import com.memesphere.global.apipayload.code.status.ErrorStatus;
@@ -14,9 +16,11 @@
1416
import com.memesphere.domain.chat.repository.ChatRepository;
1517
import lombok.RequiredArgsConstructor;
1618
import org.springframework.stereotype.Service;
19+
import org.springframework.transaction.annotation.Transactional;
1720

1821
import java.util.ArrayList;
1922
import java.util.List;
23+
import java.util.Optional;
2024

2125
@Service
2226
@RequiredArgsConstructor
@@ -25,6 +29,7 @@ public class ChatService {
2529
private final MemeCoinRepository memeCoinRepository;
2630
private final ChatRepository chatRepository;
2731
private final UserRepository userRepository;
32+
private final ChatLikeRepository chatLikeRepository;
2833

2934
public ChatResponse saveMessage(Long coin_id, ChatRequest chatRequest) {
3035

@@ -40,6 +45,7 @@ public ChatResponse saveMessage(Long coin_id, ChatRequest chatRequest) {
4045
return ChatConverter.toChatResponse(savedChat);
4146
}
4247

48+
@Transactional
4349
public ChatListResponse getChatList(Long coin_id) {
4450

4551
List<Chat> chatList = chatRepository.findAllByMemeCoin_Id(coin_id);
@@ -55,6 +61,7 @@ public ChatListResponse getChatList(Long coin_id) {
5561
}
5662

5763
// 최신 댓글을 가져오는 메서드
64+
@Transactional
5865
public ChatResponse getLatestMessages(Long coin_id) {
5966

6067
MemeCoin memeCoin = memeCoinRepository.findById(coin_id)
@@ -73,4 +80,27 @@ public ChatResponse getLatestMessages(Long coin_id) {
7380
return ChatConverter.toChatResponse(latestChat);
7481
}
7582

83+
@Transactional
84+
public String postChatLike(Long chat_id, Long user_id) {
85+
86+
User user = userRepository.findById(user_id)
87+
.orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND));
88+
89+
Chat chat = chatRepository.findById(chat_id)
90+
.orElseThrow(() -> new GeneralException(ErrorStatus.CHAT_NOT_FOUND));
91+
92+
// 사용자가 좋아요 눌렀는지 확인
93+
Optional<ChatLike> existingLike = chatLikeRepository.findByChatAndUser(chat, user);
94+
System.out.println("좋아요" + existingLike.isPresent());
95+
96+
if (existingLike.isPresent()) {
97+
chatLikeRepository.delete(existingLike.get());
98+
return "좋아요를 취소했습니다.";
99+
} else {
100+
ChatLike chatLike = ChatConverter.toChatLike(chat, user);
101+
chatLikeRepository.save(chatLike);
102+
return "좋아요를 눌렀습니다.";
103+
}
104+
}
105+
76106
}

src/main/java/com/memesphere/global/apipayload/code/status/ErrorStatus.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ public enum ErrorStatus implements BaseCode {
4141

4242
// 이미지 에러
4343
INVALID_FILE_EXTENTION(HttpStatus.BAD_REQUEST, "INVALID FILE EXTENSION", "지원되지 않는 파일 형식입니다."),
44-
PRESIGNED_URL_FAILED(HttpStatus.BAD_REQUEST, "PRESIGNED URL GENERATION FAILED", "presigned URL 생성에 실패했습니다.");
44+
PRESIGNED_URL_FAILED(HttpStatus.BAD_REQUEST, "PRESIGNED URL GENERATION FAILED", "presigned URL 생성에 실패했습니다."),
45+
46+
// 채팅 에러
47+
CHAT_NOT_FOUND(HttpStatus.NOT_FOUND, "CHAT NOT FOUND", "채팅을 찾을 수 없습니다.");
4548

4649
private final HttpStatus httpStatus;
4750
private final String code;

0 commit comments

Comments
 (0)