// // KycForm2ViewController.swift // GMERemittance // // Created by gme_2 on 12/09/2018. //Copyright © 2018 Gobal Money Express Co. Ltd. All rights reserved. // import UIKit import XLPagerTabStrip class KycForm2Model { var bank = "" var accountNumber = "" var verificationId = "" var verificationIdNumber = "" var expiryDate = "" var sourceOfFund = "" var issueDate = "" var checkIssueDate = false var checkExpiryDate = false } struct KycForm2FieldKeys { static let bank = "bank" static let accountNumber = "account number" static let verificationId = "verification id" static let verificationIdNumber = "verification id number" static let expiryDate = "expiry date" static let sourceOfFund = "source of fund" static let issueDate = "issue date" static let shouldValidateIssueDate = "issue date validation" static let shouldValidateExpiryDate = "expiry date validation" } enum KycVerificationIdType: String { case alieanCard = "Alien Registration Card" case nationalIdCard = "National ID" case passport = "Passport" } class KycForm2ViewController: UIViewController { struct Constants { static let stateRedColor = UIColor.init(hex: "#EC1C24") static let clearColor = UIColor.clear static let issueDateText = "docIssueDate" static let expiryDateText = "docExpiryDate" static let issueDateTag = 30001 static let expiryDateTag = 30002 static let errorFont = Fonts.Error.font static let errorBorderSize = AppConstants.errorBorderWidth } // MARK: IBOutlets // labels @IBOutlet weak var bankErrorLabel: UILabel! @IBOutlet weak var accountNumberErrorLabel: UILabel! @IBOutlet weak var verificationIdErrorLabel: UILabel! @IBOutlet weak var verificationIdNumberErrorLabel: UILabel! @IBOutlet weak var expiryDateErrorLabel: UILabel! @IBOutlet weak var sourceOfFundErrorLabel: UILabel! @IBOutlet weak var issueDateErrorLabel: UILabel! // textfields @IBOutlet weak var bankTextField: UITextField! @IBOutlet weak var accountNumberTextField: UITextField! @IBOutlet weak var verificationIdTextField: UITextField! @IBOutlet weak var verificationIdNumberTextField: UITextField! @IBOutlet weak var expiryDateTextField: UITextField! @IBOutlet weak var sourceOfFundTextField: UITextField! @IBOutlet weak var issueDateTextField: UITextField! // stackViews @IBOutlet weak var expiryDateStackView: UIStackView! @IBOutlet weak var issueDateStackView: UIStackView! // MARK: Properties var errorLabels: [UILabel] = [] var textfields: [UITextField] = [] var errorTextFieldDict: [String: UITextField] = [:] var errorLabelsDict: [String: UILabel] = [:] var hiddenFieldsDict: [String: UIStackView]? var hiddenFields: [UIStackView]? var kycModel: KycModel? { didSet { self.banks = kycModel?.bank self.verificationIdTypes = kycModel?.idType self.sourceOfFunds = kycModel?.sourceOfFund } } var verificationIdSelectedCardType: KycVerificationIdType = .passport { didSet { switch verificationIdSelectedCardType { case .alieanCard, .nationalIdCard: self.verificationIdNumberTextField.keyboardType = .numberPad self.verificationIdNumberTextField.addTarget(self, action: #selector(self.verificationIdTextChanged(sender:) ), for: UIControlEvents.editingChanged) break case .passport: self.verificationIdNumberTextField.keyboardType = .default self.verificationIdNumberTextField.removeTarget(self, action: #selector(self.verificationIdTextChanged(sender:) ), for: UIControlEvents.editingChanged) break } } } var banks: [KeyValueModel]? var verificationIdTypes: [VerificationIdType]? { didSet { } } var sourceOfFunds:[KeyValueModel]? var selectedBank: KeyValueModel? { didSet { self.bankTextField.text = selectedBank?.text self.kycForm2Model.bank = selectedBank?.id ?? "" } } var selectedVerificationIdType: VerificationIdType? { didSet { self.verificationIdTextField.text = self.selectedVerificationIdType?.text self.kycForm2Model.verificationId = self.selectedVerificationIdType?.id ?? "" var _views: [UIStackView] = [] _views = (self.selectedVerificationIdType?.dependent ?? []).compactMap({ print($0) return self.hiddenFieldsDict?[$0] }) self.hiddenFields?.forEach({ if _views.contains($0) { self.kycForm2Model.checkIssueDate = $0.tag == Constants.issueDateTag self.kycForm2Model.checkExpiryDate = $0.tag == Constants.expiryDateTag $0.isHidden = false }else { $0.isHidden = true } }) if selectedVerificationIdType?.text != oldValue?.text { self.verificationIdNumberTextField.text = "" } if let type = KycVerificationIdType.init(rawValue: selectedVerificationIdType?.text ?? "") { self.verificationIdSelectedCardType = type } } } var selectedSourceOfFund : KeyValueModel? { didSet { self.sourceOfFundTextField.text = selectedSourceOfFund?.text self.kycForm2Model.sourceOfFund = selectedSourceOfFund?.id ?? "" } } var delegate: KYCForm2Delegate? var presenter: KycForm2ModuleInterface? var continueActionInitiated = false var kycForm2Model: KycForm2Model = KycForm2Model() let expiaryDatePicker = UIDatePicker() let issueDatePicker = UIDatePicker() // MARK: VC's Life cycle override func viewDidLoad() { super.viewDidLoad() self.setup() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) continueActionInitiated = false validate() } // MARK: IBActions @IBAction func _continue(_ sender: UIButton) { continueActionInitiated = true self.delegate?._continue(model: self.kycForm2Model) } // MARK: Other Functions private func createModel() { self.kycForm2Model.accountNumber = self.accountNumberTextField.text! self.kycForm2Model.verificationIdNumber = self.verificationIdNumberTextField.text! self.kycForm2Model.expiryDate = self.expiryDateTextField.text! self.kycForm2Model.issueDate = self.issueDateTextField.text! } private func setup() { // all setup should be done here hideErrorLabels() setupErrorLabels() setupErrorTextFields() setupDatePicker() setupDelegates() setupHiddenFields() } private func setupHiddenFields() { self.hiddenFields = [issueDateStackView, expiryDateStackView] issueDateStackView.tag = Constants.issueDateTag expiryDateStackView.tag = Constants.expiryDateTag self.hiddenFieldsDict = [ Constants.issueDateText : issueDateStackView, Constants.expiryDateText: expiryDateStackView ] self.hiddenFieldsDict?.forEach({ $0.value.isHidden = true }) } private func validate() { createModel() self.delegate?.addModel(model: self.kycForm2Model) } @objc private func verificationIdTextChanged(sender: UITextField) { } private func setupDelegates() { self.bankTextField.delegate = self self.accountNumberTextField.delegate = self self.verificationIdTextField.delegate = self self.verificationIdNumberTextField.delegate = self self.expiryDateTextField.delegate = self self.issueDateTextField.delegate = self self.sourceOfFundTextField.delegate = self } private func setupDatePicker() { self.expiaryDatePicker.datePickerMode = .date self.expiryDateTextField.inputView = expiaryDatePicker self.expiaryDatePicker.addTarget(self, action: #selector(handleExpiryDatePicker), for: .valueChanged) self.issueDatePicker.datePickerMode = .date self.issueDateTextField.inputView = issueDatePicker issueDatePicker.maximumDate = Date() self.issueDatePicker.addTarget(self, action: #selector(handleIssueDatePicker), for: .valueChanged) } @objc private func handleIssueDatePicker(sender: UIDatePicker) { let dateFormatter = DateFormatter() let date = sender.date expiaryDatePicker.minimumDate = date dateFormatter.dateFormat = AppConstants.dateFormat // test ccr self.issueDateTextField.text = dateFormatter.string(from: sender.date) } @objc private func handleExpiryDatePicker(sender: UIDatePicker) { let dateFormatter = DateFormatter() // test ccr dateFormatter.dateFormat = AppConstants.dateFormat self.expiryDateTextField.text = dateFormatter.string(from: sender.date) } private func hideErrorLabels() { [bankErrorLabel, accountNumberErrorLabel, verificationIdErrorLabel, verificationIdNumberErrorLabel, expiryDateErrorLabel, issueDateErrorLabel, sourceOfFundErrorLabel].forEach({ $0?.isHidden = true }) } private func setupErrorLabels() { self.errorLabels = [bankErrorLabel, accountNumberErrorLabel, verificationIdErrorLabel, verificationIdNumberErrorLabel, expiryDateErrorLabel,issueDateErrorLabel, sourceOfFundErrorLabel] self.errorLabels.forEach({ $0.font = Constants.errorFont }) self.errorLabelsDict = [ KycForm2FieldKeys.bank: self.bankErrorLabel, KycForm2FieldKeys.accountNumber: self.accountNumberErrorLabel, KycForm2FieldKeys.verificationId: self.verificationIdErrorLabel, KycForm2FieldKeys.verificationIdNumber: self.verificationIdNumberErrorLabel, KycForm2FieldKeys.expiryDate: self.expiryDateErrorLabel, KycForm2FieldKeys.sourceOfFund: self.sourceOfFundErrorLabel, KycForm2FieldKeys.issueDate: self.issueDateErrorLabel ] } private func setupErrorTextFields() { self.textfields = [bankTextField, accountNumberTextField, verificationIdTextField, verificationIdNumberTextField, expiryDateTextField, sourceOfFundTextField] bankTextField.tag = 12 accountNumberTextField.tag = 13 verificationIdNumberTextField.tag = 14 expiryDateTextField.tag = 15 issueDateTextField.tag = 16 sourceOfFundTextField.tag = 17 self.errorTextFieldDict = [ KycForm2FieldKeys.bank: self.bankTextField, KycForm2FieldKeys.accountNumber: self.accountNumberTextField, KycForm2FieldKeys.verificationId: self.verificationIdTextField, KycForm2FieldKeys.verificationIdNumber: self.verificationIdNumberTextField, KycForm2FieldKeys.expiryDate: self.expiryDateTextField, KycForm2FieldKeys.sourceOfFund: self.sourceOfFundTextField ] } private func showBorder(textfield :UITextField?) { guard let textfield = textfield else {return} textfield.layer.borderColor = Constants.stateRedColor.cgColor textfield.layer.borderWidth = Constants.errorBorderSize textfield.layer.addShadow(with: Constants.stateRedColor) } private func show( error: String, label: UILabel?) { // scroll to the top of the view guard let label = label else {return} label.textColor = Constants.stateRedColor label.isHidden = false label.text = error } } // MARK: KycForm2ViewInterface extension KycForm2ViewController: KycForm2ViewInterface { func show(resut2: (isValid: Bool, errorsDick: [String : String])) { var position = 15 if resut2.isValid { // if isValid // its is not valid, lets go to security page if self.continueActionInitiated { self.delegate?._continue(model: self.kycForm2Model) } }else { resut2.errorsDick.forEach({ let label = errorLabelsDict[$0.key] self.show(error: $0.value, label: label) let textfield = errorTextFieldDict[$0.key] self.showBorder(textfield: textfield) let tag = (textfield?.tag ?? position) position = tag < position ? tag : position if let topMostTextField = self.textfields.filter({ $0.tag == tag }).first { // Todo // scroll to view here } }) } } func show(error: String) { self.alert(message: error) } func showLoading() { self.showProgressHud() } func hideLoading() { self.hideProgressHud() } } extension KycForm2ViewController: IndicatorInfoProvider { func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo { return IndicatorInfo.init(title: "Security") } } extension KycForm2ViewController: UITextFieldDelegate { func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { if textField == verificationIdNumberTextField && self.verificationIdSelectedCardType != .passport { let text = textField.text! if (range.length > 0) { // We're deleting if text.count < 7 { let newText = text.replacingOccurrences(of: "-", with: "") textField.text = newText } } else { var _text = text.replacingOccurrences(of: "-", with: "") if _text.count >= 6 { _text.insert("-", at: String.Index.init(encodedOffset: 6)) textField.text = _text } // We're adding } } return true } func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { textField.layer.addShadow(with: Constants.clearColor) textField.layer.borderWidth = 0 switch textField { case bankTextField: // show bank picker showBankPickerView() self.bankErrorLabel.isHidden = true return false case verificationIdTextField: self.verificationIdErrorLabel.isHidden = true showVerificationIdTypePicker() // show list of verificationId type return false case sourceOfFundTextField: // show source of fund picker self.sourceOfFundErrorLabel.isHidden = true self.showSourceOfFundPicker() return false default: return true } } func textFieldDidBeginEditing(_ textField: UITextField) { textField.layer.addShadow(with: Constants.clearColor) textField.layer.borderWidth = 0 switch textField { case accountNumberTextField: accountNumberErrorLabel.isHidden = true case verificationIdNumberTextField: verificationIdNumberErrorLabel.isHidden = true case expiryDateTextField: expiryDateErrorLabel.isHidden = true case issueDateTextField: issueDateErrorLabel.isHidden = true default: break } } } extension KycForm2ViewController { private func showBankPickerView() { let viewcontroller = self.getPickerViewController() let banks = self.banks ?? [] let names = banks.compactMap({$0.text}) viewcontroller.data = names viewcontroller.type = PickerTitle.bank viewcontroller.doneAction = self.bankSelected self.present(viewcontroller, animated: true, completion: nil) } private func getPickerViewController()-> ItemsPickerViewController { return UIStoryboard.init(name: "ItemsPicker", bundle: nil).instantiateViewController(withIdentifier: "ItemsPickerViewController") as! ItemsPickerViewController } func bankSelected(banks: [String]) { let _bank = self.banks?.filter({($0.text ?? "") == (banks.first ?? "") }).first self.selectedBank = _bank } private func showVerificationIdTypePicker() { let viewcontroller = self.getPickerViewController() let models = self.verificationIdTypes ?? [] let names = models.compactMap({$0.text}) viewcontroller.data = names viewcontroller.type = PickerTitle.verificationIdTypes viewcontroller.doneAction = self.cardTypeSelected self.present(viewcontroller, animated: true, completion: nil) } func cardTypeSelected(models: [String]) { let _model = self.verificationIdTypes?.filter({($0.text ?? "") == (models.first ?? "") }).first self.selectedVerificationIdType = _model } private func showSourceOfFundPicker() { let viewcontroller = self.getPickerViewController() let models = self.sourceOfFunds ?? [] let names = models.compactMap({$0.text}) viewcontroller.data = names viewcontroller.type = PickerTitle.sourceOfFund viewcontroller.doneAction = self.sourceOfFundSelected self.present(viewcontroller, animated: true, completion: nil) } func sourceOfFundSelected(models: [String]) { let _model = self.sourceOfFunds?.filter({($0.text ?? "") == (models.first ?? "") }).first self.selectedSourceOfFund = _model } }