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.

464 lines
16 KiB

6 years ago
  1. //
  2. // KycForm2ViewController.swift
  3. // GMERemittance
  4. //
  5. // Created by gme_2 on 12/09/2018.
  6. //Copyright © 2018 Gobal Money Express Co. Ltd. All rights reserved.
  7. //
  8. import UIKit
  9. import XLPagerTabStrip
  10. class KycForm2Model {
  11. var bank = ""
  12. var accountNumber = ""
  13. var verificationId = ""
  14. var verificationIdNumber = ""
  15. var expiryDate = ""
  16. var sourceOfFund = ""
  17. var issueDate = ""
  18. var checkIssueDate = false
  19. var checkExpiryDate = false
  20. }
  21. struct KycForm2FieldKeys {
  22. static let bank = "bank"
  23. static let accountNumber = "account number"
  24. static let verificationId = "verification id"
  25. static let verificationIdNumber = "verification id number"
  26. static let expiryDate = "expiry date"
  27. static let sourceOfFund = "source of fund"
  28. static let issueDate = "issue date"
  29. static let shouldValidateIssueDate = "issue date validation"
  30. static let shouldValidateExpiryDate = "expiry date validation"
  31. }
  32. class KycForm2ViewController: UIViewController {
  33. struct Constants {
  34. static let stateRedColor = UIColor.init(hex: "#EC1C24")
  35. static let clearColor = UIColor.clear
  36. static let issueDateText = "docIssueDate"
  37. static let expiryDateText = "docExpiryDate"
  38. static let issueDateTag = 30001
  39. static let expiryDateTag = 30002
  40. static let errorFont = Fonts.Error.font
  41. static let errorBorderSize = AppConstants.errorBorderWidth
  42. }
  43. // MARK: IBOutlets
  44. // labels
  45. @IBOutlet weak var bankErrorLabel: UILabel!
  46. @IBOutlet weak var accountNumberErrorLabel: UILabel!
  47. @IBOutlet weak var verificationIdErrorLabel: UILabel!
  48. @IBOutlet weak var verificationIdNumberErrorLabel: UILabel!
  49. @IBOutlet weak var expiryDateErrorLabel: UILabel!
  50. @IBOutlet weak var sourceOfFundErrorLabel: UILabel!
  51. @IBOutlet weak var issueDateErrorLabel: UILabel!
  52. // textfields
  53. @IBOutlet weak var bankTextField: UITextField!
  54. @IBOutlet weak var accountNumberTextField: UITextField!
  55. @IBOutlet weak var verificationIdTextField: UITextField!
  56. @IBOutlet weak var verificationIdNumberTextField: UITextField!
  57. @IBOutlet weak var expiryDateTextField: UITextField!
  58. @IBOutlet weak var sourceOfFundTextField: UITextField!
  59. @IBOutlet weak var issueDateTextField: UITextField!
  60. // stackViews
  61. @IBOutlet weak var expiryDateStackView: UIStackView!
  62. @IBOutlet weak var issueDateStackView: UIStackView!
  63. // MARK: Properties
  64. var errorLabels: [UILabel] = []
  65. var textfields: [UITextField] = []
  66. var errorTextFieldDict: [String: UITextField] = [:]
  67. var errorLabelsDict: [String: UILabel] = [:]
  68. var hiddenFieldsDict: [String: UIStackView]?
  69. var hiddenFields: [UIStackView]?
  70. var kycModel: KycModel? {
  71. didSet {
  72. self.banks = kycModel?.bank
  73. self.verificationIdTypes = kycModel?.idType
  74. self.sourceOfFunds = kycModel?.sourceOfFund
  75. }
  76. }
  77. var banks: [KeyValueModel]?
  78. var verificationIdTypes: [VerificationIdType]? {
  79. didSet {
  80. }
  81. }
  82. var sourceOfFunds:[KeyValueModel]?
  83. var selectedBank: KeyValueModel? {
  84. didSet {
  85. self.bankTextField.text = selectedBank?.text
  86. self.kycForm2Model.bank = selectedBank?.id ?? ""
  87. }
  88. }
  89. var selectedVerificationIdType: VerificationIdType? {
  90. didSet {
  91. self.verificationIdTextField.text = self.selectedVerificationIdType?.text
  92. self.kycForm2Model.verificationId = self.selectedVerificationIdType?.id ?? ""
  93. var _views: [UIStackView] = []
  94. _views = (self.selectedVerificationIdType?.dependent ?? []).compactMap({
  95. print($0)
  96. return self.hiddenFieldsDict?[$0]
  97. })
  98. self.hiddenFields?.forEach({
  99. if _views.contains($0) {
  100. self.kycForm2Model.checkIssueDate = $0.tag == Constants.issueDateTag
  101. self.kycForm2Model.checkExpiryDate = $0.tag == Constants.expiryDateTag
  102. $0.isHidden = false
  103. }else {
  104. $0.isHidden = true
  105. }
  106. })
  107. }
  108. }
  109. var selectedSourceOfFund : KeyValueModel? {
  110. didSet {
  111. self.sourceOfFundTextField.text = selectedSourceOfFund?.text
  112. self.kycForm2Model.sourceOfFund = selectedSourceOfFund?.id ?? ""
  113. }
  114. }
  115. var delegate: KYCForm2Delegate?
  116. var presenter: KycForm2ModuleInterface?
  117. var continueActionInitiated = false
  118. var kycForm2Model: KycForm2Model = KycForm2Model()
  119. let expiaryDatePicker = UIDatePicker()
  120. let issueDatePicker = UIDatePicker()
  121. // MARK: VC's Life cycle
  122. override func viewDidLoad() {
  123. super.viewDidLoad()
  124. self.setup()
  125. }
  126. override func viewWillDisappear(_ animated: Bool) {
  127. super.viewWillDisappear(animated)
  128. continueActionInitiated = false
  129. validate()
  130. }
  131. // MARK: IBActions
  132. @IBAction func _continue(_ sender: UIButton) {
  133. continueActionInitiated = true
  134. self.delegate?._continue(model: self.kycForm2Model)
  135. }
  136. // MARK: Other Functions
  137. private func createModel() {
  138. self.kycForm2Model.accountNumber = self.accountNumberTextField.text!
  139. self.kycForm2Model.verificationIdNumber = self.verificationIdNumberTextField.text!
  140. self.kycForm2Model.expiryDate = self.expiryDateTextField.text!
  141. self.kycForm2Model.issueDate = self.issueDateTextField.text!
  142. }
  143. private func setup() {
  144. // all setup should be done here
  145. hideErrorLabels()
  146. setupErrorLabels()
  147. setupErrorTextFields()
  148. setupDatePicker()
  149. setupDelegates()
  150. setupHiddenFields()
  151. }
  152. private func setupHiddenFields() {
  153. self.hiddenFields = [issueDateStackView, expiryDateStackView]
  154. issueDateStackView.tag = Constants.issueDateTag
  155. expiryDateStackView.tag = Constants.expiryDateTag
  156. self.hiddenFieldsDict = [
  157. Constants.issueDateText : issueDateStackView,
  158. Constants.expiryDateText: expiryDateStackView
  159. ]
  160. self.hiddenFieldsDict?.forEach({
  161. $0.value.isHidden = true
  162. })
  163. }
  164. private func validate() {
  165. createModel()
  166. self.delegate?.addModel(model: self.kycForm2Model)
  167. }
  168. private func setupDelegates() {
  169. self.bankTextField.delegate = self
  170. self.accountNumberTextField.delegate = self
  171. self.verificationIdTextField.delegate = self
  172. self.verificationIdNumberTextField.delegate = self
  173. self.expiryDateTextField.delegate = self
  174. self.issueDateTextField.delegate = self
  175. self.sourceOfFundTextField.delegate = self
  176. }
  177. private func setupDatePicker() {
  178. self.expiaryDatePicker.datePickerMode = .date
  179. self.expiryDateTextField.inputView = expiaryDatePicker
  180. self.expiaryDatePicker.addTarget(self, action: #selector(handleExpiryDatePicker), for: .valueChanged)
  181. self.issueDatePicker.datePickerMode = .date
  182. self.issueDateTextField.inputView = issueDatePicker
  183. issueDatePicker.maximumDate = Date()
  184. self.issueDatePicker.addTarget(self, action: #selector(handleIssueDatePicker), for: .valueChanged)
  185. }
  186. @objc private func handleIssueDatePicker(sender: UIDatePicker) {
  187. let dateFormatter = DateFormatter()
  188. let date = sender.date
  189. expiaryDatePicker.minimumDate = date
  190. dateFormatter.dateFormat = AppConstants.dateFormat
  191. // test ccr
  192. self.issueDateTextField.text = dateFormatter.string(from: sender.date)
  193. }
  194. @objc private func handleExpiryDatePicker(sender: UIDatePicker) {
  195. let dateFormatter = DateFormatter()
  196. // test ccr
  197. dateFormatter.dateFormat = AppConstants.dateFormat
  198. self.expiryDateTextField.text = dateFormatter.string(from: sender.date)
  199. }
  200. private func hideErrorLabels() {
  201. [bankErrorLabel, accountNumberErrorLabel, verificationIdErrorLabel, verificationIdNumberErrorLabel, expiryDateErrorLabel, issueDateErrorLabel, sourceOfFundErrorLabel].forEach({
  202. $0?.isHidden = true
  203. })
  204. }
  205. private func setupErrorLabels() {
  206. self.errorLabels = [bankErrorLabel, accountNumberErrorLabel, verificationIdErrorLabel, verificationIdNumberErrorLabel, expiryDateErrorLabel,issueDateErrorLabel, sourceOfFundErrorLabel]
  207. self.errorLabels.forEach({
  208. $0.font = Constants.errorFont
  209. })
  210. self.errorLabelsDict =
  211. [
  212. KycForm2FieldKeys.bank: self.bankErrorLabel,
  213. KycForm2FieldKeys.accountNumber: self.accountNumberErrorLabel,
  214. KycForm2FieldKeys.verificationId: self.verificationIdErrorLabel,
  215. KycForm2FieldKeys.verificationIdNumber: self.verificationIdNumberErrorLabel,
  216. KycForm2FieldKeys.expiryDate: self.expiryDateErrorLabel,
  217. KycForm2FieldKeys.sourceOfFund: self.sourceOfFundErrorLabel,
  218. KycForm2FieldKeys.issueDate: self.issueDateErrorLabel
  219. ]
  220. }
  221. private func setupErrorTextFields() {
  222. self.textfields = [bankTextField, accountNumberTextField, verificationIdTextField, verificationIdNumberTextField, expiryDateTextField, sourceOfFundTextField]
  223. bankTextField.tag = 12
  224. accountNumberTextField.tag = 13
  225. verificationIdNumberTextField.tag = 14
  226. expiryDateTextField.tag = 15
  227. issueDateTextField.tag = 16
  228. sourceOfFundTextField.tag = 17
  229. self.errorTextFieldDict =
  230. [
  231. KycForm2FieldKeys.bank: self.bankTextField,
  232. KycForm2FieldKeys.accountNumber: self.accountNumberTextField,
  233. KycForm2FieldKeys.verificationId: self.verificationIdTextField,
  234. KycForm2FieldKeys.verificationIdNumber: self.verificationIdNumberTextField,
  235. KycForm2FieldKeys.expiryDate: self.expiryDateTextField,
  236. KycForm2FieldKeys.sourceOfFund: self.sourceOfFundTextField
  237. ]
  238. }
  239. private func showBorder(textfield :UITextField?) {
  240. guard let textfield = textfield else {return}
  241. textfield.layer.borderColor = Constants.stateRedColor.cgColor
  242. textfield.layer.borderWidth = Constants.errorBorderSize
  243. textfield.layer.addShadow(with: Constants.stateRedColor)
  244. }
  245. private func show( error: String, label: UILabel?) {
  246. // scroll to the top of the view
  247. guard let label = label else {return}
  248. label.textColor = Constants.stateRedColor
  249. label.isHidden = false
  250. label.text = error
  251. }
  252. }
  253. // MARK: KycForm2ViewInterface
  254. extension KycForm2ViewController: KycForm2ViewInterface {
  255. func show(resut2: (isValid: Bool, errorsDick: [String : String])) {
  256. var position = 15
  257. if resut2.isValid { // if isValid
  258. // its is not valid, lets go to security page
  259. if self.continueActionInitiated {
  260. self.delegate?._continue(model: self.kycForm2Model)
  261. }
  262. }else {
  263. resut2.errorsDick.forEach({
  264. let label = errorLabelsDict[$0.key]
  265. self.show(error: $0.value, label: label)
  266. let textfield = errorTextFieldDict[$0.key]
  267. self.showBorder(textfield: textfield)
  268. let tag = (textfield?.tag ?? position)
  269. position = tag < position ? tag : position
  270. if let topMostTextField = self.textfields.filter({
  271. $0.tag == tag
  272. }).first {
  273. // Todo
  274. // scroll to view here
  275. }
  276. })
  277. }
  278. }
  279. func show(error: String) {
  280. self.alert(message: error)
  281. }
  282. func showLoading() {
  283. self.showProgressHud()
  284. }
  285. func hideLoading() {
  286. self.hideProgressHud()
  287. }
  288. }
  289. extension KycForm2ViewController: IndicatorInfoProvider {
  290. func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo {
  291. return IndicatorInfo.init(title: "Security")
  292. }
  293. }
  294. extension KycForm2ViewController: UITextFieldDelegate {
  295. func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
  296. textField.layer.addShadow(with: Constants.clearColor)
  297. textField.layer.borderWidth = 0
  298. switch textField {
  299. case bankTextField:
  300. // show bank picker
  301. showBankPickerView()
  302. self.bankErrorLabel.isHidden = true
  303. return false
  304. case verificationIdTextField:
  305. self.verificationIdErrorLabel.isHidden = true
  306. showVerificationIdTypePicker()
  307. // show list of verificationId type
  308. return false
  309. case sourceOfFundTextField:
  310. // show source of fund picker
  311. self.sourceOfFundErrorLabel.isHidden = true
  312. self.showSourceOfFundPicker()
  313. return false
  314. default:
  315. return true
  316. }
  317. }
  318. func textFieldDidBeginEditing(_ textField: UITextField) {
  319. textField.layer.addShadow(with: Constants.clearColor)
  320. textField.layer.borderWidth = 0
  321. switch textField {
  322. case accountNumberTextField:
  323. accountNumberErrorLabel.isHidden = true
  324. case verificationIdNumberTextField:
  325. verificationIdNumberErrorLabel.isHidden = true
  326. case expiryDateTextField:
  327. expiryDateErrorLabel.isHidden = true
  328. case issueDateTextField:
  329. issueDateErrorLabel.isHidden = true
  330. default:
  331. break
  332. }
  333. }
  334. }
  335. extension KycForm2ViewController {
  336. private func showBankPickerView() {
  337. let viewcontroller = self.getPickerViewController()
  338. let banks = self.banks ?? []
  339. let names = banks.compactMap({$0.text})
  340. viewcontroller.data = names
  341. viewcontroller.type = PickerTitle.bank
  342. viewcontroller.doneAction = self.bankSelected
  343. self.present(viewcontroller, animated: true, completion: nil)
  344. }
  345. private func getPickerViewController()-> ItemsPickerViewController {
  346. return UIStoryboard.init(name: "ItemsPicker", bundle: nil).instantiateViewController(withIdentifier: "ItemsPickerViewController") as! ItemsPickerViewController
  347. }
  348. func bankSelected(banks: [String]) {
  349. let _bank = self.banks?.filter({($0.text ?? "") == (banks.first ?? "") }).first
  350. self.selectedBank = _bank
  351. }
  352. private func showVerificationIdTypePicker() {
  353. let viewcontroller = self.getPickerViewController()
  354. let models = self.verificationIdTypes ?? []
  355. let names = models.compactMap({$0.text})
  356. viewcontroller.data = names
  357. viewcontroller.type = PickerTitle.verificationIdTypes
  358. viewcontroller.doneAction = self.cardTypeSelected
  359. self.present(viewcontroller, animated: true, completion: nil)
  360. }
  361. func cardTypeSelected(models: [String]) {
  362. let _model = self.verificationIdTypes?.filter({($0.text ?? "") == (models.first ?? "") }).first
  363. self.selectedVerificationIdType = _model
  364. }
  365. private func showSourceOfFundPicker() {
  366. let viewcontroller = self.getPickerViewController()
  367. let models = self.sourceOfFunds ?? []
  368. let names = models.compactMap({$0.text})
  369. viewcontroller.data = names
  370. viewcontroller.type = PickerTitle.sourceOfFund
  371. viewcontroller.doneAction = self.sourceOfFundSelected
  372. self.present(viewcontroller, animated: true, completion: nil)
  373. }
  374. func sourceOfFundSelected(models: [String]) {
  375. let _model = self.sourceOfFunds?.filter({($0.text ?? "") == (models.first ?? "") }).first
  376. self.selectedSourceOfFund = _model
  377. }
  378. }