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.
 
 
 
 

583 lines
21 KiB

//
// 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
}
struct StringConstants {
let headerTitle = "security_subtitle_text".localized()
let primaryBankTitle = "primary_bank_text".localized()
let primaryBankPlaceholder = "primary_bank_placeholder_text".localized()
let accountTitle = "primary_account_number_text".localized()
let accountPlaceholder = "privary_account_number_placeholder".localized()
let verificationIdTitle = "verification_id_type_text".localized()
let verificationIdPlaceholder = "verification_id_placeholder_text".localized()
let verificationNumberTitle = "verification_id_no_text".localized()
let verificationNumberPlaceholder = "verification_id_no_placeholder_text".localized()
let issueDateTittle = "Issue Date".localized()
let issueDatePlaceholder = "select_issue_date_text".localized()
let expiryDateTitle = "expiry_date_title".localized()
let expiryDatePlaceholder = "select_expiry_date_text".localized()
let sourceOfFundTitle = "source_of_fund_text".localized()
let sourceOfFundPlaceholder = "source_of_fund_placeholder_text".localized()
let saveAndContinue = "save_and_continue_text".localized()
}
// 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!
// title labels
@IBOutlet weak var bankTitleLabel: UILabel!
@IBOutlet weak var accountNumberTitleLabel: UILabel!
@IBOutlet weak var verificationIdTitleLabel: UILabel!
@IBOutlet weak var verificationIdNumberTitleLabel: UILabel!
@IBOutlet weak var expiryDateTitleLabel: UILabel!
@IBOutlet weak var sourceOfFundTitleLabel: UILabel!
@IBOutlet weak var issueDateTitleLabel: UILabel!
@IBOutlet weak var headerTitleLabel: 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!
@IBOutlet weak var saveAndContinueButton: UIButton!
// 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()
configureLanugage()
}
private func configureLanugage() {
self.bankTitleLabel.text = StringConstants().primaryBankTitle
self.bankTextField.placeholder = StringConstants().primaryBankPlaceholder
self.accountNumberTitleLabel.text = StringConstants().accountTitle
self.accountNumberTextField.placeholder = StringConstants().accountPlaceholder
self.verificationIdTitleLabel.text = StringConstants().verificationIdTitle
self.verificationIdTextField.placeholder = StringConstants().verificationIdPlaceholder
self.verificationIdNumberTitleLabel.text = StringConstants().verificationNumberTitle
self.verificationIdNumberTextField.placeholder = StringConstants().verificationNumberPlaceholder
self.issueDateTitleLabel.text = StringConstants().issueDateTittle
self.issueDateTextField.placeholder = StringConstants().issueDatePlaceholder
self.expiryDateTitleLabel.text = StringConstants().expiryDateTitle
self.expiryDateTextField.placeholder = StringConstants().expiryDatePlaceholder
self.sourceOfFundTitleLabel.text = StringConstants().sourceOfFundTitle
self.sourceOfFundTextField.placeholder = StringConstants().sourceOfFundPlaceholder
self.headerTitleLabel.text = StringConstants().headerTitle
self.saveAndContinueButton.setTitle("save_and_continue_text".localized(), for: UIControlState.normal)
}
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 self.textfields.filter({
$0.tag == tag
}).first != nil {
// 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_titile_text".localized())
}
}
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
}
}