-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWithdrawAuthViewModel.swift
More file actions
107 lines (89 loc) · 2.85 KB
/
WithdrawAuthViewModel.swift
File metadata and controls
107 lines (89 loc) · 2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//
// WithdrawAuthViewModel.swift
// Presentation
//
// Created by 임우섭 on 2/15/25.
// Copyright © 2025 com.photi. All rights reserved.
//
import Foundation
import RxCocoa
import RxSwift
import Entity
import UseCase
protocol WithdrawAuthCoordinatable: AnyObject {
func withdrawalSucceed()
func didTapBackButton()
func authenticatedFailed()
}
protocol WithdrawAuthViewModelType: AnyObject {
associatedtype Input
associatedtype Output
var disposeBag: DisposeBag { get }
var coordinator: WithdrawAuthCoordinatable? { get set }
}
final class WithdrawAuthViewModel: WithdrawAuthViewModelType {
let disposeBag = DisposeBag()
weak var coordinator: WithdrawAuthCoordinatable?
private let useCase: ProfileEditUseCase
private let didFailPasswordVerificationRelay = PublishRelay<Void>()
private let networkUnstableRelay = PublishRelay<Void>()
// MARK: - Input
struct Input {
let didTapBackButton: ControlEvent<Void>
let password: ControlProperty<String>
let didTapWithdrawButton: ControlEvent<Void>
}
// MARK: - Output
struct Output {
let didFailPasswordVerification: Signal<Void>
let networkUnstable: Signal<Void>
let isEnabledWithdrawButton: Driver<Bool>
}
// MARK: - Initializers
init(useCase: ProfileEditUseCase) {
self.useCase = useCase
}
func transform(input: Input) -> Output {
input.didTapBackButton
.bind(with: self) { owner, _ in
owner.coordinator?.didTapBackButton()
}
.disposed(by: disposeBag)
let isEnabledWithdrawButton = input.password.map { $0.isValidPassword }
input.didTapWithdrawButton
.withLatestFrom(input.password)
.bind(with: self) { owner, password in
Task { await owner.withdraw(password: password) }
}
.disposed(by: disposeBag)
return Output(
didFailPasswordVerification: didFailPasswordVerificationRelay.asSignal(),
networkUnstable: networkUnstableRelay.asSignal(),
isEnabledWithdrawButton: isEnabledWithdrawButton.asDriver(onErrorJustReturn: false)
)
}
}
// MARK: - API Methods
private extension WithdrawAuthViewModel {
@MainActor func withdraw(password: String) async {
do {
try await useCase.withdraw(with: .password(password))
coordinator?.withdrawalSucceed()
} catch {
requestFailed(with: error)
}
}
func requestFailed(with error: Error) {
guard let error = error as? APIError else { return networkUnstableRelay.accept(()) }
switch error {
case .authenticationFailed:
coordinator?.authenticatedFailed()
case let .myPageFailed(reason) where reason == .loginUnAuthenticated:
didFailPasswordVerificationRelay.accept(())
case let .myPageFailed(reason) where reason == .userNotFound:
coordinator?.authenticatedFailed()
default:
networkUnstableRelay.accept(())
}
}
}