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] 퀘스트 #35

Merged
merged 6 commits into from
Dec 2, 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
@@ -1,6 +1,7 @@
package dongguk.osori.domain.goal.controller;

import dongguk.osori.domain.goal.dto.GoalCommentDto;
import dongguk.osori.domain.goal.dto.GoalCommentRequestDto;
import dongguk.osori.domain.goal.dto.GoalCommentResponseDto;
import dongguk.osori.domain.goal.service.GoalCommentService;
import jakarta.servlet.http.HttpSession;
Expand All @@ -26,17 +27,18 @@ public ResponseEntity<GoalCommentResponseDto> addComment(
@Parameter(description = "댓글을 추가할 목표의 ID", required = true)
@PathVariable("goalId") Long goalId,
@Parameter(description = "댓글의 내용 (이모지와 내용 포함)", required = true)
@RequestBody GoalCommentDto commentDto,
@RequestBody GoalCommentRequestDto goalRequestDto,
@Parameter(hidden = true) HttpSession session) {

Long userId = (Long) session.getAttribute("userId");
if (userId == null) {
return ResponseEntity.status(401).build();
}
GoalCommentResponseDto response = goalCommentService.addComment(goalId, userId, commentDto);
GoalCommentResponseDto response = goalCommentService.addComment(goalId, userId, goalRequestDto); // goalRequestDto로 변경
return ResponseEntity.ok(response);
}


// 댓글 삭제
@Operation(summary = "댓글 삭제", description = "특정 목표의 댓글을 삭제합니다.")
@DeleteMapping("/{commentId}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dongguk.osori.domain.goal.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class GoalCommentRequestDto {
private String content;
private int emoji;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package dongguk.osori.domain.goal.service;

import dongguk.osori.domain.goal.dto.GoalCommentDto;
import dongguk.osori.domain.goal.dto.GoalCommentResponseDto;
import dongguk.osori.domain.goal.dto.GoalDetailResponseDto;
import dongguk.osori.domain.goal.dto.GoalCommentRequestDto;
import dongguk.osori.domain.goal.entity.Goal;
import dongguk.osori.domain.goal.entity.GoalComment;
import dongguk.osori.domain.goal.repository.GoalCommentRepository;
import dongguk.osori.domain.goal.repository.GoalRepository;
import dongguk.osori.domain.quest.entity.MissionType;
import dongguk.osori.domain.quest.service.QuestService;
import dongguk.osori.domain.user.entity.User;
import dongguk.osori.domain.user.repository.UserRepository;
import jakarta.transaction.Transactional;
Expand All @@ -26,24 +28,28 @@ public class GoalCommentService {
private final GoalCommentRepository goalCommentRepository;
private final GoalRepository goalRepository;
private final UserRepository userRepository;
private final QuestService questService;

// 댓글 추가
@Transactional
public GoalCommentResponseDto addComment(Long goalId, Long userId, GoalCommentDto commentDto) {
public GoalCommentResponseDto addComment(Long goalId, Long userId, GoalCommentRequestDto goalRequestDto) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("User not found"));
Goal goal = goalRepository.findById(goalId)
.orElseThrow(() -> new RuntimeException("Goal not found"));

GoalComment comment = GoalComment.builder()
.content(commentDto.getContent())
.emoji(commentDto.getEmoji())
.content(goalRequestDto.getContent())
.emoji(goalRequestDto.getEmoji())
.goal(goal)
.user(user)
.build();

goalCommentRepository.save(comment);

questService.updateMissionStatus(userId, MissionType.COMMENTED_ON_FRIEND_GOAL);


return new GoalCommentResponseDto(
comment.getCommentId(),
user.getNickname(),
Expand All @@ -53,6 +59,7 @@ public GoalCommentResponseDto addComment(Long goalId, Long userId, GoalCommentDt
);
}


// 댓글 조회
@Transactional
public Optional<GoalDetailResponseDto> getGoalDetailsWithComments(Long goalId) {
Expand Down
11 changes: 7 additions & 4 deletions src/main/java/dongguk/osori/domain/goal/service/GoalService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import dongguk.osori.domain.goal.repository.GoalCommentRepository;
import dongguk.osori.domain.goal.repository.GoalRepository;
import dongguk.osori.domain.goal.entity.Goal;
import dongguk.osori.domain.quest.entity.MissionType;
import dongguk.osori.domain.quest.service.QuestService;
import dongguk.osori.domain.user.entity.User;
import dongguk.osori.domain.user.repository.UserRepository;
import jakarta.transaction.Transactional;
Expand All @@ -25,6 +27,7 @@ public class GoalService {
private final GoalRepository goalRepository;
private final UserRepository userRepository;
private final GoalCommentRepository goalCommentRepository;
private final QuestService questService;

// 로그인된 사용자 가져오기
private User getLoggedInUser(Long userId) {
Expand All @@ -45,18 +48,18 @@ public List<GoalResponseDto> getUserGoals(Long userId) {
// 로그인된 사용자의 목표 생성
@Transactional
public GoalResponseDto createGoal(GoalDto goalDto, Long userId) {
log.debug("Creating goal for user ID: {}", userId); // 디버깅용
User user = getLoggedInUser(userId);
log.debug("User found: {}", user); // 디버깅용

// Goal Builder 사용하여 새로운 목표 생성
Goal goal = Goal.builder()
.content(goalDto.getContent())
.user(user)
.build();
log.debug("New goal created: {}", goal); // 디버깅용

goalRepository.save(goal);

// 퀘스트 업데이트
questService.updateMissionStatus(userId, MissionType.GOAL_WRITTEN);

return new GoalResponseDto(goal.getGoalId(), goal.getContent(), goal.getCreatedAt(), goal.isCompleted());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import dongguk.osori.domain.portfolio.dto.*;
import dongguk.osori.domain.portfolio.entity.*;
import dongguk.osori.domain.portfolio.repository.PortfolioRepository;
import dongguk.osori.domain.quest.entity.MissionType;
import dongguk.osori.domain.quest.service.QuestService;
import dongguk.osori.domain.user.entity.User;
import dongguk.osori.domain.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
Expand All @@ -20,6 +22,7 @@ public class PortfolioService {

private final PortfolioRepository portfolioRepository;
private final UserRepository userRepository;
private final QuestService questService;

@Transactional
public PortfolioDetailDto createPortfolio(Long userId, PortfolioRequestDto requestDto) {
Expand Down Expand Up @@ -53,6 +56,9 @@ public PortfolioDetailDto createPortfolio(Long userId, PortfolioRequestDto reque

portfolioRepository.save(portfolio);

// 퀘스트 업데이트
questService.updateMissionStatus(userId, MissionType.PORTFOLIO_WRITTEN);

return mapToDetailDto(portfolio);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package dongguk.osori.domain.quest.controller;

import dongguk.osori.domain.goal.dto.GoalResponseDto;
import dongguk.osori.domain.quest.dto.QuestAndStampStatusDto;
import dongguk.osori.domain.quest.dto.QuestStatusDto;
import dongguk.osori.domain.quest.service.QuestService;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;

@RestController
@RequestMapping("/api/quests")
@RequiredArgsConstructor
public class QuestController {

private final QuestService questService;

@GetMapping("/status")
public ResponseEntity<QuestAndStampStatusDto> getQuestStatus(HttpSession session) {
Long userId = (Long) session.getAttribute("userId");
if (userId == null) {
return ResponseEntity.status(401).build(); // Unauthorized 응답
}

QuestStatusDto questStatus = questService.getQuestStatus(userId, LocalDate.now());
int stampCount = questService.getCurrentStampCount(userId); // 현재 스탬프 개수 가져오기
boolean fullyCompleted = stampCount == 7; // 스탬프가 모두 채워졌는지 확인

QuestAndStampStatusDto response = new QuestAndStampStatusDto(questStatus, stampCount, fullyCompleted);
return ResponseEntity.ok(response);
}
}

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

import dongguk.osori.domain.quest.entity.MissionType;
import lombok.Data;

import java.time.LocalDate;

@Data
public class MissionRequestDto {
private LocalDate date;
private MissionType missionType;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package dongguk.osori.domain.quest.dto;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class QuestAndStampStatusDto {
private QuestStatusDto questStatus;
private int stampCount;
private boolean fullyCompleted;
}
14 changes: 14 additions & 0 deletions src/main/java/dongguk/osori/domain/quest/dto/QuestStatusDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package dongguk.osori.domain.quest.dto;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class QuestStatusDto {
private boolean attended;
private boolean goalWritten;
private boolean commentedOnFriendGoal;
private boolean portfolioWritten;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package dongguk.osori.domain.quest.entity;

public enum MissionType {
GOAL_WRITTEN,
COMMENTED_ON_FRIEND_GOAL,
PORTFOLIO_WRITTEN,
ATTENDANCE_CHECKED
}

63 changes: 63 additions & 0 deletions src/main/java/dongguk/osori/domain/quest/entity/Quest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package dongguk.osori.domain.quest.entity;

import dongguk.osori.domain.user.entity.User;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDate;

@Entity
@Getter
@NoArgsConstructor
public class Quest {

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

@Column(nullable = false)
private LocalDate date; // 퀘스트가 속한 날짜

@Column(nullable = false)
private boolean attended; // 출석 여부

@Column(nullable = false)
private boolean goalWritten; // 목표 작성 여부

@Column(nullable = false)
private boolean commentedOnFriendGoal; // 친구 목표에 댓글 단 여부

@Column(nullable = false)
private boolean portfolioWritten; // 포트폴리오 작성 여부

public Quest(User user, LocalDate date) {
this.user = user;
this.date = date;
}

public boolean isAllMissionsCompleted() {
return attended && goalWritten && commentedOnFriendGoal && portfolioWritten;
}

public void markAttended() {
this.attended = true;
}

public void markGoalWritten() {
this.goalWritten = true;
}

public void markCommentedOnFriendGoal() {
this.commentedOnFriendGoal = true;
}

public void markPortfolioWritten() {
this.portfolioWritten = true;
}

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

46 changes: 46 additions & 0 deletions src/main/java/dongguk/osori/domain/quest/entity/Stamp.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package dongguk.osori.domain.quest.entity;

import dongguk.osori.domain.user.entity.User;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor
public class Stamp {

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

@Column(nullable = false)
private int weekNumber; // 몇 주차 스탬프인지

@Column(nullable = false)
private int year; // 해당 연도

@Column(nullable = false)
private int count; // 스탬프 개수 (최대 7)

public Stamp(User user, int weekNumber, int year) {
this.user = user;
this.weekNumber = weekNumber;
this.year = year;
}

public void incrementStamp() {
if (count < 7) {
count++;
}
}

public boolean isFullyCompleted() {
return count == 7;
}

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dongguk.osori.domain.quest.repository;

import dongguk.osori.domain.quest.entity.Quest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.time.LocalDate;
import java.util.Optional;

@Repository
public interface QuestRepository extends JpaRepository<Quest, Long> {
Optional<Quest> findByUser_UserIdAndDate(Long userId, LocalDate date);

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dongguk.osori.domain.quest.repository;

import dongguk.osori.domain.quest.entity.Stamp;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface StampRepository extends JpaRepository<Stamp, Long> {
Optional<Stamp> findByUser_UserIdAndWeekNumberAndYear(Long userId, int weekNumber, int year);
}

Loading