SHARE
TWEET

Untitled

a guest Jun 18th, 2019 82 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top