You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

542 lines
17 KiB

5 years ago
6 years ago
6 years ago
  1. //
  2. // ExchangeRatesViewController.swift
  3. // GMERemittance
  4. //
  5. // Created by gme_2 on 24/08/2018.
  6. //Copyright © 2018 Gobal Money Express Co. Ltd. All rights reserved.
  7. //
  8. import UIKit
  9. import Hex
  10. enum PaymentMode: String {
  11. case cashDelivery = "1"
  12. case bankDeposite = "2"
  13. case homeDelivery = "12"
  14. case mobileWallet = "13"
  15. case cardPayment = "14"
  16. }
  17. class ExchangeRatesViewController: UIViewController {
  18. struct Constants {
  19. let transferFeeDetailText = StringConstants().transferFeeDetailText
  20. let currentExchangeRateText = StringConstants().currentExchangeRateText
  21. let paymentModeHeightConstant: CGFloat = 154
  22. let title = StringConstants().title
  23. }
  24. struct StringConstants {
  25. let selectPaymentModeText = ""
  26. let youSendText = "you_send_text".localized()
  27. let recepientGetsText = "receipient_gets_text".localized()
  28. let calculate = "calculate_text".localized()
  29. let title = "todays_rate_text".localized()
  30. let currentExchangeRateText = "current_exchange_rate_text".localized()
  31. let transferFeeDetailText = "transfer_fee_included_text".localized()
  32. }
  33. struct ApiConstants {
  34. static let recieverCountryId = "pCountry"
  35. static let senderCurrency = "sCurrency"
  36. static let recieverCurrency = "pCurrency"
  37. static let senderAmount = "cAmount"
  38. static let recieverAmount = "pAmount"
  39. static let paymentMethod = "serviceType"
  40. static let calcBy = "calcBy"
  41. static let recieverCountryName = "pCountryName"
  42. static let senderCountryId = "sCountry"
  43. }
  44. // MARK: IBOutlets
  45. @IBOutlet weak var scrollView: UIScrollView!
  46. @IBOutlet weak var collectionView: UICollectionView!
  47. @IBOutlet weak var exchangeBackground1: UIView!
  48. @IBOutlet weak var exchangeBackground2: UIView!
  49. @IBOutlet weak var dropDownImageView: UIImageView!
  50. @IBOutlet weak var backgroundViewCountryLabel1: UIView!
  51. @IBOutlet weak var backgroundViewCountryLabel2: UIView!
  52. @IBOutlet weak var countryListStackView: UIStackView!
  53. @IBOutlet weak var countryCodeLabel: UILabel!
  54. @IBOutlet weak var countryFlagImage: UIImageView!
  55. @IBOutlet weak var paymentModeStackViewConstraint: NSLayoutConstraint!
  56. @IBOutlet weak var paymentModeStackView: UIStackView!
  57. @IBOutlet weak var senderTextField: GMENumberTextField!
  58. @IBOutlet weak var reciepientTextField: GMENumberTextField!
  59. @IBOutlet weak var transferFeeInfoLabel: UILabel!
  60. @IBOutlet weak var exchangeRateInfoLabel: UILabel!
  61. @IBOutlet weak var youSendTitleLabel: UILabel!
  62. @IBOutlet weak var recepientGetsTitleLabel: UILabel!
  63. @IBOutlet weak var selectPaymentModeTitleLabel: UILabel!
  64. @IBOutlet weak var executeButton: UIButton!
  65. @IBOutlet weak var calculatedInfoView: UIView!
  66. @IBOutlet weak var serviceChargeView: UIStackView!
  67. @IBOutlet weak var exchangeRateView: UIStackView!
  68. var presenter: ExchangeRatesModuleInterface?
  69. var countryListTapGuesture: UITapGestureRecognizer?
  70. var selectedPaymentModeIndex = 0
  71. var translated: Bool = false
  72. var nativeCountryCode: String? = "np"
  73. var calcBy = ""
  74. private var exchangeRateModels: [ExchangeRateModel]? {
  75. didSet {
  76. let countryCode = GMEDB.shared.user.string(.countryCode)
  77. if let defaultExchangeRate = exchangeRateModels?.filter({
  78. ($0.countryCode ?? "").lowercased() == countryCode?.lowercased()
  79. }).first {
  80. selectedExchangeRateModel = defaultExchangeRate
  81. } else {
  82. selectedExchangeRateModel = exchangeRateModels?.filter({
  83. ($0.countryCode ?? "").lowercased() == "az"
  84. }).first
  85. }
  86. }
  87. }
  88. private var selectedExchangeRateModel: ExchangeRateModel? {
  89. didSet {
  90. collectionView.reloadData()
  91. let code = selectedExchangeRateModel?.countryCode?.lowercased() ?? "az"
  92. let codeEnum = CountryEnum(rawValue: code)
  93. countryFlagImage.image = codeEnum?.flag
  94. countryCodeLabel.text = selectedExchangeRateModel?.currency
  95. guard let defaultAmount = codeEnum?.getDefaultRecipientAcount(
  96. currency: selectedExchangeRateModel?.currency ?? ""
  97. ) else {
  98. calcBy = "c"
  99. senderTextField.text = codeEnum?.defaultSenderAmount.likeCommaMoney()
  100. reciepientTextField.text = ""
  101. calculateExchangeRate()
  102. return
  103. }
  104. calcBy = "p"
  105. senderTextField.text = ""
  106. reciepientTextField.text = defaultAmount.likeCommaMoney()
  107. calculateExchangeRate()
  108. }
  109. }
  110. private var exchangeRateDetailModel: ExchangeRateDetailModel? {
  111. didSet {
  112. guard let model = exchangeRateDetailModel else {
  113. showExchangeRateInfomation(isHidden: true)
  114. return
  115. }
  116. showExchangeRateInfomation(isHidden: false)
  117. reciepientTextField.text = Utility.getCommaSeperatedStringWithDecimal(
  118. numberString: model.recipientAmount ?? ""
  119. )
  120. senderTextField.text = Utility.getCommaSeperatedStringWithDecimal(
  121. numberString: model.senderAmount ?? ""
  122. )
  123. let transferFee = model.transferFee ?? ""
  124. let currency = model.senderCurrency ?? ""
  125. transferFeeInfoLabel.text =
  126. "-\(transferFee) \(currency) (" + "transfer_fee_included_text".localized() + ")"
  127. let exchangeRate = model.exchangeRate ?? ""
  128. exchangeRateInfoLabel.text = "\(exchangeRate) " + "(" + "current_exchange_rate_text".localized() + ")"
  129. calculatedInfoView.isHidden = false
  130. }
  131. }
  132. // MARK: VC's Life cycle
  133. override func viewDidLoad() {
  134. super.viewDidLoad()
  135. setup()
  136. setupDelegates()
  137. setupNavigation()
  138. self.nativeCountryCode = GMEDB.shared.user.string(.countryCode)
  139. }
  140. override func viewWillAppear(_ animated: Bool) {
  141. super.viewWillAppear(animated)
  142. self.title = Constants().title
  143. presenter?.fetchExchangeRate()
  144. }
  145. override func viewWillDisappear(_ animated: Bool) {
  146. super.viewWillDisappear(animated)
  147. self.view.endEditing(true)
  148. }
  149. // IBActions
  150. @IBAction func calculateExchangeRate(_ sender: Any?) {
  151. calculateExchangeRate()
  152. }
  153. private func calculateExchangeRate() {
  154. let model = ExchangeRateRequestModel(
  155. senderAmount: (senderTextField.text ?? "").stringRemovingComma(),
  156. senderCurrency: "KRW",
  157. senderCountryID: "118",
  158. recipientAmount: (reciepientTextField.text ?? "").stringRemovingComma(),
  159. recipientCurrency: selectedExchangeRateModel?.currency ?? "",
  160. recipientCountryID: selectedExchangeRateModel?.countryId ?? "",
  161. recipientCountry: selectedExchangeRateModel?.country ?? "",
  162. serviceType: selectedExchangeRateModel?
  163. .availableServices?
  164. .elementAt(index: selectedPaymentModeIndex)?.id ?? "",
  165. calcBy: calcBy
  166. )
  167. presenter?.exchangeCalculate(use: model)
  168. }
  169. @objc func showCountryList(_ sender: UITapGestureRecognizer) {
  170. DispatchQueue.main.async {
  171. self.reciepientTextField.resignFirstResponder()
  172. self.senderTextField.resignFirstResponder()
  173. }
  174. TablePresenterWireframe().openWith(
  175. delegate: self,
  176. model: exchangeRateModels,
  177. source: self
  178. )
  179. }
  180. // other function
  181. private func setExchangeRateUI() {
  182. [backgroundViewCountryLabel1, backgroundViewCountryLabel2]
  183. .forEach { $0?.layer.cornerRadius = 5 }
  184. [exchangeBackground1, exchangeBackground2]
  185. .forEach {
  186. $0?.layer.borderWidth = 1
  187. $0?.layer.borderColor = UIColor.themeSeparate.cgColor //init(hex: "#E0E0E0").cgColor
  188. $0?.layer.cornerRadius = 5
  189. }
  190. let dropDownImage = #imageLiteral(resourceName: "dropdown_white").withRenderingMode(UIImage.RenderingMode.alwaysTemplate)
  191. let image = dropDownImage
  192. dropDownImageView.image = image
  193. dropDownImageView.tintColor = UIColor.white
  194. senderTextField.delegate = self
  195. reciepientTextField.delegate = self
  196. }
  197. private func showExchangeRateInfomation(isHidden flag: Bool) {
  198. calculatedInfoView.isHidden = flag
  199. calculatedInfoView.alpha = flag ? 0.0 : 1.0
  200. if !flag {
  201. self.serviceChargeView.isHidden = false
  202. self.exchangeRateView.isHidden = false
  203. let animator = UIViewPropertyAnimator(duration: 0.5, curve: .easeIn) {
  204. self.serviceChargeView.alpha = 1.0
  205. }
  206. animator.addCompletion { _ in
  207. let subAnimator = UIViewPropertyAnimator(duration: 0.5, curve: .easeIn) {
  208. self.exchangeRateView.alpha = 1.0
  209. }
  210. subAnimator.startAnimation()
  211. }
  212. animator.startAnimation()
  213. } else {
  214. serviceChargeView.isHidden = true
  215. serviceChargeView.alpha = 0.0
  216. exchangeRateView.isHidden = true
  217. exchangeRateView.alpha = 0.0
  218. }
  219. }
  220. func showPaymentModeView() {
  221. UIView.animate(withDuration: 0.33) {
  222. self.paymentModeStackViewConstraint.constant = Constants().paymentModeHeightConstant
  223. self.paymentModeStackView.alpha = 1
  224. self.view.layoutIfNeeded()
  225. }
  226. }
  227. private func setupTargets() {
  228. let tapGuesture = UITapGestureRecognizer(target: self, action: #selector(showCurrencyCountryPickerview))
  229. countryListStackView.addGestureRecognizer(tapGuesture)
  230. reciepientTextField.addTarget(
  231. self,
  232. action: #selector(self.textChanged(sender:)),
  233. for: UIControl.Event.editingChanged
  234. )
  235. senderTextField.addTarget(
  236. self,
  237. action: #selector(self.textChanged(sender:)),
  238. for: UIControl.Event.editingChanged
  239. )
  240. }
  241. @objc private func textChanged(sender: UITextField) {
  242. switch sender {
  243. case senderTextField:
  244. reciepientTextField.text = ""
  245. calcBy = "c"
  246. senderTextField.text = Utility.getCommaSeperatedString(numberString: senderTextField.text!)
  247. case reciepientTextField:
  248. senderTextField.text = ""
  249. calcBy = "p"
  250. reciepientTextField.text = Utility.getCommaSeperatedString(numberString: reciepientTextField.text!)
  251. default:
  252. break
  253. }
  254. }
  255. @objc private func showCurrencyCountryPickerview() {
  256. DispatchQueue.main.async {
  257. self.reciepientTextField.resignFirstResponder()
  258. self.senderTextField.resignFirstResponder()
  259. }
  260. TablePresenterWireframe().openWith(
  261. tag: 1,
  262. delegate: self,
  263. model: exchangeRateModels,
  264. source: self
  265. )
  266. }
  267. private func setupDelegates() {
  268. self.collectionView.delegate = self
  269. self.collectionView.dataSource = self
  270. }
  271. private func setup() {
  272. setupLanguage()
  273. setupTargets()
  274. setExchangeRateUI()
  275. showExchangeRateInfomation(isHidden: true)
  276. executeButton.layer.cornerRadius = 5
  277. executeButton.backgroundColor = .themeRed
  278. senderTextField.textColor = .themeRed
  279. reciepientTextField.textColor = .themeRed
  280. backgroundViewCountryLabel1.backgroundColor = .themeBlue
  281. backgroundViewCountryLabel2.backgroundColor = .themeBlue
  282. }
  283. private func setupLanguage() {
  284. let constant = StringConstants()
  285. self.youSendTitleLabel.text = constant.youSendText
  286. self.recepientGetsTitleLabel.text = constant.recepientGetsText
  287. self.selectPaymentModeTitleLabel.text = "select_payment_mode_text".localized()
  288. self.executeButton.setTitle(constant.calculate, for: UIControl.State.normal)
  289. }
  290. private func setupNavigation() {
  291. self.setupNormalNavigation()
  292. }
  293. }
  294. extension ExchangeRatesViewController: UICollectionViewDelegate {
  295. func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
  296. self.selectedPaymentModeIndex = indexPath.row
  297. self.collectionView.reloadData()
  298. self.calculateExchangeRate(nil)
  299. }
  300. }
  301. extension ExchangeRatesViewController: UICollectionViewDataSource {
  302. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  303. return self.selectedExchangeRateModel?.availableServices?.count ?? 0
  304. }
  305. func collectionView(
  306. _ collectionView: UICollectionView,
  307. cellForItemAt indexPath: IndexPath
  308. ) -> UICollectionViewCell {
  309. let service = self.selectedExchangeRateModel?.availableServices?.elementAt(index: indexPath.row)
  310. guard let index = PaymentMode.init(rawValue: service?.id ?? "") else {
  311. return UICollectionViewCell()
  312. }
  313. switch index {
  314. case .bankDeposite:
  315. return configureBankDepositeCell(collectionView: collectionView, indexPath: indexPath)
  316. case .cashDelivery:
  317. return configureCashDeliveryCell(collectionView: collectionView, indexPath: indexPath)
  318. case .homeDelivery:
  319. return configureHomeDeliveryCell(collectionView: collectionView, indexPath: indexPath)
  320. case .mobileWallet:
  321. return configureWalletDeliveryCell(collectionView: collectionView, indexPath: indexPath)
  322. default:
  323. return configureCashDeliveryCell(collectionView: collectionView, indexPath: indexPath)
  324. }
  325. }
  326. func configureBankDepositeCell(
  327. collectionView: UICollectionView,
  328. indexPath: IndexPath
  329. ) -> UICollectionViewCell {
  330. guard let cell = collectionView.dequeueReusableCell(
  331. withReuseIdentifier: "ExchangeRateCollectionViewCell",
  332. for: indexPath
  333. ) as? ExchangeRateCollectionViewCell else {
  334. return UICollectionViewCell()
  335. }
  336. cell.cellSelected = self.selectedPaymentModeIndex == indexPath.row
  337. cell.paymentServiceMethod = self.selectedExchangeRateModel?.availableServices?.elementAt(
  338. index: indexPath.row
  339. )
  340. cell.image = #imageLiteral(resourceName: "ic_bank")
  341. cell.setup()
  342. return cell
  343. }
  344. func configureWalletDeliveryCell(
  345. collectionView: UICollectionView,
  346. indexPath: IndexPath
  347. ) -> UICollectionViewCell {
  348. guard let cell = collectionView.dequeueReusableCell(
  349. withReuseIdentifier: "ExchangeRateCollectionViewCell",
  350. for: indexPath
  351. ) as? ExchangeRateCollectionViewCell else {
  352. return UICollectionViewCell()
  353. }
  354. cell.cellSelected = self.selectedPaymentModeIndex == indexPath.row
  355. cell.paymentServiceMethod = self.selectedExchangeRateModel?.availableServices?.elementAt(
  356. index: indexPath.row
  357. )
  358. cell.image = #imageLiteral(resourceName: "wallet-transfer")
  359. cell.setup()
  360. return cell
  361. }
  362. func configureCashDeliveryCell(
  363. collectionView: UICollectionView,
  364. indexPath: IndexPath
  365. ) -> UICollectionViewCell {
  366. guard let cell = collectionView.dequeueReusableCell(
  367. withReuseIdentifier: "ExchangeRateCollectionViewCell",
  368. for: indexPath
  369. ) as? ExchangeRateCollectionViewCell else {
  370. return UICollectionViewCell()
  371. }
  372. cell.cellSelected = self.selectedPaymentModeIndex == indexPath.row
  373. cell.paymentServiceMethod = self.selectedExchangeRateModel?.availableServices?.elementAt(
  374. index: indexPath.row
  375. )
  376. cell.image = #imageLiteral(resourceName: "ic_cash")
  377. cell.setup()
  378. return cell
  379. }
  380. func configureHomeDeliveryCell(
  381. collectionView: UICollectionView,
  382. indexPath: IndexPath
  383. ) -> UICollectionViewCell {
  384. guard let cell = collectionView.dequeueReusableCell(
  385. withReuseIdentifier: "ExchangeRateCollectionViewCell",
  386. for: indexPath
  387. ) as? ExchangeRateCollectionViewCell else {
  388. return UICollectionViewCell()
  389. }
  390. cell.cellSelected = self.selectedPaymentModeIndex == indexPath.row
  391. cell.paymentServiceMethod = self.selectedExchangeRateModel?.availableServices?.elementAt(
  392. index: indexPath.row
  393. )
  394. cell.image = #imageLiteral(resourceName: "ic_homeDelivery")
  395. cell.setup()
  396. return cell
  397. }
  398. }
  399. extension ExchangeRatesViewController: FetchCountryCurrencyInformation, getExchangeRateInformation {}
  400. extension ExchangeRatesViewController: UITextFieldDelegate {
  401. func textFieldDidEndEditing(_ textField: UITextField) {
  402. self.calculateExchangeRate(nil)
  403. }
  404. }
  405. // MARK: ExchangeRatesViewInterface
  406. extension ExchangeRatesViewController: ExchangeRatesViewInterface {
  407. func setModel(with model: [ExchangeRateModel]?) {
  408. exchangeRateModels = model
  409. }
  410. func setModel(with model: ExchangeRateDetailModel?) {
  411. exchangeRateDetailModel = model
  412. }
  413. func setError(with error: Error) {
  414. if (error as NSError).code == -99 {
  415. alert(
  416. type: .error,
  417. message: error.localizedDescription,
  418. rightButtomTitle: "retry_text".localized(),
  419. okAction: {
  420. self.presenter?.fetchExchangeRate()
  421. }
  422. )
  423. return
  424. }
  425. alert(type: .error, message: error.localizedDescription)
  426. }
  427. func showLoading() {
  428. showProgressHud()
  429. }
  430. func hideLoading() {
  431. hideProgressHud()
  432. }
  433. }
  434. // MARK: - TablePresenterDelegate
  435. extension ExchangeRatesViewController: TablePresenterDelegate {
  436. func tablePresenterView(_ viewController: TablePresenterViewController) -> TablePresenterConfiguration {
  437. return TablePresenterConfiguration(
  438. presenterTitle: "search_currency_text".localized(),
  439. closeButtonTitle: "cancel_text".localized(),
  440. notFoundTitle: "no_result_found_text".localized(),
  441. searchBarPlaceHolder: "search_currency_text".localized()
  442. )
  443. }
  444. func tablePresenterView(
  445. _ viewController: TablePresenterViewController,
  446. didSelectModel model: TablePresenterProtocol?
  447. ) {
  448. showExchangeRateInfomation(isHidden: true)
  449. selectedPaymentModeIndex = 0
  450. selectedExchangeRateModel = (model as? ExchangeRateModel) ?? selectedExchangeRateModel
  451. }
  452. }