Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge :: 회원탈퇴 추가 #169

Merged
merged 3 commits into from
Feb 25, 2023
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 @@ -64,4 +64,10 @@ public extension AppComponent {
ChangeProfileImageUseCaseImpl(studentsRepository: studentsRepository)
}
}

var withdrawalUseCase: any WithdrawalUseCase {
shared {
WithdrawalUseCaseImpl(studentsRepository: studentsRepository)
}
}
}
5 changes: 5 additions & 0 deletions Projects/App/Sources/Application/NeedleGenerated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ private class MyPageDependency48d84b530313b3ee40feProvider: MyPageDependency {
var logoutUseCase: any LogoutUseCase {
return appComponent.logoutUseCase
}
var withdrawalUseCase: any WithdrawalUseCase {
return appComponent.withdrawalUseCase
}
var changeProfileComponent: ChangeProfileComponent {
return appComponent.changeProfileComponent
}
Expand Down Expand Up @@ -541,6 +544,7 @@ extension AppComponent: Registration {
localTable["checkExistGradeClassNumberUseCase-any CheckExistGradeClassNumberUseCase"] = { [unowned self] in self.checkExistGradeClassNumberUseCase as Any }
localTable["fetchMyProfileUseCase-any FetchMyProfileUseCase"] = { [unowned self] in self.fetchMyProfileUseCase as Any }
localTable["changeProfileImageUseCase-any ChangeProfileImageUseCase"] = { [unowned self] in self.changeProfileImageUseCase as Any }
localTable["withdrawalUseCase-any WithdrawalUseCase"] = { [unowned self] in self.withdrawalUseCase as Any }
localTable["remoteUsersDataSource-any RemoteUsersDataSource"] = { [unowned self] in self.remoteUsersDataSource as Any }
localTable["usersRepository-any UsersRepository"] = { [unowned self] in self.usersRepository as Any }
localTable["changePasswordUseCase-any ChangePasswordUseCase"] = { [unowned self] in self.changePasswordUseCase as Any }
Expand Down Expand Up @@ -634,6 +638,7 @@ extension MyPageComponent: Registration {
public func registerItems() {
keyPathToName[\MyPageDependency.fetchMyProfileUseCase] = "fetchMyProfileUseCase-any FetchMyProfileUseCase"
keyPathToName[\MyPageDependency.logoutUseCase] = "logoutUseCase-any LogoutUseCase"
keyPathToName[\MyPageDependency.withdrawalUseCase] = "withdrawalUseCase-any WithdrawalUseCase"
keyPathToName[\MyPageDependency.changeProfileComponent] = "changeProfileComponent-ChangeProfileComponent"
keyPathToName[\MyPageDependency.rewardPointDetailComponent] = "rewardPointDetailComponent-RewardPointDetailComponent"
keyPathToName[\MyPageDependency.checkPasswordComponent] = "checkPasswordComponent-CheckPasswordComponent"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import NeedleFoundation
public protocol MyPageDependency: Dependency {
var fetchMyProfileUseCase: any FetchMyProfileUseCase { get }
var logoutUseCase: any LogoutUseCase { get }
var withdrawalUseCase: any WithdrawalUseCase { get }
var changeProfileComponent: ChangeProfileComponent { get }
var rewardPointDetailComponent: RewardPointDetailComponent { get }
var checkPasswordComponent: CheckPasswordComponent { get }
Expand All @@ -16,7 +17,8 @@ public final class MyPageComponent: Component<MyPageDependency> {
MyPageView(
viewModel: .init(
fetchMyProfileUseCase: self.dependency.fetchMyProfileUseCase,
logoutUseCase: self.dependency.logoutUseCase
logoutUseCase: self.dependency.logoutUseCase,
withdrawalUseCase: self.dependency.withdrawalUseCase
),
changeProfileComponent: self.dependency.changeProfileComponent,
rewardPointDetailComponent: self.dependency.rewardPointDetailComponent,
Expand Down
20 changes: 20 additions & 0 deletions Projects/Features/MyPageFeature/Sources/MyPage/MyPageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,19 @@ struct MyPageView: View {
.dmsShadow()
}

VStack(alignment: .leading, spacing: 0) {
myPageOptionRowCardView(title: "회원 탈퇴")
.dmsFont(.body(.body2), color: .GrayScale.gray6)
.onTapGesture(perform: viewModel.withdrawalButtonDidTap)
.cornerRadius(10)
}
.frame(maxWidth: .infinity)
.background {
RoundedRectangle(cornerRadius: 10)
.fill(Color.GrayScale.gray1)
.dmsShadow(style: .surface)
}

Spacer()
}
.padding(.horizontal, 24)
Expand All @@ -145,6 +158,13 @@ struct MyPageView: View {
Text("정말 로그아웃 하시겠습니까?")
.dmsFont(.body(.body2), color: .GrayScale.gray6)
}
.alert("", isPresented: $viewModel.isPresentedWithdrawalAlert) {
Button("취소", role: .cancel) {}
Button("탈퇴", role: .destructive, action: viewModel.confirmWithdrawalButtonDidTap)
} message: {
Text("정말 회원 탈퇴 하시겠습니까?")
.dmsFont(.body(.body2), color: .GrayScale.gray6)
}
.onChange(of: viewModel.isNavigateChangeProfile) { newValue in
withAnimation {
tabbarHidden.wrappedValue = newValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,21 @@ final class MyPageViewModel: BaseViewModel {
@Published var isNavigateChangeProfile = false
@Published var isNavigateChangePassword = false
@Published var isNavigateRewardPointDetail = false
@Published var isPresentedWithdrawalAlert = false
@Published var isSuccessLogout = false

private let fetchMyProfileUseCase: any FetchMyProfileUseCase
private let logoutUseCase: any LogoutUseCase
private let withdrawalUseCase: any WithdrawalUseCase

public init(
fetchMyProfileUseCase: any FetchMyProfileUseCase,
logoutUseCase: any LogoutUseCase
logoutUseCase: any LogoutUseCase,
withdrawalUseCase: any WithdrawalUseCase
) {
self.fetchMyProfileUseCase = fetchMyProfileUseCase
self.logoutUseCase = logoutUseCase
self.withdrawalUseCase = withdrawalUseCase
}

func onAppear() {
Expand All @@ -41,4 +45,14 @@ final class MyPageViewModel: BaseViewModel {
func profileImageDidTap() {
isNavigateChangeProfile = true
}

func withdrawalButtonDidTap() {
isPresentedWithdrawalAlert = true
}

func confirmWithdrawalButtonDidTap() {
addCancellable(withdrawalUseCase.execute()) { [weak self] _ in
self?.isSuccessLogout = true
}
}
}
4 changes: 4 additions & 0 deletions Projects/Modules/ErrorModule/Sources/DmsError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public enum DmsError: Error {
// MARK: - Users
case currentPasswordMismatch
case photoCapacityIsLarge
case failedToWithdrawal

// MARK: - StudyRooms
case seatIsAlreadyExist
Expand Down Expand Up @@ -120,6 +121,9 @@ extension DmsError: LocalizedError {
case .photoCapacityIsLarge:
return "사진의 최대 용량을 초과했습니다."

case .failedToWithdrawal:
return "회원탈퇴에 실패했습니다. 잠시 후 다시 시도해주세요."

// MARK: - StudyRooms
case .seatIsAlreadyExist:
return "이미 신청된 자리입니다"
Expand Down
17 changes: 16 additions & 1 deletion Projects/Services/APIKit/Sources/StudentsAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public enum StudentsAPI {
case checkExistGradeClassNumber(CheckExistGradeClassNumberRequestDTO)
case fetchMyProfile
case changeProfileImage(url: String)
case withdrawal
}

extension StudentsAPI: DmsAPI {
Expand Down Expand Up @@ -44,6 +45,9 @@ extension StudentsAPI: DmsAPI {

case .changeProfileImage:
return "/profile"

case .withdrawal:
return ""
}
}

Expand All @@ -57,6 +61,9 @@ extension StudentsAPI: DmsAPI {

case .renewalPassword, .changeProfileImage:
return .patch

case .withdrawal:
return .delete
}
}

Expand Down Expand Up @@ -107,7 +114,7 @@ extension StudentsAPI: DmsAPI {

public var jwtTokenType: JwtTokenType {
switch self {
case .fetchMyProfile, .changeProfileImage:
case .fetchMyProfile, .changeProfileImage, .withdrawal:
return .accessToken

default:
Expand Down Expand Up @@ -173,6 +180,14 @@ extension StudentsAPI: DmsAPI {
401: .tokenExpired,
500: .internalServerError
]

case .withdrawal:
return [
400: .badRequest,
401: .tokenExpired,
404: .failedToWithdrawal,
500: .internalServerError
]
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ public struct StudentsRepositoryImpl: StudentsRepository {
public func changeProfileImage(url: String) -> AnyPublisher<Void, DmsError> {
remoteStudentsDataSource.changeProfileImage(url: url)
}

public func withdrawal() -> AnyPublisher<Void, DmsError> {
remoteStudentsDataSource.withdrawal()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,10 @@ public struct StudentsRepositoryStub: StudentsRepository {
.setFailureType(to: DmsError.self)
.eraseToAnyPublisher()
}

public func withdrawal() -> AnyPublisher<Void, DmsError> {
Just(())
.setFailureType(to: DmsError.self)
.eraseToAnyPublisher()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Combine
import DomainModule
import ErrorModule

public struct WithdrawalUseCaseImpl: WithdrawalUseCase {
private let studentsRepository: any StudentsRepository

public init(studentsRepository: any StudentsRepository) {
self.studentsRepository = studentsRepository
}

public func execute() -> AnyPublisher<Void, DmsError> {
studentsRepository.withdrawal()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ public protocol StudentsRepository {
func checkExistGradeClassNumber(req: CheckExistGradeClassNumberRequestDTO) -> AnyPublisher<String, DmsError>
func fetchMyProfile() -> AnyPublisher<MyProfileEntity, DmsError>
func changeProfileImage(url: String) -> AnyPublisher<Void, DmsError>
func withdrawal() -> AnyPublisher<Void, DmsError>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Combine
import ErrorModule

public protocol WithdrawalUseCase {
func execute() -> AnyPublisher<Void, DmsError>
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ public final class RemoteStudentsDataSourceImpl: BaseRemoteDataSource<StudentsAP
public func changeProfileImage(url: String) -> AnyPublisher<Void, DmsError> {
request(.changeProfileImage(url: url))
}

public func withdrawal() -> AnyPublisher<Void, DmsError> {
request(.withdrawal)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ public protocol RemoteStudentsDataSource {
func checkExistGradeClassNumber(req: CheckExistGradeClassNumberRequestDTO) -> AnyPublisher<String, DmsError>
func fetchMyProfile() -> AnyPublisher<MyProfileEntity, DmsError>
func changeProfileImage(url: String) -> AnyPublisher<Void, DmsError>
func withdrawal() -> AnyPublisher<Void, DmsError>
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,10 @@ public struct RemoteStudentsDataSourceStub: RemoteStudentsDataSource {
.setFailureType(to: DmsError.self)
.eraseToAnyPublisher()
}

public func withdrawal() -> AnyPublisher<Void, DmsError> {
Just(())
.setFailureType(to: DmsError.self)
.eraseToAnyPublisher()
}
}