|
|
// // ExistingUserKycPresenter.swift // GME Remit // // Created by Shiran on 8/18/20. //Copyright © 2020 Gobal Money Express Co. Ltd. All rights reserved. //
import RxSwift import RxCocoa import CoreLocation
class ExistingUserKycPresenter { // MARK: Properties enum Step: Int { case innerStep1 case innerStep2 } var interactor: ExistingUserKycInteractorInput? var wireframe: ExistingUserKycWireframeInput? struct Input { let viewWillAppear: Driver<Bool> let sendLocation: Driver<CLLocation>
let sourceOfFund: Driver<KeyValue?> let occupation: Driver<KeyValue?> let monthlyIncome: Driver<String> let businessType: Driver<KeyValue?> let visaStatus: Driver<KeyValue?> let idType: Driver<KeyValue?> let purpose: Driver<KeyValue?> let employerName: Driver<String> let mobile: Driver<String> let email: Driver<String> let address: Driver<String>
let isValidPersonalInfo: Driver<Bool> let personalInfoSave: Driver<Void> let editingPersonalInfo: Driver<Void> let frontIDImage: Driver<String?> let backIDImage: Driver<String?> let sideIDImage: Driver<String?> let isValidPictures: Driver<Bool> let editingPictureInfo: Driver<Void> let submit: Driver<Void> } struct Output { let isError: Driver<Error> let isProgress: Driver<Bool> let gpsAddress: Driver<String> let model: Driver<KYCInfoModel> let idTypes: Driver<[KeyValue]?> let purposes: Driver<[KeyValue]?> let busniessType: Driver<[KeyValue]?> let sourceOfFund: Driver<[KeyValue]?> let occupation: Driver<[KeyValue]?> // let monthlyIncome: Driver<[KeyValue]?> let visaStatus: Driver<[KeyValue]?> let isSetPersonalInfoModel: Driver<Bool> let isSetPictureInfoModel: Driver<Bool> let storePersonalSuccess: Driver<Bool> let storedSuccess: Driver<String> } private let disposeBag = DisposeBag() private let progressLinker = PublishSubject<Bool>() private let errorLinker = PublishSubject<Error>() private let gpsAddress = PublishSubject<String>() private let model = PublishSubject<KYCInfoModel>() private var storedPersonalInfo = PublishSubject<PersonalInfoModel?>() private var storedPictureInformation = PublishSubject<PictureInfoModel?>() private var storedPersonalSuccess = PublishSubject<String?>() private let storedSuccess = PublishSubject<String>()
func transform(input: Input) -> Output { let newPicturesInfo = Driver.combineLatest( input.isValidPictures, input.frontIDImage, input.backIDImage, input.sideIDImage ).map { (isValid, frontIdImage, backIdImage, sideIdImage) -> PictureInfoModel? in return isValid ? PictureInfoModel( idFront: frontIdImage, idBack: backIdImage, idSide: sideIdImage, additionalId: nil, facePicture: nil, additionalIdBack: nil ) : nil } let newPersonalInfo = Driver.combineLatest( input.isValidPersonalInfo, input.idType, input.visaStatus, input.occupation, input.purpose, Driver.combineLatest( input.employerName, input.sourceOfFund, input.monthlyIncome, input.mobile, input.businessType, input.email, input.address, model.map{$0.personalInformation?.nativeCountry}.asDriverOnErrorJustComplete() ).map({ (employerName, sourceOfFund, monthlyIncome, mobile, businessType, email, address, nativeCountry) -> PersonalInfoModel in return PersonalInfoModel( email: email, address: address, visaStatus: nil, sourceOfFund: sourceOfFund?.id, monthlyIncome: monthlyIncome, mobile: mobile, idType: nil, additionalIdType: nil, businessType: businessType?.id, nativeCountry: nativeCountry, employeerName: employerName, occupation: nil, purpose: nil, isBackIDRequired: nil ) }) ).map { (isValid, idType, visaStatus, occupation, purpose, info) -> PersonalInfoModel? in if isValid{ var personalInfo = info personalInfo.idType = idType?.id personalInfo.visaStatus = visaStatus?.id personalInfo.occupation = occupation?.id personalInfo.purpose = purpose?.id return personalInfo } return nil } let isSetPersonalInformation = Driver .combineLatest(input.isValidPersonalInfo, storedPersonalInfo.asDriverOnErrorJustComplete()) .map { $0 && $1 != nil } let isSetPictureInformation = Driver .combineLatest(input.isValidPictures, storedPictureInformation.asDriverOnErrorJustComplete()) .map {$0 && $1 != nil} let storePersonalSuccess = Driver .combineLatest(input.isValidPersonalInfo, storedPersonalSuccess.asDriverOnErrorJustComplete()) .map {$0 && $1 != nil} input.viewWillAppear.drive(onNext: { [weak self] (value) in self?.progressLinker.onNext(value) self?.interactor?.fetchInformation() }).disposed(by: disposeBag) input.sendLocation.drive(onNext: { [weak self] in self?.progressLinker.onNext(true) let geocoder = CLGeocoder() let locale = Locale(identifier: "en-US") geocoder.reverseGeocodeLocation($0, preferredLocale: locale) {(placemarks, error) in if let error = error { self?.progressLinker.onNext(false) self?.errorLinker.onNext(error) } if let address: [CLPlacemark] = placemarks { let name = address.last?.name ?? "" let locality = address.last?.locality ?? "" self?.progressLinker.onNext(false) let mergedAddress = "\(name) \(locality)"//.extract(regex: "[A-Z0-9a-z\\s]") self?.gpsAddress.onNext(mergedAddress) } } }).disposed(by: disposeBag) input.editingPersonalInfo .withLatestFrom(newPersonalInfo) { $1 } .withLatestFrom(storedPersonalInfo.asDriverOnErrorJustComplete()) {($0, $1)} .drive(onNext: {[weak self] in guard let new = $0, let stored = $1 else { return } if new != stored { self?.storedPersonalInfo.onNext(nil) } }) .disposed(by: disposeBag) input.editingPictureInfo .withLatestFrom(newPicturesInfo) { $1 } .withLatestFrom(storedPictureInformation.asDriverOnErrorJustComplete()) {($0, $1)} .drive(onNext: {[weak self] in guard let new = $0, let stored = $1 else { return } if new != stored { self?.storedPictureInformation.onNext(nil) } }) .disposed(by: disposeBag) input.personalInfoSave .withLatestFrom(newPersonalInfo) { $1 } .drive(onNext: {[weak self] in let saveModel = KYCSaveInformation( type: Step.innerStep1.rawValue, personalInformation: $0, pictures: nil ) self?.progressLinker.onNext(true) self?.interactor?.saveInformation(with: saveModel) }).disposed(by: disposeBag) input.submit .withLatestFrom(newPersonalInfo) { $1 } .withLatestFrom(newPicturesInfo) { ($0, $1) } .drive(onNext: {[weak self] in let saveModel = KYCSaveInformation( type: Step.innerStep2.rawValue, personalInformation: $0, pictures: $1 ) self?.progressLinker.onNext(true) self?.interactor?.saveInformation(with: saveModel) }).disposed(by: disposeBag) return Output( isError: errorLinker.asDriverOnErrorJustComplete(), isProgress: progressLinker.asDriverOnErrorJustComplete(), gpsAddress: gpsAddress.asDriverOnErrorJustComplete(), model: model.asDriverOnErrorJustComplete(), idTypes: model.map {$0.idType}.asDriverOnErrorJustComplete(), purposes: model.map {$0.purpose}.asDriverOnErrorJustComplete(), busniessType: model.map {$0.businessType}.asDriverOnErrorJustComplete(), sourceOfFund: model.map {$0.sourceOfFund}.asDriverOnErrorJustComplete(), occupation: model.map {$0.occupation}.asDriverOnErrorJustComplete(), // monthlyIncome: model.map {$0.monthlyIncome}.asDriverOnErrorJustComplete(), visaStatus: model.map {$0.visaStatus}.asDriverOnErrorJustComplete(), isSetPersonalInfoModel: isSetPersonalInformation, isSetPictureInfoModel: isSetPictureInformation, storePersonalSuccess: storePersonalSuccess, storedSuccess: storedSuccess.asDriverOnErrorJustComplete() ) } }
// MARK: ExistingUserKyc interactor output interface
extension ExistingUserKycPresenter: ExistingUserKycInteractorOutput { func setModel(with model: KYCInfoModel) { progressLinker.onNext(false) self.model.onNext(model) guard let personalInformation = model.personalInformation, !personalInformation.isHasEmptyValue() else { storedPersonalInfo.onNext(nil) return } storedPersonalInfo.onNext(model.personalInformation) guard let pictures = model.pictures, !pictures.isHasEmptyValue() else { storedPictureInformation.onNext(nil) return } storedPictureInformation.onNext(pictures) } func setSaveResult(with storedModel: KYCSaveInformation?, message: String) { progressLinker.onNext(false) guard let storedModel = storedModel, let type = Step(rawValue: storedModel.type) else { return } switch type { case .innerStep1: storedPersonalInfo.onNext(storedModel.personalInformation) storedPersonalSuccess.onNext(message) DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.storedPersonalSuccess.onNext(nil) } case .innerStep2: storedPictureInformation.onNext(storedModel.pictures) storedSuccess.onNext(message) } } func setError(with error: Error) { progressLinker.onNext(false) errorLinker.onNext(error)
} }
|