mirror of
https://github.com/AU-COVIDSafe/mobile-ios.git
synced 2025-04-19 21:15:21 +00:00
COVIDSafe code from version 2.4 (#45)
This commit is contained in:
parent
f14aa60482
commit
377bc0009b
63 changed files with 3096 additions and 372 deletions
379
CovidSafe/RestrictionTableViewController.swift
Normal file
379
CovidSafe/RestrictionTableViewController.swift
Normal file
|
@ -0,0 +1,379 @@
|
|||
//
|
||||
// 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!
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue