diff --git a/src/main/java/com/ripple/BE/learning/controller/ConceptController.java b/src/main/java/com/ripple/BE/learning/controller/ConceptController.java index 1ecf161..f5b9ee2 100644 --- a/src/main/java/com/ripple/BE/learning/controller/ConceptController.java +++ b/src/main/java/com/ripple/BE/learning/controller/ConceptController.java @@ -1,7 +1,9 @@ package com.ripple.BE.learning.controller; import com.ripple.BE.global.dto.response.ApiResponse; +import com.ripple.BE.learning.dto.ConceptDTO; import com.ripple.BE.learning.dto.ConceptListDTO; +import com.ripple.BE.learning.dto.response.ConceptDetailResponse; import com.ripple.BE.learning.dto.response.ConceptListResponse; import com.ripple.BE.learning.service.concept.ConceptService; import com.ripple.BE.user.domain.CustomUserDetails; @@ -59,4 +61,15 @@ public ResponseEntity> scrapConcept( conceptService.scrapConcept(currentUser.getId(), conceptId); return ResponseEntity.status(HttpStatus.OK).body(ApiResponse.EMPTY_RESPONSE); } + + @Operation(summary = "개별 개념 학습 조회", description = "개별 개념 학습을 조회합니다.") + @GetMapping("/learning/{conceptId}") + public ResponseEntity> getConcept( + final @PathVariable("conceptId") long conceptId) { + + ConceptDTO concept = conceptService.getConcept(conceptId); + + return ResponseEntity.status(HttpStatus.OK) + .body(ApiResponse.from(ConceptDetailResponse.toConceptDetailResponse(concept))); + } } diff --git a/src/main/java/com/ripple/BE/learning/controller/QuizController.java b/src/main/java/com/ripple/BE/learning/controller/QuizController.java index c34195e..5cd6c85 100644 --- a/src/main/java/com/ripple/BE/learning/controller/QuizController.java +++ b/src/main/java/com/ripple/BE/learning/controller/QuizController.java @@ -51,7 +51,6 @@ public ResponseEntity> startQuiz( @PostMapping("/{learningSetId}/quizzes/{quizId}") public ResponseEntity> submitAnswer( final @AuthenticationPrincipal CustomUserDetails currentUser, - final @PathVariable("learningSetId") long learningSetId, final @PathVariable("quizId") long quizId, final @RequestBody @Valid SubmitAnswerRequest request) { diff --git a/src/main/java/com/ripple/BE/learning/dto/ConceptDTO.java b/src/main/java/com/ripple/BE/learning/dto/ConceptDTO.java index 5085a6b..92e0afc 100644 --- a/src/main/java/com/ripple/BE/learning/dto/ConceptDTO.java +++ b/src/main/java/com/ripple/BE/learning/dto/ConceptDTO.java @@ -29,4 +29,13 @@ public static ConceptDTO toConceptDTO(final Map excelData) { Level.valueOf(excelData.get(LEVEL)), excelData.get(LEARNING_SET_NAME)); } + + public static ConceptDTO toScrapConceptDTO(final Concept concept) { + return new ConceptDTO( + concept.getConceptId(), + concept.getName(), + concept.getExplanation(), + concept.getLevel(), + concept.getLearningSet().getName()); + } } diff --git a/src/main/java/com/ripple/BE/learning/dto/ConceptListDTO.java b/src/main/java/com/ripple/BE/learning/dto/ConceptListDTO.java index 3cc3ed8..106ea60 100644 --- a/src/main/java/com/ripple/BE/learning/dto/ConceptListDTO.java +++ b/src/main/java/com/ripple/BE/learning/dto/ConceptListDTO.java @@ -9,4 +9,8 @@ public record ConceptListDTO(List conceptList // 개념 리스트 public static ConceptListDTO toConceptListDTO(final List conceptList) { return new ConceptListDTO(conceptList.stream().map(ConceptDTO::toConceptDTO).toList()); } + + public static ConceptListDTO toScrapConceptListDTO(final List conceptList) { + return new ConceptListDTO(conceptList.stream().map(ConceptDTO::toScrapConceptDTO).toList()); + } } diff --git a/src/main/java/com/ripple/BE/learning/dto/FailQuizListDTO.java b/src/main/java/com/ripple/BE/learning/dto/FailQuizListDTO.java new file mode 100644 index 0000000..fcf5185 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/dto/FailQuizListDTO.java @@ -0,0 +1,11 @@ +package com.ripple.BE.learning.dto; + +import com.ripple.BE.learning.domain.quiz.Quiz; +import java.util.List; + +public record FailQuizListDTO(List failQuizList) { + + public static FailQuizListDTO toFailQuizListDTO(final List quizList) { + return new FailQuizListDTO(quizList.stream().map(QuizDTO::toFailQuizDTO).toList()); + } +} diff --git a/src/main/java/com/ripple/BE/learning/dto/QuizDTO.java b/src/main/java/com/ripple/BE/learning/dto/QuizDTO.java index d28adb3..3648a9b 100644 --- a/src/main/java/com/ripple/BE/learning/dto/QuizDTO.java +++ b/src/main/java/com/ripple/BE/learning/dto/QuizDTO.java @@ -78,4 +78,32 @@ public static QuizDTO toQuizDTO(AddLevelTestQuizRequest request) { request.explanation(), null); } + + public static QuizDTO toFailQuizDTO(final Quiz quiz) { + return new QuizDTO( + quiz.getId(), + quiz.getName(), + null, + null, + null, + null, + null, + null, + null, + quiz.getLearningSet().getName()); + } + + public static QuizDTO toScrapQuizDTO(final Quiz quiz) { + return new QuizDTO( + quiz.getId(), + quiz.getName(), + null, + null, + quiz.getLevel(), + null, + null, + null, + null, + quiz.getLearningSet().getName()); + } } diff --git a/src/main/java/com/ripple/BE/learning/dto/QuizListDTO.java b/src/main/java/com/ripple/BE/learning/dto/QuizListDTO.java index 04c695e..e772c4c 100644 --- a/src/main/java/com/ripple/BE/learning/dto/QuizListDTO.java +++ b/src/main/java/com/ripple/BE/learning/dto/QuizListDTO.java @@ -8,4 +8,8 @@ public record QuizListDTO(List quizList) { public static QuizListDTO toQuizListDTO(final List quizList) { return new QuizListDTO(quizList.stream().map(QuizDTO::toQuizDTO).toList()); } + + public static QuizListDTO toQuizScrapListDTO(final List quizList) { + return new QuizListDTO(quizList.stream().map(QuizDTO::toScrapQuizDTO).toList()); + } } diff --git a/src/main/java/com/ripple/BE/learning/dto/response/ConceptDetailResponse.java b/src/main/java/com/ripple/BE/learning/dto/response/ConceptDetailResponse.java new file mode 100644 index 0000000..bf7d824 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/dto/response/ConceptDetailResponse.java @@ -0,0 +1,15 @@ +package com.ripple.BE.learning.dto.response; + +import com.ripple.BE.learning.dto.ConceptDTO; + +public record ConceptDetailResponse( + long id, String name, String explanation, String level, String learningSetName) { + public static ConceptDetailResponse toConceptDetailResponse(ConceptDTO conceptDTO) { + return new ConceptDetailResponse( + conceptDTO.conceptId(), + conceptDTO.name(), + conceptDTO.explanation(), + conceptDTO.level().name(), + conceptDTO.learningSetName()); + } +} diff --git a/src/main/java/com/ripple/BE/learning/dto/response/FailQuizListResponse.java b/src/main/java/com/ripple/BE/learning/dto/response/FailQuizListResponse.java new file mode 100644 index 0000000..4d91610 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/dto/response/FailQuizListResponse.java @@ -0,0 +1,11 @@ +package com.ripple.BE.learning.dto.response; + +import com.ripple.BE.learning.dto.FailQuizListDTO; +import java.util.List; + +public record FailQuizListResponse(List failQuizList) { + public static FailQuizListResponse toFailQuizListResponse(final FailQuizListDTO failQuizListDTO) { + return new FailQuizListResponse( + failQuizListDTO.failQuizList().stream().map(FailQuizResponse::toFailQuizResponse).toList()); + } +} diff --git a/src/main/java/com/ripple/BE/learning/dto/response/FailQuizResponse.java b/src/main/java/com/ripple/BE/learning/dto/response/FailQuizResponse.java new file mode 100644 index 0000000..23d30d0 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/dto/response/FailQuizResponse.java @@ -0,0 +1,9 @@ +package com.ripple.BE.learning.dto.response; + +import com.ripple.BE.learning.dto.QuizDTO; + +public record FailQuizResponse(Long id, String name, String learningSet) { + public static FailQuizResponse toFailQuizResponse(final QuizDTO quizDTO) { + return new FailQuizResponse(quizDTO.id(), quizDTO.name(), quizDTO.learningSetName()); + } +} diff --git a/src/main/java/com/ripple/BE/learning/dto/response/ScrapConceptListResponse.java b/src/main/java/com/ripple/BE/learning/dto/response/ScrapConceptListResponse.java new file mode 100644 index 0000000..c26d948 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/dto/response/ScrapConceptListResponse.java @@ -0,0 +1,13 @@ +package com.ripple.BE.learning.dto.response; + +import com.ripple.BE.learning.dto.ConceptListDTO; +import java.util.List; + +public record ScrapConceptListResponse(List scrapConceptList) { + public static ScrapConceptListResponse toScrapConceptListResponse(ConceptListDTO conceptListDTO) { + return new ScrapConceptListResponse( + conceptListDTO.conceptList().stream() + .map(ScrapConceptResponse::toScrapConceptResponse) + .toList()); + } +} diff --git a/src/main/java/com/ripple/BE/learning/dto/response/ScrapConceptResponse.java b/src/main/java/com/ripple/BE/learning/dto/response/ScrapConceptResponse.java new file mode 100644 index 0000000..b22dd48 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/dto/response/ScrapConceptResponse.java @@ -0,0 +1,17 @@ +package com.ripple.BE.learning.dto.response; + +import com.ripple.BE.learning.dto.ConceptDTO; +import com.ripple.BE.user.domain.type.Level; +import lombok.Builder; + +@Builder +public record ScrapConceptResponse(long id, String name, String LearningSetName, Level level) { + public static ScrapConceptResponse toScrapConceptResponse(ConceptDTO conceptDTO) { + return ScrapConceptResponse.builder() + .id(conceptDTO.conceptId()) + .name(conceptDTO.name()) + .LearningSetName(conceptDTO.learningSetName()) + .level(conceptDTO.level()) + .build(); + } +} diff --git a/src/main/java/com/ripple/BE/learning/dto/response/ScrapQuizListResponse.java b/src/main/java/com/ripple/BE/learning/dto/response/ScrapQuizListResponse.java new file mode 100644 index 0000000..623a933 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/dto/response/ScrapQuizListResponse.java @@ -0,0 +1,11 @@ +package com.ripple.BE.learning.dto.response; + +import com.ripple.BE.learning.dto.QuizListDTO; +import java.util.List; + +public record ScrapQuizListResponse(List scrapQuizList) { + public static ScrapQuizListResponse toScrapQuizListResponse(final QuizListDTO quizListDTO) { + return new ScrapQuizListResponse( + quizListDTO.quizList().stream().map(ScrapQuizResponse::toScrapQuizResponse).toList()); + } +} diff --git a/src/main/java/com/ripple/BE/learning/dto/response/ScrapQuizResponse.java b/src/main/java/com/ripple/BE/learning/dto/response/ScrapQuizResponse.java new file mode 100644 index 0000000..aeb69aa --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/dto/response/ScrapQuizResponse.java @@ -0,0 +1,18 @@ +package com.ripple.BE.learning.dto.response; + +import com.ripple.BE.learning.dto.QuizDTO; +import com.ripple.BE.user.domain.type.Level; +import lombok.Builder; + +@Builder +public record ScrapQuizResponse(long quizId, String quizName, String learningSetName, Level level) { + + public static ScrapQuizResponse toScrapQuizResponse(QuizDTO quizDTO) { + return builder() + .quizId(quizDTO.id()) + .quizName(quizDTO.name()) + .learningSetName(quizDTO.learningSetName()) + .level(quizDTO.level()) + .build(); + } +} diff --git a/src/main/java/com/ripple/BE/learning/exception/LearningException.java b/src/main/java/com/ripple/BE/learning/exception/LearningException.java index 0bdab13..9135a4f 100644 --- a/src/main/java/com/ripple/BE/learning/exception/LearningException.java +++ b/src/main/java/com/ripple/BE/learning/exception/LearningException.java @@ -1,6 +1,6 @@ package com.ripple.BE.learning.exception; -import com.ripple.BE.global.exception.errorcode.ErrorCode; +import com.ripple.BE.learning.exception.errorcode.LearningErrorCode; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -8,5 +8,5 @@ @RequiredArgsConstructor public class LearningException extends RuntimeException { - private final ErrorCode errorCode; + private final LearningErrorCode errorCode; } diff --git a/src/main/java/com/ripple/BE/learning/exception/QuizException.java b/src/main/java/com/ripple/BE/learning/exception/QuizException.java index 47363c7..48238b2 100644 --- a/src/main/java/com/ripple/BE/learning/exception/QuizException.java +++ b/src/main/java/com/ripple/BE/learning/exception/QuizException.java @@ -1,6 +1,6 @@ package com.ripple.BE.learning.exception; -import com.ripple.BE.global.exception.errorcode.ErrorCode; +import com.ripple.BE.learning.exception.errorcode.QuizErrorCode; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -8,5 +8,5 @@ @RequiredArgsConstructor public class QuizException extends RuntimeException { - private final ErrorCode errorCode; + private final QuizErrorCode errorCode; } diff --git a/src/main/java/com/ripple/BE/learning/exception/errorcode/LearningErrorCode.java b/src/main/java/com/ripple/BE/learning/exception/errorcode/LearningErrorCode.java index de7f4f2..ab40a55 100644 --- a/src/main/java/com/ripple/BE/learning/exception/errorcode/LearningErrorCode.java +++ b/src/main/java/com/ripple/BE/learning/exception/errorcode/LearningErrorCode.java @@ -13,6 +13,7 @@ public enum LearningErrorCode implements ErrorCode { HttpStatus.INTERNAL_SERVER_ERROR, "Failed to save learning set excel file"), CONCEPT_NOT_FOUND(HttpStatus.NOT_FOUND, "Concept not found"), + CONCEPT_ALREADY_SCRAP(HttpStatus.BAD_REQUEST, "Concept already scrap"), QUIZ_PROGRESS_NOT_FOUND(HttpStatus.NOT_FOUND, "Quiz progress not found"), QUIZ_NOT_FOUND(HttpStatus.NOT_FOUND, "Quiz not found"); diff --git a/src/main/java/com/ripple/BE/learning/exception/errorcode/QuizErrorCode.java b/src/main/java/com/ripple/BE/learning/exception/errorcode/QuizErrorCode.java index b7ddd85..179fca4 100644 --- a/src/main/java/com/ripple/BE/learning/exception/errorcode/QuizErrorCode.java +++ b/src/main/java/com/ripple/BE/learning/exception/errorcode/QuizErrorCode.java @@ -8,7 +8,8 @@ @Getter @RequiredArgsConstructor public enum QuizErrorCode implements ErrorCode { - QUIZ_NOT_FOUND(HttpStatus.NOT_FOUND, "Quiz not found"); + QUIZ_NOT_FOUND(HttpStatus.NOT_FOUND, "Quiz not found"), + QUIZ_ALREADY_SCRAP(HttpStatus.BAD_REQUEST, "Quiz already scrap"); private final HttpStatus httpStatus; private final String message; diff --git a/src/main/java/com/ripple/BE/learning/repository/ConceptScrapRepository.java b/src/main/java/com/ripple/BE/learning/repository/ConceptScrapRepository.java deleted file mode 100644 index 187268a..0000000 --- a/src/main/java/com/ripple/BE/learning/repository/ConceptScrapRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.ripple.BE.learning.repository; - -import com.ripple.BE.learning.domain.concept.ConceptScrap; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface ConceptScrapRepository extends JpaRepository {} diff --git a/src/main/java/com/ripple/BE/learning/repository/QuizScrapRepository.java b/src/main/java/com/ripple/BE/learning/repository/QuizScrapRepository.java deleted file mode 100644 index 8ebdaf3..0000000 --- a/src/main/java/com/ripple/BE/learning/repository/QuizScrapRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.ripple.BE.learning.repository; - -import com.ripple.BE.learning.domain.quiz.QuizScrap; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface QuizScrapRepository extends JpaRepository {} diff --git a/src/main/java/com/ripple/BE/learning/repository/ConceptRepository.java b/src/main/java/com/ripple/BE/learning/repository/concept/ConceptRepository.java similarity index 89% rename from src/main/java/com/ripple/BE/learning/repository/ConceptRepository.java rename to src/main/java/com/ripple/BE/learning/repository/concept/ConceptRepository.java index ad0b84f..62ac02e 100644 --- a/src/main/java/com/ripple/BE/learning/repository/ConceptRepository.java +++ b/src/main/java/com/ripple/BE/learning/repository/concept/ConceptRepository.java @@ -1,4 +1,4 @@ -package com.ripple.BE.learning.repository; +package com.ripple.BE.learning.repository.concept; import com.ripple.BE.learning.domain.concept.Concept; import com.ripple.BE.learning.domain.learningset.LearningSet; diff --git a/src/main/java/com/ripple/BE/learning/repository/conceptScrap/ConceptScrapRepository.java b/src/main/java/com/ripple/BE/learning/repository/conceptScrap/ConceptScrapRepository.java new file mode 100644 index 0000000..b627431 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/repository/conceptScrap/ConceptScrapRepository.java @@ -0,0 +1,11 @@ +package com.ripple.BE.learning.repository.conceptScrap; + +import com.ripple.BE.learning.domain.concept.ConceptScrap; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ConceptScrapRepository + extends JpaRepository, ConceptScrapRepositoryCustom { + Boolean existsByConcept_ConceptIdAndUserId(Long conceptId, Long userId); +} diff --git a/src/main/java/com/ripple/BE/learning/repository/conceptScrap/ConceptScrapRepositoryCustom.java b/src/main/java/com/ripple/BE/learning/repository/conceptScrap/ConceptScrapRepositoryCustom.java new file mode 100644 index 0000000..cb89f83 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/repository/conceptScrap/ConceptScrapRepositoryCustom.java @@ -0,0 +1,10 @@ +package com.ripple.BE.learning.repository.conceptScrap; + +import com.ripple.BE.learning.domain.concept.Concept; +import com.ripple.BE.user.domain.type.Level; +import java.util.List; + +public interface ConceptScrapRepositoryCustom { + + List findConceptsScrappedByUserAndLevel(Long userId, Level level); +} diff --git a/src/main/java/com/ripple/BE/learning/repository/conceptScrap/ConceptScrapRepositoryCustomImpl.java b/src/main/java/com/ripple/BE/learning/repository/conceptScrap/ConceptScrapRepositoryCustomImpl.java new file mode 100644 index 0000000..692525a --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/repository/conceptScrap/ConceptScrapRepositoryCustomImpl.java @@ -0,0 +1,26 @@ +package com.ripple.BE.learning.repository.conceptScrap; + +import static com.ripple.BE.learning.domain.concept.QConcept.*; +import static com.ripple.BE.learning.domain.concept.QConceptScrap.*; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.ripple.BE.learning.domain.concept.Concept; +import com.ripple.BE.user.domain.type.Level; +import java.util.List; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class ConceptScrapRepositoryCustomImpl implements ConceptScrapRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + @Override + public List findConceptsScrappedByUserAndLevel(Long userId, Level level) { + return queryFactory + .select(concept) + .from(conceptScrap) + .join(conceptScrap.concept, concept) + .where(conceptScrap.user.id.eq(userId), concept.level.eq(level)) + .fetch(); + } +} diff --git a/src/main/java/com/ripple/BE/learning/repository/LearningSetRepository.java b/src/main/java/com/ripple/BE/learning/repository/learningSet/LearningSetRepository.java similarity index 83% rename from src/main/java/com/ripple/BE/learning/repository/LearningSetRepository.java rename to src/main/java/com/ripple/BE/learning/repository/learningSet/LearningSetRepository.java index 8e53ce6..fff601a 100644 --- a/src/main/java/com/ripple/BE/learning/repository/LearningSetRepository.java +++ b/src/main/java/com/ripple/BE/learning/repository/learningSet/LearningSetRepository.java @@ -1,4 +1,4 @@ -package com.ripple.BE.learning.repository; +package com.ripple.BE.learning.repository.learningSet; import com.ripple.BE.learning.domain.learningset.LearningSet; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/com/ripple/BE/learning/repository/UserLearningSetRepository.java b/src/main/java/com/ripple/BE/learning/repository/learningSet/UserLearningSetRepository.java similarity index 94% rename from src/main/java/com/ripple/BE/learning/repository/UserLearningSetRepository.java rename to src/main/java/com/ripple/BE/learning/repository/learningSet/UserLearningSetRepository.java index 6abffbb..e0823d6 100644 --- a/src/main/java/com/ripple/BE/learning/repository/UserLearningSetRepository.java +++ b/src/main/java/com/ripple/BE/learning/repository/learningSet/UserLearningSetRepository.java @@ -1,4 +1,4 @@ -package com.ripple.BE.learning.repository; +package com.ripple.BE.learning.repository.learningSet; import com.ripple.BE.learning.domain.learningset.UserLearningSet; import com.ripple.BE.user.domain.type.Level; diff --git a/src/main/java/com/ripple/BE/learning/repository/QuizRepository.java b/src/main/java/com/ripple/BE/learning/repository/quiz/QuizRepository.java similarity index 92% rename from src/main/java/com/ripple/BE/learning/repository/QuizRepository.java rename to src/main/java/com/ripple/BE/learning/repository/quiz/QuizRepository.java index 9e96071..1ea100c 100644 --- a/src/main/java/com/ripple/BE/learning/repository/QuizRepository.java +++ b/src/main/java/com/ripple/BE/learning/repository/quiz/QuizRepository.java @@ -1,4 +1,4 @@ -package com.ripple.BE.learning.repository; +package com.ripple.BE.learning.repository.quiz; import com.ripple.BE.learning.domain.learningset.LearningSet; import com.ripple.BE.learning.domain.quiz.Quiz; @@ -9,7 +9,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; -public interface QuizRepository extends JpaRepository { +public interface QuizRepository extends JpaRepository, QuizRepositoryCustom { int countByLevel(Level level); diff --git a/src/main/java/com/ripple/BE/learning/repository/quiz/QuizRepositoryCustom.java b/src/main/java/com/ripple/BE/learning/repository/quiz/QuizRepositoryCustom.java new file mode 100644 index 0000000..6257cc3 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/repository/quiz/QuizRepositoryCustom.java @@ -0,0 +1,10 @@ +package com.ripple.BE.learning.repository.quiz; + +import com.ripple.BE.learning.domain.quiz.Quiz; +import com.ripple.BE.user.domain.type.Level; +import java.util.List; + +public interface QuizRepositoryCustom { + + List findFailedQuizzesByUserAndLevel(long userId, Level level); +} diff --git a/src/main/java/com/ripple/BE/learning/repository/quiz/QuizRepositoryCustomImpl.java b/src/main/java/com/ripple/BE/learning/repository/quiz/QuizRepositoryCustomImpl.java new file mode 100644 index 0000000..b29d910 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/repository/quiz/QuizRepositoryCustomImpl.java @@ -0,0 +1,26 @@ +package com.ripple.BE.learning.repository.quiz; + +import static com.ripple.BE.learning.domain.quiz.QFailQuiz.*; +import static com.ripple.BE.learning.domain.quiz.QQuiz.*; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.ripple.BE.learning.domain.quiz.Quiz; +import com.ripple.BE.user.domain.type.Level; +import java.util.List; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class QuizRepositoryCustomImpl implements QuizRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + @Override + public List findFailedQuizzesByUserAndLevel(long userId, Level level) { + return queryFactory + .select(quiz) + .from(failQuiz) + .join(failQuiz.quiz, quiz) + .where(failQuiz.user.id.eq(userId), quiz.level.eq(level)) + .fetch(); + } +} diff --git a/src/main/java/com/ripple/BE/learning/repository/quizScrap/QuizScrapRepository.java b/src/main/java/com/ripple/BE/learning/repository/quizScrap/QuizScrapRepository.java new file mode 100644 index 0000000..a3cc37d --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/repository/quizScrap/QuizScrapRepository.java @@ -0,0 +1,11 @@ +package com.ripple.BE.learning.repository.quizScrap; + +import com.ripple.BE.learning.domain.quiz.QuizScrap; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface QuizScrapRepository + extends JpaRepository, QuizScrapRepositoryCustom { + Boolean existsByQuizIdAndUserId(Long quizId, Long userId); +} diff --git a/src/main/java/com/ripple/BE/learning/repository/quizScrap/QuizScrapRepositoryCustom.java b/src/main/java/com/ripple/BE/learning/repository/quizScrap/QuizScrapRepositoryCustom.java new file mode 100644 index 0000000..4415f88 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/repository/quizScrap/QuizScrapRepositoryCustom.java @@ -0,0 +1,10 @@ +package com.ripple.BE.learning.repository.quizScrap; + +import com.ripple.BE.learning.domain.quiz.Quiz; +import com.ripple.BE.user.domain.type.Level; +import java.util.List; + +public interface QuizScrapRepositoryCustom { + + List findQuizScrappedByUserAndLevel(Long userId, Level level); +} diff --git a/src/main/java/com/ripple/BE/learning/repository/quizScrap/QuizScrapRepositoryCustomImpl.java b/src/main/java/com/ripple/BE/learning/repository/quizScrap/QuizScrapRepositoryCustomImpl.java new file mode 100644 index 0000000..7774a25 --- /dev/null +++ b/src/main/java/com/ripple/BE/learning/repository/quizScrap/QuizScrapRepositoryCustomImpl.java @@ -0,0 +1,28 @@ +package com.ripple.BE.learning.repository.quizScrap; + +import static com.ripple.BE.learning.domain.quiz.QQuiz.*; +import static com.ripple.BE.learning.domain.quiz.QQuizScrap.*; +import static com.ripple.BE.post.domain.QPost.*; +import static com.ripple.BE.post.domain.QPostScrap.*; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.ripple.BE.learning.domain.quiz.Quiz; +import com.ripple.BE.user.domain.type.Level; +import java.util.List; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class QuizScrapRepositoryCustomImpl implements QuizScrapRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + @Override + public List findQuizScrappedByUserAndLevel(Long userId, Level level) { + return queryFactory + .select(quiz) + .from(quizScrap) + .join(quizScrap.quiz, quiz) + .where(quizScrap.user.id.eq(userId), quiz.level.eq(level)) + .fetch(); + } +} diff --git a/src/main/java/com/ripple/BE/learning/service/LevelTestService.java b/src/main/java/com/ripple/BE/learning/service/LevelTestService.java index eac514f..d258ed4 100644 --- a/src/main/java/com/ripple/BE/learning/service/LevelTestService.java +++ b/src/main/java/com/ripple/BE/learning/service/LevelTestService.java @@ -12,7 +12,7 @@ import com.ripple.BE.learning.dto.QuizSubmitDTO; import com.ripple.BE.learning.dto.response.LevelTestResultResponse; import com.ripple.BE.learning.exception.QuizException; -import com.ripple.BE.learning.repository.QuizRepository; +import com.ripple.BE.learning.repository.quiz.QuizRepository; import com.ripple.BE.user.domain.User; import com.ripple.BE.user.domain.type.Level; import com.ripple.BE.user.exception.UserException; diff --git a/src/main/java/com/ripple/BE/learning/service/concept/ConceptService.java b/src/main/java/com/ripple/BE/learning/service/concept/ConceptService.java index 0087081..9b3d306 100644 --- a/src/main/java/com/ripple/BE/learning/service/concept/ConceptService.java +++ b/src/main/java/com/ripple/BE/learning/service/concept/ConceptService.java @@ -4,12 +4,13 @@ import com.ripple.BE.learning.domain.concept.ConceptScrap; import com.ripple.BE.learning.domain.learningset.LearningSet; import com.ripple.BE.learning.domain.learningset.UserLearningSet; +import com.ripple.BE.learning.dto.ConceptDTO; import com.ripple.BE.learning.dto.ConceptListDTO; import com.ripple.BE.learning.exception.LearningException; import com.ripple.BE.learning.exception.errorcode.LearningErrorCode; -import com.ripple.BE.learning.repository.ConceptRepository; -import com.ripple.BE.learning.repository.ConceptScrapRepository; -import com.ripple.BE.learning.repository.UserLearningSetRepository; +import com.ripple.BE.learning.repository.concept.ConceptRepository; +import com.ripple.BE.learning.repository.conceptScrap.ConceptScrapRepository; +import com.ripple.BE.learning.repository.learningSet.UserLearningSetRepository; import com.ripple.BE.learning.service.learningset.LearningSetService; import com.ripple.BE.user.domain.User; import com.ripple.BE.user.domain.type.Level; @@ -23,6 +24,7 @@ @RequiredArgsConstructor @Service @Slf4j +@Transactional(readOnly = true) public class ConceptService { private final LearningSetService learningSetService; @@ -78,6 +80,11 @@ public void completeConceptLearning( */ @Transactional public void scrapConcept(final long userId, final long conceptId) { + // 이미 스크랩한 개념인지 확인 + if (conceptScrapRepository.existsByConcept_ConceptIdAndUserId(conceptId, userId)) { + throw new LearningException(LearningErrorCode.CONCEPT_ALREADY_SCRAP); + } + User user = userService.findUserById(userId); Concept concept = conceptRepository @@ -86,4 +93,19 @@ public void scrapConcept(final long userId, final long conceptId) { conceptScrapRepository.save(ConceptScrap.builder().user(user).concept(concept).build()); } + + /** + * 개별 개념 조회 + * + * @param conceptId + * @return 개념 반환 + */ + public ConceptDTO getConcept(final long conceptId) { + Concept concept = + conceptRepository + .findById(conceptId) + .orElseThrow(() -> new LearningException(LearningErrorCode.CONCEPT_NOT_FOUND)); + + return ConceptDTO.toScrapConceptDTO(concept); + } } diff --git a/src/main/java/com/ripple/BE/learning/service/learningset/LearningAdminService.java b/src/main/java/com/ripple/BE/learning/service/learningset/LearningAdminService.java index 3760ece..29f2db0 100644 --- a/src/main/java/com/ripple/BE/learning/service/learningset/LearningAdminService.java +++ b/src/main/java/com/ripple/BE/learning/service/learningset/LearningAdminService.java @@ -10,8 +10,8 @@ import com.ripple.BE.learning.dto.QuizDTO; import com.ripple.BE.learning.exception.LearningException; import com.ripple.BE.learning.exception.errorcode.LearningErrorCode; -import com.ripple.BE.learning.repository.LearningSetRepository; -import com.ripple.BE.learning.repository.QuizRepository; +import com.ripple.BE.learning.repository.learningSet.LearningSetRepository; +import com.ripple.BE.learning.repository.quiz.QuizRepository; import java.util.List; import java.util.Map; import java.util.stream.Collectors; diff --git a/src/main/java/com/ripple/BE/learning/service/learningset/LearningSetService.java b/src/main/java/com/ripple/BE/learning/service/learningset/LearningSetService.java index 1d9dc94..271c91c 100644 --- a/src/main/java/com/ripple/BE/learning/service/learningset/LearningSetService.java +++ b/src/main/java/com/ripple/BE/learning/service/learningset/LearningSetService.java @@ -5,8 +5,8 @@ import com.ripple.BE.learning.dto.UserLearningSetListDTO; import com.ripple.BE.learning.exception.LearningException; import com.ripple.BE.learning.exception.errorcode.LearningErrorCode; -import com.ripple.BE.learning.repository.LearningSetRepository; -import com.ripple.BE.learning.repository.UserLearningSetRepository; +import com.ripple.BE.learning.repository.learningSet.LearningSetRepository; +import com.ripple.BE.learning.repository.learningSet.UserLearningSetRepository; import com.ripple.BE.user.domain.User; import com.ripple.BE.user.domain.type.Level; import com.ripple.BE.user.repository.UserRepository; diff --git a/src/main/java/com/ripple/BE/learning/service/quiz/QuizService.java b/src/main/java/com/ripple/BE/learning/service/quiz/QuizService.java index 782ea3a..d5eccb8 100644 --- a/src/main/java/com/ripple/BE/learning/service/quiz/QuizService.java +++ b/src/main/java/com/ripple/BE/learning/service/quiz/QuizService.java @@ -14,9 +14,10 @@ import com.ripple.BE.learning.exception.LearningException; import com.ripple.BE.learning.exception.QuizException; import com.ripple.BE.learning.exception.errorcode.LearningErrorCode; -import com.ripple.BE.learning.repository.QuizRepository; -import com.ripple.BE.learning.repository.QuizScrapRepository; -import com.ripple.BE.learning.repository.UserLearningSetRepository; +import com.ripple.BE.learning.exception.errorcode.QuizErrorCode; +import com.ripple.BE.learning.repository.learningSet.UserLearningSetRepository; +import com.ripple.BE.learning.repository.quiz.QuizRepository; +import com.ripple.BE.learning.repository.quizScrap.QuizScrapRepository; import com.ripple.BE.learning.service.learningset.LearningSetService; import com.ripple.BE.user.domain.User; import com.ripple.BE.user.domain.type.Level; @@ -162,10 +163,16 @@ private QuizDTO getQuizDTO(final QuizListDTO quizListDTO, final long quizId) { */ @Transactional public void scrapQuiz(final long userId, final long quizId) { + // 이미 스크랩한 퀴즈인지 확인 + if (quizScrapRepository.existsByQuizIdAndUserId(quizId, userId)) { + throw new QuizException(QuizErrorCode.QUIZ_ALREADY_SCRAP); + } User user = userService.findUserById(userId); Quiz quiz = - quizRepository.findById(quizId).orElseThrow(() -> new QuizException(QUIZ_NOT_FOUND)); + quizRepository + .findById(quizId) + .orElseThrow(() -> new QuizException(QuizErrorCode.QUIZ_NOT_FOUND)); quizScrapRepository.save(QuizScrap.builder().user(user).quiz(quiz).build()); } diff --git a/src/main/java/com/ripple/BE/post/dto/LikeCommentDTO.java b/src/main/java/com/ripple/BE/post/dto/LikeCommentDTO.java new file mode 100644 index 0000000..05cebef --- /dev/null +++ b/src/main/java/com/ripple/BE/post/dto/LikeCommentDTO.java @@ -0,0 +1,18 @@ +package com.ripple.BE.post.dto; + +import com.ripple.BE.post.domain.Comment; +import com.ripple.BE.post.domain.type.PostType; +import java.time.LocalDateTime; + +public record LikeCommentDTO( + Long id, String content, String postName, PostType type, LocalDateTime createdDate) { + + public static LikeCommentDTO toLikeCommentDTO(Comment comment) { + return new LikeCommentDTO( + comment.getId(), + comment.getContent(), + comment.getPost().getTitle(), + comment.getPost().getType(), + comment.getCreatedDate()); + } +} diff --git a/src/main/java/com/ripple/BE/post/dto/LikeCommentListDTO.java b/src/main/java/com/ripple/BE/post/dto/LikeCommentListDTO.java new file mode 100644 index 0000000..cc18bd1 --- /dev/null +++ b/src/main/java/com/ripple/BE/post/dto/LikeCommentListDTO.java @@ -0,0 +1,11 @@ +package com.ripple.BE.post.dto; + +import com.ripple.BE.post.domain.Comment; +import java.util.List; + +public record LikeCommentListDTO(List likeCommentDTOList) { + public static LikeCommentListDTO toLikeCommentListDTO(List commentList) { + return new LikeCommentListDTO( + commentList.stream().map(LikeCommentDTO::toLikeCommentDTO).toList()); + } +} diff --git a/src/main/java/com/ripple/BE/post/dto/response/LikeCommentListResponse.java b/src/main/java/com/ripple/BE/post/dto/response/LikeCommentListResponse.java new file mode 100644 index 0000000..be1cdef --- /dev/null +++ b/src/main/java/com/ripple/BE/post/dto/response/LikeCommentListResponse.java @@ -0,0 +1,14 @@ +package com.ripple.BE.post.dto.response; + +import com.ripple.BE.post.dto.LikeCommentListDTO; +import java.util.List; + +public record LikeCommentListResponse(List likeCommentResponses) { + public static LikeCommentListResponse toLikeCommentListResponse( + LikeCommentListDTO likeCommentListDTO) { + return new LikeCommentListResponse( + likeCommentListDTO.likeCommentDTOList().stream() + .map(LikeCommentResponse::toLikeCommentResponse) + .toList()); + } +} diff --git a/src/main/java/com/ripple/BE/post/dto/response/LikeCommentResponse.java b/src/main/java/com/ripple/BE/post/dto/response/LikeCommentResponse.java new file mode 100644 index 0000000..d801e27 --- /dev/null +++ b/src/main/java/com/ripple/BE/post/dto/response/LikeCommentResponse.java @@ -0,0 +1,17 @@ +package com.ripple.BE.post.dto.response; + +import com.ripple.BE.global.utils.RelativeTimeFormatter; +import com.ripple.BE.post.domain.type.PostType; +import com.ripple.BE.post.dto.LikeCommentDTO; + +public record LikeCommentResponse( + Long id, String content, String postName, PostType type, String createdDate) { + public static LikeCommentResponse toLikeCommentResponse(LikeCommentDTO likeCommentDTO) { + return new LikeCommentResponse( + likeCommentDTO.id(), + likeCommentDTO.content(), + likeCommentDTO.postName(), + likeCommentDTO.type(), + RelativeTimeFormatter.formatRelativeTime(likeCommentDTO.createdDate())); + } +} diff --git a/src/main/java/com/ripple/BE/post/repository/commentlike/CommentLikeRepository.java b/src/main/java/com/ripple/BE/post/repository/commentlike/CommentLikeRepository.java index f9569cf..17ebddd 100644 --- a/src/main/java/com/ripple/BE/post/repository/commentlike/CommentLikeRepository.java +++ b/src/main/java/com/ripple/BE/post/repository/commentlike/CommentLikeRepository.java @@ -6,7 +6,8 @@ import org.springframework.stereotype.Repository; @Repository -public interface CommentLikeRepository extends JpaRepository { +public interface CommentLikeRepository + extends JpaRepository, CommentLikeRepositoryCustom { Optional findByCommentIdAndUserId(long commentId, long userId); diff --git a/src/main/java/com/ripple/BE/post/repository/commentlike/CommentLikeRepositoryCustom.java b/src/main/java/com/ripple/BE/post/repository/commentlike/CommentLikeRepositoryCustom.java new file mode 100644 index 0000000..81207de --- /dev/null +++ b/src/main/java/com/ripple/BE/post/repository/commentlike/CommentLikeRepositoryCustom.java @@ -0,0 +1,8 @@ +package com.ripple.BE.post.repository.commentlike; + +import com.ripple.BE.post.domain.Comment; +import java.util.List; + +public interface CommentLikeRepositoryCustom { + List findCommentsLikedByUser(Long userId); +} diff --git a/src/main/java/com/ripple/BE/post/repository/commentlike/CommentLikeRepositoryCustomImpl.java b/src/main/java/com/ripple/BE/post/repository/commentlike/CommentLikeRepositoryCustomImpl.java new file mode 100644 index 0000000..c3bb1a0 --- /dev/null +++ b/src/main/java/com/ripple/BE/post/repository/commentlike/CommentLikeRepositoryCustomImpl.java @@ -0,0 +1,27 @@ +package com.ripple.BE.post.repository.commentlike; + +import static com.ripple.BE.post.domain.QComment.*; +import static com.ripple.BE.post.domain.QCommentLike.*; +import static com.ripple.BE.post.domain.QPost.*; +import static com.ripple.BE.post.domain.QPostLike.*; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.ripple.BE.post.domain.Comment; +import java.util.List; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class CommentLikeRepositoryCustomImpl implements CommentLikeRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + @Override + public List findCommentsLikedByUser(Long userId) { + return queryFactory + .select(comment) + .from(commentLike) + .join(commentLike.comment, comment) + .where(commentLike.user.id.eq(userId)) + .fetch(); + } +} diff --git a/src/main/java/com/ripple/BE/user/controller/UserController.java b/src/main/java/com/ripple/BE/user/controller/UserController.java index c9c48e2..eb61e53 100644 --- a/src/main/java/com/ripple/BE/user/controller/UserController.java +++ b/src/main/java/com/ripple/BE/user/controller/UserController.java @@ -1,9 +1,18 @@ package com.ripple.BE.user.controller; import com.ripple.BE.global.dto.response.ApiResponse; +import com.ripple.BE.learning.dto.ConceptListDTO; +import com.ripple.BE.learning.dto.FailQuizListDTO; +import com.ripple.BE.learning.dto.QuizListDTO; +import com.ripple.BE.learning.dto.response.FailQuizListResponse; +import com.ripple.BE.learning.dto.response.ScrapConceptListResponse; +import com.ripple.BE.learning.dto.response.ScrapQuizListResponse; +import com.ripple.BE.post.dto.LikeCommentListDTO; import com.ripple.BE.post.dto.PostListDTO; +import com.ripple.BE.post.dto.response.LikeCommentListResponse; import com.ripple.BE.post.dto.response.PostListResponse; import com.ripple.BE.user.domain.CustomUserDetails; +import com.ripple.BE.user.domain.type.Level; import com.ripple.BE.user.dto.ProgressDTO; import com.ripple.BE.user.dto.ProgressResponse; import com.ripple.BE.user.dto.UpdateUserProfileRequest; @@ -21,6 +30,7 @@ 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.RequestParam; import org.springframework.web.bind.annotation.RestController; @RequiredArgsConstructor @@ -100,4 +110,53 @@ public ResponseEntity> getUserLearningProgress( return ResponseEntity.status(HttpStatus.OK) .body(ApiResponse.from(ProgressResponse.toProgressResponse(progressDTO))); } + + @Operation(summary = "틀린 문제 조회", description = "로그인 한 유저가 틀렸던 문제를 조회합니다.") + @GetMapping("/wrong-quizzes") + public ResponseEntity> getWrongQuizzes( + @AuthenticationPrincipal CustomUserDetails customUserDetails, + final @RequestParam(defaultValue = "BEGINNER") Level level) { + + FailQuizListDTO failQuizListDTO = + myPageService.getMyFailQuizzes(customUserDetails.getId(), level); + + return ResponseEntity.status(HttpStatus.OK) + .body(ApiResponse.from(FailQuizListResponse.toFailQuizListResponse(failQuizListDTO))); + } + + @Operation(summary = "내가 좋아요한 댓글 조회", description = "로그인한 유저가 좋아요한 댓글을 조회합니다.") + @GetMapping("/like-comments") + public ResponseEntity> getMyLikeComments( + @AuthenticationPrincipal CustomUserDetails customUserDetails) { + + LikeCommentListDTO myLikeComments = myPageService.getMyLikeComments(customUserDetails.getId()); + + return ResponseEntity.status(HttpStatus.OK) + .body(ApiResponse.from(LikeCommentListResponse.toLikeCommentListResponse(myLikeComments))); + } + + @Operation(summary = "내가 스크랩한 퀴즈 조회", description = "로그인한 유저가 스크랩한 퀴즈를 조회합니다.") + @GetMapping("/scrap-quizzes") + public ResponseEntity> getMyScrapQuizzes( + @AuthenticationPrincipal CustomUserDetails customUserDetails, + @RequestParam(defaultValue = "BEGINNER") Level level) { + + QuizListDTO myScrapQuizzes = myPageService.getMyScrapQuizzes(customUserDetails.getId(), level); + + return ResponseEntity.status(HttpStatus.OK) + .body(ApiResponse.from(ScrapQuizListResponse.toScrapQuizListResponse(myScrapQuizzes))); + } + + @Operation(summary = "내가 스크랩한 개념 학습 조회", description = "로그인한 유저가 스크랩한 학습을 조회합니다.") + @GetMapping("/scrap-concepts") + public ResponseEntity> getMyScrapConcepts( + @AuthenticationPrincipal CustomUserDetails customUserDetails, + @RequestParam(defaultValue = "BEGINNER") Level level) { + + ConceptListDTO conceptListDTO = myPageService.getMyConcepts(customUserDetails.getId(), level); + + return ResponseEntity.status(HttpStatus.OK) + .body( + ApiResponse.from(ScrapConceptListResponse.toScrapConceptListResponse(conceptListDTO))); + } } diff --git a/src/main/java/com/ripple/BE/user/service/MyPageService.java b/src/main/java/com/ripple/BE/user/service/MyPageService.java index 622ffd9..64a6e00 100644 --- a/src/main/java/com/ripple/BE/user/service/MyPageService.java +++ b/src/main/java/com/ripple/BE/user/service/MyPageService.java @@ -1,11 +1,23 @@ package com.ripple.BE.user.service; +import com.ripple.BE.learning.domain.concept.Concept; +import com.ripple.BE.learning.domain.quiz.Quiz; +import com.ripple.BE.learning.dto.ConceptListDTO; +import com.ripple.BE.learning.dto.FailQuizListDTO; +import com.ripple.BE.learning.dto.QuizListDTO; +import com.ripple.BE.learning.repository.conceptScrap.ConceptScrapRepository; +import com.ripple.BE.learning.repository.quiz.QuizRepository; +import com.ripple.BE.learning.repository.quizScrap.QuizScrapRepository; +import com.ripple.BE.post.domain.Comment; import com.ripple.BE.post.domain.Post; +import com.ripple.BE.post.dto.LikeCommentListDTO; import com.ripple.BE.post.dto.PostListDTO; import com.ripple.BE.post.repository.comment.CommentRepository; +import com.ripple.BE.post.repository.commentlike.CommentLikeRepository; import com.ripple.BE.post.repository.post.PostRepository; import com.ripple.BE.post.repository.postlike.PostLikeRepository; import com.ripple.BE.post.repository.postscrap.PostScrapRepository; +import com.ripple.BE.user.domain.type.Level; import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -20,8 +32,12 @@ public class MyPageService { private final PostRepository postRepository; private final PostLikeRepository postLikeRepository; + private final CommentLikeRepository commentLikeRepository; private final CommentRepository commentRepository; private final PostScrapRepository postScrapRepository; + private final QuizRepository quizRepository; + private final QuizScrapRepository quizScrapRepository; + private final ConceptScrapRepository conceptScrapRepository; @Transactional(readOnly = true) public PostListDTO getMyPosts(final long userId) { @@ -54,4 +70,36 @@ public PostListDTO getMyScrapPosts(final long userId) { return PostListDTO.toPostListDTO(posts); } + + @Transactional(readOnly = true) + public FailQuizListDTO getMyFailQuizzes(final long userId, Level level) { + + List failedQuizzesByUserAndLevel = + quizRepository.findFailedQuizzesByUserAndLevel(userId, level); + + return FailQuizListDTO.toFailQuizListDTO(failedQuizzesByUserAndLevel); + } + + @Transactional(readOnly = true) + public LikeCommentListDTO getMyLikeComments(final long userId) { + + List commentsLikedByUser = commentLikeRepository.findCommentsLikedByUser(userId); + + return LikeCommentListDTO.toLikeCommentListDTO(commentsLikedByUser); + } + + public QuizListDTO getMyScrapQuizzes(final long userId, final Level level) { + + List quizzes = quizScrapRepository.findQuizScrappedByUserAndLevel(userId, level); + + return QuizListDTO.toQuizScrapListDTO(quizzes); + } + + public ConceptListDTO getMyConcepts(final long userId, final Level level) { + + List concepts = + conceptScrapRepository.findConceptsScrappedByUserAndLevel(userId, level); + + return ConceptListDTO.toScrapConceptListDTO(concepts); + } } diff --git a/src/main/java/com/ripple/BE/user/service/UserProgressService.java b/src/main/java/com/ripple/BE/user/service/UserProgressService.java index 31bd74b..c96a134 100644 --- a/src/main/java/com/ripple/BE/user/service/UserProgressService.java +++ b/src/main/java/com/ripple/BE/user/service/UserProgressService.java @@ -1,7 +1,7 @@ package com.ripple.BE.user.service; -import com.ripple.BE.learning.repository.ConceptRepository; -import com.ripple.BE.learning.repository.QuizRepository; +import com.ripple.BE.learning.repository.concept.ConceptRepository; +import com.ripple.BE.learning.repository.quiz.QuizRepository; import com.ripple.BE.user.domain.User; import com.ripple.BE.user.domain.type.Level; import com.ripple.BE.user.dto.ProgressDTO;