Skip to content
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ out/

### VS Code ###
.vscode/

.env
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.cokerthon.Team3_Backend.domain.auth.dto.request.LoginRequest;
import com.cokerthon.Team3_Backend.domain.auth.dto.request.SignupRequest;
import com.cokerthon.Team3_Backend.domain.auth.dto.response.AuthResponse;
import com.cokerthon.Team3_Backend.domain.auth.exception.AuthSuccessCode;
import com.cokerthon.Team3_Backend.domain.auth.exception.code.AuthSuccessCode;
import com.cokerthon.Team3_Backend.domain.auth.service.AuthService;
import com.cokerthon.Team3_Backend.global.apiPayload.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.cokerthon.Team3_Backend.domain.auth.exception;
package com.cokerthon.Team3_Backend.domain.auth.exception.code;

import com.cokerthon.Team3_Backend.global.apiPayload.code.BaseErrorCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

import com.cokerthon.Team3_Backend.global.apiPayload.code.BaseErrorCode;

@Getter
@AllArgsConstructor
public enum AuthErrorCode implements BaseErrorCode {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.cokerthon.Team3_Backend.domain.auth.exception;
package com.cokerthon.Team3_Backend.domain.auth.exception.code;

import com.cokerthon.Team3_Backend.global.apiPayload.code.BaseSuccessCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

import com.cokerthon.Team3_Backend.global.apiPayload.code.BaseSuccessCode;

@Getter
@AllArgsConstructor
public enum AuthSuccessCode implements BaseSuccessCode {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.cokerthon.Team3_Backend.domain.auth.dto.request.LoginRequest;
import com.cokerthon.Team3_Backend.domain.auth.dto.request.SignupRequest;
import com.cokerthon.Team3_Backend.domain.auth.dto.response.AuthResponse;
import com.cokerthon.Team3_Backend.domain.auth.exception.AuthErrorCode;
import com.cokerthon.Team3_Backend.domain.auth.exception.code.AuthErrorCode;
import com.cokerthon.Team3_Backend.domain.auth.exception.AuthException;
import com.cokerthon.Team3_Backend.domain.user.entity.User;
import com.cokerthon.Team3_Backend.domain.user.repository.UserRepository;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.cokerthon.Team3_Backend.domain.community.controller;

import java.util.List;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.cokerthon.Team3_Backend.domain.community.dto.response.CommunityResDto;
import com.cokerthon.Team3_Backend.domain.community.service.CommunityService;
import com.cokerthon.Team3_Backend.domain.emotion.dto.response.LikeResDto;
import com.cokerthon.Team3_Backend.domain.emotion.service.EmotionLikeService;
import com.cokerthon.Team3_Backend.domain.user.entity.User;
import com.cokerthon.Team3_Backend.global.apiPayload.ApiResponse;
import com.cokerthon.Team3_Backend.global.apiPayload.code.GeneralSuccessCode;
import com.cokerthon.Team3_Backend.global.security.CurrentUser;

import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;

@RestController
@RequestMapping("/api/community")
@RequiredArgsConstructor
public class CommunityController {

private final CommunityService communityService;
private final EmotionLikeService emotionLikeService;

@GetMapping
@Operation(summary = "공개 감정 글 목록 조회", description = "공개(PUBLIC)로 설정된 모든 사용자의 감정 글을 최신순으로 조회")
public ApiResponse<List<CommunityResDto>> getCommunityList() {
List<CommunityResDto> response = communityService.getCommunityList();
return ApiResponse.onSuccess(GeneralSuccessCode.OK, response);
}

@PostMapping("/like")
@Operation(summary = "힘내요 토글", description = "emotionId를 파라미터로 받아 힘내요를 등록하거나 취소합니다.")
public ApiResponse<LikeResDto> toggleLike(
@RequestParam(name = "emotionId") Long emotionId,
@CurrentUser User user
) {
LikeResDto result = emotionLikeService.toggleLike(user, emotionId);
return ApiResponse.onSuccess(GeneralSuccessCode.OK, result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.cokerthon.Team3_Backend.domain.community.dto.response;

import java.time.LocalDateTime;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;

@Builder
@Schema(description = "커뮤니티 조회 응답 DTO")
public record CommunityResDto(

@Schema(description = "감정 글 ID")
@NotNull
Long id,

@Schema(description = "작성자 닉네임")
String nickname,

@Schema(description = "감정 점수")
int emotionScore,

@Schema(description = "감정 글 본문")
String content,

@Schema(description = "힘내요 수")
long likeCount,

@Schema(description = "작성 시간")
LocalDateTime createdAt
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.cokerthon.Team3_Backend.domain.community.service;

import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cokerthon.Team3_Backend.domain.community.dto.response.CommunityResDto;
import com.cokerthon.Team3_Backend.domain.emotion.repository.EmotionRecordRepository;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class CommunityService {

private final EmotionRecordRepository emotionRecordRepository;

@Transactional(readOnly = true)
public List<CommunityResDto> getCommunityList() {
return emotionRecordRepository.findAllCommunityPosts();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.cokerthon.Team3_Backend.domain.emotion.converter;

import com.cokerthon.Team3_Backend.domain.emotion.dto.response.LikeResDto;

import lombok.experimental.UtilityClass;

@UtilityClass
public class EmotionLikeConverter {

public static LikeResDto toLikeResDto(Long emotionId, int currentLikeCount, boolean isLiked) {
return LikeResDto.builder()
.id(emotionId)
.likeCount(currentLikeCount)
.like(isLiked)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.cokerthon.Team3_Backend.domain.emotion.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;

@Builder
@Schema(description = "감정 글 힘내요 응답 DTO")
public record LikeResDto(

@Schema(description = "게시글 ID")
Long id,

@Schema(description = "힘내요 수")
int likeCount,

@Schema(description = "힘내요 여부")
boolean like
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.cokerthon.Team3_Backend.domain.emotion.repository;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;

import com.cokerthon.Team3_Backend.domain.emotion.entity.EmotionLike;
import com.cokerthon.Team3_Backend.domain.emotion.entity.EmotionRecord;
import com.cokerthon.Team3_Backend.domain.user.entity.User;

public interface EmotionLikeRepository extends JpaRepository<EmotionLike, Long> {

long countByEmotion(EmotionRecord emotion);

Optional<EmotionLike> findByUserAndEmotion(User user, EmotionRecord emotion);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.cokerthon.Team3_Backend.domain.emotion.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import com.cokerthon.Team3_Backend.domain.community.dto.response.CommunityResDto;
import com.cokerthon.Team3_Backend.domain.emotion.entity.EmotionRecord;

public interface EmotionRecordRepository extends JpaRepository<EmotionRecord, Long> {

@Query("SELECT new com.cokerthon.Team3_Backend.domain.community.dto.response.CommunityResDto(" +
"r.id, u.nickname, r.emotionScore, r.content, COUNT(l), r.createdAt) " +
"FROM EmotionRecord r " +
"JOIN r.user u " +
"LEFT JOIN EmotionLike l ON l.emotion = r " +
"WHERE r.visibility = com.cokerthon.Team3_Backend.domain.emotion.enums.Visibility.PUBLIC " + // Visiblity -> Visibility 로 수정
"GROUP BY r.id, u.nickname, r.emotionScore, r.content, r.createdAt " +
"ORDER BY r.createdAt DESC")
List<CommunityResDto> findAllCommunityPosts();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.cokerthon.Team3_Backend.domain.emotion.service;

import java.time.LocalDateTime;
import java.util.Optional;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cokerthon.Team3_Backend.domain.emotion.converter.EmotionLikeConverter;
import com.cokerthon.Team3_Backend.domain.emotion.dto.response.LikeResDto;
import com.cokerthon.Team3_Backend.domain.emotion.entity.EmotionLike;
import com.cokerthon.Team3_Backend.domain.emotion.entity.EmotionRecord;
import com.cokerthon.Team3_Backend.domain.emotion.exception.EmotionException;
import com.cokerthon.Team3_Backend.domain.emotion.exception.code.EmotionErrorCode;
import com.cokerthon.Team3_Backend.domain.emotion.repository.EmotionLikeRepository;
import com.cokerthon.Team3_Backend.domain.emotion.repository.EmotionRecordRepository;
import com.cokerthon.Team3_Backend.domain.user.entity.User;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class EmotionLikeService {

private final EmotionRecordRepository emotionRecordRepository;
private final EmotionLikeRepository emotionLikeRepository;

@Transactional
public LikeResDto toggleLike(User user, Long emotionId) {
EmotionRecord emotion = emotionRecordRepository.findById(emotionId)
.orElseThrow(() -> new EmotionException(EmotionErrorCode.EMOTION_NOT_FOUND));

Optional<EmotionLike> existingLike = emotionLikeRepository.findByUserAndEmotion(user, emotion);
boolean isLiked;

if (existingLike.isPresent()) {
emotionLikeRepository.delete(existingLike.get());
isLiked = false;
} else {
EmotionLike newLike = EmotionLike.builder()
.user(user)
.emotion(emotion)
.createdAt(LocalDateTime.now())
.build();
emotionLikeRepository.save(newLike);
isLiked = true;
}

int currentLikeCount = (int) emotionLikeRepository.countByEmotion(emotion);

return EmotionLikeConverter.toLikeResDto(emotionId, currentLikeCount, isLiked);
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.cokerthon.Team3_Backend.global.security;

import com.cokerthon.Team3_Backend.domain.auth.exception.AuthErrorCode;
import com.cokerthon.Team3_Backend.domain.auth.exception.code.AuthErrorCode;
import com.cokerthon.Team3_Backend.domain.auth.exception.AuthException;
import com.cokerthon.Team3_Backend.domain.user.entity.User;
import com.cokerthon.Team3_Backend.domain.user.repository.UserRepository;
Expand Down