Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BE: [feat] 크루 채팅 보내기 및 조회 기능 #83 #167

Merged
merged 1 commit into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package RunningMachines.R2R.domain.crew.chat.controller;

import RunningMachines.R2R.domain.crew.chat.dto.ChatMessageCreateRequestDto;
import RunningMachines.R2R.domain.crew.chat.dto.ChatMessageResponseDto;
import RunningMachines.R2R.domain.crew.chat.entity.CrewChatImage;
import RunningMachines.R2R.domain.crew.chat.entity.CrewChatMessage;
import RunningMachines.R2R.domain.crew.chat.service.ChatCommandService;
import RunningMachines.R2R.domain.crew.chat.service.ChatQueryService;
import RunningMachines.R2R.domain.user.entity.User;
import RunningMachines.R2R.domain.user.service.AuthCommandService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/crew/{crewId}/chat")
@RequiredArgsConstructor
public class ChatController {
private final ChatCommandService chatCommandService;
private final ChatQueryService chatQueryService;
private final AuthCommandService authCommandService;

@GetMapping
public ResponseEntity<List<ChatMessageResponseDto>> getChatMessages(@PathVariable Long crewId) {
return ResponseEntity.ok(chatQueryService.getChatMessages(crewId));
}

@PostMapping
public ResponseEntity<ChatMessageResponseDto> createChatMessage(@PathVariable Long crewId, @RequestBody ChatMessageCreateRequestDto requestDto) {
User currentUser = authCommandService.getCurrentUser();
ChatMessageResponseDto responseDto = chatCommandService.createChatMessage(crewId, currentUser, requestDto);
return ResponseEntity.ok(responseDto);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package RunningMachines.R2R.domain.crew.chat.dto;

import lombok.Builder;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

@Data
@Builder
public class ChatMessageCreateRequestDto {
private Long crewId;
private String content;
private List<MultipartFile> images;

public static ChatMessageCreateRequestDto of(Long crewId, String content, List<MultipartFile> images) {
return ChatMessageCreateRequestDto.builder()
.crewId(crewId)
.content(content)
.images(images)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package RunningMachines.R2R.domain.crew.chat.dto;

import lombok.Builder;
import lombok.Data;

import java.util.List;

@Data
@Builder
public class ChatMessageResponseDto {
private Long crewId;
private String senderNickname;
private String content;
private List<String> imageUrls;
private String createdAt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package RunningMachines.R2R.domain.crew.chat.entity;

import RunningMachines.R2R.global.util.BaseEntity;
import jakarta.persistence.*;
import lombok.*;

@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class CrewChatImage extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String imageUrl;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "chat_message_id")
private CrewChatMessage chatMessage;

public void setChatMessage(CrewChatMessage chatMessage) {
this.chatMessage = chatMessage;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package RunningMachines.R2R.domain.crew.chat.entity;

import RunningMachines.R2R.domain.crew.common.entity.Crew;
import RunningMachines.R2R.domain.user.entity.User;
import RunningMachines.R2R.global.util.BaseEntity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CrewChatMessage extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "crew_id", nullable = false)
private Crew crew;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User sender;

private String content;

@OneToMany(mappedBy = "chatMessage", cascade = CascadeType.ALL, orphanRemoval = true)
private List<CrewChatImage> chatImages = new ArrayList<>();

public void addChatImage(CrewChatImage crewChatImage) {
this.chatImages.add(crewChatImage);
crewChatImage.setChatMessage(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package RunningMachines.R2R.domain.crew.chat.repository;

import RunningMachines.R2R.domain.crew.chat.entity.CrewChatMessage;
import RunningMachines.R2R.domain.crew.common.entity.Crew;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface ChatMessageRepository extends JpaRepository<CrewChatMessage, Long> {
List<CrewChatMessage> findByCrewOrderByCreatedAtAsc(Crew crew);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package RunningMachines.R2R.domain.crew.chat.service;

import RunningMachines.R2R.domain.crew.chat.dto.ChatMessageCreateRequestDto;
import RunningMachines.R2R.domain.crew.chat.dto.ChatMessageResponseDto;
import RunningMachines.R2R.domain.crew.chat.entity.CrewChatImage;
import RunningMachines.R2R.domain.crew.chat.entity.CrewChatMessage;
import RunningMachines.R2R.domain.crew.chat.repository.ChatMessageRepository;
import RunningMachines.R2R.domain.crew.common.entity.Crew;
import RunningMachines.R2R.domain.crew.common.repository.CrewRepository;
import RunningMachines.R2R.domain.user.entity.User;
import RunningMachines.R2R.global.s3.S3Provider;
import RunningMachines.R2R.global.s3.S3RequestDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ChatCommandService {
private final ChatMessageRepository chatMessageRepository;
private final CrewRepository crewRepository;
private final S3Provider s3Provider;

public ChatMessageResponseDto createChatMessage(Long crewId, User sender, ChatMessageCreateRequestDto requestDto) {
Crew crew = crewRepository.findById(crewId)
.orElseThrow(() -> new IllegalArgumentException("크루를 찾을 수 없습니다."));

CrewChatMessage chatMessage = CrewChatMessage.builder()
.crew(crew)
.sender(sender)
.content(requestDto.getContent())
.build();

List<MultipartFile> images = requestDto.getImages();
if (images!=null) {
for (MultipartFile image : images) {
String imageUrl = s3Provider.uploadFile(image, S3RequestDto.builder()
.userId(sender.getId())
.dirName("chat-images")
.build());
CrewChatImage chatImage = CrewChatImage.builder()
.imageUrl(imageUrl)
.build();
chatMessage.addChatImage(chatImage);
}
}
chatMessageRepository.save(chatMessage);

return ChatMessageResponseDto.builder()
.crewId(crew.getId())
.senderNickname(sender.getNickname())
.content(chatMessage.getContent())
.imageUrls(chatMessage.getChatImages() == null ? List.of() :chatMessage.getChatImages().stream()
.map(CrewChatImage::getImageUrl)
.collect(Collectors.toList()))
.createdAt(chatMessage.getCreatedAt().format(DateTimeFormatter.ofPattern("MM-dd HH:mm")))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package RunningMachines.R2R.domain.crew.chat.service;

import RunningMachines.R2R.domain.crew.chat.dto.ChatMessageResponseDto;
import RunningMachines.R2R.domain.crew.chat.repository.ChatMessageRepository;
import RunningMachines.R2R.domain.crew.common.repository.CrewRepository;
import RunningMachines.R2R.domain.crew.common.entity.Crew;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ChatQueryService {
private final ChatMessageRepository chatMessageRepository;
private final CrewRepository crewRepository;

public List<ChatMessageResponseDto> getChatMessages(Long crewId) {
Crew crew = crewRepository.findById(crewId)
.orElseThrow(() -> new IllegalArgumentException("크루를 찾을 수 없습니다."));

return chatMessageRepository.findByCrewOrderByCreatedAtAsc(crew)
.stream()
.map(crewChatMessage -> ChatMessageResponseDto.builder()
.crewId(crew.getId())
.senderNickname(crewChatMessage.getSender().getNickname())
.content(crewChatMessage.getContent())
.imageUrls(crewChatMessage.getChatImages().stream()
.map(crewChatImage -> crewChatImage.getImageUrl())
.collect(Collectors.toList()))
.createdAt(crewChatMessage.getCreatedAt().format(DateTimeFormatter.ofPattern("MM-dd HH:mm")))
.build())
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ public class GalleryPostController {
private final GalleryPostCommandService galleryPostCommandService;
private final GalleryPostQueryService galleryPostQueryService;
private final GalleryPostLikeService galleryPostLikeService;
private final CrewPostCommentRepository crewPostCommentRepository;
private final CrewPostCommentService crewPostCommentService;

@PostMapping
Expand Down Expand Up @@ -63,4 +62,12 @@ public ResponseEntity<List<CrewPostCommentResponseDto>> getComments(@PathVariabl
List<CrewPostCommentResponseDto> comments = crewPostCommentService.getComments(crewPostId);
return ResponseEntity.ok(comments);
}

@GetMapping("/redirectToChat")
public ResponseEntity<Void> redirectToChat(@PathVariable Long crewId) {
String chatUrl = "/crew/" + crewId + "/chat";
return ResponseEntity.status(303) // Redirect 상태 코드
.header("Location", chatUrl)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,12 @@ public ResponseEntity<NoticePostResponseDto> getNoticePostDetail(@PathVariable L
public ResponseEntity<CrewMainNoticeResponseDto> getNoticePostsByCrew(@PathVariable Long crewId) {
return ResponseEntity.ok(noticePostQueryService.getNoticePostsByCrew(crewId));
}

@GetMapping("/redirectToChat")
public ResponseEntity<Void> redirectToChat(@PathVariable Long crewId) {
String chatUrl = "/crew/" + crewId + "/chat";
return ResponseEntity.status(303) // Redirect 상태 코드
.header("Location", chatUrl)
.build();
}
}