Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class SwaggerConfig {
"/v1/user-address-verified",
"/v1/behaviourtips/**",
"/v1/sponsors/**",
"/v1/my-page/**",
)
.pathsToExclude("/v1/behaviourtips")
.pathsToExclude("/v1/sponsors")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@ package com.numberone.daepiro.domain.community.repository.article
import com.numberone.daepiro.domain.address.entity.Address
import com.numberone.daepiro.domain.community.dto.request.GetArticleRequest
import com.numberone.daepiro.domain.community.dto.response.ArticleListResponse
import com.numberone.daepiro.domain.mypage.dto.request.GetMyArticleRequest
import org.springframework.data.domain.Slice

interface ArticleRepositoryCustom {
fun getArticles(
request: GetArticleRequest,
addressValues: List<Address>
): Slice<ArticleListResponse>

fun getMyArticles(
userId: Long,
request: GetMyArticleRequest
): Slice<ArticleListResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import com.numberone.daepiro.domain.community.dto.response.ArticleListResponse
import com.numberone.daepiro.domain.community.dto.response.QAddressResponse
import com.numberone.daepiro.domain.community.dto.response.QArticleListResponse
import com.numberone.daepiro.domain.community.dto.response.QAuthorResponse
import com.numberone.daepiro.domain.community.entity.ArticleStatus
import com.numberone.daepiro.domain.community.entity.QArticle.article
import com.numberone.daepiro.domain.mypage.dto.request.GetMyArticleRequest
import com.numberone.daepiro.global.utils.SecurityContextUtils
import com.querydsl.core.types.Expression
import com.querydsl.core.types.dsl.BooleanExpression
Expand Down Expand Up @@ -75,6 +77,52 @@ class ArticleRepositoryCustomImpl(
)
}

override fun getMyArticles(userId: Long, request: GetMyArticleRequest): Slice<ArticleListResponse> {
val pageable = request.getPageable()

val content = queryFactory.select(
QArticleListResponse(
article.id,
article.status,
article.type.stringValue(),
article.category,
article.title,
article.body,
article.likeCount,
article.viewCount,
article.commentCount,
article.reportCount,
QAddressResponse(
caseWhenLocationVisible(address.id, null),
caseWhenLocationVisible(address.siDo, null),
caseWhenLocationVisible(address.siGunGu, null)
),
article.createdAt,
article.lastModifiedAt,
QAuthorResponse(
article.authUser.id,
article.authUser.nickname,
article.authUser.realname,
article.authUser.isCompletedOnboarding,
article.authUser.profileImageUrl
),
article.authUser.id.eq(SecurityContextUtils.getUserId()),
)
).from(article)
.leftJoin(address).on(article.address.id.eq(address.id))
.where(article.authUser.id.eq(userId), article.status.eq(ArticleStatus.ACTIVE))
.orderBy(article.id.desc())
.offset(pageable.offset)
.limit(pageable.pageSize + 1L)
.fetch()

return SliceImpl(
content,
pageable,
hasNextPage(content, pageable.pageSize)
)
}

private fun hasNextPage(contents: MutableList<ArticleListResponse>, pageSize: Int): Boolean {
return if (contents.size > pageSize) {
contents.removeAt(pageSize) // 초과한 한 개 제거
Expand Down
100 changes: 100 additions & 0 deletions src/main/kotlin/com/numberone/daepiro/domain/mypage/api/MyPageApiV1.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.numberone.daepiro.domain.mypage.api

import com.numberone.daepiro.domain.community.dto.response.ArticleListResponse
import com.numberone.daepiro.domain.mypage.dto.request.EditAddressesRequest
import com.numberone.daepiro.domain.mypage.dto.request.EditDisasterTypesRequest
import com.numberone.daepiro.domain.mypage.dto.request.EditProfileRequest
import com.numberone.daepiro.domain.mypage.dto.request.GetMyArticleRequest
import com.numberone.daepiro.domain.mypage.dto.request.InquireRequest
import com.numberone.daepiro.domain.mypage.dto.response.MyAddressesResponse
import com.numberone.daepiro.domain.mypage.dto.response.MyDisasterTypesResponse
import com.numberone.daepiro.domain.mypage.dto.response.MyNotificationResponse
import com.numberone.daepiro.domain.mypage.dto.response.MyProfileResponse
import com.numberone.daepiro.global.dto.ApiResult
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.data.domain.Slice
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping

@Tag(name = "MyPage API", description = "마이페이지 API")
@RequestMapping("/v1/my-page")
interface MyPageApiV1 {
@GetMapping("/profiles")
@Operation(summary = "마이페이지 프로필 조회", description = "마이페이지 프로필을 조회합니다.")
fun getMyProfile(): ApiResult<MyProfileResponse>

@GetMapping("/notifications")
@Operation(summary = "마이페이지 알림 설정 조회", description = "마이페이지 알림 설정을 조회합니다.")
fun getMyNotification(): ApiResult<MyNotificationResponse>

@GetMapping("/addresses")
@Operation(summary = "마이페이지 재난알림 지역 설정 조회", description = "마이페이지 재난알림 지역 설정을 조회합니다.")
fun getMyAddresses(): ApiResult<MyAddressesResponse>

@GetMapping("/disaster-types")
@Operation(summary = "마이페이지 재난유형 설정 조회", description = "마이페이지 재난유형 설정을 조회합니다.")
fun getMyDisasterTypes(): ApiResult<MyDisasterTypesResponse>

@GetMapping("/articles")
@Operation(summary = "마이페이지 내가 쓴 글 조회", description = "마이페이지 내가 쓴 글을 조회합니다. page는 1부터 시작합니다.")
fun getMyArticles(
@ModelAttribute request: GetMyArticleRequest
): ApiResult<Slice<ArticleListResponse>>

// @GetMapping("/announcement")
// @Operation(summary = "마이페이지 공지사항 조회", description = "마이페이지 공지사항을 조회합니다.")
// fun getAnnouncement():ApiResult<>

@PutMapping("/profiles")
@Operation(summary = "마이페이지 프로필 수정", description = "프로필을 수정합니다.")
fun updateMyProfile(
@RequestBody request: EditProfileRequest
): ApiResult<Unit>

@PutMapping("/notifications/{type}")
@Operation(
summary = "마이페이지 알림 설정 수정", description = """
커뮤니티 또는 재난 알림 수신 유무를 변경합니다.
on이면 off로, off면 on으로 변경됩니다.

알림 타입은 영어 소문자로 입력해주세요!
"""
)
fun updateMyNotification(
@Schema(description = "알림 타입 (community 또는 disaster)", example = "community") @PathVariable type: String
): ApiResult<Unit>

@PutMapping("/addresses")
@Operation(summary = "마이페이지 재난알림 지역 설정 수정", description = "재난알림 지역 설정을 수정합니다.")
fun updateMyAddresses(
@RequestBody request: EditAddressesRequest
): ApiResult<Unit>

@PutMapping("/disaster-types")
@Operation(summary = "마이페이지 재난유형 설정 수정", description = "재난유형 설정을 수정합니다.")
fun updateMyDisasterTypes(
@RequestBody request: EditDisasterTypesRequest
): ApiResult<Unit>

@PostMapping("/inquires")
@Operation(
summary = "문의하기", description = """
문의하기를 합니다.
문의 유형에느 아래 중 하나의 영단어 대문자 값을 입력해주세요.
SERVICE: 서비스 개선
DISASTER: 재난 알림 및 정보
COMMUNITY: 커뮤니티 이용
ETC: 기타
"""
)
fun inquire(
@RequestBody request: InquireRequest
): ApiResult<Unit>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.numberone.daepiro.domain.mypage.controller

import com.numberone.daepiro.domain.community.dto.response.ArticleListResponse
import com.numberone.daepiro.domain.mypage.api.MyPageApiV1
import com.numberone.daepiro.domain.mypage.dto.request.EditAddressesRequest
import com.numberone.daepiro.domain.mypage.dto.request.EditDisasterTypesRequest
import com.numberone.daepiro.domain.mypage.dto.request.EditProfileRequest
import com.numberone.daepiro.domain.mypage.dto.request.GetMyArticleRequest
import com.numberone.daepiro.domain.mypage.dto.request.InquireRequest
import com.numberone.daepiro.domain.mypage.dto.response.MyAddressesResponse
import com.numberone.daepiro.domain.mypage.dto.response.MyDisasterTypesResponse
import com.numberone.daepiro.domain.mypage.dto.response.MyNotificationResponse
import com.numberone.daepiro.domain.mypage.dto.response.MyProfileResponse
import com.numberone.daepiro.domain.mypage.service.MyPageService
import com.numberone.daepiro.global.dto.ApiResult
import com.numberone.daepiro.global.utils.SecurityContextUtils
import org.springframework.data.domain.Slice
import org.springframework.web.bind.annotation.RestController

@RestController
class MyPageController(
private val myPageService: MyPageService
) : MyPageApiV1 {
override fun getMyProfile(): ApiResult<MyProfileResponse> {
val userId = SecurityContextUtils.getUserId()
return myPageService.getMyProfile(userId)
}

override fun getMyNotification(): ApiResult<MyNotificationResponse> {
val userId = SecurityContextUtils.getUserId()
return myPageService.getMyNotification(userId)
}

override fun getMyAddresses(): ApiResult<MyAddressesResponse> {
val userId = SecurityContextUtils.getUserId()
return myPageService.getMyAddresses(userId)
}

override fun getMyDisasterTypes(): ApiResult<MyDisasterTypesResponse> {
val userId = SecurityContextUtils.getUserId()
return myPageService.getMyDisasterTypes(userId)
}

override fun getMyArticles(
request: GetMyArticleRequest
): ApiResult<Slice<ArticleListResponse>> {
val userId = SecurityContextUtils.getUserId()
return myPageService.getMyArticles(userId, request)
}

override fun updateMyProfile(request: EditProfileRequest): ApiResult<Unit> {
val userId = SecurityContextUtils.getUserId()
myPageService.updateMyProfile(userId, request)
return ApiResult.ok()
}

override fun updateMyNotification(type: String): ApiResult<Unit> {
val userId = SecurityContextUtils.getUserId()
myPageService.updateMyNotification(userId, type)
return ApiResult.ok()
}

override fun updateMyAddresses(request: EditAddressesRequest): ApiResult<Unit> {
val userId = SecurityContextUtils.getUserId()
myPageService.updateMyAddresses(userId, request)
return ApiResult.ok()
}

override fun updateMyDisasterTypes(request: EditDisasterTypesRequest): ApiResult<Unit> {
val userId = SecurityContextUtils.getUserId()
myPageService.updateMyDisasterTypes(userId, request)
return ApiResult.ok()
}

override fun inquire(request: InquireRequest): ApiResult<Unit> {
val userId = SecurityContextUtils.getUserId()
myPageService.inquire(userId, request)
return ApiResult.ok()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.numberone.daepiro.domain.mypage.dto.request

import com.numberone.daepiro.domain.user.dto.request.AddressRequest
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.Size

data class EditAddressesRequest(
@field:Size(min = 1, max = 3, message = "주소는 1개 이상 3개 이하로 입력해주세요.")
val addresses: List<AddressRequest>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.numberone.daepiro.domain.mypage.dto.request

import io.swagger.v3.oas.annotations.media.Schema

data class EditDisasterTypesRequest(
@Schema(
description = "재난 유형",
example = "[\"지진\", \"화재\", \"태풍\"]",
)
val disasterTypes: List<String>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.numberone.daepiro.domain.mypage.dto.request

import io.swagger.v3.oas.annotations.media.Schema

data class EditProfileRequest(
@Schema(description = "변경할 실명", example = "송승희")
val realname: String,

@Schema(description = "변경할 닉네임 (중복체크 필요)", example = "초코송이")
val nickname: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.numberone.daepiro.domain.mypage.dto.request

import io.swagger.v3.oas.annotations.media.Schema
import org.springdoc.core.annotations.ParameterObject
import org.springframework.data.domain.Pageable

@ParameterObject
data class GetMyArticleRequest(
@Schema(description = "페이지 번호(1부터 시작)", example = "1")
val page: Int,
@Schema(description = "페이지 사이즈", example = "10")
val size: Int,
){
fun getPageable(): Pageable {
return Pageable.ofSize(size).withPage(page - 1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.numberone.daepiro.domain.mypage.dto.request

import com.numberone.daepiro.domain.mypage.entity.InquiryType
import io.swagger.v3.oas.annotations.media.Schema

data class InquireRequest(
@Schema(
description = "문의 유형",
example = "COMMUNITY"
)
val type: InquiryType,
@Schema(
description = "문의 내용",
example = "커뮤니티 이용 중 발생한 문제에 대해 문의드립니다.",
)
val content: String,
@Schema(
description = "연락받을 이메일",
example = "example@naver.com"
)
val email: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.numberone.daepiro.domain.mypage.dto.response

import com.numberone.daepiro.domain.address.entity.UserAddress
import com.numberone.daepiro.domain.user.entity.UserEntity
import io.swagger.v3.oas.annotations.media.Schema

data class MyAddressesResponse(
val addresses: List<AddressResponse>
) {
companion object {
fun of(
user: UserEntity
): MyAddressesResponse {
return MyAddressesResponse(
addresses = user.userAddresses.map { AddressResponse.of(it) }
)
}
}
}

data class AddressResponse(
@Schema(description = "이름", example = "집")
val name: String,

@Schema(description = "주소", example = "서울특별시 영등포구 신길동")
val address: String
) {
companion object {
fun of(
address: UserAddress
): AddressResponse {
return AddressResponse(
name = address.name,
address = address.address.toFullAddress()
)
}
}
}
Loading
Loading