diff --git a/src/main/java/umc/kkijuk/server/career/controller/CareerSearchController.java b/src/main/java/umc/kkijuk/server/career/controller/CareerSearchController.java index 5a291aa..47a4cf7 100644 --- a/src/main/java/umc/kkijuk/server/career/controller/CareerSearchController.java +++ b/src/main/java/umc/kkijuk/server/career/controller/CareerSearchController.java @@ -139,4 +139,19 @@ public CareerResponse> findCareerForTimeline( } + @GetMapping("/list") + @Operation( + summary = "활동 리스트", + description = "새로운 활동 기록 추가 모달에 필요한 활동 정보들을 조회합니다.") + public CareerResponse> findCareerForNewDetail( + @RequestHeader("Authorization") String token + ){ + Member requestMember = loginUser.extractMemberId(token); + return CareerResponse.success( + CareerResponseMessage.CAREER_FINDALL_SUCCESS, + careerSearchService.findCareerForNewDetail(requestMember) + ); + + } + } diff --git a/src/main/java/umc/kkijuk/server/career/controller/response/CareerTitleResponse.java b/src/main/java/umc/kkijuk/server/career/controller/response/CareerTitleResponse.java new file mode 100644 index 0000000..04e00d7 --- /dev/null +++ b/src/main/java/umc/kkijuk/server/career/controller/response/CareerTitleResponse.java @@ -0,0 +1,27 @@ +package umc.kkijuk.server.career.controller.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Data +@Getter +@Setter +@Builder +@AllArgsConstructor +@Schema(description = "활동 요약 정보 응답 DTO") +public class CareerTitleResponse { + + @Schema(description = "활동 ID", example = "42") + private Long careerId; + @Schema(description = "카테고리 정보 (id, 설명, name)") + private CategoryResponse category; + @Schema(description = "활동 제목", example = "끼적 백엔드 개발") + private String title; + @Schema(description = "활동 별칭", example = "Spring Boot API") + private String alias; +} diff --git a/src/main/java/umc/kkijuk/server/career/service/CareerSearchService.java b/src/main/java/umc/kkijuk/server/career/service/CareerSearchService.java index 9becdbd..c69a9d8 100644 --- a/src/main/java/umc/kkijuk/server/career/service/CareerSearchService.java +++ b/src/main/java/umc/kkijuk/server/career/service/CareerSearchService.java @@ -20,4 +20,5 @@ public interface CareerSearchService { List findCareerWithKeyword(Member requestMember, String keyword, String sort); + List findCareerForNewDetail(Member requestMember); } diff --git a/src/main/java/umc/kkijuk/server/career/service/CareerSearchServiceImpl.java b/src/main/java/umc/kkijuk/server/career/service/CareerSearchServiceImpl.java index 4e61375..5bc73e5 100644 --- a/src/main/java/umc/kkijuk/server/career/service/CareerSearchServiceImpl.java +++ b/src/main/java/umc/kkijuk/server/career/service/CareerSearchServiceImpl.java @@ -305,7 +305,34 @@ public List findCareerWithKeyword(Member requestMember, Stri } + @Override + public List findCareerForNewDetail(Member requestMember) { + Long memberId = requestMember.getId(); + List careers = new ArrayList<>(); + + careers.addAll(activityRepository.findByMemberId(memberId)); + careers.addAll(projectJpaRepository.findByMemberId(memberId)); + careers.addAll(eduCareerJpaRepository.findByMemberId(memberId)); + careers.addAll(employmentJpaRepository.findByMemberId(memberId)); + careers.addAll(circleRepository.findByMemberId(memberId)); + careers.addAll(competitionJpaRepository.findByMemberId(memberId)); + careers.addAll(etcRepository.findByMemberId(memberId)); + return careers.stream() + .sorted(Comparator.comparing(BaseCareer::getStartdate).reversed()) + .map(career -> CareerTitleResponse.builder() + .careerId(career.getId()) + .title(career.getName()) + .alias(career.getAlias()) + .category(new CategoryResponse( + CareerType.fromClass(career).getId(), + CareerType.fromClass(career).getDescription(), + CareerType.fromClass(career).name() + )) + .build() + ) + .collect(Collectors.toList()); + } //타임라인 쪽에서 데이터 구별 하기 위함 diff --git a/src/main/java/umc/kkijuk/server/detail/controller/CareerDetailController.java b/src/main/java/umc/kkijuk/server/detail/controller/CareerDetailController.java index f99e60c..157ca20 100644 --- a/src/main/java/umc/kkijuk/server/detail/controller/CareerDetailController.java +++ b/src/main/java/umc/kkijuk/server/detail/controller/CareerDetailController.java @@ -5,12 +5,15 @@ import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; +import umc.kkijuk.server.career.controller.response.FindDetailResponse; import umc.kkijuk.server.common.LoginUser; import umc.kkijuk.server.detail.controller.response.BaseCareerDetailResponse; import umc.kkijuk.server.detail.controller.response.CareerDetailResponse; +import umc.kkijuk.server.detail.controller.response.RecentCareerDetailResponse; import umc.kkijuk.server.detail.dto.CareerDetailReqDto; import umc.kkijuk.server.detail.dto.CareerDetailUpdateReqDto; import umc.kkijuk.server.detail.service.BaseCareerDetailService; @@ -78,4 +81,15 @@ public CareerDetailResponse update( } + @GetMapping("/dashboard") + @Operation(summary = "홈화면 활동 기록 조회", description = "홈 화면에서 가장 최근에 기록한 활동기록 3개를 조회합니다. ") + public CareerDetailResponse> board(@RequestHeader("Authorization") String token){ + Member requestMember = loginUser.extractMemberId(token); + return CareerDetailResponse.success( + HttpStatus.OK, + "최근에 작성한 활동 기록 3개를 성공적으로 조회했습니다.", + careerDetailService.boardDetail(requestMember) + ); + } + } diff --git a/src/main/java/umc/kkijuk/server/detail/controller/response/RecentCareerDetailResponse.java b/src/main/java/umc/kkijuk/server/detail/controller/response/RecentCareerDetailResponse.java new file mode 100644 index 0000000..eeac377 --- /dev/null +++ b/src/main/java/umc/kkijuk/server/detail/controller/response/RecentCareerDetailResponse.java @@ -0,0 +1,44 @@ +package umc.kkijuk.server.detail.controller.response; + +import java.time.LocalDate; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import umc.kkijuk.server.career.controller.response.CategoryResponse; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Data +@Getter +@Setter +@Builder +@AllArgsConstructor +@Schema(description = "최근 활동 기록 응답 DTO") +public class RecentCareerDetailResponse { + + @Schema(description = "활동 기록 ID", example = "123") + private Long detailId; + @Schema(description = "활동 기록 제목", example = "끼적 백엔드") + private String detailTitle; + @Schema(description = "활동 기록 내용", example = "끼적 api 개발~..") + private String detailContent; + @Schema(description = "활동 기록 시작일", example = "2025-05-01") + private LocalDate detailStartDate; + @Schema(description = "활동 기록 종료일", example = "2025-06-30") + private LocalDate detailEndDate; + @Schema(description = "활동 기록에 연결된 태그 목록") + private List tags; + + @Schema(description = "활동 ID", example = "77") + private Long careerId; + @Schema(description = "활동 제목", example = "대외활동 - 백엔드") + private String careerTitle; + @Schema(description = "활동 별칭", example = "스프링부트") + private String careerAlias; + @Schema(description = "활동 카테고리 정보 (id, 설명, name)") + private CategoryResponse category; +} + diff --git a/src/main/java/umc/kkijuk/server/detail/dto/converter/BaseCareerDetailConverter.java b/src/main/java/umc/kkijuk/server/detail/dto/converter/BaseCareerDetailConverter.java index e7e8daf..ad37642 100644 --- a/src/main/java/umc/kkijuk/server/detail/dto/converter/BaseCareerDetailConverter.java +++ b/src/main/java/umc/kkijuk/server/detail/dto/converter/BaseCareerDetailConverter.java @@ -1,5 +1,10 @@ package umc.kkijuk.server.detail.dto.converter; +import java.util.stream.Collectors; +import umc.kkijuk.server.career.controller.response.CategoryResponse; +import umc.kkijuk.server.career.domain.BaseCareer; +import umc.kkijuk.server.detail.controller.response.RecentCareerDetailResponse; +import umc.kkijuk.server.detail.controller.response.TagResponse; import umc.kkijuk.server.detail.domain.BaseCareerDetail; import umc.kkijuk.server.detail.domain.CareerType; import umc.kkijuk.server.detail.dto.CareerDetailReqDto; @@ -24,5 +29,22 @@ public static BaseCareerDetail toBaseCareerDetail(Member requestMember, CareerDe } + public static RecentCareerDetailResponse toResponse(BaseCareerDetail detail, BaseCareer baseCareer, CareerType type) { + return new RecentCareerDetailResponse( + detail.getId(), + detail.getTitle(), + detail.getContent(), + detail.getStartDate(), + detail.getEndDate(), + detail.getCareerTagList().stream() + .map(tag -> new TagResponse(tag.getTag())) + .collect(Collectors.toList()), + baseCareer.getId(), + baseCareer.getName(), + baseCareer.getAlias(), + new CategoryResponse(type.getId(), type.getDescription(), type.name()) + ); + } + } diff --git a/src/main/java/umc/kkijuk/server/detail/repository/CareerDetailJpaRepository.java b/src/main/java/umc/kkijuk/server/detail/repository/CareerDetailJpaRepository.java index d458fca..080709a 100644 --- a/src/main/java/umc/kkijuk/server/detail/repository/CareerDetailJpaRepository.java +++ b/src/main/java/umc/kkijuk/server/detail/repository/CareerDetailJpaRepository.java @@ -65,4 +65,6 @@ List findByCareerIdAndCareerType(@Param("careerType") CareerTy "JOIN FETCH ct.tag t " + "WHERE EXISTS (SELECT 1 FROM CareerDetailTag ct2 WHERE ct2.baseCareerDetail=bcd AND ct2.tag.id=:tagId)" ) List findByTag(@Param("tagId") Long tagId); + + List findTop3ByMemberIdOrderByCreatedAtDesc(Long id); } diff --git a/src/main/java/umc/kkijuk/server/detail/repository/CareerDetailRepository.java b/src/main/java/umc/kkijuk/server/detail/repository/CareerDetailRepository.java index dcce867..966599c 100644 --- a/src/main/java/umc/kkijuk/server/detail/repository/CareerDetailRepository.java +++ b/src/main/java/umc/kkijuk/server/detail/repository/CareerDetailRepository.java @@ -18,4 +18,7 @@ public interface CareerDetailRepository { List findByMemberIdAndKeyword(Long id, String keyword); List findByTag(Long id); + + + List findTop3ByMemberIdOrderByCreatedAtDesc(Long id); } diff --git a/src/main/java/umc/kkijuk/server/detail/repository/CareerDetailRepositoryImpl.java b/src/main/java/umc/kkijuk/server/detail/repository/CareerDetailRepositoryImpl.java index 37041fe..4bed713 100644 --- a/src/main/java/umc/kkijuk/server/detail/repository/CareerDetailRepositoryImpl.java +++ b/src/main/java/umc/kkijuk/server/detail/repository/CareerDetailRepositoryImpl.java @@ -41,4 +41,9 @@ public List findByMemberIdAndKeyword(Long id, String keyword) public List findByTag(Long id) { return careerDetailJpaRepository.findByTag(id); } + + @Override + public List findTop3ByMemberIdOrderByCreatedAtDesc(Long id) { + return careerDetailJpaRepository.findTop3ByMemberIdOrderByCreatedAtDesc(id); + } } diff --git a/src/main/java/umc/kkijuk/server/detail/service/BaseCareerDetailService.java b/src/main/java/umc/kkijuk/server/detail/service/BaseCareerDetailService.java index 30ef2c6..4d578fa 100644 --- a/src/main/java/umc/kkijuk/server/detail/service/BaseCareerDetailService.java +++ b/src/main/java/umc/kkijuk/server/detail/service/BaseCareerDetailService.java @@ -1,6 +1,9 @@ package umc.kkijuk.server.detail.service; +import java.util.List; +import umc.kkijuk.server.career.controller.response.FindDetailResponse; import umc.kkijuk.server.detail.controller.response.BaseCareerDetailResponse; +import umc.kkijuk.server.detail.controller.response.RecentCareerDetailResponse; import umc.kkijuk.server.detail.dto.CareerDetailReqDto; import umc.kkijuk.server.detail.dto.CareerDetailUpdateReqDto; import umc.kkijuk.server.member.domain.Member; @@ -11,4 +14,6 @@ public interface BaseCareerDetailService { void deleteDetail(Member requestMember, Long careerId, Long detailId); BaseCareerDetailResponse updateDetail(Member requestMember, CareerDetailUpdateReqDto request, Long careerId, Long detailId); + + List boardDetail(Member requestMember); } \ No newline at end of file diff --git a/src/main/java/umc/kkijuk/server/detail/service/BaseCareerDetailServiceImpl.java b/src/main/java/umc/kkijuk/server/detail/service/BaseCareerDetailServiceImpl.java index df48924..285dca3 100644 --- a/src/main/java/umc/kkijuk/server/detail/service/BaseCareerDetailServiceImpl.java +++ b/src/main/java/umc/kkijuk/server/detail/service/BaseCareerDetailServiceImpl.java @@ -1,14 +1,20 @@ package umc.kkijuk.server.detail.service; +import java.time.LocalDate; +import java.util.Objects; import lombok.Builder; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import umc.kkijuk.server.career.controller.response.CategoryResponse; +import umc.kkijuk.server.career.controller.response.FindDetailResponse; import umc.kkijuk.server.career.domain.*; import umc.kkijuk.server.career.repository.*; import umc.kkijuk.server.common.domian.exception.*; import umc.kkijuk.server.detail.controller.response.BaseCareerDetailResponse; +import umc.kkijuk.server.detail.controller.response.RecentCareerDetailResponse; +import umc.kkijuk.server.detail.controller.response.TagResponse; import umc.kkijuk.server.detail.domain.*; import umc.kkijuk.server.detail.domain.mapping.CareerDetailTag; import umc.kkijuk.server.detail.dto.CareerDetailReqDto; @@ -92,6 +98,22 @@ public BaseCareerDetailResponse updateDetail(Member requestMember, CareerDetailU return new BaseCareerDetailResponse(careerDetailRepository.save(baseCareerDetail)); } + @Override + public List boardDetail(Member requestMember) { + List details = careerDetailRepository.findTop3ByMemberIdOrderByCreatedAtDesc(requestMember.getId()); + + return details.stream() + .map(detail -> { + CareerType type = detail.getCareerType(); + Long careerId = detail.getCareerId(); + BaseCareer baseCareer = findBaseCareerByType(type, careerId); + if (baseCareer == null) return null; + return BaseCareerDetailConverter.toResponse(detail, baseCareer, type); + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + private void validateOwner(BaseCareer career, Member requestMember) { if (!career.getMemberId().equals(requestMember.getId())) { throw new OwnerMismatchException();