Advertisement
Guest User

Untitled

a guest
Jun 18th, 2019
165
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 37.88 KB | None | 0 0
  1. //
  2. // BestOffersViewController.swift
  3. // finance
  4. //
  5. // Created by David Yanez on 4/2/18.
  6. // Copyright © 2018 creditsesame. All rights reserved.
  7. //
  8.  
  9. import UIKit
  10. import SnapKit
  11.  
  12. enum OffersTab: String {
  13. case creditCards = "CCs"
  14. case personalLoans = "PLs"
  15. }
  16.  
  17. enum FilterCategory: Int {
  18. case bestCards
  19. case cashBack
  20. case noAnnualFee
  21. case introPurchaseAPR
  22. case rewards
  23. case balanceTransfer
  24.  
  25. var pagePosition: String {
  26. switch self {
  27. case .bestCards:
  28. return AnalyticsPagePosition.bestCards
  29. case .cashBack:
  30. return AnalyticsPagePosition.cashBack
  31. case .noAnnualFee:
  32. return AnalyticsPagePosition.noAnnualFee
  33. case .introPurchaseAPR:
  34. return AnalyticsPagePosition.introPurchaseAPR
  35. case .rewards:
  36. return AnalyticsPagePosition.rewards
  37. case .balanceTransfer:
  38. return AnalyticsPagePosition.balanceTransfer
  39. }
  40. }
  41. }
  42.  
  43. class BestOffersViewController: OffersViewController, UITableViewDelegate, UITableViewDataSource {
  44.  
  45. let ccHeaderIdentifier = "BestCardsHeaderView"
  46. let notFoundIdentifier = "notFoundCellIdentifier"
  47. let pLHeaderIdentifier = "BestPersonalLoanHeaderView"
  48. let footerIdentifier = "MoreCardsFooter"
  49. let newMoreCardsButton = "NewMoreCardsButton"
  50. let dismissViewTag = 989898
  51.  
  52. var bestCards: [CreditCard]?
  53. var creditCardSections: [[CreditCard]] = []
  54. var personalLoan: PersonalLoan?
  55. var offersHeaderView: UIView!
  56. var currentTab: OffersTab = .creditCards
  57. var previousPLCallWasEmptyNoErrors = false
  58. var inputError: Bool {
  59. return incomeInputError || amountInputError
  60. }
  61. var incomeInputError = false
  62. var amountInputError = false
  63.  
  64. var loanAmount: Int {
  65. get {
  66. return AppContext.shared.pLAmountNeeded
  67. }
  68. set {
  69. AppContext.shared.pLAmountNeeded = newValue
  70. }
  71. }
  72.  
  73. var loanAmountTextField: UITextField?
  74. var annualIncomeTextField: UITextField?
  75. var timer: CSTimer?
  76.  
  77. override var screeName: String {
  78. get {
  79. return currentTab == .creditCards ? AnalyticsScreenName.ccOffers : AnalyticsScreenName.plOffers
  80. }
  81. }
  82.  
  83. let filters: [FilterData] = [FilterData(title: " Best Cards", imageName: "star_bestCards"), FilterData(title: " Cash Back", imageName: "cash_cashBack"), FilterData(title: " No Annual Fee", imageName: "calendar_noAnnualFee"), FilterData(title: " 0% Intro Purchase APR", imageName: "shopping_oapr"), FilterData(title: " Rewards", imageName: "palmTrees_rewards"), FilterData(title: " Balance Transfer", imageName: "pig_balanceTransfer")
  84. ]
  85.  
  86. var lastFilterSelected: Int {
  87. get {
  88. return UserDefaults.standard.integer(forKey: "lastFilterSelected")
  89. }
  90. set {
  91. UserDefaults.standard.set(newValue, forKey: "lastFilterSelected")
  92. UserDefaults.standard.synchronize()
  93. }
  94. }
  95.  
  96. override func viewDidLoad() {
  97. super.viewDidLoad()
  98. edgesForExtendedLayout = []
  99. tableView.register(UINib(nibName: ccHeaderIdentifier, bundle: nil), forHeaderFooterViewReuseIdentifier: ccHeaderIdentifier)
  100. tableView.register(UINib(nibName: pLHeaderIdentifier, bundle: nil), forHeaderFooterViewReuseIdentifier: pLHeaderIdentifier)
  101. tableView.register(UINib(nibName: footerIdentifier, bundle: nil), forHeaderFooterViewReuseIdentifier: footerIdentifier)
  102. tableView.register(UINib(nibName: newMoreCardsButton, bundle: nil), forHeaderFooterViewReuseIdentifier: newMoreCardsButton)
  103. tableView.register(UITableViewCell.self, forCellReuseIdentifier: notFoundIdentifier)
  104.  
  105. tableView.estimatedRowHeight = 300
  106. tableView.rowHeight = UITableView.automaticDimension
  107. tableView.estimatedSectionHeaderHeight = 300
  108. tableView.sectionHeaderHeight = UITableView.automaticDimension
  109. tableView.estimatedSectionFooterHeight = 36
  110. tableView.separatorStyle = .singleLine
  111. tableView.separatorColor = .white
  112. tableView.backgroundColor = UIColor.creditSesameLightGrayBackgroundColor
  113. configureStatusBar(color: UIColor.white)
  114.  
  115.  
  116. if CreditSesameRestClient.shared.canShowCreditCardsFilter, TestingManager.shared.newCCFilteringVariation == Variations.variation {
  117. loadData(index: FilterCategory(rawValue: lastFilterSelected) ?? .bestCards)
  118. } else {
  119. loadData(index: .bestCards)
  120. configureFooter()
  121. }
  122.  
  123. configureHeader()
  124.  
  125. }
  126.  
  127. override func scrollToTop() {
  128. tableView?.setContentOffset(.zero, animated: true)
  129. }
  130.  
  131. func configureHeader() {
  132. offersHeaderView = UIView.loadNib("OffersHeaderView")
  133. offersHeaderView.backgroundColor = UIColor.white
  134. let titleLabel = offersHeaderView.labelWithTag(20)
  135. let descriptionLabel = offersHeaderView.labelWithTag(21)
  136. let ccButton = offersHeaderView.buttonWithTag(31)
  137. let pLButton = offersHeaderView.buttonWithTag(41)
  138. titleLabel?.font = UIFont.latoHeavy(20)
  139. titleLabel?.textColor = UIColor.creditSesameGrayTextColor
  140. titleLabel?.text = NSLocalizedString("Your Borrowing Power", comment: "Your Borrowing Power")
  141.  
  142. let textDescription = NSLocalizedString("CreditCardBorrowingPowerDescription", comment: "card borrowing description")
  143. let boldText = NSLocalizedString("credit profile", comment: "credit profile text")
  144. let attributedDescription = NSMutableAttributedString(string: textDescription, attributes: [NSAttributedString.Key.font : UIFont.lato(16), NSAttributedString.Key.foregroundColor : UIColor.creditSesameDarkTextColor])
  145. attributedDescription.addAttributes([NSAttributedString.Key.font : UIFont.latoBold(16)], range: (textDescription as NSString).range(of: boldText))
  146. descriptionLabel?.attributedText = attributedDescription
  147. descriptionLabel?.numberOfLines = 0
  148. descriptionLabel?.lineBreakMode = .byWordWrapping
  149.  
  150. let height = offersHeaderView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
  151. let headerView = UITableViewHeaderFooterView(frame: CGRect(x: 0, y: 0, width: 0, height: height))
  152. headerView.backgroundColor = UIColor.clear
  153.  
  154. headerView.addSubview(offersHeaderView)
  155. offersHeaderView.clipsToBounds = true
  156. offersHeaderView.snp.makeConstraints { (make) in
  157. make.edges.equalToSuperview()
  158. }
  159.  
  160. let selectedttributtes = [NSAttributedString.Key.font : UIFont.lato(16),
  161. NSAttributedString.Key.foregroundColor : UIColor.creditSesameCyan,
  162. NSAttributedString.Key.kern : 0.5] as [NSAttributedString.Key : Any]
  163.  
  164. let unselectedAttributtes = [NSAttributedString.Key.font : UIFont.lato(16),
  165. NSAttributedString.Key.foregroundColor : UIColor.init(rgb: 0x757575),
  166. NSAttributedString.Key.kern : 0.5] as [NSAttributedString.Key : Any]
  167.  
  168. let creditTitle = NSAttributedString(string: NSLocalizedString("Credit Cards", comment: "credit cards button"), attributes: selectedttributtes)
  169. let creditTitleUnSelected = NSAttributedString(string: creditTitle.string, attributes: unselectedAttributtes)
  170. ccButton?.setAttributedTitle(creditTitle, for: .selected)
  171. ccButton?.setAttributedTitle(creditTitleUnSelected, for: .normal)
  172. ccButton?.isSelected = true
  173. ccButton?.addTarget(self, action: #selector(switchToCards), for: .touchUpInside)
  174.  
  175. let debtTitle = NSAttributedString(string: NSLocalizedString("Personal Loans", comment: "personal loans button"), attributes: selectedttributtes)
  176. let debtTitleUnSelected = NSAttributedString(string: debtTitle.string, attributes: unselectedAttributtes)
  177. pLButton?.setAttributedTitle(debtTitleUnSelected, for: .normal)
  178. pLButton?.setAttributedTitle(debtTitle, for: .selected)
  179. pLButton?.backgroundColor = UIColor.clear
  180. pLButton?.isSelected = false
  181. pLButton?.addTarget(self, action: #selector(switchToPLs), for: .touchUpInside)
  182.  
  183. let button = offersHeaderView.buttonWithTag(10)
  184. button?.setThemeAdvertiserDisclosure()
  185. button?.backgroundColor = UIColor.clear
  186. button?.addTarget(self, action: #selector(showAdvertisersDisclosureTooltip), for: .touchUpInside)
  187.  
  188. tableView.tableHeaderView = headerView
  189. addOrRemoveSegmentFilter()
  190. }
  191.  
  192. func disclosureFooterView() -> DisclosureFooterView {
  193. let disclosureFooterView = DisclosureFooterView()
  194. disclosureFooterView.providerTermsPressed = { [weak self] in
  195. self?.showProviderTermsDisclosureTooltip()
  196. }
  197. disclosureFooterView.editorialDisclosurePressed = { [weak self] in
  198. self?.showEditorialDisclosureTooltip()
  199.  
  200. }
  201.  
  202. return disclosureFooterView
  203. }
  204.  
  205. func configureFooter() {
  206.  
  207. if currentTab == .personalLoans || (CreditSesameRestClient.shared.canShowCreditCardsFilter && TestingManager.shared.newCCFilteringVariation == Variations.variation) {
  208. tableView.tableFooterView = nil
  209. return
  210. }
  211.  
  212. let offersFooterView = UIView.loadNib("OffersFooterView")
  213. offersFooterView.backgroundColor = UIColor.creditSesameLightGrayBackgroundColor
  214. let balanceButton = offersFooterView.buttonWithTag(11)!
  215. balanceButton.addTarget(self, action: #selector(browseCategories(button:)), for: .touchUpInside)
  216. balanceButton.accessibilityLabel = NSLocalizedString("Balance Transfer", comment: "BT Cards Header")
  217. let zeroPercentButton = offersFooterView.buttonWithTag(12)!
  218. zeroPercentButton.addTarget(self, action: #selector(browseCategories(button:)), for: .touchUpInside)
  219. zeroPercentButton.accessibilityLabel = NSLocalizedString("ZeroPurchaseAPR", comment: "0% Intro Purchase APR Header")
  220. let rewardsButton = offersFooterView.buttonWithTag(13)!
  221. rewardsButton.addTarget(self, action: #selector(browseCategories(button:)), for: .touchUpInside)
  222. rewardsButton.accessibilityLabel = NSLocalizedString("Rewards", comment: "Rewards Cards Header")
  223.  
  224. let titleLabel = offersFooterView.labelWithTag(10)
  225. titleLabel?.font = UIFont.latoBold(20)
  226. titleLabel?.textColor = UIColor.creditSesameDarkTextColor
  227. titleLabel?.text = NSLocalizedString("Credit Card Categories", comment: "Footer categories")
  228. let height = offersFooterView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
  229. let footerView = UITableViewHeaderFooterView(frame: CGRect(x: 0, y: 0, width: 0, height: height))
  230. footerView.backgroundColor = UIColor.clear
  231. footerView.addSubview(offersFooterView)
  232. offersFooterView.clipsToBounds = true
  233. offersFooterView.snp.makeConstraints { (make) in
  234. make.edges.equalToSuperview()
  235. }
  236.  
  237. let disclosureContainerView = offersFooterView.viewWithTag(14)
  238. let disclosureView = disclosureFooterView()
  239. disclosureContainerView?.addSubview(disclosureView)
  240. disclosureView.snp.makeConstraints { make in
  241. make.edges.equalToSuperview()
  242. }
  243.  
  244. tableView.tableFooterView = footerView
  245. }
  246.  
  247. func loadPersonalLoanIfNeeded(isInputChange: Bool = false) {
  248.  
  249. let currentIncome = CreditSesameRestClient.shared.user?.annualIncome
  250. let currentAmount = AppContext.shared.pLAmountNeeded
  251. // update income and amount if they did change
  252. var needsNewPLFromServer = false
  253. if let income = annualIncomeTextField?.text?.removeMoneyFormat() {
  254. if let userIncome = currentIncome, income.doubleValue != userIncome.doubleValue {
  255. let newIncome = isInputChange ? income : userIncome
  256. annualIncomeTextField?.text = String.moneyFormattedString(number: newIncome)
  257. incomeInputError = false
  258. needsNewPLFromServer = true
  259. }
  260. }
  261. if let amount = loanAmountTextField?.text?.removeMoneyFormat() {
  262. if amount.intValue != currentAmount {
  263. let newAmount = isInputChange ? amount : NSNumber(value: currentAmount)
  264. loanAmountTextField?.text = String.moneyFormattedString(number: newAmount)
  265. amountInputError = false
  266. needsNewPLFromServer = true
  267. }
  268. }
  269.  
  270. if (personalLoan != nil || (personalLoan == nil && previousPLCallWasEmptyNoErrors && !inputError)) && !needsNewPLFromServer {
  271. self.tableView.reloadData()
  272. self.configureFooter()
  273. self.addOrRemoveSegmentFilter()
  274. return
  275. }
  276.  
  277. let annualIncome = annualIncomeTextField?.text?.removeMoneyFormat().intValue ?? CreditSesameRestClient.shared.user?.annualIncome?.intValue ?? 0
  278. let amount = loanAmountTextField?.text?.removeMoneyFormat().intValue ?? loanAmount
  279.  
  280. showProgressView()
  281.  
  282. CreditSesameRestClient.shared.getAllPersonalLoans(loanAmount: amount, annualIncome: annualIncome, page: 1, itemsPerPage: 10) { (personalLoans, error) in
  283. self.hideProgressView()
  284.  
  285. if let _ = error {
  286. self.personalLoan = nil
  287. self.previousPLCallWasEmptyNoErrors = false
  288. }
  289. else if let personalLoans = personalLoans, personalLoans.count > 0 {
  290. self.personalLoan = personalLoans.first
  291. self.previousPLCallWasEmptyNoErrors = false
  292. }
  293. else {
  294. self.personalLoan = nil
  295. self.previousPLCallWasEmptyNoErrors = true
  296. }
  297. self.tableView.reloadData()
  298. self.configureFooter()
  299. self.addOrRemoveSegmentFilter()
  300. }
  301. }
  302.  
  303. override func keyboardWillShow(_ notification: Notification) {
  304. super.keyboardWillShow(notification)
  305.  
  306. if view.viewWithTag(dismissViewTag) == nil {
  307. let dismissView = UIView()
  308. let dismissTapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapView(_:)))
  309. dismissView.tag = dismissViewTag
  310. dismissView.backgroundColor = UIColor.clear
  311. dismissView.addGestureRecognizer(dismissTapGesture)
  312. view.addSubview(dismissView)
  313. dismissView.snp.makeConstraints { make in
  314. make.edges.equalToSuperview()
  315. }
  316. }
  317. }
  318.  
  319. override func keyboardWillHide(_ notification: Notification) {
  320. super.keyboardWillHide(notification)
  321.  
  322. if let v = view.viewWithTag(dismissViewTag) {
  323. v.removeFromSuperview()
  324. }
  325. }
  326.  
  327. @objc func switchToCards() {
  328.  
  329. if currentTab == .creditCards {
  330. return
  331. }
  332.  
  333. let ccButton = offersHeaderView.buttonWithTag(31)
  334. let ccBorderView = offersHeaderView.viewWithTag(32)
  335. let pLButton = offersHeaderView.buttonWithTag(41)
  336. let pLBorderView = offersHeaderView.viewWithTag(42)
  337.  
  338. ccButton?.isSelected = true
  339. ccBorderView?.isHidden = false
  340. pLButton?.isSelected = false
  341. pLBorderView?.isHidden = true
  342.  
  343. currentTab = .creditCards
  344. addOrRemoveSegmentFilter()
  345. tableView.reloadData()
  346. configureFooter()
  347. trackViewPage()
  348. }
  349.  
  350. @objc func switchToPLs() {
  351.  
  352. if currentTab == .personalLoans {
  353. return
  354. }
  355.  
  356. let ccButton = offersHeaderView.buttonWithTag(31)
  357. let ccBorderView = offersHeaderView.viewWithTag(32)
  358. let pLButton = offersHeaderView.buttonWithTag(41)
  359. let pLBorderView = offersHeaderView.viewWithTag(42)
  360.  
  361. ccButton?.isSelected = false
  362. ccBorderView?.isHidden = true
  363. pLButton?.isSelected = true
  364. pLBorderView?.isHidden = false
  365.  
  366. currentTab = .personalLoans
  367. loadPersonalLoanIfNeeded()
  368. trackViewPage()
  369. }
  370.  
  371. @objc func browseCategories(button: UIButton) {
  372.  
  373. switch button.tag {
  374. case 11:
  375.  
  376. let cards = CreditSesameRestClient.shared.balanceTransferCards ?? []
  377. self.openCreditCards(screen: .bestCardsBT, creditCards: cards)
  378. trackClickNavigation(navigationLocation: AnalyticsNavLocation.bestCardsBT)
  379. case 12:
  380.  
  381. let cards = CreditSesameRestClient.shared.zeroPercentCards ?? []
  382. self.openCreditCards(screen: .bestCardsZeroPercent, creditCards: cards)
  383. trackClickNavigation(navigationLocation: AnalyticsNavLocation.bestCardsZeroPercent)
  384. case 13:
  385.  
  386. let cards = CreditSesameRestClient.shared.rewardsCards ?? []
  387. self.openCreditCards(screen: .bestCardsRewards, creditCards: cards)
  388. trackClickNavigation(navigationLocation: AnalyticsNavLocation.bestCardsRewards)
  389. default:
  390. break
  391. }
  392. }
  393.  
  394. @objc func viewMoreCards(button: UIButton) {
  395. openCreditCardsMarketplace()
  396. }
  397.  
  398. @objc func editAmount() {
  399. loanAmountTextField?.becomeFirstResponder()
  400. }
  401.  
  402. @objc func editIncome() {
  403. annualIncomeTextField?.becomeFirstResponder()
  404. }
  405.  
  406. override func viewWillAppear(_ animated: Bool) {
  407. super.viewWillAppear(animated)
  408. navigationController?.setNavigationBarHidden(true, animated: true)
  409. creditSesameNavigationController?.setNavigationBarHidden(true, animated: true)
  410. }
  411.  
  412. override func viewDidAppear(_ animated: Bool) {
  413. super.viewDidAppear(animated)
  414.  
  415.  
  416.  
  417. if currentTab == .personalLoans {
  418. self.loadPersonalLoanIfNeeded()
  419. }
  420. }
  421.  
  422. func loadData(index: FilterCategory) {
  423. switch index {
  424. case .bestCards:
  425. creditCardSections = [CreditSesameRestClient.shared.bestCards ?? []]
  426. case .cashBack:
  427. creditCardSections = [CreditSesameRestClient.shared.cashBackCards ?? []]
  428. case .noAnnualFee:
  429. creditCardSections = [CreditSesameRestClient.shared.noAnnualFeeCards ?? []]
  430. case .introPurchaseAPR:
  431. creditCardSections = [CreditSesameRestClient.shared.zeroPercentCards ?? []]
  432. case .rewards:
  433. creditCardSections = [CreditSesameRestClient.shared.rewardsCards ?? []]
  434. case .balanceTransfer:
  435. creditCardSections = [CreditSesameRestClient.shared.balanceTransferCards ?? []]
  436. }
  437. self.tableView.reloadData()
  438. }
  439.  
  440. func addOrRemoveSegmentFilter() {
  441. let spaceFilterView: UIView = offersHeaderView.viewWithTag(49)!
  442. let segmentControl = offersHeaderView.viewWithTag(43) as! DGScrollableSegmentControl
  443. spaceFilterView.backgroundColor = UIColor.creditSesameLightGrayBackgroundColor
  444. segmentControl.backgroundColor = UIColor.creditSesameLightGrayBackgroundColor
  445. segmentControl.delegate = self
  446. segmentControl.datasource = self
  447.  
  448. segmentControl.updateHeightConstraint(height: 0, constraintIdentifier: "filterHeight")
  449. spaceFilterView.updateHeightConstraint(height: 0, constraintIdentifier: "heightSpaceFilter")
  450.  
  451. if CreditSesameRestClient.shared.canShowCreditCardsFilter, TestingManager.shared.newCCFilteringVariation == Variations.variation, currentTab == .creditCards {
  452. segmentControl.updateHeightConstraint(height: 32, constraintIdentifier: "filterHeight")
  453. spaceFilterView.updateHeightConstraint(height: 16, constraintIdentifier: "heightSpaceFilter")
  454. }
  455.  
  456. sizeHeaderToFit()
  457. }
  458.  
  459. func sizeHeaderToFit() {
  460. if let headerView = tableView.tableHeaderView {
  461. headerView.setNeedsLayout()
  462. headerView.layoutIfNeeded()
  463.  
  464. let height = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
  465. var frame = headerView.frame
  466. frame.size.height = height
  467. headerView.frame = frame
  468.  
  469. tableView.tableHeaderView = headerView
  470. }
  471. }
  472.  
  473. func numberOfSections(in tableView: UITableView) -> Int {
  474. return 1
  475. }
  476.  
  477. func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  478. switch currentTab {
  479. case .creditCards:
  480. let cards = creditCardSections[section]
  481. return min(3, cards.count)
  482. case .personalLoans:
  483. return 1
  484. }
  485. }
  486.  
  487. func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
  488. switch currentTab {
  489. case .creditCards:
  490. let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: ccHeaderIdentifier)
  491. let backgroundView = view?.viewWithTag(10)
  492. let label = view?.labelWithTag(11)
  493.  
  494. backgroundView?.backgroundColor = UIColor.creditSesameLightGrayBackgroundColor
  495.  
  496. label?.font = UIFont.latoBlack(20)
  497. label?.textColor = UIColor.creditSesameDarkTextColor
  498.  
  499. let attributedText = NSMutableAttributedString(string: NSLocalizedString("Best Cards", comment: "Best Cards Cards Header"), attributes:
  500. [NSAttributedString.Key.foregroundColor : UIColor.init(rgb: 0x929292),
  501. NSAttributedString.Key.font : UIFont.lato(20)])
  502. attributedText.addAttributes([NSAttributedString.Key.foregroundColor : UIColor.creditSesameGrayTextColor,
  503. NSAttributedString.Key.font : UIFont.latoHeavy(20)], range: (attributedText.string as NSString).range(of: "Best Cards"))
  504. label?.attributedText = attributedText
  505. view?.addTopSeparator()
  506. if CreditSesameRestClient.shared.canShowCreditCardsFilter, TestingManager.shared.newCCFilteringVariation == Variations.variation {
  507. return nil
  508. } else {
  509. return view
  510. }
  511.  
  512. case .personalLoans:
  513. let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: pLHeaderIdentifier)
  514. let amountLabel = view?.labelWithTag(21)
  515. let amountView = view?.viewWithTag(200)
  516. let amountTextField = view?.textFieldWithTag(22) as? TextField
  517. let amountTooltip = view?.buttonWithTag(23)
  518. let incomeLabel = view?.labelWithTag(31)
  519. let incomeView = view?.viewWithTag(300)
  520. let incomeTextField = view?.textFieldWithTag(32) as? TextField
  521. let incomeTooltip = view?.buttonWithTag(33)
  522.  
  523. let amountNumber = loanAmountTextField?.text?.removeMoneyFormat() ?? NSNumber(value: loanAmount)
  524. let annualIncome = annualIncomeTextField?.text?.removeMoneyFormat() ?? CreditSesameRestClient.shared.user?.annualIncome ?? NSNumber(value: 0)
  525.  
  526. amountLabel?.font = UIFont.lato(16)
  527. amountLabel?.textColor = UIColor.creditSesameGrayTextColor
  528. amountLabel?.text = NSLocalizedString("Loan Amount", comment: "loan amount label")
  529. amountTextField?.text = String.moneyFormattedString(number: amountNumber)
  530. amountTextField?.font = UIFont.latoMedium(16)
  531. amountTextField?.textColor = UIColor.black
  532. amountTextField?.keyboardType = .numberPad
  533. amountTextField?.delegate = self
  534. amountTextField?.maxCharacters = 6
  535. amountView?.layer.borderColor = UIColor.creditSesameGrayBackgroundColor.cgColor
  536. amountView?.layer.borderWidth = 1
  537. loanAmountTextField = amountTextField
  538. amountTooltip?.addTarget(self, action: #selector(showPLAmountTooltip), for: .touchUpInside)
  539.  
  540. amountView?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(editAmount)))
  541.  
  542. incomeLabel?.font = UIFont.lato(16)
  543. incomeLabel?.textColor = UIColor.creditSesameGrayTextColor
  544. incomeLabel?.text = NSLocalizedString("Annual Income", comment: "income label")
  545. incomeTextField?.text = String.moneyFormattedString(number: annualIncome)
  546. incomeTextField?.font = UIFont.latoMedium(16)
  547. incomeTextField?.textColor = UIColor.black
  548. incomeTextField?.keyboardType = .numberPad
  549. incomeTextField?.delegate = self
  550. incomeTextField?.maxCharacters = 7
  551. incomeView?.layer.borderColor = UIColor.creditSesameGrayBackgroundColor.cgColor
  552. incomeView?.layer.borderWidth = 1
  553. annualIncomeTextField = incomeTextField
  554. incomeTooltip?.addTarget(self, action: #selector(showPLIncomeTooltip), for: .touchUpInside)
  555.  
  556. incomeView?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(editIncome)))
  557.  
  558. return view
  559. }
  560.  
  561. }
  562.  
  563. func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
  564. return currentTab == .creditCards ? (CreditSesameRestClient.shared.canShowCreditCardsFilter && TestingManager.shared.newCCFilteringVariation == Variations.variation ? 72 : 36) : 60
  565. }
  566.  
  567. func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
  568. let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: footerIdentifier)
  569. let actionView = view?.viewWithTag(100)
  570. let button = view?.buttonWithTag(10)
  571. let line = view?.viewWithTag(11)
  572. line?.backgroundColor = UIColor.creditSesameLightGrayBackgroundColor
  573. button?.setTitleColor(UIColor.creditSesameCyan, for: .normal)
  574. button?.titleLabel?.font = UIFont.lato(14)
  575. view?.backgroundColor = UIColor.white
  576. actionView?.addTopSeparator()
  577. actionView?.addBottomSeparator()
  578.  
  579. switch currentTab {
  580. case .creditCards:
  581.  
  582. if CreditSesameRestClient.shared.canShowCreditCardsFilter, TestingManager.shared.newCCFilteringVariation == Variations.variation {
  583. return newMoreFooterView
  584. }
  585. button?.setTitle(NSLocalizedString("See All Credit Cards", comment: "More Cards button"), for: .normal)
  586. button?.superview?.tag = section
  587. button?.removeTarget(self, action: #selector(openPersonalLoansMarketplace), for: .touchUpInside)
  588. button?.addTarget(self, action: #selector(viewMoreCards), for: .touchUpInside)
  589.  
  590. case .personalLoans:
  591. guard let _ = personalLoan else {
  592. return nil
  593. }
  594. button?.setTitle(NSLocalizedString("See More Personal Loans", comment: "More Cards button"), for: .normal)
  595. button?.removeTarget(self, action: #selector(viewMoreCards), for: .touchUpInside)
  596. button?.addTarget(self, action: #selector(openPersonalLoansMarketplace), for: .touchUpInside)
  597.  
  598. }
  599.  
  600. return view
  601.  
  602. }
  603.  
  604. var newMoreFooterView: UIView? {
  605. let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: newMoreCardsButton)
  606. let button = view?.buttonWithTag(10)
  607. button?.setTitleColor(UIColor.white, for: .normal)
  608. button?.titleLabel?.font = UIFont.latoSemiBold(13)
  609. button?.backgroundColor = UIColor.creditSesameCyan
  610. button?.setTitle(NSLocalizedString("Search All Credit Cards", comment: "More Cards"), for: .normal)
  611. view?.addTopSeparator()
  612. button?.addTarget(self, action: #selector(viewMoreCards), for: .touchUpInside)
  613. return view
  614. }
  615.  
  616. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  617. switch currentTab {
  618. case .creditCards:
  619. let creditCards = creditCardSections[indexPath.section]
  620. let creditCard = creditCards[indexPath.row]
  621. var creditCardCell: ClickApplyCell? = nil
  622. var pagePosition: String
  623. pagePosition = AnalyticsPagePosition.bestCards
  624. if CreditSesameRestClient.shared.canShowCreditCardsFilter, TestingManager.shared.newCCFilteringVariation == Variations.variation {
  625. let filterCategory = FilterCategory(rawValue: lastFilterSelected) ?? .bestCards
  626. pagePosition = filterCategory.pagePosition
  627. }
  628. creditCardCell = cellForCreditCard(creditCard: creditCard, offerType: .estimatedCreditLimit)
  629. creditCardCell?.contentView.tag = indexPath.row
  630.  
  631. let offerPosition = numberOfOffersTill(section: indexPath.section, tableView: tableView) + indexPath.row + 1
  632. creditCardCell?.cellPosition = "\(offerPosition)"
  633. creditCardCell?.pagePosition = pagePosition
  634. creditCardCell?.offer = creditCard
  635. creditCardCell?.selectionStyle = .none
  636. creditCardCell?.addTopSeparator()
  637.  
  638. trackViewOfferCreditCard(creditCard: creditCard, pagePosition: pagePosition, pageLocation: nil, offerPosition: creditCardCell?.cellPosition!)
  639. return creditCardCell!
  640.  
  641. case .personalLoans:
  642. if let loan = personalLoan {
  643. let personalLoanCell = cellForPersonalLoan(pL: loan, offerType: loan.offerType)
  644. let offerPosition = numberOfOffersTill(section: indexPath.section, tableView: tableView) + indexPath.row + 1
  645. personalLoanCell.cellPosition = "\(offerPosition)"
  646. personalLoanCell.pagePosition = nil
  647. personalLoanCell.pageLocation = nil
  648. personalLoanCell.offer = loan
  649. personalLoanCell.selectionStyle = .none
  650.  
  651. trackViewOfferPersonalLoan(personalLoan: personalLoan!, pagePosition: nil, pageLocation: nil, offerPosition: "1")
  652. return personalLoanCell
  653. }
  654. else if let cell = tableView.dequeueReusableCell(withIdentifier: notFoundIdentifier) {
  655.  
  656. for v in cell.contentView.subviews {
  657. v.removeFromSuperview()
  658. }
  659.  
  660. let view = UIView.loadNib("OffersNotFoundView")
  661. let titleLabel = view.labelWithTag(10)
  662. let contentLabel = view.labelWithTag(11)
  663. let actionView = view.viewWithTag(20)
  664. let actionButton = view.buttonWithTag(21)
  665. let accessibilityView = view.viewWithTag(30)!
  666.  
  667. titleLabel?.font = UIFont.latoHeavy(18)
  668. titleLabel?.textColor = UIColor.init(rgb: 0x606060)
  669. titleLabel?.text = ClientConfigurationManager.shared.configurationFile?.disclaimers?.loansNotFoundTitle ?? NSLocalizedString("Loans Offer Not Found title", comment: "Not found title")
  670. contentLabel?.font = UIFont.lato(14)
  671. contentLabel?.textColor = UIColor.init(rgb: 0x606060)
  672. contentLabel?.textAlignment = .left
  673. contentLabel?.text = ClientConfigurationManager.shared.configurationFile?.disclaimers?.loansNotFoundContent ?? NSLocalizedString("Loans Offer Not Found content", comment: "Not found content")
  674. contentLabel?.numberOfLines = 0
  675. contentLabel?.lineBreakMode = .byWordWrapping
  676.  
  677. actionView?.isHidden = false
  678. let buttonTitle = currentTab == .creditCards ? NSLocalizedString("Search All Credit Cards", comment: "Market place button") : NSLocalizedString("Search All Personal Loans", comment: "Market place button")
  679. actionButton?.setThemeInfoButton(title: buttonTitle)
  680. let selector = currentTab == .creditCards ? #selector(openCreditCardsMarketplace) : #selector(openPersonalLoansMarketplace)
  681. actionButton?.addTarget(self, action: selector, for: .touchUpInside)
  682.  
  683. cell.contentView.addSubview(view)
  684. view.snp.makeConstraints({ make in
  685. make.edges.equalToSuperview()
  686. })
  687.  
  688. cell.selectionStyle = .none
  689. cell.backgroundColor = UIColor.creditSesameLightGrayBackgroundColor
  690.  
  691. accessibilityView.isAccessibilityElement = true
  692. accessibilityView.accessibilityLabel = "\(titleLabel?.text ?? ""): \(contentLabel?.text ?? "")"
  693.  
  694. return cell
  695. }
  696. }
  697.  
  698. return UITableViewCell()
  699. }
  700.  
  701. func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  702. tableView.deselectRow(at: indexPath, animated: true)
  703. }
  704.  
  705. }
  706.  
  707. extension BestOffersViewController: UITextFieldDelegate {
  708.  
  709. func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
  710. textField.text = "\(textField.text?.removeMoneyFormat().intValue ?? 0)"
  711.  
  712. if textField == self.loanAmountTextField {
  713. trackClick(clickType: AnalyticsClickType.enterLoanAmount, pagePosition: nil)
  714. }
  715.  
  716. // update annual income
  717. if textField == self.annualIncomeTextField {
  718. trackClick(clickType: AnalyticsClickType.updateIncome, pagePosition: nil)
  719. }
  720.  
  721. return true
  722. }
  723.  
  724. func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
  725.  
  726. let currentString = textField.text! as NSString
  727. let newString = currentString.replacingCharacters(in: range, with: string) as NSString
  728.  
  729. if let textField = textField as? TextField, let maxLength = textField.maxCharacters, newString.length > maxLength {
  730. return false
  731. }
  732.  
  733. if let timer = timer {
  734. timer.startTimer()
  735. }
  736. else {
  737. timer = CSTimer()
  738. timer?.action = {
  739.  
  740. if (self.annualIncomeTextField?.text?.count ?? 0) == 0 || (self.loanAmountTextField?.text?.count ?? 0) == 0 {
  741. return
  742. }
  743.  
  744. self.loadPersonalLoanIfNeeded(isInputChange: true)
  745. DispatchQueue.main.async {
  746. self.hideKeyboard()
  747. }
  748. }
  749. timer?.startTimer()
  750. }
  751. return true
  752. }
  753.  
  754. func textFieldDidEndEditing(_ textField: UITextField) {
  755. let money = textField.text?.removeMoneyFormat().doubleValue ?? 0
  756.  
  757. // update amount needed
  758. if textField == self.loanAmountTextField {
  759. guard money >= 0 && money <= 100000 else {
  760. let message = ClientConfigurationManager.shared.configurationFile?.errorValidation?.errorLoanAmount ?? NSLocalizedString("AmountNeededTooltip", comment: "amount loan error")
  761. showAppClientError(message)
  762. textField.text = String.moneyFormattedString(number: NSNumber(value: money))
  763. amountInputError = true
  764. return
  765. }
  766. amountInputError = false
  767. loanAmount = Int(money)
  768. }
  769.  
  770. // update annual income
  771. if textField == self.annualIncomeTextField {
  772. guard money > 0 else {
  773. let message = ClientConfigurationManager.shared.configurationFile?.errorValidation?.errorAnnualIncome ?? NSLocalizedString("CalculateDTIIncomeError", comment: "invalid income error")
  774. showAppClientError(message)
  775. textField.text = String.moneyFormattedString(number: NSNumber(value: money))
  776. incomeInputError = true
  777. return
  778. }
  779.  
  780. incomeInputError = false
  781. let user = CreditSesameRestClient.shared.user?.copy() as? User ?? User()
  782. if user.annualIncome?.doubleValue != money {
  783. user.annualIncome = NSNumber(value: money)
  784. CreditSesameRestClient.shared.updateUser(user: user, password: AppContext.shared.password)
  785. }
  786. }
  787.  
  788. textField.text = String.moneyFormattedString(number: NSNumber(value: money))
  789. }
  790. }
  791.  
  792. extension BestOffersViewController: DGScrollableSegmentControlDataSource,DGScrollableSegmentControlDelegate {
  793.  
  794.  
  795. func numbersOfItem() -> Int {
  796. return filters.count
  797. }
  798.  
  799. func itemfor(_ index: Int) -> DGItem {
  800.  
  801. let item = DGItem()
  802. item.setTitle(filters[index].title, for: .normal)
  803. item.isSelected = index == lastFilterSelected
  804. item.setImage(UIImage(named: filters[index].imageName), for: .normal)
  805. item.titleLabel?.font = UIFont.latoSemiBold(12)
  806.  
  807. if item.isSelected {
  808. item.setTitleColor(UIColor.white, for: .normal)
  809. item.backgroundColor = UIColor.creditSesameCyan
  810. } else {
  811. item.setTitleColor(UIColor.creditSesameCyan, for: .normal)
  812. item.backgroundColor = UIColor.white
  813. }
  814. item.updateBorder()
  815.  
  816. return item
  817.  
  818. }
  819.  
  820. func didSelect(_ item: DGItem, atIndex index: Int) {
  821. lastFilterSelected = index
  822. let filterCategory = FilterCategory(rawValue: lastFilterSelected) ?? .bestCards
  823. loadData(index: filterCategory)
  824. switch filterCategory {
  825. case .bestCards:
  826. trackClick(clickType: AnalyticsClickType.filter, pagePosition: AnalyticsPagePosition.bestCards)
  827. case .cashBack:
  828. trackClick(clickType: AnalyticsClickType.filter, pagePosition: AnalyticsPagePosition.cashBack)
  829. case .noAnnualFee:
  830. trackClick(clickType: AnalyticsClickType.filter, pagePosition: AnalyticsPagePosition.noAnnualFee)
  831. case .introPurchaseAPR:
  832. trackClick(clickType: AnalyticsClickType.filter, pagePosition: AnalyticsPagePosition.introPurchaseAPR)
  833. case .rewards:
  834. trackClick(clickType: AnalyticsClickType.filter, pagePosition: AnalyticsPagePosition.rewards)
  835. case .balanceTransfer:
  836. trackClick(clickType: AnalyticsClickType.filter, pagePosition: AnalyticsPagePosition.balanceTransfer)
  837. }
  838. }
  839. }
  840.  
  841. struct FilterData {
  842.  
  843. var title = ""
  844. var imageName = ""
  845.  
  846. init(title: String, imageName: String) {
  847. self.title = title
  848. self.imageName = imageName
  849. }
  850.  
  851. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement