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.

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