Skip to content

Commit 4fa4885

Browse files
authored
Merge branch 'develop' into fix/78-timezone
2 parents a12c61f + 616e6ec commit 4fa4885

28 files changed

+268
-126
lines changed

src/main/java/com/memesphere/domain/chartdata/repository/ChartDataRepository.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
import com.memesphere.domain.chartdata.entity.ChartData;
44
import com.memesphere.domain.memecoin.entity.MemeCoin;
5+
import org.springframework.data.domain.Pageable;
56
import org.springframework.data.jpa.repository.EntityGraph;
67
import org.springframework.data.jpa.repository.JpaRepository;
78
import org.springframework.data.jpa.repository.Query;
89
import org.springframework.data.repository.query.Param;
910

10-
import java.awt.print.Pageable;
1111
import java.math.BigDecimal;
1212
import java.time.LocalDateTime;
1313
import java.util.List;
@@ -28,4 +28,8 @@ public interface ChartDataRepository extends JpaRepository<ChartData, Long> {
2828
LocalDateTime findRecordedTimeByCoinId1();
2929

3030
List<ChartData> findByMemeCoinOrderByRecordedTimeDesc(MemeCoin memeCoin);
31+
32+
//TODO: 위아래 코드 합치는 방법 찾기
33+
List<ChartData> findByMemeCoinOrderByRecordedTimeDesc(MemeCoin memeCoin, Pageable pageable);
34+
3135
}

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

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@
44
import com.memesphere.domain.chat.dto.response.ChatResponse;
55
import com.memesphere.domain.chat.service.ChatService;
66
import com.memesphere.global.apipayload.ApiResponse;
7+
import com.memesphere.global.jwt.CustomUserDetails;
78
import io.swagger.v3.oas.annotations.Operation;
89
import io.swagger.v3.oas.annotations.tags.Tag;
910
import lombok.RequiredArgsConstructor;
11+
import org.springframework.data.domain.Page;
12+
import org.springframework.data.domain.Pageable;
1013
import org.springframework.messaging.handler.annotation.DestinationVariable;
1114
import org.springframework.messaging.handler.annotation.MessageMapping;
1215
import org.springframework.messaging.handler.annotation.Payload;
1316
import org.springframework.messaging.handler.annotation.SendTo;
14-
import org.springframework.web.bind.annotation.GetMapping;
15-
import org.springframework.web.bind.annotation.PathVariable;
16-
import org.springframework.web.bind.annotation.RestController;
17+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
18+
import org.springframework.web.bind.annotation.*;
1719

1820
@Tag(name = "실시간 채팅", description = "실시간 채팅 관련 API")
1921
@RestController
@@ -22,16 +24,25 @@ public class ChatController {
2224

2325
private final ChatService chatService;
2426

25-
@MessageMapping("/chat/{coin_id}")
26-
@SendTo("/sub/{coin_id}")
27+
@MessageMapping("/chat/{coin_id}") // 클라이언트가 pub/chat/{coin_id}로 STOMP 메시지를 전송하면 실행됨
28+
@SendTo("/sub/{coin_id}") // 메서드가 반환한 데이터를 구독 중인 클라이언트에게 전송
2729
public ChatResponse chat(@DestinationVariable("coin_id") Long coin_id,
2830
@Payload ChatRequest chatRequest) {
2931

3032
return chatService.saveMessage(coin_id, chatRequest);
3133
}
3234

35+
@GetMapping("/chat/{coin_id}/list")
36+
@Operation(summary = "코인별 채팅 전체 메시지 조회 API",
37+
description = "특정 코인의 채팅방의 전체 메시지를 보여줍니다.")
38+
public ApiResponse<Page<ChatResponse>> getChatList(@PathVariable("coin_id") Long coin_id,
39+
Pageable pageable) {
40+
41+
return ApiResponse.onSuccess(chatService.getChatList(coin_id, pageable));
42+
}
43+
3344
//최신 댓글 조회 Api
34-
@GetMapping("/latest/{coin_id}")
45+
@GetMapping("/chat/{coin_id}/latest")
3546
@Operation(summary = "코인별 최신 댓글 조회 API",
3647
description = "특정 코인에 대한 최신 댓글을 반환합니다. 요청 시 최신 댓글 하나만 가져옵니다.")
3748
public ApiResponse<ChatResponse> getLatestMessages(
@@ -42,4 +53,16 @@ public ApiResponse<ChatResponse> getLatestMessages(
4253

4354
return ApiResponse.onSuccess(latestMessage);
4455
}
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+
}
4568
}

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package com.memesphere.domain.chat.converter;
22

33
import com.memesphere.domain.chat.entity.Chat;
4+
import com.memesphere.domain.chat.entity.ChatLike;
45
import com.memesphere.domain.memecoin.entity.MemeCoin;
56
import com.memesphere.domain.chat.dto.request.ChatRequest;
67
import com.memesphere.domain.chat.dto.response.ChatResponse;
8+
import com.memesphere.domain.user.entity.User;
79

810
public class ChatConverter {
911

10-
public static Chat toChat(MemeCoin memeCoin, ChatRequest chatRequest) {
12+
public static Chat toChat(MemeCoin memeCoin, ChatRequest chatRequest, User user) {
1113

1214
return Chat.builder()
13-
// .user(user)
15+
.user(user)
1416
.memeCoin(memeCoin)
1517
.message(chatRequest.getMessage())
1618
.build();
@@ -27,4 +29,11 @@ public static ChatResponse toChatResponse(Chat chat) {
2729
.nickname(chat.getUser().getNickname())
2830
.build();
2931
}
32+
33+
public static ChatLike toChatLike(Chat chat, User user) {
34+
return ChatLike.builder()
35+
.user(user)
36+
.chat(chat)
37+
.build();
38+
}
3039
}

src/main/java/com/memesphere/domain/chat/dto/request/ChatRequest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
@NoArgsConstructor
1111
public class ChatRequest {
1212

13-
@Schema(description = "메시지 내용")
13+
@Schema(description = "닉네임", example = "코인전문가")
14+
private String nickname;
15+
16+
@Schema(description = "메시지 내용", example = "도지코인 현재 얼마인가요?")
1417
private String message;
1518
}

src/main/java/com/memesphere/domain/chat/entity/Chat.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class Chat extends BaseEntity {
2525
@Column(name="chat_id")
2626
private Long id;
2727

28-
@Column
28+
@Column(columnDefinition = "varchar(500)", nullable = false)
2929
private String message;
3030

3131
@ManyToOne(fetch=FetchType.LAZY)

src/main/java/com/memesphere/domain/chat/repository/ChatCustomRepository.java

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/main/java/com/memesphere/domain/chat/repository/ChatCustomRepositoryImpl.java

Lines changed: 0 additions & 5 deletions
This file was deleted.
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+
}
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package com.memesphere.domain.chat.repository;
22

33
import com.memesphere.domain.chat.entity.Chat;
4+
import org.springframework.data.domain.Page;
5+
import org.springframework.data.domain.Pageable;
46
import org.springframework.data.jpa.repository.JpaRepository;
57

6-
public interface ChatRepository extends JpaRepository<Chat, Long>, ChatCustomRepository {
8+
import java.util.List;
9+
10+
public interface ChatRepository extends JpaRepository<Chat, Long> {
711

812
Chat findFirstByMemeCoin_IdOrderByCreatedAtDesc(Long coin_id);
13+
Page<Chat> findAllByMemeCoin_Id(Long coin_id, Pageable pageable);
914
}

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

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
import com.memesphere.domain.chat.converter.ChatConverter;
44
import com.memesphere.domain.chat.entity.Chat;
5+
import com.memesphere.domain.chat.entity.ChatLike;
6+
import com.memesphere.domain.chat.repository.ChatLikeRepository;
7+
import com.memesphere.domain.user.entity.User;
8+
import com.memesphere.domain.user.repository.UserRepository;
59
import com.memesphere.global.apipayload.code.status.ErrorStatus;
610
import com.memesphere.global.apipayload.exception.GeneralException;
711
import com.memesphere.domain.memecoin.entity.MemeCoin;
@@ -10,30 +14,47 @@
1014
import com.memesphere.domain.memecoin.repository.MemeCoinRepository;
1115
import com.memesphere.domain.chat.repository.ChatRepository;
1216
import lombok.RequiredArgsConstructor;
17+
import org.springframework.data.domain.Page;
18+
import org.springframework.data.domain.Pageable;
1319
import org.springframework.stereotype.Service;
20+
import org.springframework.transaction.annotation.Transactional;
21+
22+
import java.util.Optional;
1423

1524
@Service
1625
@RequiredArgsConstructor
1726
public class ChatService {
1827

1928
private final MemeCoinRepository memeCoinRepository;
2029
private final ChatRepository chatRepository;
30+
private final UserRepository userRepository;
31+
private final ChatLikeRepository chatLikeRepository;
2132

2233
public ChatResponse saveMessage(Long coin_id, ChatRequest chatRequest) {
2334

2435
MemeCoin memeCoin = memeCoinRepository.findById(coin_id)
2536
.orElseThrow(() -> new GeneralException(ErrorStatus.MEMECOIN_NOT_FOUND));
2637

27-
Chat chat = ChatConverter.toChat(memeCoin, chatRequest);
38+
User user = userRepository.findByNickname(chatRequest.getNickname())
39+
.orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND));
40+
41+
Chat chat = ChatConverter.toChat(memeCoin, chatRequest, user);
2842
Chat savedChat = chatRepository.save(chat);
2943

3044
return ChatConverter.toChatResponse(savedChat);
3145
}
3246

47+
@Transactional
48+
public Page<ChatResponse> getChatList(Long coin_id, Pageable pageable) {
49+
50+
Page<Chat> chatPage = chatRepository.findAllByMemeCoin_Id(coin_id, pageable);
51+
return chatPage.map(ChatConverter::toChatResponse);
52+
}
53+
3354
// 최신 댓글을 가져오는 메서드
55+
@Transactional
3456
public ChatResponse getLatestMessages(Long coin_id) {
3557

36-
3758
MemeCoin memeCoin = memeCoinRepository.findById(coin_id)
3859
//id에 해당하는 밈코인 없을 때
3960
.orElseThrow(() -> new GeneralException(ErrorStatus.MEMECOIN_NOT_FOUND));
@@ -50,4 +71,26 @@ public ChatResponse getLatestMessages(Long coin_id) {
5071
return ChatConverter.toChatResponse(latestChat);
5172
}
5273

74+
@Transactional
75+
public String postChatLike(Long chat_id, Long user_id) {
76+
77+
User user = userRepository.findById(user_id)
78+
.orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND));
79+
80+
Chat chat = chatRepository.findById(chat_id)
81+
.orElseThrow(() -> new GeneralException(ErrorStatus.CHAT_NOT_FOUND));
82+
83+
// 사용자가 좋아요 눌렀는지 확인
84+
Optional<ChatLike> existingLike = chatLikeRepository.findByChatAndUser(chat, user);
85+
86+
if (existingLike.isPresent()) {
87+
chatLikeRepository.delete(existingLike.get());
88+
return "좋아요를 취소했습니다.";
89+
} else {
90+
ChatLike chatLike = ChatConverter.toChatLike(chat, user);
91+
chatLikeRepository.save(chatLike);
92+
return "좋아요를 눌렀습니다.";
93+
}
94+
}
95+
5396
}

0 commit comments

Comments
 (0)