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.

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