Skip to content

Commit

Permalink
feat: admin 페이지에 학교 추가 기능 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
xxeol2 committed Sep 21, 2023
1 parent e9bbeee commit 2486eb5
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import com.festago.admin.dto.AdminFestivalResponse;
import com.festago.admin.dto.AdminResponse;
import com.festago.admin.dto.AdminSchoolResponse;
import com.festago.admin.dto.AdminStageResponse;
import com.festago.admin.dto.AdminTicketResponse;
import com.festago.festival.domain.Festival;
import com.festago.festival.repository.FestivalRepository;
import com.festago.school.domain.School;
import com.festago.school.repository.SchoolRepository;
import com.festago.stage.domain.Stage;
import com.festago.stage.repository.StageRepository;
import com.festago.ticket.domain.Ticket;
Expand All @@ -26,25 +29,36 @@ public class AdminService {
private final FestivalRepository festivalRepository;
private final StageRepository stageRepository;
private final TicketRepository ticketRepository;
private final SchoolRepository schoolRepository;

public AdminService(FestivalRepository festivalRepository, StageRepository stageRepository,
TicketRepository ticketRepository) {
TicketRepository ticketRepository,
SchoolRepository schoolRepository) {
this.festivalRepository = festivalRepository;
this.stageRepository = stageRepository;
this.ticketRepository = ticketRepository;
this.schoolRepository = schoolRepository;
}

@Transactional(readOnly = true)
public AdminResponse getAdminResponse() {
List<School> allSchool = schoolRepository.findAll();
List<Ticket> allTicket = ticketRepository.findAll();
List<Stage> allStage = stageRepository.findAll();
List<Festival> allFestival = festivalRepository.findAll();
return new AdminResponse(
schoolResponses(allSchool),
ticketResponses(allTicket),
stageResponses(allStage),
festivalResponses(allFestival));
}

private List<AdminSchoolResponse> schoolResponses(List<School> schools) {
return schools.stream()
.map(AdminSchoolResponse::from)
.toList();
}

private List<AdminTicketResponse> ticketResponses(List<Ticket> tickets) {
return tickets.stream()
.map(this::ticketResponse)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import java.util.List;

public record AdminResponse(

List<AdminSchoolResponse> adminSchools,

List<AdminTicketResponse> adminTickets,
List<AdminStageResponse> adminStageResponse,
List<AdminFestivalResponse> adminFestivalResponse) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.festago.admin.dto;

import com.festago.school.domain.School;

public record AdminSchoolResponse(
Long id,
String domain,
String name) {

public static AdminSchoolResponse from(School school) {
return new AdminSchoolResponse(
school.getId(),
school.getDomain(),
school.getName()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
import com.festago.festival.application.FestivalService;
import com.festago.festival.dto.FestivalCreateRequest;
import com.festago.festival.dto.FestivalResponse;
import com.festago.school.application.SchoolService;
import com.festago.school.dto.SchoolCreateRequest;
import com.festago.school.dto.SchoolResponse;
import com.festago.stage.application.StageService;
import com.festago.stage.dto.StageCreateRequest;
import com.festago.stage.dto.StageResponse;
Expand Down Expand Up @@ -52,19 +55,28 @@ public class AdminController {
private final TicketService ticketService;
private final AdminService adminService;
private final AdminAuthService adminAuthService;
private final SchoolService schoolService;
private final Optional<BuildProperties> properties;

public AdminController(FestivalService festivalService, StageService stageService, TicketService ticketService,
AdminService adminService, AdminAuthService adminAuthService,
Optional<BuildProperties> buildProperties) {
SchoolService schoolService, Optional<BuildProperties> buildProperties) {
this.festivalService = festivalService;
this.stageService = stageService;
this.ticketService = ticketService;
this.adminService = adminService;
this.adminAuthService = adminAuthService;
this.schoolService = schoolService;
this.properties = buildProperties;
}

@PostMapping("/schools")
public ResponseEntity<SchoolResponse> createSchool(@RequestBody @Valid SchoolCreateRequest request) {
SchoolResponse response = schoolService.create(request);
return ResponseEntity.ok()
.body(response);
}

@PostMapping("/festivals")
public ResponseEntity<FestivalResponse> createFestival(@RequestBody @Valid FestivalCreateRequest request) {
FestivalResponse response = festivalService.create(request);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.festago.school.application;

import com.festago.school.domain.School;
import com.festago.school.dto.SchoolCreateRequest;
import com.festago.school.dto.SchoolResponse;
import com.festago.school.dto.SchoolsResponse;
import com.festago.school.repository.SchoolRepository;
import org.springframework.stereotype.Service;
Expand All @@ -14,6 +17,12 @@ public class SchoolService {
public SchoolService(SchoolRepository schoolRepository) {
this.schoolRepository = schoolRepository;
}

public SchoolResponse create(SchoolCreateRequest request) {
// TODO: doamin, name 중복 예외?
School school = schoolRepository.save(new School(request.domain(), request.name()));
return SchoolResponse.from(school);
}

@Transactional(readOnly = true)
public SchoolsResponse findAll() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.festago.school.dto;

import jakarta.validation.constraints.NotNull;

public record SchoolCreateRequest(
@NotNull(message = "name 은 null 일 수 없습니다.") String name,
@NotNull(message = "domain 은 null 일 수 없습니다.") String domain
) {

}
2 changes: 1 addition & 1 deletion backend/src/main/resources/static/css/admin/admin-page.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
margin: 10px; /* Add some margin around each form section */
background-color: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
min-width: 300px; /* Set a minimum width for each form section to prevent them from becoming too narrow */
min-width: 230px; /* Set a minimum width for each form section to prevent them from becoming too narrow */
}

h2 {
Expand Down
54 changes: 50 additions & 4 deletions backend/src/main/resources/static/js/admin/admin-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,28 @@ function fetchDataAndUpdateDataSection() {
// Clear existing data before appending new data
dataSection.innerHTML = "";

// 1. 축제 생성 요청 데이터 섹션
// 1. 학교 생성 요청 데이터 섹션
const schoolDataDiv = createDataSection(
"학교 목록",
data.adminSchools
);
dataSection.appendChild(schoolDataDiv);

// 2. 축제 생성 요청 데이터 섹션
const festivalDataDiv = createDataSection(
"축제 목록",
data.adminFestivalResponse
);
dataSection.appendChild(festivalDataDiv);

// 2. 공연 생성 요청 데이터 섹션
// 3. 공연 생성 요청 데이터 섹션
const stageDataDiv = createDataSection(
"공연 목록",
data.adminStageResponse
);
dataSection.appendChild(stageDataDiv);

// 3. 티켓 생성 요청 데이터 섹션
// 4. 티켓 생성 요청 데이터 섹션
const ticketDataDiv = createDataSection(
"티켓 목록",
data.adminTickets
Expand Down Expand Up @@ -112,6 +119,44 @@ function formatEntryTimeAmount(entryTimeAmount) {
return formattedString;
}

// 학교 생성 버튼 클릭 시 요청 보내기
document.getElementById("createSchoolForm").addEventListener("submit",
function (event) {
event.preventDefault();
const formData = new FormData(event.target);
const festivalData = {
name: formData.get("schoolName"),
domain: formData.get("domain")
};

fetch("/admin/schools", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(festivalData)
})
.then(response => {
if (response.ok) {
return response.json();
} else {
return response.json().then(data => {
throw new Error(data.message || "학교 생성에 실패하였습니다.");
});
}
})
.then(data => {
// 성공: 알림창 표시하고 폼 필드 초기화
alert("학교가 성공적으로 생성되었습니다!");
// Fetch data again and update dataSection
fetchDataAndUpdateDataSection();
})
.catch(error => {
// 오류: 알림창 표시
alert(error.message);
});
});

// 축제 생성 버튼 클릭 시 요청 보내기
document.getElementById("createFestivalForm").addEventListener("submit",
function (event) {
Expand All @@ -121,7 +166,8 @@ document.getElementById("createFestivalForm").addEventListener("submit",
name: formData.get("name"),
startDate: formData.get("startDate"),
endDate: formData.get("endDate"),
thumbnail: formData.get("thumbnail")
thumbnail: formData.get("thumbnail"),
schoolId: formData.get("schoolId")
};

fetch("/admin/festivals", {
Expand Down
16 changes: 16 additions & 0 deletions backend/src/main/resources/templates/admin/admin-page.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@
</head>
<body>
<div class="container">
<div class="form-section">
<h2>학교 생성 요청</h2>
<form id="createSchoolForm" method="post" action="#">
<label for="schoolName">이름:</label>
<input id="schoolName" name="schoolName" required type="text"><br>

<label for="domain">도메인:</label>
<input id="domain" name="domain" required type="text"><br>

<button type="submit">학교 생성</button>
</form>
</div>

<div class="form-section">
<h2>축제 생성 요청</h2>
<form id="createFestivalForm" method="post" action="#">
Expand All @@ -22,6 +35,9 @@ <h2>축제 생성 요청</h2>
<label for="thumbnail">썸네일:</label>
<input id="thumbnail" name="thumbnail" required type="text"><br>

<label for="schoolId">학교 ID:</label>
<input id="schoolId" name="schoolId" required type="text"><br>

<button type="submit">축제 생성</button>
</form>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
import com.festago.festival.application.FestivalService;
import com.festago.festival.dto.FestivalCreateRequest;
import com.festago.festival.dto.FestivalResponse;
import com.festago.school.application.SchoolService;
import com.festago.school.dto.SchoolCreateRequest;
import com.festago.school.dto.SchoolResponse;
import com.festago.stage.application.StageService;
import com.festago.stage.dto.StageCreateRequest;
import com.festago.stage.dto.StageResponse;
Expand Down Expand Up @@ -69,6 +72,9 @@ class AdminControllerTest {
@MockBean
AdminAuthService adminAuthService;

@MockBean
SchoolService schoolService;

@SpyBean
AuthExtractor authExtractor;

Expand Down Expand Up @@ -108,6 +114,34 @@ class AdminControllerTest {
.andExpect(status().isOk());
}

@Test
@WithMockAuth(role = Role.ADMIN)
void 학교_생성() throws Exception {
// given
String domain = "festago.com";
String name = "페스타고 대학교";

SchoolCreateRequest request = new SchoolCreateRequest(name, domain);

SchoolResponse expected = new SchoolResponse(1L, domain, name);

given(schoolService.create(any(SchoolCreateRequest.class)))
.willReturn(expected);

// when && then
String content = mockMvc.perform(post("/admin/schools")
.content(objectMapper.writeValueAsString(request))
.contentType(MediaType.APPLICATION_JSON)
.cookie(new Cookie("token", "token")))
.andDo(print())
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString(StandardCharsets.UTF_8);
SchoolResponse actual = objectMapper.readValue(content, SchoolResponse.class);
assertThat(actual).isEqualTo(expected);
}

@Test
@WithMockAuth(role = Role.ADMIN)
void 축제_생성() throws Exception {
Expand Down

0 comments on commit 2486eb5

Please sign in to comment.