Skip to content
Closed
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
10 changes: 10 additions & 0 deletions src/main/java/gg/agit/konect/domain/event/controller/EventApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import gg.agit.konect.domain.event.dto.EventBoothMapResponse;
import gg.agit.konect.domain.event.dto.EventBoothsResponse;
import gg.agit.konect.domain.event.dto.EventContentsResponse;
import gg.agit.konect.domain.event.dto.EventMiniEventsResponse;
import gg.agit.konect.domain.event.dto.EventProgramsResponse;
import gg.agit.konect.domain.event.enums.EventProgramType;
Expand Down Expand Up @@ -54,4 +55,13 @@ ResponseEntity<EventMiniEventsResponse> getEventMiniEvents(
@RequestParam(defaultValue = "20") @Min(1) Integer limit,
@UserId Integer userId
);

@Operation(summary = "행사 콘텐츠 목록을 조회한다.")
@GetMapping("/{eventId}/contents")
ResponseEntity<EventContentsResponse> getEventContents(
@PathVariable Integer eventId,
@RequestParam(required = false) String category,
@RequestParam(defaultValue = "1") @Min(1) Integer page,
@RequestParam(defaultValue = "20") @Min(1) Integer limit
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import gg.agit.konect.domain.event.dto.EventBoothMapResponse;
import gg.agit.konect.domain.event.dto.EventBoothsResponse;
import gg.agit.konect.domain.event.dto.EventContentsResponse;
import gg.agit.konect.domain.event.dto.EventMiniEventsResponse;
import gg.agit.konect.domain.event.dto.EventProgramsResponse;
import gg.agit.konect.domain.event.enums.EventProgramType;
Expand Down Expand Up @@ -42,4 +43,10 @@ public ResponseEntity<EventMiniEventsResponse> getEventMiniEvents(Integer eventI
Integer userId) {
return ResponseEntity.ok(eventService.getEventMiniEvents(eventId, page, limit, userId));
}

@Override
public ResponseEntity<EventContentsResponse> getEventContents(Integer eventId, String category, Integer page,
Integer limit) {
return ResponseEntity.ok(eventService.getEventContents(eventId, category, page, limit));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package gg.agit.konect.domain.event.dto;

import java.time.LocalDateTime;

public record EventContentSummaryResponse(
Integer contentId,
String title,
String thumbnailUrl,
String type,
String summary,
LocalDateTime publishedAt
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package gg.agit.konect.domain.event.dto;

import java.util.List;

public record EventContentsResponse(
Long totalCount,
Integer currentCount,
Integer totalPage,
Integer currentPage,
List<EventContentSummaryResponse> contents
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package gg.agit.konect.domain.event.enums;

public enum EventContentType {
ARTICLE,
IMAGE,
VIDEO
}
59 changes: 59 additions & 0 deletions src/main/java/gg/agit/konect/domain/event/model/EventContent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package gg.agit.konect.domain.event.model;

import static jakarta.persistence.EnumType.STRING;
import static jakarta.persistence.FetchType.LAZY;
import static jakarta.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;

import java.time.LocalDateTime;

import gg.agit.konect.domain.event.enums.EventContentType;
import gg.agit.konect.global.model.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Entity
@Table(name = "event_content")
@NoArgsConstructor(access = PROTECTED)
public class EventContent extends BaseEntity {

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", nullable = false, updatable = false, unique = true)
private Integer id;

@ManyToOne(fetch = LAZY)
@JoinColumn(name = "event_id", nullable = false, updatable = false)
private Event event;

@Column(name = "title", nullable = false, length = 100)
private String title;

@Column(name = "summary", nullable = false, length = 255)
private String summary;

@Column(name = "body", columnDefinition = "TEXT")
private String body;

@Column(name = "thumbnail_url", length = 255)
private String thumbnailUrl;

@Enumerated(STRING)
@Column(name = "type", nullable = false, length = 20)
private EventContentType type;

@Column(name = "published_at")
private LocalDateTime publishedAt;

@Column(name = "display_order", nullable = false)
private Integer displayOrder;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package gg.agit.konect.domain.event.repository;

import java.util.List;

import org.springframework.data.repository.Repository;

import gg.agit.konect.domain.event.model.EventContent;

public interface EventContentRepository extends Repository<EventContent, Integer> {

List<EventContent> findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId);

int countByEventId(Integer eventId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import gg.agit.konect.domain.event.dto.EventBoothMapResponse;
import gg.agit.konect.domain.event.dto.EventBoothSummaryResponse;
import gg.agit.konect.domain.event.dto.EventBoothsResponse;
import gg.agit.konect.domain.event.dto.EventContentSummaryResponse;
import gg.agit.konect.domain.event.dto.EventContentsResponse;
import gg.agit.konect.domain.event.dto.EventMiniEventSummaryResponse;
import gg.agit.konect.domain.event.dto.EventMiniEventsResponse;
import gg.agit.konect.domain.event.dto.EventProgramSummaryResponse;
Expand All @@ -18,11 +20,13 @@
import gg.agit.konect.domain.event.model.EventBooth;
import gg.agit.konect.domain.event.model.EventBoothMap;
import gg.agit.konect.domain.event.model.EventBoothMapItem;
import gg.agit.konect.domain.event.model.EventContent;
import gg.agit.konect.domain.event.model.EventMiniEvent;
import gg.agit.konect.domain.event.model.EventProgram;
import gg.agit.konect.domain.event.repository.EventBoothMapItemRepository;
import gg.agit.konect.domain.event.repository.EventBoothMapRepository;
import gg.agit.konect.domain.event.repository.EventBoothRepository;
import gg.agit.konect.domain.event.repository.EventContentRepository;
import gg.agit.konect.domain.event.repository.EventMiniEventRepository;
import gg.agit.konect.domain.event.repository.EventProgramRepository;
import gg.agit.konect.domain.event.repository.EventRepository;
Expand All @@ -40,6 +44,7 @@ public class EventService {
private final EventBoothMapRepository eventBoothMapRepository;
private final EventBoothMapItemRepository eventBoothMapItemRepository;
private final EventMiniEventRepository eventMiniEventRepository;
private final EventContentRepository eventContentRepository;

public EventProgramsResponse getEventPrograms(Integer eventId, EventProgramType type, Integer page, Integer limit,
Integer userId) {
Expand Down Expand Up @@ -99,6 +104,7 @@ public EventBoothMapResponse getEventBoothMap(Integer eventId) {
.map(this::toEventBoothMapItemResponse)
.toList();

// 부스 목록 응답과 같은 구역 값을 맵에서도 그대로 내려 프론트가 별도 매핑 없이 재사용할 수 있게 맞춘다.
List<EventBoothMapResponse.ZoneResponse> zones = booths.stream()
.map(EventBoothMapResponse.BoothMapItemResponse::zone)
.filter(zone -> zone != null && !zone.isBlank())
Expand Down Expand Up @@ -131,6 +137,31 @@ public EventMiniEventsResponse getEventMiniEvents(Integer eventId, Integer page,
);
}

public EventContentsResponse getEventContents(Integer eventId, String category, Integer page, Integer limit) {
getEvent(eventId);

List<EventContent> filteredContents = eventContentRepository.findAllByEventIdOrderByDisplayOrderAscIdAsc(
eventId).stream()
// 콘텐츠 타입 enum 이름과 동일한 문자열만 허용해 의도하지 않은 부분 일치를 막는다.
.filter(content -> category == null || category.isBlank() || content.getType()
.name()
.equalsIgnoreCase(category))
.toList();

PagedResult<EventContent> pagedContents = paginate(filteredContents, page, limit);
List<EventContentSummaryResponse> contents = pagedContents.items().stream()
.map(this::toEventContentSummaryResponse)
.toList();

return new EventContentsResponse(
(long)pagedContents.totalCount(),
contents.size(),
pagedContents.totalPage(),
page,
contents
);
}

private void getEvent(Integer eventId) {
eventRepository.findById(eventId)
.orElseThrow(() -> CustomException.of(NOT_FOUND_EVENT));
Expand Down Expand Up @@ -196,6 +227,17 @@ private EventMiniEventSummaryResponse toEventMiniEventSummaryResponse(EventMiniE
);
}

private EventContentSummaryResponse toEventContentSummaryResponse(EventContent content) {
return new EventContentSummaryResponse(
content.getId(),
content.getTitle(),
content.getThumbnailUrl(),
content.getType().name(),
content.getSummary(),
content.getPublishedAt()
);
}

private record PagedResult<T>(List<T> items, int totalCount, int totalPage) {
}
}
17 changes: 17 additions & 0 deletions src/main/resources/db/migration/V70__add_event_tables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,20 @@ CREATE TABLE IF NOT EXISTS event_mini_event

FOREIGN KEY (event_id) REFERENCES event (id) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS event_content
(
id INT AUTO_INCREMENT PRIMARY KEY,
event_id INT NOT NULL,
title VARCHAR(100) NOT NULL,
summary VARCHAR(255) NOT NULL,
body TEXT,
thumbnail_url VARCHAR(255),
type ENUM ('ARTICLE', 'IMAGE', 'VIDEO') NOT NULL,
published_at TIMESTAMP,
display_order INT NOT NULL DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,

FOREIGN KEY (event_id) REFERENCES event (id) ON DELETE CASCADE
);
Loading