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

✨ [Feat] 목표 댓글 및 피드 #26

Merged
merged 2 commits into from
Nov 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
531 changes: 0 additions & 531 deletions .idea/dbnavigator.xml

This file was deleted.

13 changes: 0 additions & 13 deletions src/main/java/dongguk/osori/domain/goal/GoalRepository.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package dongguk.osori.domain.goal.controller;

import dongguk.osori.domain.goal.dto.FeedGoalDto;
import dongguk.osori.domain.goal.dto.GoalDetailResponseDto;
import dongguk.osori.domain.goal.service.GoalService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RequiredArgsConstructor
@RestController
@RequestMapping("/api/feeds")
public class FeedController {

private final GoalService goalService;

@Operation(summary = "팔로우한 사람들의 오늘 날짜 목표 조회", description = "팔로우한 사람들의 오늘 날짜 목표를 피드에서 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "목표 조회 성공"),
@ApiResponse(responseCode = "401", description = "인증되지 않은 사용자")
})
@GetMapping
public ResponseEntity<List<FeedGoalDto>> getTodayFeedGoals(HttpSession session) {
Long userId = (Long) session.getAttribute("userId");
if (userId == null) {
return ResponseEntity.status(401).build();
}
List<FeedGoalDto> feedGoals = goalService.getTodayFeedGoals(userId);
return ResponseEntity.ok(feedGoals);
}

@Operation(summary = "단일 목표 상세 조회", description = "단일 목표와 그에 달린 모든 댓글을 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "목표 상세 조회 성공"),
@ApiResponse(responseCode = "404", description = "목표를 찾을 수 없음")
})
@GetMapping("/{goalId}")
public ResponseEntity<GoalDetailResponseDto> getGoalDetailsWithComments(@PathVariable("goalId") Long goalId) {
Optional<GoalDetailResponseDto> goalDetails = goalService.getGoalDetailsWithComments(goalId);
return goalDetails.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package dongguk.osori.domain.goal.controller;

import dongguk.osori.domain.goal.dto.GoalCommentDto;
import dongguk.osori.domain.goal.dto.GoalCommentResponseDto;
import dongguk.osori.domain.goal.service.GoalCommentService;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/goals/{goalId}/comments")
@RequiredArgsConstructor
public class GoalCommentController {

private final GoalCommentService goalCommentService;

// 댓글 추가
@PostMapping
public ResponseEntity<GoalCommentResponseDto> addComment(
@PathVariable("goalId") Long goalId,
@RequestBody GoalCommentDto commentDto,
HttpSession session) {
Long userId = (Long) session.getAttribute("userId");
if (userId == null) {
return ResponseEntity.status(401).build();
}
GoalCommentResponseDto response = goalCommentService.addComment(goalId, userId, commentDto);
return ResponseEntity.ok(response);
}

// 댓글 삭제
@DeleteMapping("/{commentId}")
public ResponseEntity<Void> deleteComment(
@PathVariable("goalId") Long goalId,
@PathVariable("commentId") Long commentId,
@RequestAttribute("userId") Long userId) {
goalCommentService.deleteComment(commentId, userId);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package dongguk.osori.domain.goal;
package dongguk.osori.domain.goal.controller;

import dongguk.osori.domain.goal.dto.GoalCompletionDto;
import dongguk.osori.domain.goal.dto.GoalDto;
import dongguk.osori.domain.goal.entity.Goal;
import dongguk.osori.domain.goal.dto.*;
import dongguk.osori.domain.goal.service.GoalService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
Expand Down Expand Up @@ -31,27 +29,45 @@ public class GoalController {
@ApiResponse(responseCode = "401", description = "인증되지 않은 사용자")
})
@GetMapping
public ResponseEntity<List<Goal>> getUserGoals(HttpSession session) {
public ResponseEntity<List<GoalResponseDto>> getUserGoals(HttpSession session) {
Long userId = (Long) session.getAttribute("userId");
if (userId == null) {
return ResponseEntity.status(401).build();
}
List<Goal> goals = goalService.getUserGoals(userId);
List<GoalResponseDto> goals = goalService.getUserGoals(userId);
return ResponseEntity.ok(goals);
}

@Operation(summary = "목표 단일 조회", description = "특정 목표의 내용을 조회하고 연관된 댓글을 함께 보여줍니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "목표 조회 성공"),
@ApiResponse(responseCode = "401", description = "인증되지 않은 사용자"),
@ApiResponse(responseCode = "404", description = "목표를 찾을 수 없음")
})
@GetMapping("/{goalId}")
public ResponseEntity<GoalDetailResponseDto> getGoalById(@PathVariable("goalId") Long goalId, HttpSession session) {
Long userId = (Long) session.getAttribute("userId");
if (userId == null) {
return ResponseEntity.status(401).build();
}
Optional<GoalDetailResponseDto> goalDetail = goalService.getGoalDetailsWithComments(goalId);
return goalDetail.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}


@Operation(summary = "로그인한 사용자의 목표 생성", description = "로그인한 사용자의 새로운 목표를 생성합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "목표 생성 성공"),
@ApiResponse(responseCode = "401", description = "인증되지 않은 사용자")
})
@PostMapping
public ResponseEntity<Goal> createGoal(@RequestBody GoalDto goalDto, HttpSession session) {
public ResponseEntity<GoalResponseDto> createGoal(@RequestBody GoalDto goalDto, HttpSession session) {
Long userId = (Long) session.getAttribute("userId");
if (userId == null) {
return ResponseEntity.status(401).build();
}
Goal createdGoal = goalService.createGoal(goalDto, userId);
GoalResponseDto createdGoal = goalService.createGoal(goalDto, userId);
return ResponseEntity.ok(createdGoal);
}

Expand All @@ -62,12 +78,12 @@ public ResponseEntity<Goal> createGoal(@RequestBody GoalDto goalDto, HttpSession
@ApiResponse(responseCode = "404", description = "목표를 찾을 수 없음")
})
@PatchMapping("/{goalId}")
public ResponseEntity<Goal> updateGoal(@PathVariable("goalId") Long goalId, @RequestBody GoalDto goalDto, HttpSession session) {
public ResponseEntity<GoalResponseDto> updateGoal(@PathVariable("goalId") Long goalId, @RequestBody GoalDto goalDto, HttpSession session) {
Long userId = (Long) session.getAttribute("userId");
if (userId == null) {
return ResponseEntity.status(401).build();
}
Optional<Goal> updatedGoal = goalService.updateGoal(goalId, goalDto, userId);
Optional<GoalResponseDto> updatedGoal = goalService.updateGoal(goalId, goalDto, userId);
return updatedGoal.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}
Expand All @@ -83,7 +99,7 @@ public ResponseEntity<Void> deleteGoal(@PathVariable("goalId") Long goalId, Http
if (userId == null) {
return ResponseEntity.status(401).build();
}
goalService.deleteGoal(goalId, userId);
goalService.deleteGoal(userId, goalId);
return ResponseEntity.noContent().build();
}

Expand All @@ -94,12 +110,12 @@ public ResponseEntity<Void> deleteGoal(@PathVariable("goalId") Long goalId, Http
@ApiResponse(responseCode = "404", description = "목표를 찾을 수 없음")
})
@PatchMapping("/{goalId}/completion")
public ResponseEntity<Goal> updateGoalCompletion(@PathVariable("goalId") Long goalId, @RequestBody GoalCompletionDto goalCompletionDto, HttpSession session) {
public ResponseEntity<GoalResponseDto> updateGoalCompletion(@PathVariable("goalId") Long goalId, @RequestBody GoalCompletionDto goalCompletionDto, HttpSession session) {
Long userId = (Long) session.getAttribute("userId");
if (userId == null) {
return ResponseEntity.status(401).build();
}
Optional<Goal> updatedGoal = goalService.updateGoalCompletionStatus(goalId, goalCompletionDto, userId);
Optional<GoalResponseDto> updatedGoal = goalService.updateGoalCompletionStatus(goalId, goalCompletionDto, userId);
return updatedGoal.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/dongguk/osori/domain/goal/dto/FeedGoalDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dongguk.osori.domain.goal.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.time.LocalDateTime;

@Getter
@AllArgsConstructor
public class FeedGoalDto {
private Long goalId;
private String authorNickname;
private LocalDateTime createdAt;
private boolean completed;
private String content;
private int commentCount;
}
18 changes: 18 additions & 0 deletions src/main/java/dongguk/osori/domain/goal/dto/GoalCommentDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package dongguk.osori.domain.goal.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class GoalCommentDto {
private Long commentId;
private String nickname;
private String content;
private LocalDateTime createdAt;
private int emoji;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dongguk.osori.domain.goal.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.time.LocalDateTime;

@Getter
@AllArgsConstructor
public class GoalCommentResponseDto {
private Long commentId;
private String nickname;
private String content;
private LocalDateTime createdAt;
private int emoji;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package dongguk.osori.domain.goal.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.time.LocalDateTime;
import java.util.List;

@Getter
@AllArgsConstructor
public class GoalDetailResponseDto {
private Long goalId;
private String content;
private String nickname;
private LocalDateTime createdAt;
private boolean completed;
private List<GoalCommentResponseDto> comments;
}
2 changes: 1 addition & 1 deletion src/main/java/dongguk/osori/domain/goal/dto/GoalDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
@AllArgsConstructor
@NoArgsConstructor
public class GoalDto {
private String context;
private String content;
}
17 changes: 17 additions & 0 deletions src/main/java/dongguk/osori/domain/goal/dto/GoalResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dongguk.osori.domain.goal.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class GoalResponseDto {
private Long goalId;
private String content;
private LocalDateTime createdAt;
private boolean completed;
}
30 changes: 22 additions & 8 deletions src/main/java/dongguk/osori/domain/goal/entity/Goal.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import lombok.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@AllArgsConstructor
@NoArgsConstructor
Expand All @@ -14,11 +16,12 @@
@Entity
public class Goal {

@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long goalId;

@Column(nullable = false)
private String context;
private String content;

@Column(nullable = false)
private LocalDateTime createdAt;
Expand All @@ -31,10 +34,20 @@ public class Goal {
@JsonIgnore
private User user;

@OneToMany(mappedBy = "goal", cascade = CascadeType.ALL, orphanRemoval = true)
private List<GoalComment> comments = new ArrayList<>();

public void updateContext(String context) { this.context = context; }
public void markAsCompleted() { this.completed = true; }
public void markAsIncomplete() { this.completed = false; }
public void updateContent(String content) {
this.content = content;
}

public void markAsCompleted() {
this.completed = true;
}

public void markAsIncomplete() {
this.completed = false;
}

@PrePersist
public void prePersist() {
Expand All @@ -43,9 +56,10 @@ public void prePersist() {
}

@Builder
public Goal(String context, User user) {
this.context = context;
public Goal(String content, User user) {
this.content = content;
this.user = user;
this.createdAt = LocalDateTime.now();
this.completed = false;
}

}
Loading
Loading