mirror of
https://github.com/AU-COVIDSafe/mobile-ios.git
synced 2025-04-05 06:14:59 +00:00
380 lines
15 KiB
Swift
380 lines
15 KiB
Swift
![]() |
//
|
||
|
// RestrictionTableViewController.swift
|
||
|
// CovidSafe
|
||
|
//
|
||
|
// Copyright © 2021 Australian Government. All rights reserved.
|
||
|
//
|
||
|
|
||
|
import UIKit
|
||
|
|
||
|
let restrictionSelectedStateKey = "restrictionSelectedStateKey"
|
||
|
let restrictionSelectedActivityKey = "restrictionSelectedActivityKey"
|
||
|
|
||
|
class RestrictionTableViewController: UITableViewController {
|
||
|
|
||
|
@IBOutlet var tableFooterView: UIView!
|
||
|
|
||
|
lazy var restrictionSelectedState: StateTerritory = {
|
||
|
guard let value = UserDefaults.standard.value(forKey: restrictionSelectedStateKey) as? String else {
|
||
|
return StateTerritory.AU
|
||
|
}
|
||
|
return StateTerritory(rawValue: value)!
|
||
|
}(){
|
||
|
didSet {
|
||
|
UserDefaults.standard.set(restrictionSelectedState.rawValue, forKey: restrictionSelectedStateKey)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lazy var restrictionSelectedActivity: JurisdictionalRestrictionActivity? = {
|
||
|
guard let value = UserDefaults.standard.value(forKey: restrictionSelectedActivityKey) as? String, !value.isEmpty else {
|
||
|
return nil
|
||
|
}
|
||
|
return value
|
||
|
}(){
|
||
|
didSet {
|
||
|
UserDefaults.standard.set(restrictionSelectedActivity, forKey: restrictionSelectedActivityKey)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var stateRestrictions: StateRestriction?
|
||
|
|
||
|
var jurisdictionalRestrictionActivities: [JurisdictionalRestrictionActivity] = []
|
||
|
|
||
|
override func viewDidLoad() {
|
||
|
super.viewDidLoad()
|
||
|
|
||
|
tableView.register(UINib(nibName: "SimpleTableViewCell", bundle: nil), forCellReuseIdentifier: "SimpleTableCell")
|
||
|
tableView.register(UINib(nibName: "SelectionTableViewCell", bundle: nil), forCellReuseIdentifier: "SelectionTableCell")
|
||
|
tableView.register(UINib(nibName: "TableSectionHeaderView", bundle: nil), forHeaderFooterViewReuseIdentifier: "SectionHeader")
|
||
|
|
||
|
// call api if needed
|
||
|
if restrictionSelectedState != .AU {
|
||
|
getRestrictions(shouldFetchFromApi: true)
|
||
|
} else {
|
||
|
setupTableFooter()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// MARK: - Table view data source
|
||
|
|
||
|
func reloadTableView() {
|
||
|
setupTableFooter()
|
||
|
tableView.reloadData()
|
||
|
}
|
||
|
|
||
|
func setupTableFooter() {
|
||
|
tableView.tableFooterView = restrictionSelectedState == .AU || restrictionSelectedActivity == nil ? tableFooterView : nil
|
||
|
}
|
||
|
|
||
|
override func numberOfSections(in tableView: UITableView) -> Int {
|
||
|
if restrictionSelectedState != .AU && restrictionSelectedActivity != nil {
|
||
|
// top section for selection, bottom for data from restrictions API
|
||
|
return 2
|
||
|
}
|
||
|
|
||
|
return 1
|
||
|
}
|
||
|
|
||
|
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||
|
|
||
|
if section == 0 {
|
||
|
return restrictionSelectedState == .AU ? 1 : 2
|
||
|
} else {
|
||
|
if let selectedActivity = restrictionSelectedActivity,
|
||
|
let activities = stateRestrictions?.activities {
|
||
|
|
||
|
let activity = activities.first { (activity) -> Bool in
|
||
|
return activity.activityTitle == selectedActivity
|
||
|
}
|
||
|
|
||
|
let hasMainContent = activity?.mainContent != nil && !(activity?.mainContent?.isEmpty ?? true)
|
||
|
let includeMainContent = hasMainContent ? 1 : 0
|
||
|
return (activity?.sections?.count ?? 0) + includeMainContent
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||
|
|
||
|
if indexPath.section == 0 {
|
||
|
// check if value is present
|
||
|
let isValueEmpty = indexPath.row == 0 ? restrictionSelectedState == .AU : restrictionSelectedActivity?.isEmpty ?? true
|
||
|
|
||
|
if isValueEmpty {
|
||
|
let cell = tableView.dequeueReusableCell(withIdentifier: "SimpleTableCell") as! SimpleTableViewCell
|
||
|
cell.title.textColor = UIColor.covidSafeColor
|
||
|
cell.rightImageView.image = UIImage(named: "chevron-right-green")
|
||
|
cell.rightImageView.isHidden = true
|
||
|
configureSimpleCell(cell: cell, row: indexPath.row)
|
||
|
cell.selectionStyle = .none
|
||
|
return cell
|
||
|
} else {
|
||
|
let cell = tableView.dequeueReusableCell(withIdentifier: "SelectionTableCell") as! SelectionTableViewCell
|
||
|
configureSelectionCell(cell: cell, row: indexPath.row)
|
||
|
cell.selectionStyle = .none
|
||
|
return cell
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let cell = tableView.dequeueReusableCell(withIdentifier: "SimpleTableCell") as! SimpleTableViewCell
|
||
|
cell.title.textColor = UIColor.covidSafeDarkFontColor
|
||
|
cell.rightImageView.image = UIImage(named: "ChevronRight")
|
||
|
cell.rightImageView.isHidden = false
|
||
|
|
||
|
cell.title.text = ""
|
||
|
if let selectedActivity = restrictionSelectedActivity {
|
||
|
cell.title.text = getSectionTitle(for: selectedActivity, indexPath: indexPath)
|
||
|
}
|
||
|
return cell
|
||
|
}
|
||
|
|
||
|
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
|
||
|
if section == 1 {
|
||
|
let sectionHeaderView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "SectionHeader") as! SectionHeaderView
|
||
|
|
||
|
guard let selectedActivity = restrictionSelectedActivity, let activity = getActivity(activityName: selectedActivity) else {
|
||
|
sectionHeaderView.title.text = ""
|
||
|
return sectionHeaderView
|
||
|
}
|
||
|
|
||
|
let dateFormatter = DateFormatter()
|
||
|
dateFormatter.dateStyle = .medium
|
||
|
dateFormatter.timeStyle = .short
|
||
|
sectionHeaderView.title.text = activity.dateUpdated
|
||
|
return sectionHeaderView
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||
|
if section == 0 {
|
||
|
// returning nil does not suffice
|
||
|
return 0
|
||
|
} else {
|
||
|
// automatic
|
||
|
return -1
|
||
|
}
|
||
|
}
|
||
|
|
||
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||
|
|
||
|
if indexPath.section == 1 {
|
||
|
// if should show content
|
||
|
let contentView = RestrictionDetailsViewController(nibName: "RestrictionsView", bundle: nil)
|
||
|
contentView.hideSubtitle = false
|
||
|
contentView.hideBackButton = false
|
||
|
|
||
|
contentView.titleString = ""
|
||
|
contentView.subtitleString = ""
|
||
|
contentView.htmlString = ""
|
||
|
if let selectedActivity = restrictionSelectedActivity {
|
||
|
contentView.titleString = getSectionTitle(for: selectedActivity, indexPath: indexPath)
|
||
|
contentView.subtitleString = getSectionSubtitle(for: indexPath)
|
||
|
contentView.htmlString = getSectionHtmlContent(for: selectedActivity, indexPath: indexPath)
|
||
|
}
|
||
|
navigationController?.pushViewController(contentView, animated: true)
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var tableViewController: UITableViewController!
|
||
|
|
||
|
if indexPath.row == 0 {
|
||
|
// bring up state selections
|
||
|
let selectStateTerritoryViewController = SelectableTableViewController<StateTerritory>()
|
||
|
selectStateTerritoryViewController.title = "restrictions_select_state".localizedString()
|
||
|
selectStateTerritoryViewController.selectedValue = restrictionSelectedState
|
||
|
selectStateTerritoryViewController.data = [getStateValues()]
|
||
|
selectStateTerritoryViewController.delegate = self
|
||
|
|
||
|
tableViewController = selectStateTerritoryViewController
|
||
|
|
||
|
} else if indexPath.row == 1 {
|
||
|
// bring up activity selections
|
||
|
let selectActivityyViewController = SelectableTableViewController<JurisdictionalRestrictionActivity>()
|
||
|
selectActivityyViewController.title = "restrictions_select_activity".localizedString()
|
||
|
selectActivityyViewController.selectedValue = restrictionSelectedActivity
|
||
|
selectActivityyViewController.data = [jurisdictionalRestrictionActivities]
|
||
|
selectActivityyViewController.delegate = self
|
||
|
|
||
|
tableViewController = selectActivityyViewController
|
||
|
}
|
||
|
|
||
|
let navController = UINavigationController(rootViewController: tableViewController)
|
||
|
present(navController, animated: true, completion: nil)
|
||
|
}
|
||
|
|
||
|
func configureSimpleCell(cell: SimpleTableViewCell, row: Int) {
|
||
|
if row == 0 {
|
||
|
cell.title.text = "restrictions_select_state".localizedString()
|
||
|
} else {
|
||
|
cell.title.text = "restrictions_select_activity".localizedString()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func configureSelectionCell(cell: SelectionTableViewCell, row: Int) {
|
||
|
|
||
|
if row == 0 {
|
||
|
cell.title.text = "restrictions_state".localizedString()
|
||
|
cell.selection.text = restrictionSelectedState.stateTerritoryFullName()
|
||
|
} else {
|
||
|
cell.selection.text = restrictionSelectedActivity
|
||
|
cell.title.text = "restrictions_activity".localizedString()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//MARK: selectable options
|
||
|
|
||
|
func getStateValues() -> [StateTerritory] {
|
||
|
return [StateTerritory.ACT,
|
||
|
StateTerritory.NSW,
|
||
|
StateTerritory.NT,
|
||
|
StateTerritory.QLD,
|
||
|
StateTerritory.SA,
|
||
|
StateTerritory.TAS,
|
||
|
StateTerritory.VIC,
|
||
|
StateTerritory.WA]
|
||
|
}
|
||
|
|
||
|
//MARK: data retrieval
|
||
|
|
||
|
fileprivate func getSectionTitle(for selectedActivity: JurisdictionalRestrictionActivity, indexPath: IndexPath) -> String {
|
||
|
guard let activity = getActivity(activityName: selectedActivity) else {
|
||
|
return ""
|
||
|
}
|
||
|
let hasMainContent = activity.mainContent != nil && !activity.mainContent!.isEmpty
|
||
|
if hasMainContent && indexPath.row == 0 {
|
||
|
return "main_restrictions".localizedString()
|
||
|
}
|
||
|
|
||
|
let indexOffset = hasMainContent ? -1 : 0
|
||
|
guard let activitySections = activity.sections,
|
||
|
activitySections.count > (indexPath.row + indexOffset) else {
|
||
|
return ""
|
||
|
}
|
||
|
return activitySections[indexPath.row + indexOffset].title ?? ""
|
||
|
|
||
|
}
|
||
|
|
||
|
fileprivate func getSectionHtmlContent(for selectedActivity: JurisdictionalRestrictionActivity, indexPath: IndexPath) -> String? {
|
||
|
guard let activity = getActivity(activityName: selectedActivity) else {
|
||
|
return nil
|
||
|
}
|
||
|
let hasMainContent = activity.mainContent != nil && !activity.mainContent!.isEmpty
|
||
|
if hasMainContent && indexPath.row == 0 {
|
||
|
return activity.mainContent
|
||
|
}
|
||
|
|
||
|
let indexOffset = hasMainContent ? -1 : 0
|
||
|
guard let activitySections = activity.sections,
|
||
|
activitySections.count > (indexPath.row + indexOffset) else {
|
||
|
return nil
|
||
|
}
|
||
|
return activitySections[indexPath.row + indexOffset].content ?? nil
|
||
|
|
||
|
}
|
||
|
|
||
|
fileprivate func getSectionSubtitle(for indexPath: IndexPath) -> String {
|
||
|
return "\(restrictionSelectedState.rawValue) - \(restrictionSelectedActivity ?? "")"
|
||
|
}
|
||
|
|
||
|
fileprivate func getActivity(activityName: JurisdictionalRestrictionActivity) -> RestrictionsActivity? {
|
||
|
|
||
|
if let activities = stateRestrictions?.activities {
|
||
|
|
||
|
let activity = activities.first { (activity) -> Bool in
|
||
|
return activity.activityTitle == activityName
|
||
|
}
|
||
|
|
||
|
return activity
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// MARK: Selected state territory delegate
|
||
|
|
||
|
extension RestrictionTableViewController: TableSelectionDelegate {
|
||
|
|
||
|
func didChangeSelectedValue(selectedValue: Any) {
|
||
|
var didChangeState = false
|
||
|
if let value = selectedValue as? StateTerritory {
|
||
|
didChangeState = restrictionSelectedState != value
|
||
|
restrictionSelectedState = value
|
||
|
restrictionSelectedActivity = nil
|
||
|
}
|
||
|
|
||
|
if let value = selectedValue as? JurisdictionalRestrictionActivity {
|
||
|
restrictionSelectedActivity = value
|
||
|
}
|
||
|
getRestrictions(shouldFetchFromApi: didChangeState || stateRestrictions == nil)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
extension RestrictionTableViewController {
|
||
|
|
||
|
fileprivate func getRestrictions(shouldFetchFromApi: Bool) {
|
||
|
guard restrictionSelectedState != .AU, shouldFetchFromApi else {
|
||
|
// reload to reflect selections in the table
|
||
|
reloadTableView()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// call API
|
||
|
RestrictionsAPI.getRestrictions(forState: restrictionSelectedState) { (restrictionsResponse, error) in
|
||
|
guard error == nil else {
|
||
|
// handle api error
|
||
|
let errorVC = CSGenericErrorViewController(nibName: "CSGenericErrorView", bundle: nil)
|
||
|
errorVC.errorViewModel =
|
||
|
CSGenericErrorViewModel(errorTitle: "restrictions_error_heading".localizedString(),
|
||
|
errorContentDescription: "restrictions_error_message".localizedString(),
|
||
|
mainButtonLabel: "restrictions_error_try".localizedString(),
|
||
|
mainButtonCallback: {
|
||
|
self.getRestrictions(shouldFetchFromApi: true)
|
||
|
},
|
||
|
secondaryButtonLabel: "restrictions_error_dismiss".localizedString(),
|
||
|
secondaryButtonCallback: nil)
|
||
|
self.present(errorVC, animated: true, completion: nil)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
self.stateRestrictions = restrictionsResponse
|
||
|
self.retrieveActivities()
|
||
|
self.reloadTableView()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fileprivate func retrieveActivities() {
|
||
|
guard let restrictions = stateRestrictions, let activities = restrictions.activities else {
|
||
|
return
|
||
|
}
|
||
|
jurisdictionalRestrictionActivities = []
|
||
|
for activity in activities {
|
||
|
if let activityName = activity.activityTitle {
|
||
|
jurisdictionalRestrictionActivities.append(activityName)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class SimpleTableViewCell: UITableViewCell {
|
||
|
|
||
|
@IBOutlet weak var title: UILabel!
|
||
|
@IBOutlet weak var rightImageView: UIImageView!
|
||
|
}
|
||
|
|
||
|
class SelectionTableViewCell: UITableViewCell {
|
||
|
|
||
|
@IBOutlet weak var title: UILabel!
|
||
|
@IBOutlet weak var selection: UILabel!
|
||
|
}
|
||
|
|
||
|
class SectionHeaderView: UITableViewHeaderFooterView {
|
||
|
|
||
|
@IBOutlet weak var title: UILabel!
|
||
|
}
|