diff --git a/src/main/java/com/example/RealMatch/user/application/service/UserService.java b/src/main/java/com/example/RealMatch/user/application/service/UserService.java index 495d8d17..b634c32b 100644 --- a/src/main/java/com/example/RealMatch/user/application/service/UserService.java +++ b/src/main/java/com/example/RealMatch/user/application/service/UserService.java @@ -20,6 +20,7 @@ import com.example.RealMatch.user.infrastructure.ScrapMockDataProvider; import com.example.RealMatch.user.presentation.code.UserErrorCode; import com.example.RealMatch.user.presentation.dto.request.MyEditInfoRequestDto; +import com.example.RealMatch.user.presentation.dto.request.MyProfileCardUpdateRequestDto; import com.example.RealMatch.user.presentation.dto.response.MyEditInfoResponseDto; import com.example.RealMatch.user.presentation.dto.response.MyLoginResponseDto; import com.example.RealMatch.user.presentation.dto.response.MyPageResponseDto; @@ -146,6 +147,30 @@ public MyLoginResponseDto getSocialLoginInfo(Long userId) { return MyLoginResponseDto.from(linkedProviders); } + @Transactional + public MyProfileCardResponseDto updateMyProfileImage( + Long userId, + MyProfileCardUpdateRequestDto request + ) { + // 유저 조회 + User user = userRepository.findById(userId) + .orElseThrow(() -> new CustomException(UserErrorCode.USER_NOT_FOUND)); + + // 매칭 검사 진행 여부 예외 처리 - 매칭 검사를 안하면 프로필 카드가 없음 + UserMatchingDetail detail = userMatchingDetailRepository + .findByUserIdAndIsDeprecatedFalse(userId) + .orElseThrow(() -> new CustomException(UserErrorCode.PROFILE_CARD_NOT_FOUND)); + + // 이미지 URL만 교체 + user.updateProfileImage(request.getProfileImageUrl()); + + // 변경된 프로필 이미지로 프로필 카드 DTO 재생성 + List categories = + userContentCategoryRepository.findByUserId(userId); + + return MyProfileCardResponseDto.from(user, detail, categories); + } + @Transactional(readOnly = true) public boolean isNicknameAvailable(String nickname) { return nicknameValidator.isAvailable(nickname); diff --git a/src/main/java/com/example/RealMatch/user/presentation/controller/UserController.java b/src/main/java/com/example/RealMatch/user/presentation/controller/UserController.java index d6e0bd34..55affa0f 100644 --- a/src/main/java/com/example/RealMatch/user/presentation/controller/UserController.java +++ b/src/main/java/com/example/RealMatch/user/presentation/controller/UserController.java @@ -20,6 +20,7 @@ import com.example.RealMatch.user.application.service.UserService; import com.example.RealMatch.user.application.service.UserWithdrawService; import com.example.RealMatch.user.presentation.dto.request.MyEditInfoRequestDto; +import com.example.RealMatch.user.presentation.dto.request.MyProfileCardUpdateRequestDto; import com.example.RealMatch.user.presentation.dto.response.FavoriteBrandListResponseDto; import com.example.RealMatch.user.presentation.dto.response.FavoriteCampaignListResponseDto; import com.example.RealMatch.user.presentation.dto.response.MyEditInfoResponseDto; @@ -166,4 +167,13 @@ public CustomResponse getMyFavoriteCampaigns( ) ); } + @PatchMapping("/me/profile-image") + public CustomResponse updateMyProfileImage( + @AuthenticationPrincipal CustomUserDetails userDetails, + @RequestBody @Valid MyProfileCardUpdateRequestDto request + ) { + return CustomResponse.ok( + userService.updateMyProfileImage(userDetails.getUserId(), request) + ); + } } diff --git a/src/main/java/com/example/RealMatch/user/presentation/dto/request/MyProfileCardUpdateRequestDto.java b/src/main/java/com/example/RealMatch/user/presentation/dto/request/MyProfileCardUpdateRequestDto.java new file mode 100644 index 00000000..17f8394e --- /dev/null +++ b/src/main/java/com/example/RealMatch/user/presentation/dto/request/MyProfileCardUpdateRequestDto.java @@ -0,0 +1,14 @@ +package com.example.RealMatch.user.presentation.dto.request; + +import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class MyProfileCardUpdateRequestDto { + + @jakarta.validation.constraints.NotBlank + @Size(max = 255) + private String profileImageUrl; +} diff --git a/src/main/java/com/example/RealMatch/user/presentation/swagger/UserSwagger.java b/src/main/java/com/example/RealMatch/user/presentation/swagger/UserSwagger.java index c6e8cfe5..413a5fd1 100644 --- a/src/main/java/com/example/RealMatch/user/presentation/swagger/UserSwagger.java +++ b/src/main/java/com/example/RealMatch/user/presentation/swagger/UserSwagger.java @@ -11,6 +11,7 @@ import com.example.RealMatch.match.domain.entity.enums.CampaignSortType; import com.example.RealMatch.match.presentation.dto.request.MatchRequestDto; import com.example.RealMatch.user.presentation.dto.request.MyEditInfoRequestDto; +import com.example.RealMatch.user.presentation.dto.request.MyProfileCardUpdateRequestDto; import com.example.RealMatch.user.presentation.dto.response.FavoriteBrandListResponseDto; import com.example.RealMatch.user.presentation.dto.response.FavoriteCampaignListResponseDto; import com.example.RealMatch.user.presentation.dto.response.MyEditInfoResponseDto; @@ -148,7 +149,7 @@ CustomResponse checkNicknameAvailable( @RequestParam String nickname ); - @Operation(summary = "회원 탈퇴", description = "회원 탈퇴(Soft Delete) 처리 후 role을 WITHDRAWN으로 변경합니다.") + @Operation(summary = "회원 탈퇴 API By 고경수 ", description = "회원 탈퇴(Soft Delete) 처리 후 role을 WITHDRAWN으로 변경합니다.") CustomResponse withdraw( @Parameter(hidden = true) @AuthenticationPrincipal CustomUserDetails userDetails ); @@ -207,4 +208,11 @@ CustomResponse getMyFavoriteCampaigns( @RequestParam(required = false) CampaignSortType sort ); + + @Operation(summary = "프로필 이미지 수정 API By 고경수", + description = "Attachment API로 업로드된 이미지 URL을 받아 프로필 이미지를 변경합니다") + CustomResponse updateMyProfileImage( + @Parameter(hidden = true) CustomUserDetails userDetails, + @RequestBody MyProfileCardUpdateRequestDto request + ); }