diff --git a/src/main/java/com/brainpix/post/dto/MyDefaultPageIdeaListDto.java b/src/main/java/com/brainpix/post/dto/MyDefaultPageIdeaListDto.java new file mode 100644 index 00000000..fe967973 --- /dev/null +++ b/src/main/java/com/brainpix/post/dto/MyDefaultPageIdeaListDto.java @@ -0,0 +1,11 @@ +package com.brainpix.post.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class MyDefaultPageIdeaListDto { + private Long id; + private String title; +} diff --git a/src/main/java/com/brainpix/profile/controller/MyPageController.java b/src/main/java/com/brainpix/profile/controller/MyPageController.java index 8bdea35f..900f5b0b 100644 --- a/src/main/java/com/brainpix/profile/controller/MyPageController.java +++ b/src/main/java/com/brainpix/profile/controller/MyPageController.java @@ -8,16 +8,20 @@ import com.brainpix.api.ApiResponse; import com.brainpix.api.CommonPageResponse; +import com.brainpix.api.swagger.SwaggerPageable; +import com.brainpix.post.dto.MyDefaultPageIdeaListDto; import com.brainpix.profile.dto.MyPageResponseDto; import com.brainpix.profile.service.MyPageService; import com.brainpix.security.authorization.AllUser; import com.brainpix.security.authorization.UserId; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @RestController @RequestMapping("/my-page") +@Tag(name = "마이페이지 기본 화면 조회", description = "마이페이지 기본 화면 조회 관련 API") @RequiredArgsConstructor public class MyPageController { @@ -33,8 +37,9 @@ public ResponseEntity> getMyPage(@UserId Long use @AllUser @Operation(summary = "'내 아이디어' 조회", description = "특정 사용자가 작성한 아이디어 목록을 페이징 처리하여 조회합니다") + @SwaggerPageable @GetMapping("/ideas") - public ResponseEntity>> getMyIdeas( + public ResponseEntity>> getMyIdeas( @UserId Long userId, Pageable pageable) { return ResponseEntity.ok( diff --git a/src/main/java/com/brainpix/profile/controller/ProfileController.java b/src/main/java/com/brainpix/profile/controller/ProfileController.java index 2a201a53..888cb7f6 100644 --- a/src/main/java/com/brainpix/profile/controller/ProfileController.java +++ b/src/main/java/com/brainpix/profile/controller/ProfileController.java @@ -18,10 +18,12 @@ import com.brainpix.security.authorization.UserId; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @RestController @RequestMapping("/profile") +@Tag(name = "본인 프로필 조회/수정 API", description = "개인/기업 본인시 소유한 계정의 프로필을 조회 및 수정 API 입니다.") @RequiredArgsConstructor public class ProfileController { diff --git a/src/main/java/com/brainpix/profile/controller/PublicProfileController.java b/src/main/java/com/brainpix/profile/controller/PublicProfileController.java index 8c610404..b2966bf0 100644 --- a/src/main/java/com/brainpix/profile/controller/PublicProfileController.java +++ b/src/main/java/com/brainpix/profile/controller/PublicProfileController.java @@ -10,6 +10,7 @@ import com.brainpix.api.ApiResponse; import com.brainpix.api.CommonPageResponse; +import com.brainpix.api.swagger.SwaggerPageable; import com.brainpix.profile.dto.CompanyProfileResponseDto; import com.brainpix.profile.dto.IndividualProfileResponseDto; import com.brainpix.profile.dto.PublicProfileResponseDto; @@ -18,10 +19,12 @@ import com.brainpix.security.authorization.UserId; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @RestController @RequestMapping("/public-profile") // 기존 마이페이지 조회 API와 구별 +@Tag(name = "상대방 프로필 조회 API", description = "상대방 계정의 프로필을 조회 API 입니다.") @RequiredArgsConstructor public class PublicProfileController { @@ -53,6 +56,7 @@ public ResponseEntity> getPublicCompanyPr @AllUser @Operation(summary = "사용자 게시글 조회", description = "특정 사용자가 작성한 공개 게시글을 조회합니다.") @GetMapping + @SwaggerPageable public ResponseEntity>> getPostsByUser( @UserId Long userId, @PageableDefault(sort = "createdDate", direction = Sort.Direction.DESC) Pageable pageable) { diff --git a/src/main/java/com/brainpix/profile/converter/MyProfileConverter.java b/src/main/java/com/brainpix/profile/converter/MyProfileConverter.java index 6910e85b..8e57420c 100644 --- a/src/main/java/com/brainpix/profile/converter/MyProfileConverter.java +++ b/src/main/java/com/brainpix/profile/converter/MyProfileConverter.java @@ -20,27 +20,26 @@ public IndividualProfileResponseDto toDto(User user) { return IndividualProfileResponseDto.builder() .userType("개인") .specializations(profile.getSpecializationList().stream() - .map(Enum::name) - .collect(Collectors.joining("/"))) // 전문 분야를 '/'로 구분 + .toList()) .name(user.getName()) .selfIntroduction(profile.getSelfIntroduction()) .contacts(profile.getContacts().stream() .map(contact -> IndividualProfileResponseDto.ContactDto.builder() - .type(contact.getType().name()) + .type(contact.getType()) .value(contact.getValue()) .build()) .collect(Collectors.toList())) .stacks(profile.getStacks().stream() .map(stack -> IndividualProfileResponseDto.StackDto.builder() .stackName(stack.getStackName()) - .proficiency(stack.getStackProficiency().name()) + .proficiency(stack.getStackProficiency()) .build()) .collect(Collectors.toList())) .careers(profile.getCareers().stream() .map(career -> IndividualProfileResponseDto.CareerDto.builder() .content(career.getCareerContent()) - .startDate(career.getStartDate().toString()) - .endDate(career.getEndDate().toString()) + .startDate(career.getStartDate()) + .endDate(career.getEndDate()) .build()) .collect(Collectors.toList())) .build(); @@ -52,14 +51,13 @@ public CompanyProfileResponseDto toCompanyDto(Company user) { return CompanyProfileResponseDto.builder() .userType("기업") .specializations(profile.getSpecializationList().stream() - .map(Enum::name) - .collect(Collectors.joining("/"))) // 기업 분야를 '/'로 구분 + .toList()) .name(user.getName()) .selfIntroduction(profile.getSelfIntroduction()) .businessInformation(profile.getBusinessInformation()) .companyInformations(profile.getCompanyInformations().stream() .map(info -> CompanyProfileResponseDto.CompanyInformationDto.builder() - .type(info.getCompanyInformationType().name()) + .type(info.getCompanyInformationType()) .value(info.getValue()) .build()) .collect(Collectors.toList())) diff --git a/src/main/java/com/brainpix/profile/converter/ProfileConverter.java b/src/main/java/com/brainpix/profile/converter/ProfileConverter.java index 7569b234..6a9d4f5f 100644 --- a/src/main/java/com/brainpix/profile/converter/ProfileConverter.java +++ b/src/main/java/com/brainpix/profile/converter/ProfileConverter.java @@ -1,6 +1,5 @@ package com.brainpix.profile.converter; -import java.time.YearMonth; import java.util.List; import java.util.stream.Collectors; @@ -26,7 +25,7 @@ public Stack toStack(IndividualProfileUpdateDto.StackDto dto, IndividualProfile } public Career toCareer(IndividualProfileUpdateDto.CareerDto dto, IndividualProfile profile) { - return new Career(dto.getContent(), YearMonth.parse(dto.getStartDate()), YearMonth.parse(dto.getEndDate()), + return new Career(dto.getContent(), dto.getStartDate(), dto.getEndDate(), profile); } diff --git a/src/main/java/com/brainpix/profile/converter/ProfilePostConverter.java b/src/main/java/com/brainpix/profile/converter/ProfilePostConverter.java index 7f9e4fcf..704fb9c6 100644 --- a/src/main/java/com/brainpix/profile/converter/ProfilePostConverter.java +++ b/src/main/java/com/brainpix/profile/converter/ProfilePostConverter.java @@ -17,18 +17,17 @@ public class ProfilePostConverter { */ public PublicProfileResponseDto.PostPreviewDto toRequestTaskPreviewDto(RequestTask task, long savedCount) { String openScope = parseOpenScope(task.getPostAuth()); - String dDayString = task.getDeadline().toString(); String writerName = getDisplayName(task.getWriter()); return PublicProfileResponseDto.PostPreviewDto.builder() .postId(task.getId()) .openScope(openScope) - .categoryName("요청 과제 > " + task.getSpecialization()) + .specialization(task.getSpecialization()) .title(task.getTitle()) .writerName(writerName) .savedCount(savedCount) .viewCount(task.getViewCount()) - .deadline(dDayString) + .deadline(task.getDeadline()) .thumbnailImage(task.getFirstImage()) .writerImageUrl(task.getWriter().getProfileImage()) .build(); @@ -44,7 +43,7 @@ public PublicProfileResponseDto.PostPreviewDto toIdeaMarketPreviewDto(IdeaMarket return PublicProfileResponseDto.PostPreviewDto.builder() .postId(market.getId()) .openScope(openScope) - .categoryName("아이디어 마켓 > " + market.getSpecialization()) + .specialization(market.getSpecialization()) .title(market.getTitle()) .writerName(writerName) .savedCount(savedCount) @@ -65,19 +64,18 @@ public PublicProfileResponseDto.PostPreviewDto toCollaborationHubPreviewDto(Coll long totalMembers = hub.getCollaborations().stream() .mapToLong(rec -> rec.getGathering().getTotalQuantity()) .sum(); - String dDayString = hub.getDeadline().toString(); String openScope = parseOpenScope(hub.getPostAuth()); String writerName = getDisplayName(hub.getWriter()); return PublicProfileResponseDto.PostPreviewDto.builder() .postId(hub.getId()) .openScope(openScope) - .categoryName("협업 광장 > " + hub.getSpecialization()) + .specialization(hub.getSpecialization()) .title(hub.getTitle()) .writerName(writerName) .savedCount(savedCount) .viewCount(hub.getViewCount()) - .deadline(dDayString) + .deadline(hub.getDeadline()) .thumbnailImage(hub.getFirstImage()) .currentMembers(currentMembers) .totalMembers(totalMembers) diff --git a/src/main/java/com/brainpix/profile/dto/CompanyProfileResponseDto.java b/src/main/java/com/brainpix/profile/dto/CompanyProfileResponseDto.java index 755dd09e..c96203ab 100644 --- a/src/main/java/com/brainpix/profile/dto/CompanyProfileResponseDto.java +++ b/src/main/java/com/brainpix/profile/dto/CompanyProfileResponseDto.java @@ -2,6 +2,9 @@ import java.util.List; +import com.brainpix.profile.entity.CompanyInformationType; +import com.brainpix.profile.entity.Specialization; + import lombok.Builder; import lombok.Getter; @@ -9,7 +12,7 @@ @Builder public class CompanyProfileResponseDto { private String userType; // 개인/기업 - private String specializations; // 기업 분야 (e.g., "IT/디자인") + private List specializations; private String name; // 기업 이름 private String selfIntroduction; // 기업 소개 private String businessInformation; // 사업 정보 @@ -19,7 +22,7 @@ public class CompanyProfileResponseDto { @Getter @Builder public static class CompanyInformationDto { - private String type; // 기업 정보 타입 + private CompanyInformationType type; // 기업 정보 타입 private String value; // 기업 정보 값 } diff --git a/src/main/java/com/brainpix/profile/dto/IndividualProfileResponseDto.java b/src/main/java/com/brainpix/profile/dto/IndividualProfileResponseDto.java index a8e9441e..9f437321 100644 --- a/src/main/java/com/brainpix/profile/dto/IndividualProfileResponseDto.java +++ b/src/main/java/com/brainpix/profile/dto/IndividualProfileResponseDto.java @@ -1,7 +1,16 @@ package com.brainpix.profile.dto; +import java.time.YearMonth; import java.util.List; +import org.springframework.format.annotation.DateTimeFormat; + +import com.brainpix.profile.entity.ContactType; +import com.brainpix.profile.entity.Specialization; +import com.brainpix.profile.entity.StackProficiency; +import com.fasterxml.jackson.annotation.JsonFormat; + +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Getter; @@ -9,18 +18,23 @@ @Builder public class IndividualProfileResponseDto { private String userType; // 개인/기업 - private String specializations; // 전문 분야 (e.g., "IT/디자인") + private List specializations; // 전문 분야 (e.g., "IT/디자인") private String name; // 사용자 이름 private String selfIntroduction; // 자기소개 - private List contacts; // 개별 정보 - private List stacks; // 보유 기술 - private List careers; // 경력 사항 + @Builder.Default + private List contacts = List.of(); // 기본값 빈 리스트 + + @Builder.Default + private List stacks = List.of(); + + @Builder.Default + private List careers = List.of(); @Getter @Builder public static class ContactDto { - private String type; // 연락처 유형 + private ContactType type; // 연락처 유형 private String value; // 연락처 값 } @@ -28,15 +42,21 @@ public static class ContactDto { @Builder public static class StackDto { private String stackName; // 스택 이름 - private String proficiency; // 숙련도 (상/중/하) + private StackProficiency proficiency; // 숙련도 (상/중/하) } @Getter @Builder public static class CareerDto { private String content; // 경력 내용 - private String startDate; // 시작 날짜 - private String endDate; // 종료 날짜 + @Schema(type = "string", example = "yyyy-MM") + @DateTimeFormat(pattern = "yyyy-MM") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM") + private YearMonth startDate; // 시작 날짜 + @Schema(type = "string", example = "yyyy-MM") + @DateTimeFormat(pattern = "yyyy-MM") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM") + private YearMonth endDate; // 종료 날짜 } } diff --git a/src/main/java/com/brainpix/profile/dto/IndividualProfileUpdateDto.java b/src/main/java/com/brainpix/profile/dto/IndividualProfileUpdateDto.java index e75df0b0..5287f688 100644 --- a/src/main/java/com/brainpix/profile/dto/IndividualProfileUpdateDto.java +++ b/src/main/java/com/brainpix/profile/dto/IndividualProfileUpdateDto.java @@ -1,11 +1,16 @@ package com.brainpix.profile.dto; +import java.time.YearMonth; import java.util.List; +import org.springframework.format.annotation.DateTimeFormat; + import com.brainpix.profile.entity.ContactType; import com.brainpix.profile.entity.Specialization; import com.brainpix.profile.entity.StackProficiency; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; @Getter @@ -40,7 +45,13 @@ public static class StackDto { @Getter public static class CareerDto { private String content; // 경력 내용 - private String startDate; // 시작 날짜 (YYYY-MM) - private String endDate; // 종료 날짜 (YYYY-MM) + @Schema(type = "string", example = "yyyy-MM") + @DateTimeFormat(pattern = "yyyy-MM") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM") + private YearMonth startDate; // 시작 날짜 (YYYY-MM) + @Schema(type = "string", example = "yyyy-MM") + @DateTimeFormat(pattern = "yyyy-MM") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM") + private YearMonth endDate; // 종료 날짜 (YYYY-MM) } } diff --git a/src/main/java/com/brainpix/profile/dto/MyPageResponseDto.java b/src/main/java/com/brainpix/profile/dto/MyPageResponseDto.java index a518ca61..f82dd36d 100644 --- a/src/main/java/com/brainpix/profile/dto/MyPageResponseDto.java +++ b/src/main/java/com/brainpix/profile/dto/MyPageResponseDto.java @@ -2,6 +2,8 @@ import java.util.List; +import com.brainpix.profile.entity.Specialization; + import lombok.Builder; import lombok.Getter; @@ -10,7 +12,7 @@ public class MyPageResponseDto { private String name; // 사용자 이름 private String userType; // 개인/기업 - private List specializations; // 분야 (최대 2개) + private List specializations; // 분야 (최대 2개) private long ideaCount; // 아이디어 작성 횟수 private long collaborationCount; // 협업 경험 횟수 private String selfIntroduction; // 자기소개 diff --git a/src/main/java/com/brainpix/profile/dto/PublicProfileResponseDto.java b/src/main/java/com/brainpix/profile/dto/PublicProfileResponseDto.java index 67195e81..4d073a15 100644 --- a/src/main/java/com/brainpix/profile/dto/PublicProfileResponseDto.java +++ b/src/main/java/com/brainpix/profile/dto/PublicProfileResponseDto.java @@ -3,6 +3,11 @@ import java.time.LocalDateTime; import java.util.List; +import org.springframework.format.annotation.DateTimeFormat; + +import com.brainpix.profile.entity.Specialization; +import com.fasterxml.jackson.annotation.JsonFormat; + import lombok.Builder; import lombok.Getter; @@ -11,7 +16,7 @@ public class PublicProfileResponseDto { private String userType; // 개인/기업 private String nickname; // 닉네임 - private String categories; // 전문 분야 (e.g., "디자인/기획") + private List specializations; // 전문 분야 (e.g., "디자인/기획") private String selfIntroduction; // 자기소개 private List posts; // 게시물 리스트 @@ -20,18 +25,19 @@ public class PublicProfileResponseDto { public static class PostPreviewDto { private Long postId; // 게시글 PK private String openScope; // 공개 범위 - private String categoryName; // 카테고리 이름 + private Specialization specialization; // 카테고리 이름 private String title; // 제목 private String writerName; // 작성자 이름 private Long savedCount; // 스크랩/즐겨찾기 횟수 private Long viewCount; // 조회수 - private String deadline; // 마감일 (D-3 등) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime deadline;// 마감일 private String thumbnailImage; // 썸네일 이미지 private String writerImageUrl; // 작성자 이미지 URL private Long price; // (아이디어 마켓 전용) private Long currentMembers; // (협업 광장 전용) private Long totalMembers; // (협업 광장 전용) - private LocalDateTime createdDate; } } diff --git a/src/main/java/com/brainpix/profile/service/MyPageService.java b/src/main/java/com/brainpix/profile/service/MyPageService.java index 118644ec..8645f7ee 100644 --- a/src/main/java/com/brainpix/profile/service/MyPageService.java +++ b/src/main/java/com/brainpix/profile/service/MyPageService.java @@ -11,11 +11,12 @@ import com.brainpix.api.exception.BrainPixException; import com.brainpix.joining.repository.CollectionGatheringRepository; import com.brainpix.joining.repository.RequestTaskPurchasingRepository; -import com.brainpix.post.entity.idea_market.IdeaMarket; +import com.brainpix.post.dto.MyDefaultPageIdeaListDto; import com.brainpix.post.repository.IdeaMarketRepository; import com.brainpix.profile.dto.MyPageResponseDto; import com.brainpix.profile.entity.CompanyProfile; import com.brainpix.profile.entity.IndividualProfile; +import com.brainpix.profile.entity.Specialization; import com.brainpix.user.entity.Company; import com.brainpix.user.entity.Individual; import com.brainpix.user.entity.User; @@ -31,16 +32,14 @@ public class MyPageService { private final UserRepository userRepository; private final IdeaMarketRepository ideaMarketRepository; private final CollectionGatheringRepository collectionGatheringRepository; - private final RequestTaskPurchasingRepository requestTaskPurchasingRepositoryl; + private final RequestTaskPurchasingRepository requestTaskPurchasingRepository; public MyPageResponseDto getMyPage(Long userId) { User user = userRepository.findById(userId) - .orElseThrow(() -> new BrainPixException(CommonErrorCode.RESOURCE_NOT_FOUND)); + .orElseThrow(() -> new BrainPixException(CommonErrorCode.USER_NOT_FOUND)); // 분야 (최대 2개) - List specializations = user.getProfile().getSpecializationList().stream() - .map(Enum::name) - .toList(); + List specializations = user.getProfile().getSpecializationList().stream().toList(); // 아이디어 작성 횟수 (아이디어 마켓 게시물 수) long ideaCount = ideaMarketRepository.countByWriterId(user.getId()); @@ -60,11 +59,11 @@ public MyPageResponseDto getMyPage(Long userId) { .build(); } - public Page getMyIdeas(Long userId, Pageable pageable) { + public Page getMyIdeas(Long userId, Pageable pageable) { User user = userRepository.findById(userId) - .orElseThrow(() -> new BrainPixException(CommonErrorCode.RESOURCE_NOT_FOUND)); + .orElseThrow(() -> new BrainPixException(CommonErrorCode.USER_NOT_FOUND)); return ideaMarketRepository.findByWriter(user, pageable) - .map(IdeaMarket::getTitle); + .map(ideaMarket -> new MyDefaultPageIdeaListDto(ideaMarket.getId(), ideaMarket.getTitle())); } private long calculateCollaborationCount(User user) { @@ -73,7 +72,7 @@ private long calculateCollaborationCount(User user) { long initialGatherings = collectionGatheringRepository.countByJoinerIdAndInitialGathering(user.getId(), true); // RequestTaskRecruitment: 요청 과제에서 승인된 횟수 - long approvedRequestTasks = requestTaskPurchasingRepositoryl.countByBuyerIdAndAccepted(user.getId(), true); + long approvedRequestTasks = requestTaskPurchasingRepository.countByBuyerIdAndAccepted(user.getId(), true); return approvedCollaborations + initialGatherings + approvedRequestTasks; }