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.

584 lines
22 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. //
  2. // KycForm1ViewController.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. //"select_issue_date_text" = "Select issue date";
  9. //"select_expiry_date_text" = "Select expiry date";
  10. import UIKit
  11. import XLPagerTabStrip
  12. class KycForm1Model {
  13. var firstName = ""
  14. var middleName = ""
  15. var lastName = ""
  16. var gender = ""
  17. // var dob = ""
  18. var mobile = ""
  19. var email = ""
  20. var nativeCountry = ""
  21. var country = ""
  22. var province = ""
  23. var occupation = ""
  24. var referralCode = ""
  25. }
  26. class Occupation {
  27. var title: String?
  28. var id: String?
  29. }
  30. struct KycForm1FieldKeys {
  31. static let firstName = "fullname"
  32. static let gender = "gender"
  33. static let mobileNumber = "mobile number"
  34. static let email = "email"
  35. static let nativeCountry = "native country"
  36. static let country = "address"
  37. static let province = "province"
  38. static let occupation = "occupation"
  39. static let referralCode = "referralCode"
  40. }
  41. class KycForm1ViewController: UIViewController {
  42. struct Constants {
  43. static let segmentBackgroundViewColor = UIColor.init(hex: "E7EDF2")
  44. static let stateRedColor = UIColor.init(hex: "#EC1C24")
  45. static let errorBorderWidth = AppConstants.errorBorderWidth
  46. static let errorLabelFont = Fonts.Error.font
  47. static let clearColor = UIColor.clear
  48. static let male = "male_text".localized()
  49. static let female = "female_text".localized()
  50. static let other = "other_text".localized()
  51. static let cancelTitleString = "cancel_text".localized()
  52. }
  53. struct StringConstants {
  54. let fullname = "full_name_text".localized()
  55. let fullnamePlaceholder = "full_name_placeholder_text".localized()
  56. let mobileNumber = "mobile_number_text".localized()
  57. let mobilePlaceholder = "mobile_number_placeholder_text".localized()
  58. let email = "email_text_optional".localized()
  59. let emailPlaceholder = "placeholder_enter_receiver_email_text".localized()
  60. let gender = "gender_text".localized()
  61. let genderPlacholder = "gender_placeholder_text".localized()
  62. let nativeCountry = "native_country_text".localized()
  63. let nativeCountryPlaceholder = "native_country_placeholder_text".localized()
  64. let addressInKorea = "address_in_korea_text".localized()
  65. let addressPlaceholder = "address_in_korea_text".localized()
  66. let province = "province_text".localized()
  67. let provincePlaceholder = "province_placeholder_text".localized()
  68. let occupation = "occupation_text".localized()
  69. let occupationPlaceholder = "occupation_placeholder_text".localized()
  70. let saveAndCoutinueText = "save_and_continue_text".localized()
  71. let referralCode = "referral_code_text".localized()
  72. }
  73. // MARK: IBOutlets
  74. @IBOutlet weak var scrollView: UIScrollView!
  75. // validation labels
  76. @IBOutlet weak var headerTItleLabel: UILabel!
  77. @IBOutlet weak var firstNameErrorLabel: UILabel!
  78. @IBOutlet weak var middleNameErrorLabel: UILabel!
  79. @IBOutlet weak var lastNameErrorLabel: UILabel!
  80. @IBOutlet weak var genderErrorLabel: UILabel!
  81. @IBOutlet weak var dobErrorLabel: UILabel!
  82. @IBOutlet weak var mobileNumberErrorLabel: UILabel!
  83. @IBOutlet weak var emailErrorLabel: UILabel!
  84. @IBOutlet weak var nativeCountryErrorLabel: UILabel!
  85. @IBOutlet weak var countryErrorLabel: UILabel!
  86. @IBOutlet weak var provinceErrorLabel: UILabel!
  87. @IBOutlet weak var occupationErrorLabel: UILabel!
  88. @IBOutlet weak var referralCodeErrorLabel: UILabel!
  89. // textfields
  90. @IBOutlet weak var firstNameTextField: UITextField!
  91. @IBOutlet weak var middleNmaeTextField: UITextField!
  92. @IBOutlet weak var lastNameTextField: UITextField!
  93. @IBOutlet weak var genderTextField: UITextField!
  94. @IBOutlet weak var dobTextField: UITextField!
  95. @IBOutlet weak var mobileNumberTextField: UITextField!
  96. @IBOutlet weak var emailTextField: UITextField!
  97. @IBOutlet weak var nativeCountryTextField: UITextField!
  98. @IBOutlet weak var countryTextField: UITextField!
  99. @IBOutlet weak var provinceTextField: UITextField!
  100. @IBOutlet weak var occupationTextField: UITextField!
  101. @IBOutlet weak var referralCodeTextField: UITextField!
  102. // title labels
  103. @IBOutlet weak var fullnameTitleLabel: UILabel!
  104. @IBOutlet weak var mobileNumberTitleLabel: UILabel!
  105. @IBOutlet weak var emailTitleLabel: UILabel!
  106. @IBOutlet weak var genderTitleLabel: UILabel!
  107. @IBOutlet weak var nativeCountryTitleLabel: UILabel!
  108. @IBOutlet weak var addressInKoreaTitleLabel: UILabel!
  109. @IBOutlet weak var provinceTitleLabel: UILabel!
  110. @IBOutlet weak var occupationTitleLabel: UILabel!
  111. @IBOutlet weak var referralCodeTitleLabel: UILabel!
  112. @IBOutlet weak var saveAndContinue: UIButton!
  113. // MARK: Properties
  114. var presenter: KycForm1ModuleInterface?
  115. var kycForm1Model: KycForm1Model = KycForm1Model()
  116. var continueActionInitiated = false
  117. let datePicker = UIDatePicker()
  118. var errorTextFieldDict: [String: UITextField] = [:]
  119. var errorLabelsDict: [String: UILabel] = [:]
  120. var errorLabels: [UILabel] = []
  121. var textfields: [UITextField] = []
  122. var delegate: KYCForm1Delegate?
  123. var countries: [KeyValueModel]?
  124. var occupations: [KeyValueModel]?
  125. var kycModel: KycModel? {
  126. didSet {
  127. self.countries = kycModel?.nativeCountry
  128. self.occupations = kycModel?.occupations
  129. self.proviences = kycModel?.city
  130. }
  131. }
  132. var proviences: [KeyValueModel]?
  133. var selectedCountry: SendMoneyCountryViewModel? {
  134. didSet {
  135. self.nativeCountryTextField.text = selectedCountry?.name
  136. self.kycForm1Model.nativeCountry = selectedCountry?.id ?? ""
  137. }
  138. }
  139. var selectedProvience: KeyValueModel? {
  140. didSet {
  141. self.provinceTextField.text = selectedProvience?.text
  142. self.kycForm1Model.province = selectedProvience?.id ?? ""
  143. }
  144. }
  145. var selectedOccupation: KeyValueModel? {
  146. didSet {
  147. self.occupationTextField.text = selectedOccupation?.text
  148. self.kycForm1Model.occupation = selectedOccupation?.id ?? ""
  149. }
  150. }
  151. // MARK: VC's Life cycle
  152. override func viewDidLoad() {
  153. super.viewDidLoad()
  154. self.setup()
  155. presenter?.viewIsReady()
  156. }
  157. override func viewWillAppear(_ animated: Bool) {
  158. super.viewWillAppear(animated)
  159. self.view.endEditing(true)
  160. removeFocus()
  161. }
  162. override func viewWillDisappear(_ animated: Bool) {
  163. super.viewWillDisappear(animated)
  164. self.view.endEditing(true)
  165. self.continueActionInitiated = false
  166. self.validate()
  167. }
  168. // MARK: IBActions
  169. @IBAction func save(_ sender: UIButton) {
  170. self.view.endEditing(true)
  171. self.continueActionInitiated = true
  172. self.delegate?._continue(model: self.kycForm1Model)
  173. // validate()
  174. }
  175. // MARK: Other Functions
  176. private func removeFocus() {
  177. self.textfields.forEach({
  178. $0.resignFirstResponder()
  179. })
  180. }
  181. private func createModel() {
  182. self.kycForm1Model.firstName = self.firstNameTextField.text!
  183. self.kycForm1Model.middleName = self.middleNmaeTextField.text!
  184. self.kycForm1Model.lastName = self.lastNameTextField.text!
  185. self.kycForm1Model.gender = self.genderTextField.text!
  186. // self.kycForm1Model.dob = self.dobTextField.text!
  187. self.kycForm1Model.mobile = self.mobileNumberTextField.text!
  188. self.kycForm1Model.email = self.emailTextField.text!
  189. self.kycForm1Model.country = self.countryTextField.text! // this is addres field
  190. self.kycForm1Model.referralCode = self.referralCodeTextField.text ?? ""
  191. }
  192. private func setup() {
  193. // all setup should be done here
  194. hideErrorLabels()
  195. setupErrorLabels()
  196. setupErrorTextFields()
  197. setupDelegates()
  198. self.setupDatePicker()
  199. self.setupEmail()
  200. configureLanguage()
  201. }
  202. private func configureLanguage() {
  203. self.headerTItleLabel.text = "personal_subtitle_text".localized()
  204. self.fullnameTitleLabel.text = StringConstants().fullname
  205. self.mobileNumberTitleLabel.text = StringConstants().mobileNumber
  206. self.emailTitleLabel.text = StringConstants().email
  207. self.genderTitleLabel.text = StringConstants().gender
  208. self.nativeCountryTitleLabel.text = StringConstants().nativeCountry
  209. self.addressInKoreaTitleLabel.text = StringConstants().addressInKorea
  210. self.provinceTitleLabel.text = StringConstants().province
  211. self.occupationTitleLabel.text = StringConstants().occupation
  212. self.referralCodeTitleLabel.text = StringConstants().referralCode
  213. self.saveAndContinue.setTitle(StringConstants().saveAndCoutinueText, for: UIControlState.normal)
  214. self.firstNameTextField.placeholder = StringConstants().fullnamePlaceholder
  215. self.mobileNumberTextField.placeholder = StringConstants().mobilePlaceholder
  216. self.emailTextField.placeholder = StringConstants().emailPlaceholder
  217. self.genderTextField.placeholder = StringConstants().genderPlacholder
  218. self.nativeCountryTextField.placeholder = StringConstants().nativeCountryPlaceholder
  219. self.countryTextField.placeholder = StringConstants().addressPlaceholder
  220. self.provinceTextField.placeholder = StringConstants().provincePlaceholder
  221. self.occupationTextField.placeholder = StringConstants().occupationPlaceholder
  222. }
  223. private func setupEmail() {
  224. if let email = UserDefaults.standard.string(forKey: UserKeys.email) {
  225. self.emailTextField.text = email
  226. self.emailTextField.isUserInteractionEnabled = false
  227. }
  228. }
  229. private func setupDelegates() {
  230. self.firstNameTextField.delegate = self
  231. self.lastNameTextField.delegate = self
  232. self.middleNmaeTextField.delegate = self
  233. self.genderTextField.delegate = self
  234. self.emailTextField.delegate = self
  235. self.dobTextField.delegate = self
  236. self.countryTextField.delegate = self
  237. self.nativeCountryTextField.delegate = self
  238. self.occupationTextField.delegate = self
  239. self.mobileNumberTextField.delegate = self
  240. self.provinceTextField.delegate = self
  241. }
  242. private func setupDatePicker() {
  243. self.datePicker.datePickerMode = .date
  244. self.dobTextField.inputView = datePicker
  245. datePicker.maximumDate = Date()
  246. self.datePicker.addTarget(self, action: #selector(handleDatePicker(sender:)), for: .valueChanged)
  247. }
  248. @objc private func handleDatePicker(sender: UIDatePicker) {
  249. let dateFormatter = DateFormatter()
  250. // test ccr
  251. dateFormatter.dateFormat = AppConstants.dateFormat
  252. self.dobTextField.text = dateFormatter.string(from: sender.date)
  253. }
  254. private func validate() {
  255. self.createModel()
  256. self.delegate?.addModel(model: self.kycForm1Model)
  257. }
  258. private func hideErrorLabels() {
  259. [firstNameErrorLabel, middleNameErrorLabel, lastNameErrorLabel, genderErrorLabel, dobErrorLabel, mobileNumberErrorLabel, emailErrorLabel, nativeCountryErrorLabel, countryErrorLabel, provinceErrorLabel, occupationErrorLabel, referralCodeErrorLabel].forEach({
  260. $0?.isHidden = true
  261. })
  262. }
  263. private func setupErrorLabels() {
  264. self.errorLabels = [firstNameErrorLabel, middleNameErrorLabel, lastNameErrorLabel, genderErrorLabel, dobErrorLabel, mobileNumberErrorLabel, emailErrorLabel, nativeCountryErrorLabel, nativeCountryErrorLabel, provinceErrorLabel, occupationErrorLabel, countryErrorLabel, referralCodeErrorLabel]
  265. self.errorLabels.forEach({
  266. $0.font = Constants.errorLabelFont
  267. })
  268. self.errorLabelsDict =
  269. [
  270. KycForm1FieldKeys.firstName: self.firstNameErrorLabel,
  271. KycForm1FieldKeys.gender: self.genderErrorLabel,
  272. // KycForm1FieldKeys.dob: self.dobErrorLabel,
  273. KycForm1FieldKeys.mobileNumber: self.mobileNumberErrorLabel,
  274. KycForm1FieldKeys.email: self.emailErrorLabel,
  275. KycForm1FieldKeys.nativeCountry: self.nativeCountryErrorLabel,
  276. KycForm1FieldKeys.country: self.countryErrorLabel,
  277. KycForm1FieldKeys.province: self.provinceErrorLabel,
  278. KycForm1FieldKeys.occupation: self.occupationErrorLabel
  279. ]
  280. }
  281. private func setupErrorTextFields() {
  282. self.textfields = [firstNameTextField, lastNameTextField, middleNmaeTextField, genderTextField, dobTextField, mobileNumberTextField, emailTextField, nativeCountryTextField, countryTextField, provinceTextField, occupationTextField]
  283. firstNameTextField.tag = 1
  284. middleNmaeTextField.tag = 2
  285. lastNameTextField.tag = 3
  286. genderTextField.tag = 4
  287. dobTextField.tag = 5
  288. mobileNumberTextField.tag = 6
  289. emailTextField.tag = 7
  290. nativeCountryTextField.tag = 8
  291. countryTextField.tag = 9
  292. provinceTextField.tag = 10
  293. occupationTextField.tag = 11
  294. self.errorTextFieldDict =
  295. [
  296. KycForm1FieldKeys.firstName: self.firstNameTextField,
  297. KycForm1FieldKeys.gender: self.genderTextField,
  298. KycForm1FieldKeys.mobileNumber: self.mobileNumberTextField,
  299. KycForm1FieldKeys.email: self.emailTextField,
  300. KycForm1FieldKeys.nativeCountry: self.nativeCountryTextField,
  301. KycForm1FieldKeys.country: self.countryTextField,
  302. KycForm1FieldKeys.province: self.provinceTextField,
  303. KycForm1FieldKeys.occupation: self.occupationTextField
  304. ]
  305. }
  306. private func showBorder(textfield :UITextField?) {
  307. guard let textfield = textfield else {return}
  308. textfield.layer.borderColor = Constants.stateRedColor.cgColor
  309. textfield.layer.borderWidth = Constants.errorBorderWidth
  310. textfield.layer.addShadow(with: Constants.stateRedColor)
  311. }
  312. private func show( error: String, label: UILabel?) {
  313. // scroll to the top of the view
  314. guard let label = label else {return}
  315. label.textColor = Constants.stateRedColor
  316. label.isHidden = false
  317. label.text = error
  318. }
  319. }
  320. // MARK: KycForm1ViewInterface
  321. extension KycForm1ViewController: KycForm1ViewInterface {
  322. // todo remove this from this viper flow. its now in parent
  323. func show(result: (doesNotSucks: Bool, errorsDick: [String : String])) {
  324. var position = 11
  325. if result.doesNotSucks { // if isValid
  326. // its is not valid, lets go to security page only if continue button was tapped
  327. if self.continueActionInitiated {
  328. self.delegate?._continue(model: self.kycForm1Model)
  329. }
  330. }else {
  331. result.errorsDick.forEach({
  332. let label = errorLabelsDict[$0.key]
  333. self.show(error: $0.value, label: label)
  334. let textfield = errorTextFieldDict[$0.key]
  335. self.showBorder(textfield: textfield)
  336. let tag = (textfield?.tag ?? position)
  337. position = tag < position ? tag : position
  338. if self.textfields.filter({
  339. $0.tag == tag
  340. }).first != nil {
  341. // Todo
  342. // scroll to view here
  343. }
  344. })
  345. }
  346. }
  347. func show(model: KycModel) {
  348. self.delegate?.show(model: model)
  349. self.kycModel = model
  350. }
  351. func show(error: String) {
  352. self.alert(message: error)
  353. }
  354. func showLoading() {
  355. self.showProgressHud()
  356. }
  357. func hideLoading() {
  358. self.hideProgressHud()
  359. }
  360. }
  361. extension KycForm1ViewController: IndicatorInfoProvider {
  362. func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo {
  363. return IndicatorInfo.init(title: "personal_title_text".localized())
  364. }
  365. }
  366. extension KycForm1ViewController: UITextFieldDelegate {
  367. func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
  368. textField.layer.addShadow(with: Constants.clearColor)
  369. switch textField {
  370. case genderTextField:
  371. self.genderErrorLabel.isHidden = true
  372. genderTextField.layer.borderWidth = 0
  373. self.view.endEditing(true)
  374. self.showGenderPicker()
  375. return false
  376. case nativeCountryTextField:
  377. self.nativeCountryErrorLabel.isHidden = true
  378. nativeCountryTextField.layer.borderWidth = 0
  379. self.view.endEditing(true)
  380. self.showCountryPickerview()
  381. return false
  382. case provinceTextField:
  383. self.provinceErrorLabel.isHidden = true
  384. provinceTextField.layer.borderWidth = 0
  385. self.view.endEditing(true)
  386. self.showProviencePickerview()
  387. return false
  388. case occupationTextField:
  389. self.occupationErrorLabel.isHidden = true
  390. occupationTextField.layer.borderWidth = 0
  391. self.view.endEditing(true)
  392. self.showOccupationPickerView()
  393. return false
  394. default:
  395. return true
  396. }
  397. }
  398. func textFieldDidBeginEditing(_ textField: UITextField) {
  399. textField.layer.addShadow(with: Constants.clearColor)
  400. textField.layer.borderWidth = 0
  401. switch textField {
  402. case firstNameTextField:
  403. self.firstNameErrorLabel.isHidden = true
  404. case middleNmaeTextField:
  405. self.middleNameErrorLabel.isHidden = true
  406. case lastNameTextField:
  407. self.lastNameErrorLabel.isHidden = true
  408. case genderTextField:
  409. self.genderErrorLabel.isHidden = true
  410. case dobTextField:
  411. self.dobErrorLabel.isHidden = true
  412. case mobileNumberTextField:
  413. self.mobileNumberErrorLabel.isHidden = true
  414. case emailTextField:
  415. self.emailErrorLabel.isHidden = true
  416. case nativeCountryTextField:
  417. self.nativeCountryErrorLabel.isHidden = true
  418. case countryTextField:
  419. self.countryErrorLabel.isHidden = true
  420. case provinceTextField:
  421. self.provinceErrorLabel.isHidden = true
  422. case occupationTextField:
  423. self.occupationErrorLabel.isHidden = true
  424. default:
  425. break
  426. }
  427. }
  428. }
  429. extension KycForm1ViewController {
  430. private func showCountryPickerview() {
  431. let viewcontroller = UIStoryboard.init(name: "CountryPicker", bundle: nil).instantiateViewController(withIdentifier: "CountryPickerViewController") as! CountryPickerViewController
  432. let _countries = self.countries ?? []
  433. let data: [SendMoneyCountryViewModel] = _countries.map({
  434. let model = SendMoneyCountryViewModel()
  435. model.id = $0.id
  436. model.name = $0.text
  437. // model.code = $0.code
  438. return model
  439. })
  440. viewcontroller.data = data
  441. viewcontroller.doneAction = self.countrySelected
  442. // viewcontroller.defaultSelectedData = [self.selectedCountry]
  443. viewcontroller.type = PickerTitle.country
  444. self.present(viewcontroller, animated: true, completion: nil)
  445. }
  446. func countrySelected(models: [SendMoneyCountryViewModel]) {
  447. self.selectedCountry = models.first
  448. }
  449. private func showGenderPicker() {
  450. let alertcontroller = UIAlertController.init(title: "gender_text".localized(), message: nil, preferredStyle: .actionSheet)
  451. alertcontroller.view.tintColor = UIColor.init(hex: "#7b7a7a")
  452. let maleAction = UIAlertAction(title: Constants.male, style: .default, handler: { _ in
  453. self.genderTextField.text = Constants.male
  454. })
  455. let femaleAction = UIAlertAction(title: Constants.female, style: .default, handler: { _ in
  456. self.genderTextField.text = Constants.female
  457. })
  458. let otherAction = UIAlertAction(title: Constants.other, style: .default, handler: { _ in
  459. self.genderTextField.text = Constants.other
  460. })
  461. let cancelAction = UIAlertAction(title: Constants.cancelTitleString, style: .cancel, handler: nil)
  462. alertcontroller.addAction(maleAction)
  463. alertcontroller.addAction(femaleAction)
  464. alertcontroller.addAction(otherAction)
  465. alertcontroller.addAction(cancelAction)
  466. self.present(alertcontroller, animated: true, completion: nil)
  467. }
  468. private func showOccupationPickerView() {
  469. let viewcontroller = self.getPickerViewController()
  470. let occupations = self.occupations ?? []
  471. let names = occupations.compactMap({$0.text})
  472. viewcontroller.data = names
  473. viewcontroller.type = PickerTitle.occupation
  474. viewcontroller.doneAction = self.occupationSelected
  475. self.present(viewcontroller, animated: true, completion: nil)
  476. }
  477. private func getPickerViewController()-> ItemsPickerViewController {
  478. return UIStoryboard.init(name: "ItemsPicker", bundle: nil).instantiateViewController(withIdentifier: "ItemsPickerViewController") as! ItemsPickerViewController
  479. }
  480. func occupationSelected(occupations: [String]) {
  481. let _occupation = self.occupations?.filter({($0.text ?? "") == (occupations.first ?? "") }).first
  482. self.selectedOccupation = _occupation
  483. }
  484. private func showProviencePickerview() {
  485. let viewcontroller = self.getPickerViewController()
  486. let proviences = self.proviences
  487. let names = (proviences ?? []).compactMap({$0.text})
  488. viewcontroller.data = names
  489. viewcontroller.type = PickerTitle.state
  490. viewcontroller.doneAction = self.provienceSelected
  491. self.present(viewcontroller, animated: true, completion: nil)
  492. }
  493. func provienceSelected(provience: [String]) {
  494. let _provience = (self.proviences ?? []).filter({
  495. ($0.text ?? "") == (provience.first ?? "")
  496. })
  497. self.selectedProvience = _provience.first
  498. }
  499. }