Skip to content

Instantly share code, notes, and snippets.

@photizzo
Created August 15, 2020 18:16
Show Gist options
  • Save photizzo/e926f8245eb0e1188d721e9b83784892 to your computer and use it in GitHub Desktop.
Save photizzo/e926f8245eb0e1188d721e9b83784892 to your computer and use it in GitHub Desktop.
//
// HomeViewModel.swift
// Okukk
//
// Created by Ememobong Akpanekpo on 06/02/2020.
// Copyright © 2020 AltaLabs. All rights reserved.
//
import Domain
import RxCocoa
import RxSwift
import UIKit
class HomeViewModel: ViewModelType {
let navigator: HomeNavigator
let instrumentUseCase: InstrumentUseCase
let userUserCase: UsersUseCase
let cacheUserCase: UsersUseCase
let mutualFundUseCase: MutualFundUseCase
let mutualFundNavigator: MutualFundsNavigator
var offset = 0
var currentCount = 0
var isLoading = false
var mutualFunds: [MutualFund] = []
init(navigator: HomeNavigator,
instrumentUseCase: InstrumentUseCase,
userUserCase: UsersUseCase,
cacheUserCase: UsersUseCase,
mutualFundNavigator: MutualFundsNavigator,
mutualFundUseCase: MutualFundUseCase) {
self.navigator = navigator
self.instrumentUseCase = instrumentUseCase
self.userUserCase = userUserCase
self.cacheUserCase = cacheUserCase
self.mutualFundNavigator = mutualFundNavigator
self.mutualFundUseCase = mutualFundUseCase
}
struct Input {
let trigger: Driver<Void>
let toSearchTrigger: Driver<Void>
let toBuySingleStock: Driver<IndexPath>
let toAddBVNTrigger: Driver<Void>
let addCardTrigger: Driver<AddUserCardParam>
let addWatchListTrigger: Driver<Instrument>
let toSavingsTrigger: Driver<Void>
let selectedMutualFundTrigger: Driver<IndexPath>
let loadMoreData: Driver<Void>
let completeAccount: Driver<Void>
}
struct Output {
let fetching: Driver<Bool>
let error: Driver<Error>
let watchListFetching: Driver<Bool>
let watchListerror: Driver<Error>
let toSearch: Driver<Void>
let toBuySingleStock: Driver<Void>
let allInstruments: Driver<[Instrument]>
let userWallet: Driver<[HomeUserWallet]>
let toAddBVN: Driver<Void>
let user: Driver<User.Data>
let toAddUserCard: Driver<Void>
let addWatchListCard: Driver<Void>
let toSavings: Driver<Void>
let filteredMutualFund: Driver<[MutualFund]>
let toMutualFundDetails: Driver<MutualFund>
let toCompleteAccount: Driver<Void>
}
// swiftlint:disable function_body_length
// swiftlint:disable cyclomatic_complexity
func transform(input: HomeViewModel.Input) -> HomeViewModel.Output {
let activityIndicator = ActivityIndicator()
let errorTracker = ErrorTracker()
let fetching = activityIndicator.asDriver()
let errors = errorTracker.asDriver()
let watchListActivityIndicator = ActivityIndicator()
let watchListErrorTracker = ErrorTracker()
let watchListFetching = watchListActivityIndicator.asDriver()
let watchListErrors = watchListErrorTracker.asDriver()
let toSearch = input.toSearchTrigger.do(onNext: { [weak self] in
self?.navigator.toSearchStocks()
})
let allInstruments = input.trigger
.flatMapLatest { (_) -> Driver<[Instrument]> in
self.instrumentUseCase.getInstruments(offset: 0).take(1)
.trackActivity(activityIndicator)
.trackError(errorTracker)
.asDriverOnErrorJustComplete()
}
let toBuySingleStock = input.toBuySingleStock.withLatestFrom(allInstruments) {(index, allInstruments) -> Void in
let instrument = allInstruments[index.row]
self.navigator.toBuySingleStockScene(instrument: instrument, portfolio: nil, watchList: nil)
}
let userWallet = input.trigger
.flatMapLatest { (_) -> Driver<[HomeUserWallet]> in
self.userUserCase.fetchUserWallet()
.map({ data in
var normalWallet: HomeUserWallet = HomeUserWallet(type: WalletType.globalWallet, globalValue: 0.0, localValue: 0.0)
var giftCardWallet: HomeUserWallet = HomeUserWallet(type: WalletType.globalGiftCardWallet, globalValue: 0.0, localValue: 0.0)
var mutualFundWallet: HomeUserWallet = HomeUserWallet(type: WalletType.mutualFundGlobalWallet, globalValue: 0.0, localValue: 0.0)
var stockWallet: HomeUserWallet = HomeUserWallet(type: WalletType.stocksGlobalWallet, globalValue: 0.0, localValue: 0.0)
var savingsWallet: HomeUserWallet = HomeUserWallet(type: WalletType.savingsGlobalWallet, globalValue: 0.0, localValue: 0.0)
let driveWallet: HomeUserWallet = HomeUserWallet(type: nil, globalValue: 0.0, localValue: 0.0, driveBalance: data.driveWealthWallet.availableBalane, driveTrading: data.driveWealthWallet.tradingBalance, driveWithdrawal: data.driveWealthWallet.withdrawal)
data.otherWallets.forEach { wallet in
switch wallet.walletType {
case .globalWallet:
normalWallet.globalValue = wallet.balance
case .localWallet:
normalWallet.localValue = wallet.balance
case .globalGiftCardWallet:
giftCardWallet.globalValue = wallet.balance
case .localGiftCardWallet:
giftCardWallet.localValue = wallet.balance
case .mutualFundLocalWallet:
mutualFundWallet.localValue = wallet.balance
case .mutualFundGlobalWallet:
mutualFundWallet.globalValue = wallet.balance
case .stocksLocalWallet:
stockWallet.localValue = wallet.balance
case .stocksGlobalWallet:
stockWallet.globalValue = wallet.balance
case .savingsLocalWallet:
savingsWallet.localValue = wallet.balance
case .savingsGlobalWallet:
savingsWallet.globalValue = wallet.balance
}
}
return [normalWallet, driveWallet, giftCardWallet, mutualFundWallet, stockWallet, savingsWallet]
})
.trackError(errorTracker)
.asDriverOnErrorJustComplete()
}
let user = input.trigger
.flatMapLatest { _ in
self.userUserCase.fetchUser(id: "")
.asDriverOnErrorJustComplete()
}
// swiftlint:disable force_cast
let toAddBVN = input.toAddBVNTrigger
.do(onNext: { _ in
self.navigator.toAddBVN(navigationController: (self.navigator as! DefaultHomeNavigator).navigationController)
})
let toCompleteAccount = input.completeAccount.withLatestFrom(user)
.map { user -> Void in
if !user.isBVNValidated && !user.canTrade {
return self.navigator.toAddBVN(navigationController: (self.navigator as! DefaultHomeNavigator).navigationController)
} else {
return AppDelegate.shared.rootViewController.showUserProfileScenes()
}
}
// swiftlint:enable force_cast
let toAddUserCard = input.addCardTrigger
.flatMapLatest { (addUserCardParam) -> Driver<Void> in
self.userUserCase.addUserCard(param: addUserCardParam)
.trackActivity(activityIndicator)
.trackError(errorTracker)
.asDriverOnErrorJustComplete()
}.mapToVoid()
.do(onNext: { _ in
self.navigator.showSuccessfulCardTransaction()
})
let addWatchList = input.addWatchListTrigger
.flatMapLatest { (instrument) -> Driver<Void> in
self.instrumentUseCase.addToWishList(param: instrument)
.trackActivity(watchListActivityIndicator)
.trackError(watchListErrorTracker)
.asDriverOnErrorJustComplete()
}.mapToVoid()
let toSavings = input.toSavingsTrigger
.map { _ in
self.navigator.toCreateSavings()
}
let allMutualFunds = Driver.combineLatest(
self.mutualFundUseCase.getMutualFunds(offset: offset, param: GetMutualFundParam(currency: Currency.ngn))
.trackActivity(watchListActivityIndicator)
.trackError(watchListErrorTracker)
.asDriverOnErrorJustComplete(),
self.mutualFundUseCase.getMutualFunds(offset: offset, param: GetMutualFundParam(currency: Currency.usd))
.trackActivity(watchListActivityIndicator)
.trackError(watchListErrorTracker)
.asDriverOnErrorJustComplete())
.flatMap { params -> Driver<[MutualFund]> in
var funds = params.0
params.1.forEach({ fund in
funds.append(fund)
})
return Driver.just(funds.sorted(by: { (lhs, rhs) -> Bool in
lhs.name < rhs.name
}))
}
let filteredMutualFund = Driver.merge(input.trigger, input.loadMoreData).flatMapLatest { _ -> Driver<[MutualFund]> in
return allMutualFunds
.flatMap({ data -> Driver<[MutualFund]> in
let countBefore = self.mutualFunds.count
data.forEach({ fund in
self.mutualFunds.append(fund)
})
if countBefore < self.mutualFunds.removingDuplicates().count {
print("offset: \(self.offset)")
self.offset += 1
self.currentCount = data.count
self.isLoading = false
}
return Driver.just(self.mutualFunds.removingDuplicates())
})
}
let selectedMutualFund = input.selectedMutualFundTrigger.withLatestFrom(filteredMutualFund) { (indexPath, selectedMutualFund) -> MutualFund in
selectedMutualFund[indexPath.row]
}.do(onNext: { mutualFund in
self.mutualFundNavigator.toMutualFundsDetails(mutualFund: mutualFund)
})
return Output(fetching: fetching,
error: errors,
watchListFetching: watchListFetching,
watchListerror: watchListErrors,
toSearch: toSearch,
toBuySingleStock: toBuySingleStock,
allInstruments: allInstruments,
userWallet: userWallet,
toAddBVN: toAddBVN,
user: user,
toAddUserCard: toAddUserCard,
addWatchListCard: addWatchList,
toSavings: toSavings,
filteredMutualFund: filteredMutualFund,
toMutualFundDetails: selectedMutualFund,
toCompleteAccount: toCompleteAccount)
}
// swiftlint:enable cyclomatic_complexity
// swiftlint:enable function_body_length
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment