-
Notifications
You must be signed in to change notification settings - Fork 3
[feat] 퀴즈 조회, 수정, 삭제 API 구현 #31
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
Changes from 6 commits
098dc1d
c26c489
a0fd2f9
0147325
e7ddc83
9ed7545
f7ded66
db0e8ff
5885b66
780f03b
6d9483c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,31 @@ | ||
| package io.f1.backend.domain.quiz.app; | ||
|
|
||
| import static io.f1.backend.domain.quiz.mapper.QuizMapper.pageQuizToPageQuizListResponse; | ||
| import static io.f1.backend.domain.quiz.mapper.QuizMapper.quizCreateRequestToQuiz; | ||
| import static io.f1.backend.domain.quiz.mapper.QuizMapper.quizToQuizCreateResponse; | ||
| import static io.f1.backend.domain.quiz.mapper.QuizMapper.toQuizListPageResponse; | ||
|
|
||
| import static java.nio.file.Files.deleteIfExists; | ||
|
|
||
| import io.f1.backend.domain.question.app.QuestionService; | ||
| import io.f1.backend.domain.question.dto.QuestionRequest; | ||
| import io.f1.backend.domain.quiz.dao.QuizRepository; | ||
| import io.f1.backend.domain.quiz.dto.QuizCreateRequest; | ||
| import io.f1.backend.domain.quiz.dto.QuizCreateResponse; | ||
| import io.f1.backend.domain.quiz.dto.QuizListPageResponse; | ||
| import io.f1.backend.domain.quiz.dto.QuizListResponse; | ||
| import io.f1.backend.domain.quiz.dto.QuizUpdateRequest; | ||
| import io.f1.backend.domain.quiz.entity.Quiz; | ||
| import io.f1.backend.domain.user.dao.UserRepository; | ||
| import io.f1.backend.domain.user.entity.User; | ||
| import io.micrometer.common.util.StringUtils; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
|
|
||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.data.domain.Page; | ||
| import org.springframework.data.domain.Pageable; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
| import org.springframework.web.multipart.MultipartFile; | ||
|
|
@@ -23,8 +34,10 @@ | |
| import java.nio.file.Path; | ||
| import java.nio.file.Paths; | ||
| import java.util.List; | ||
| import java.util.NoSuchElementException; | ||
| import java.util.UUID; | ||
|
|
||
| @Slf4j | ||
| @Service | ||
| @RequiredArgsConstructor | ||
| public class QuizService { | ||
|
|
@@ -91,4 +104,89 @@ private String convertToThumbnailPath(MultipartFile thumbnailFile) throws IOExce | |
| private String getExtension(String filename) { | ||
| return filename.substring(filename.lastIndexOf(".") + 1); | ||
| } | ||
|
|
||
| @Transactional | ||
| public void deleteQuiz(Long quizId) { | ||
|
|
||
| Quiz quiz = | ||
| quizRepository | ||
| .findById(quizId) | ||
| .orElseThrow(() -> new NoSuchElementException("존재하지 않는 퀴즈입니다.")); | ||
|
|
||
| // TODO : util 메서드에서 사용자 ID 꺼내쓰는 식으로 수정하기 | ||
| if (1L != quiz.getCreator().getId()) { | ||
| throw new RuntimeException("권한이 없습니다."); | ||
| } | ||
|
|
||
| deleteOldThumbnailFileIfNeeded(quiz.getThumbnailUrl()); | ||
| quizRepository.deleteById(quizId); | ||
| } | ||
|
|
||
| @Transactional | ||
| public void updateQuiz(Long quizId, MultipartFile thumbnailFile, QuizUpdateRequest request) | ||
| throws IOException { | ||
|
|
||
| Quiz quiz = | ||
| quizRepository | ||
| .findById(quizId) | ||
| .orElseThrow(() -> new NoSuchElementException("존재하지 않는 퀴즈입니다.")); | ||
|
|
||
| if (request.title() != null) { | ||
| quiz.changeTitle(request.title()); | ||
| } | ||
|
|
||
| if (request.description() != null) { | ||
| quiz.changeDescription(request.description()); | ||
| } | ||
|
|
||
| if (thumbnailFile != null && !thumbnailFile.isEmpty()) { | ||
| validateImageFile(thumbnailFile); | ||
| String newThumbnailPath = convertToThumbnailPath(thumbnailFile); | ||
|
|
||
| deleteOldThumbnailFileIfNeeded(quiz.getThumbnailUrl()); | ||
| quiz.changeThumbnailUrl(newThumbnailPath); | ||
| } | ||
| } | ||
|
|
||
| private void deleteOldThumbnailFileIfNeeded(String oldFilename) { | ||
|
||
| if (oldFilename.contains("default")) { | ||
|
||
| return; | ||
| } | ||
|
|
||
| // oldFilename : /images/thumbnail/123asd.jpg | ||
| // filename : 123asd.jpg | ||
| String filename = oldFilename.substring(oldFilename.lastIndexOf("/") + 1); | ||
| Path filePath = Paths.get(uploadPath, filename).toAbsolutePath(); | ||
|
|
||
| try { | ||
| boolean deleted = deleteIfExists(filePath); | ||
| if (deleted) { | ||
| log.info("기존 썸네일 삭제 완료 : {}", filePath); | ||
| } else { | ||
| log.info("기존 썸네일 존재 X : {}", filePath); | ||
| } | ||
| } catch (IOException e) { | ||
| log.error("기존 썸네일 삭제 중 오류 : {}", filePath); | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
|
|
||
| @Transactional(readOnly = true) | ||
| public QuizListPageResponse getQuizzes(String title, String creator, Pageable pageable) { | ||
|
|
||
| Page<Quiz> quizzes; | ||
|
|
||
| // 검색어가 있을 때 | ||
| if (StringUtils.isBlank(title)) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [L5-참고의견]
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헉 import가 잘못됐네요 ! 감사합니다 ! 혹시 멘토링 때 그 차이점이 뭐라고 하셨나요? |
||
| quizzes = quizRepository.findQuizzesByTitleContaining(title, pageable); | ||
| } else if (StringUtils.isBlank(creator)) { | ||
| quizzes = quizRepository.findQuizzesByCreator_NicknameContaining(creator, pageable); | ||
| } else { // 검색어가 없을 때 혹은 빈 문자열일 때 | ||
| quizzes = quizRepository.findAll(pageable); | ||
| } | ||
|
|
||
| Page<QuizListResponse> quizListResponses = pageQuizToPageQuizListResponse(quizzes); | ||
|
|
||
| return toQuizListPageResponse(quizListResponses); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package io.f1.backend.domain.quiz.dto; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public record QuizListPageResponse( | ||
| int totalPages, int currentPage, long totalElements, List<QuizListResponse> quiz) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package io.f1.backend.domain.quiz.dto; | ||
|
|
||
| public record QuizListResponse( | ||
| Long quizId, | ||
| String title, | ||
| String description, | ||
| String creatorNickname, | ||
| int numberOfQuestion, | ||
| String thumbnailUrl) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| package io.f1.backend.domain.quiz.dto; | ||
|
|
||
| public record QuizUpdateRequest(String title, String description) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이부분은 지금 퀴즈리스트에 대한 정렬이 적용이 된건가요?.?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
퀴즈 리스트에 대한 정렬은 적용되지 않았습니다 !
따로 정한 기준은 없었던 것 같은데,,, 제가 기억이 안 나는 걸까요..? 혹시 어떤 정렬을 해야 할까요?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[L4-변경제안]
최신순, 인기순 정렬을 변경하는 기능은 정의하지 않았지만, 디폴트 정렬은 있어야 사용자에게 일관적인 리스트를 보여줄 수 있다고 생각합니다!(명시하지않아서 디폴트 정렬로 나오는 것 같지만, 안정적으로 명시하는게 좋다는 의견입니다) 현재 1번부터 나오는 asc라면 desc로 정렬하면(최신순) 어떨까하는 의견입니다. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오..! 그렇군요. 페이징을 처음해봐서 정렬까지 같이 처리해주는 기능이 있는지 몰랐는데 디폴트로 정렬기준이 있다면 아주 유용하고 좋을 것 같습니다. 의견 반영해서 커밋 다시 올렸습니다. 좋은 의견 감사합니다 !!