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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.example.leets_7th.common.service;

public class ImageService {
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,15 @@ public enum ErrorStatus implements BaseStatus {
FORBIDDEN(HttpStatus.FORBIDDEN, "COMM_403", "접근 권한이 없습니다."),
NOT_FOUND(HttpStatus.NOT_FOUND, "COMM_404", "요청한 자원을 찾을 수 없습니다."),
METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED, "COMM_405", "허용되지 않은 메소드입니다."),
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMM_500", "서버 내부 오류입니다.");
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMM_500", "서버 내부 오류입니다."),

// User
USER_NOT_FOUND(HttpStatus.NOT_FOUND,"USER_404","사용자를 찾을 수 없습니다."),


// Post
POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST_404","게시글을 찾을 수 없습니다."),
POST_ALREADY_DELETED(HttpStatus.BAD_REQUEST,"POST_400","이미 삭제된 게시글입니다.");

private final HttpStatus httpStatus;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,15 @@
public enum SuccessStatus implements BaseStatus {

// test
HEALTH_CHECK_SUCCESS_STATUS(HttpStatus.OK,"TEST_200","OK"),
STRING_REPEAT_SUCCESS(HttpStatus.CREATED,"TEST_201","문자열을 성공적으로 출력했습니다.");
HEALTH_CHECK_SUCCESS_STATUS(HttpStatus.OK, "TEST_200", "OK"),
STRING_REPEAT_SUCCESS(HttpStatus.CREATED, "TEST_201", "문자열을 성공적으로 출력했습니다."),

GET_ALL_POST_SUCCESS(HttpStatus.OK, "POST_2001", "게시글 목록 조회에 성공했습니다."),
GET_POST_DETAIL_SUCCESS(HttpStatus.OK, "POST_2002", "게시글 상세 조회에 성공했습니다."),
CREATE_POST_SUCCESS(HttpStatus.CREATED, "POST_2011", "게시글 생성에 성공했습니다."),
UPDATE_POST_SUCCESS(HttpStatus.CREATED, "POST_2003", "게시글 수정에 성공했습니다."),
DELETE_POST_SUCCESS(HttpStatus.OK, "POST_2004", "게시글 삭제에 성공했습니다.");


private final HttpStatus httpStatus;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.example.leets_7th.domain.comment.controller;

import com.example.leets_7th.domain.comment.controller.docs.CommentControllerDocs;

public class CommentController implements CommentControllerDocs {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.leets_7th.domain.comment.controller.docs;

import io.swagger.v3.oas.annotations.tags.Tag;

@Tag(name = "Comment", description = "댓글 API")
public interface CommentControllerDocs {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.example.leets_7th.domain.post.controller;

import com.example.leets_7th.common.response.ApiResponse;
import com.example.leets_7th.common.status.SuccessStatus;
import com.example.leets_7th.domain.post.controller.docs.PostControllerDocs;
import com.example.leets_7th.domain.post.dto.request.CreatePostRequest;
import com.example.leets_7th.domain.post.dto.request.GetPostRequest;
import com.example.leets_7th.domain.post.dto.request.UpdatePostRequest;
import com.example.leets_7th.domain.post.dto.response.CreatePostResponse;
import com.example.leets_7th.domain.post.dto.response.GetPostDetailResponse;
import com.example.leets_7th.domain.post.dto.response.GetPostResponse;
import com.example.leets_7th.domain.post.dto.response.UpdatePostResponse;
import com.example.leets_7th.domain.post.service.PostCommandService;
import com.example.leets_7th.domain.post.service.PostQueryService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RequestMapping("/api/posts")
@RestController
@Validated
@RequiredArgsConstructor
public class PostController implements PostControllerDocs {

private final PostCommandService postCommandService;
private final PostQueryService postQueryService;

@Override
@GetMapping
public ResponseEntity<ApiResponse<GetPostResponse>> getAllPost(
@Valid @ModelAttribute GetPostRequest request
) {
GetPostResponse response = postQueryService.getAllPost(request);
return ApiResponse.success(SuccessStatus.GET_ALL_POST_SUCCESS, response);
}

@Override
@GetMapping("/{postId}")
public ResponseEntity<ApiResponse<GetPostDetailResponse>> getDetailPost(
@RequestParam Long userId,
@PathVariable Long postId
) {
GetPostDetailResponse response = postQueryService.getPostDetail(userId, postId);
return ApiResponse.success(SuccessStatus.GET_POST_DETAIL_SUCCESS, response);
}

@Override
@PostMapping
public ResponseEntity<ApiResponse<CreatePostResponse>> createPost(
@RequestParam Long userId,
@RequestBody @Valid CreatePostRequest request
) {
CreatePostResponse response = postCommandService.createPost(userId, request);
return ApiResponse.success(SuccessStatus.CREATE_POST_SUCCESS, response);
}

@Override
@PatchMapping("/{postId}")
public ResponseEntity<ApiResponse<UpdatePostResponse>> updatePost(
@RequestParam Long userId,
@PathVariable Long postId,
@Valid @RequestBody UpdatePostRequest request
) {
UpdatePostResponse response = postCommandService.updatePost(userId, postId, request);
return ApiResponse.success(SuccessStatus.UPDATE_POST_SUCCESS, response);
}

@Override
@DeleteMapping("/{postId}")
public ResponseEntity<ApiResponse<Void>> deletePost(
@RequestParam Long userId,
@Valid @PathVariable Long postId
) {
postCommandService.deletePost(userId, postId);
return ApiResponse.success(SuccessStatus.DELETE_POST_SUCCESS);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.example.leets_7th.domain.post.controller.docs;

import com.example.leets_7th.common.response.ApiResponse;
import com.example.leets_7th.domain.post.dto.request.CreatePostRequest;
import com.example.leets_7th.domain.post.dto.request.GetPostRequest;
import com.example.leets_7th.domain.post.dto.request.UpdatePostRequest;
import com.example.leets_7th.domain.post.dto.response.CreatePostResponse;
import com.example.leets_7th.domain.post.dto.response.GetPostDetailResponse;
import com.example.leets_7th.domain.post.dto.response.GetPostResponse;
import com.example.leets_7th.domain.post.dto.response.UpdatePostResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@Tag(name = "Post", description = "게시글 관련 API")
public interface PostControllerDocs {

@Operation(summary = "게시글 목록 조회", description = "게시글 리스트를 조회합니다.")
@GetMapping
ResponseEntity<ApiResponse<GetPostResponse>> getAllPost(
@Valid @ModelAttribute GetPostRequest request
);

@Operation(summary = "게시글 상세 조회", description = "특정 게시글의 상세 정보를 조회합니다.")
@GetMapping("/{postId}")
ResponseEntity<ApiResponse<GetPostDetailResponse>> getDetailPost(
@RequestParam Long userId,
@PathVariable Long postId
);

@Operation(summary = "게시글 생성", description = "새로운 게시글을 생성합니다.")
@PostMapping
ResponseEntity<ApiResponse<CreatePostResponse>> createPost(
@RequestParam Long userId,
@RequestBody @Valid CreatePostRequest request
);

@Operation(summary = "게시글 수정", description = "기존 게시글을 수정합니다.")
@PatchMapping("/{postId}")
ResponseEntity<ApiResponse<UpdatePostResponse>> updatePost(
@RequestParam Long userId,
@PathVariable Long postId,
@Valid @RequestBody UpdatePostRequest request
);

@Operation(summary = "게시글 삭제", description = "게시글을 삭제합니다.")
@DeleteMapping("/{postId}")
ResponseEntity<ApiResponse<Void>> deletePost(
@RequestParam Long userId,
@Valid @PathVariable Long postId
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.example.leets_7th.domain.post.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;

public record CreatePostRequest(

@Schema(example = "제목")
@NotBlank(message = "제목은 공백일 수 없습니다")
String title,

@Schema(example = "내용")
@NotBlank(message = "내용은 공백일 수 없습니다")
String content,

Integer thumbnailIndex

) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.example.leets_7th.domain.post.dto.request;

public record GetPostDetailRequest() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.example.leets_7th.domain.post.dto.request;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

public record GetPostRequest(

@NotNull(message = "userId는 필수입니다")
Long userId,

@Min(value = 1, message = "page는 1 이상이어야 합니다")
int page,

@Min(value = 1, message = "size는 1 이상이어야 합니다")
@Max(value = 50, message = "size는 50 이하여야 합니다")
int size
) {
public Pageable toPageable() {
return PageRequest.of(page - 1, size, Sort.by("createdAt").descending());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.example.leets_7th.domain.post.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;

public record UpdatePostRequest(

@Schema(example = "제목")
@NotBlank(message = "제목은 공백일 수 없습니다")
String title,

@Schema(example = "내용")
@NotBlank(message = "내용은 공백일 수 없습니다")
String content,

Integer thumbnailIndex

) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.example.leets_7th.domain.post.dto.response;

public record CreatePostResponse(
Long postId,
String thumbnailUrl
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.example.leets_7th.domain.post.dto.response;

import com.example.leets_7th.domain.post.entity.Image;
import com.example.leets_7th.domain.post.entity.Post;
import java.time.LocalDateTime;
import java.util.List;

public record GetPostDetailResponse(
Long postId,
String title,
String content,
String thumbnailImageUrl,
String author,
List<String> imageUrls,
LocalDateTime createdAt
) {
public static GetPostDetailResponse from(Post post) {
return new GetPostDetailResponse(
post.getId(),
post.getTitle(),
post.getContent(),
post.getThumbnailImageUrl(),
post.getUser().getName(),
post.getImages().stream()
.map(Image::getImageUrl)
.toList(),
post.getCreatedAt()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.example.leets_7th.domain.post.dto.response;

import java.util.List;

public record GetPostResponse(
List<PostSummary> posts,
int page,
int size,
long totalElements,
int totalPages
) {
public static GetPostResponse of(
List<PostSummary> posts,
int page,
int size,
long totalElements,
int totalPages
) {
return new GetPostResponse(posts, page, size, totalElements, totalPages);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.example.leets_7th.domain.post.dto.response;

import com.example.leets_7th.domain.post.entity.Post;

import java.time.LocalDateTime;

public record PostSummary(
Long postId,
String title,
String thumbnailImageUrl,
String author,
LocalDateTime createdAt
) {
public static PostSummary from(Post post) {
return new PostSummary(
post.getId(),
post.getTitle(),
post.getThumbnailImageUrl(),
post.getUser().getName(),
post.getCreatedAt()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.leets_7th.domain.post.dto.response;

import java.time.LocalDateTime;

public record UpdatePostResponse(
Long postId,
LocalDateTime updatedAt
) {}
13 changes: 13 additions & 0 deletions src/main/java/com/example/leets_7th/domain/post/entity/Post.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import jakarta.persistence.*;
import lombok.*;

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

Expand Down Expand Up @@ -38,11 +39,23 @@ public class Post extends BaseEntity {
@OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Comment> comments = new ArrayList<>();

@Column(name = "deleted_at")
private LocalDateTime deletedAt;

@Builder
public Post(User user, String title, String content, String thumbnailImageUrl) {
this.user = user;
this.title = title;
this.content = content;
this.thumbnailImageUrl = thumbnailImageUrl;
}

public void update(String title, String content) {
this.title = title;
this.content = content;
}

public void delete() {
this.deletedAt = LocalDateTime.now();
}
}
Loading