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.

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