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

[Feature] - 여행기 작성 API 및 여행기 전체 조회 API 구현 #68

Merged
merged 12 commits into from
Jul 21, 2024
Merged
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
package woowacourse.touroot.travelogue.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.net.URI;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.converters.models.PageableAsQueryParam;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import woowacourse.touroot.travelogue.dto.TravelogueResponse;
import woowacourse.touroot.travelogue.dto.request.TravelogueRequest;
import woowacourse.touroot.travelogue.dto.response.TravelogueResponse;
import woowacourse.touroot.travelogue.service.TravelogueFacadeService;

@Tag(name = "여행기")
Expand All @@ -20,9 +30,29 @@ public class TravelogueController {

private final TravelogueFacadeService travelogueFacadeService;

@Operation(description = "여행기 작성")
@PostMapping
public ResponseEntity<TravelogueResponse> createTravelogue(@Valid @RequestBody TravelogueRequest request) {
TravelogueResponse response = travelogueFacadeService.createTravelogue(request);

return ResponseEntity.created(URI.create("/api/v1/travelogues/" + response.id()))
.body(response);
Comment on lines +38 to +39

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여행 계획 작성 api에서는 ResponseEntity.ok()를 반환하는데, 어느 쪽을 바꾸든 맞추는게 좋을 것 같습니다.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

201 Created 사용하기로 결정했습니다!

}

@Operation(description = "여행기 상세 조회")
@GetMapping("/{id}")
public ResponseEntity<TravelogueResponse> findTravelogue(@Valid @PathVariable Long id) {
return ResponseEntity.ok(travelogueFacadeService.findTravelogueById(id));
}

@Operation(description = "여행기 메인 페이지 조회")
@PageableAsQueryParam
@GetMapping
public ResponseEntity<Page<TravelogueResponse>> findMainPageTravelogues(
@Parameter(hidden = true)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 hidden이면 swagger에서 표시가 안되는걸로 아는데 숨겨두신 이유가 있을까요?
파라미터로 받는만큼 클라이언트 쪽에서 테스트 가능성도 열어두는게 좋을 것 같아요! 디폴트를 설정해주셔서 숨기지 않아도 테스트에 불편함은 없을 것 같습니다

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 파라미터를 hidden으로 해두지 않으면 JSON 오브젝트 형태의 body로 받게 됩니다. 그래서 @PageableAsQueryParam을 달아둔건데, 이렇게 하면 쿼리 파라미터로 페이지네이션 옵션을 각각 입력 받을 수 있습니다. 즉, 충분히 테스트 가능합니다!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

방금 확인했는데 깔끔하네요!! 지금 방식 그대로가 좋은 것 같습니닷

@PageableDefault(size = 5, sort = "id", direction = Direction.DESC)
Pageable pageable
) {
return ResponseEntity.ok(travelogueFacadeService.findTravelogues(pageable));
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package woowacourse.touroot.travelogue.domain.day.domain;
package woowacourse.touroot.travelogue.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
Expand All @@ -10,12 +10,13 @@
import jakarta.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import woowacourse.touroot.entity.BaseEntity;
import woowacourse.touroot.travelogue.domain.Travelogue;

@Getter
@EqualsAndHashCode(of = "id", callSuper = false)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Entity
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package woowacourse.touroot.travelogue.domain.photo.domain;
package woowacourse.touroot.travelogue.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
Expand All @@ -13,7 +13,6 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import woowacourse.touroot.entity.BaseEntity;
import woowacourse.touroot.travelogue.domain.place.domain.TraveloguePlace;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
Expand All @@ -35,7 +34,7 @@ public class TraveloguePhoto extends BaseEntity {
@ManyToOne(fetch = FetchType.LAZY)
private TraveloguePlace traveloguePlace;

public TraveloguePhoto(String key, Integer order, TraveloguePlace traveloguePlace) {
public TraveloguePhoto(Integer order, String key, TraveloguePlace traveloguePlace) {
this(null, key, order, traveloguePlace);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package woowacourse.touroot.travelogue.domain.place.domain;
package woowacourse.touroot.travelogue.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
Expand All @@ -14,7 +14,6 @@
import lombok.NoArgsConstructor;
import woowacourse.touroot.entity.BaseEntity;
import woowacourse.touroot.place.domain.Place;
import woowacourse.touroot.travelogue.domain.day.domain.TravelogueDay;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package woowacourse.touroot.travelogue.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import woowacourse.touroot.travelogue.domain.Travelogue;
import woowacourse.touroot.travelogue.domain.TravelogueDay;

public record TravelogueDayRequest(
@Schema(description = "여행기 장소 목록")
@NotNull(message = "여행기 장소 목록은 비어있을 수 없습니다.")
@Valid
List<TraveloguePlaceRequest> places
) {

public TravelogueDay toTravelogueDay(int order, Travelogue travelogue) {
return new TravelogueDay(order, travelogue);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package woowacourse.touroot.travelogue.dto.request;

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

public record TravelogueLocationRequest(
@Schema(description = "여행기 장소 위도", example = "37.5175896")
@NotNull(message = "여행기 장소 위도는 비어있을 수 없습니다.")
String lat,
@Schema(description = "여행기 장소 경도", example = "127.0867236")
@NotNull(message = "여행기 장소 경도는 비어있을 수 없습니다.")
String lng
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package woowacourse.touroot.travelogue.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import woowacourse.touroot.travelogue.domain.TraveloguePhoto;
import woowacourse.touroot.travelogue.domain.TraveloguePlace;

public record TraveloguePhotoRequest(
@Schema(description = "여행기 장소 사진 Key", example = "photo.png")
@NotNull(message = "여행기 장소 사진 Key 값은 비어있을 수 없습니다.")
String key
) {

public TraveloguePhoto toTraveloguePhoto(int order, TraveloguePlace traveloguePlace) {
return new TraveloguePhoto(order, key, traveloguePlace);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package woowacourse.touroot.travelogue.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import woowacourse.touroot.place.domain.Place;
import woowacourse.touroot.travelogue.domain.TravelogueDay;
import woowacourse.touroot.travelogue.domain.TraveloguePlace;

public record TraveloguePlaceRequest(
@Schema(description = "여행기 장소 이름", example = "선릉 캠퍼스")
@NotNull(message = "여행기 장소 이름은 비어있을 수 없습니다.")
String name,
@Schema(description = "여행기 장소 위치 정보")
@NotNull(message = "여행기 장소 위치 정보는 비어있을 수 없습니다.")
@Valid
TravelogueLocationRequest location,
@Schema(description = "여행기 장소 설명", example = "성담 빌딩에 위치한 선릉 캠퍼스입니다.")
String description,
@Schema(description = "여행기 장소 사진")
@NotNull(message = "여행기 장소 사진은 비어있을 수 없습니다.")
@Valid
List<TraveloguePhotoRequest> photos
) {

public TraveloguePlace toTraveloguePlace(int order, Place place, TravelogueDay travelogueDay) {
return new TraveloguePlace(order, description, place, travelogueDay);
}

public Place toPlace() {
return new Place(name, location.lat(), location.lng());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package woowacourse.touroot.travelogue.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import woowacourse.touroot.travelogue.domain.Travelogue;

public record TravelogueRequest(
@Schema(description = "여행기 제목", example = "서울 강남 여행기")
@NotNull(message = "여행기 제목은 비어있을 수 없습니다.")
String title,
@Schema(description = "여행기 섬네일", example = "https://thumbnail.png")
@NotNull(message = "여행기 섬네일은 비어있을 수 없습니다.")
String thumbnail,
@Schema(description = "여행기 일자 목록")
@NotNull(message = "여행기 일자 목록은 비어있을 수 없습니다.")
@Valid
List<TravelogueDayRequest> days
) {

public Travelogue toTravelogue() {
return new Travelogue(title, thumbnail);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package woowacourse.touroot.travelogue.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.Builder;
import woowacourse.touroot.travelogue.domain.TravelogueDay;

@Builder
public record TravelogueDayResponse(
@Schema(description = "여행기 일자 ID", example = "1")
Long id,
@Schema(description = "여행기 장소 목록")
List<TraveloguePlaceResponse> places
) {

public static TravelogueDayResponse of(TravelogueDay day, List<TraveloguePlaceResponse> places) {
return TravelogueDayResponse.builder()
.id(day.getId())
.places(places)
.build();
}
}
Loading
Loading