99 lines
4.0 KiB
Swift
99 lines
4.0 KiB
Swift
import Combine
|
|
import Foundation
|
|
|
|
final class GiftRecipientAddressViewModel: ObservableObject {
|
|
@Published var recipientName: String = ""
|
|
@Published var recipientPhoneNumber: String = ""
|
|
@Published var recipientZipCode: String = ""
|
|
@Published var recipientAddress: String = ""
|
|
@Published var recipientAddressDetail: String = ""
|
|
@Published var recipientTermsAgreed: Bool = false
|
|
@Published var recipientPrivacyAgreed: Bool = false
|
|
|
|
@Published private(set) var isSubmitting = false
|
|
@Published var errorMessage = ""
|
|
@Published var isShowPopup = false
|
|
@Published var isShowSuccessToast = false
|
|
let successMessage = "배송지 입력 완료"
|
|
|
|
private let applicationNo: String
|
|
private let onSubmitted: () -> Void
|
|
private let repository = GiftRepository()
|
|
private var mutationSubscription: AnyCancellable?
|
|
@Published private(set) var hasSubmitted = false
|
|
private var hasNotifiedSubmission = false
|
|
|
|
init(applicationNo: String, onSubmitted: @escaping () -> Void) {
|
|
self.applicationNo = applicationNo
|
|
self.onSubmitted = onSubmitted
|
|
}
|
|
|
|
var canSubmit: Bool {
|
|
!isSubmitting && !hasSubmitted && recipientTermsAgreed && recipientPrivacyAgreed
|
|
&& GiftContactInputRule.name.acceptsSubmission(recipientName)
|
|
&& GiftContactInputRule.phoneNumber.acceptsSubmission(recipientPhoneNumber)
|
|
&& [recipientZipCode, recipientAddress].allSatisfy {
|
|
!$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
|
}
|
|
}
|
|
|
|
func submit() {
|
|
guard canSubmit else { return }
|
|
|
|
isSubmitting = true
|
|
errorMessage = ""
|
|
isShowPopup = false
|
|
|
|
let request = SubmitGiftRecipientAddressRequest(
|
|
recipientName: recipientName.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
recipientPhoneNumber: recipientPhoneNumber.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
recipientZipCode: recipientZipCode.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
recipientAddress: recipientAddress.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
recipientAddressDetail: recipientAddressDetail.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
recipientTermsAgreed: recipientTermsAgreed,
|
|
recipientPrivacyAgreed: recipientPrivacyAgreed
|
|
)
|
|
mutationSubscription = repository.submitRecipientAddress(applicationNo: applicationNo, request: request)
|
|
.receive(on: DispatchQueue.main)
|
|
.sink { [weak self] result in
|
|
guard let self, !self.hasSubmitted else { return }
|
|
if case .failure(let error) = result {
|
|
self.finishFailure(data: error.response?.data)
|
|
}
|
|
} receiveValue: { [weak self] response in
|
|
guard let self, !self.hasSubmitted else { return }
|
|
do {
|
|
let decoded = try JSONDecoder().decode(ApiResponseWithoutData.self, from: response.data)
|
|
guard decoded.success else {
|
|
self.finishFailure(data: response.data)
|
|
return
|
|
}
|
|
self.hasSubmitted = true
|
|
self.isSubmitting = false
|
|
self.isShowSuccessToast = true
|
|
} catch {
|
|
self.finishFailure(data: response.data)
|
|
}
|
|
}
|
|
}
|
|
|
|
func successToastDidDismiss() {
|
|
guard hasSubmitted, !isShowSuccessToast, !hasNotifiedSubmission else { return }
|
|
|
|
hasNotifiedSubmission = true
|
|
onSubmitted()
|
|
}
|
|
|
|
private func finishFailure(data: Data?) {
|
|
struct ErrorResponse: Decodable {
|
|
let message: String?
|
|
}
|
|
|
|
let decoded = data.flatMap { try? JSONDecoder().decode(ErrorResponse.self, from: $0) }
|
|
let message = decoded?.message?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
|
isSubmitting = false
|
|
errorMessage = message.isEmpty ? I18n.Common.commonError : message
|
|
isShowPopup = true
|
|
}
|
|
}
|