Files
sodalive-ios/SodaLive/Sources/V2/Gift/RecipientAddress/GiftRecipientAddressViewModel.swift
T

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
}
}