Basic report screen

This commit is contained in:
Selim Mustafaev 2022-06-13 20:15:31 +03:00
parent 1b952af498
commit b3c8a809dd
5 changed files with 321 additions and 16 deletions

View File

@ -31,6 +31,7 @@
7A28283327E7263B0049BDBF /* UIStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A28283227E7263B0049BDBF /* UIStackView.swift */; }; 7A28283327E7263B0049BDBF /* UIStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A28283227E7263B0049BDBF /* UIStackView.swift */; };
7A28283627E74C110049BDBF /* SwiftEntryKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7A28283527E74C110049BDBF /* SwiftEntryKit */; }; 7A28283627E74C110049BDBF /* SwiftEntryKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7A28283527E74C110049BDBF /* SwiftEntryKit */; };
7A28283827E74D930049BDBF /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A28283727E74D930049BDBF /* CheckController.swift */; }; 7A28283827E74D930049BDBF /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A28283727E74D930049BDBF /* CheckController.swift */; };
7A2977212857595700060A2A /* ReportController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2977202857595700060A2A /* ReportController.swift */; };
7A2B6CD427FCE93C00519F1E /* TestSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2B6CD327FCE93C00519F1E /* TestSettings.swift */; }; 7A2B6CD427FCE93C00519F1E /* TestSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2B6CD327FCE93C00519F1E /* TestSettings.swift */; };
7A2B6CD727FCED0500519F1E /* XCUIApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2B6CD527FCEC8600519F1E /* XCUIApplication.swift */; }; 7A2B6CD727FCED0500519F1E /* XCUIApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2B6CD527FCEC8600519F1E /* XCUIApplication.swift */; };
7A36E55C27FB55570025AACB /* Testing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A36E55B27FB55570025AACB /* Testing.swift */; }; 7A36E55C27FB55570025AACB /* Testing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A36E55B27FB55570025AACB /* Testing.swift */; };
@ -163,6 +164,7 @@
7A28283027E721A70049BDBF /* UIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = "<group>"; }; 7A28283027E721A70049BDBF /* UIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = "<group>"; };
7A28283227E7263B0049BDBF /* UIStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIStackView.swift; sourceTree = "<group>"; }; 7A28283227E7263B0049BDBF /* UIStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIStackView.swift; sourceTree = "<group>"; };
7A28283727E74D930049BDBF /* CheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckController.swift; sourceTree = "<group>"; }; 7A28283727E74D930049BDBF /* CheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckController.swift; sourceTree = "<group>"; };
7A2977202857595700060A2A /* ReportController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportController.swift; sourceTree = "<group>"; };
7A2B6CD327FCE93C00519F1E /* TestSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSettings.swift; sourceTree = "<group>"; }; 7A2B6CD327FCE93C00519F1E /* TestSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSettings.swift; sourceTree = "<group>"; };
7A2B6CD527FCEC8600519F1E /* XCUIApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIApplication.swift; sourceTree = "<group>"; }; 7A2B6CD527FCEC8600519F1E /* XCUIApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIApplication.swift; sourceTree = "<group>"; };
7A36E55B27FB55570025AACB /* Testing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Testing.swift; sourceTree = "<group>"; }; 7A36E55B27FB55570025AACB /* Testing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Testing.swift; sourceTree = "<group>"; };
@ -298,6 +300,7 @@
6841A0A6580C6E9FF26DC6E2 /* HistoryController.swift */, 6841A0A6580C6E9FF26DC6E2 /* HistoryController.swift */,
6841A5A586BC03AA21D73DF4 /* SettingsController.swift */, 6841A5A586BC03AA21D73DF4 /* SettingsController.swift */,
7A28283727E74D930049BDBF /* CheckController.swift */, 7A28283727E74D930049BDBF /* CheckController.swift */,
7A2977202857595700060A2A /* ReportController.swift */,
); );
path = Controllers; path = Controllers;
sourceTree = "<group>"; sourceTree = "<group>";
@ -815,6 +818,7 @@
7A28283827E74D930049BDBF /* CheckController.swift in Sources */, 7A28283827E74D930049BDBF /* CheckController.swift in Sources */,
6841A7D2375D35B0102D7DEC /* SwiftMaskTextfield.swift in Sources */, 6841A7D2375D35B0102D7DEC /* SwiftMaskTextfield.swift in Sources */,
6841ABD5E4B126DEF3612BBD /* PNKeyboard.swift in Sources */, 6841ABD5E4B126DEF3612BBD /* PNKeyboard.swift in Sources */,
7A2977212857595700060A2A /* ReportController.swift in Sources */,
7A24C19C27EE25B400049E7F /* PlateView.swift in Sources */, 7A24C19C27EE25B400049E7F /* PlateView.swift in Sources */,
7A24C19D27EE25B400049E7F /* FlagLayer.swift in Sources */, 7A24C19D27EE25B400049E7F /* FlagLayer.swift in Sources */,
); );

View File

@ -9,6 +9,18 @@
<key>orderHint</key> <key>orderHint</key>
<integer>0</integer> <integer>0</integer>
</dict> </dict>
<key>AutoCat2.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>AutoCat2UITests.testExample.xcscheme</key>
<dict>
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>8</integer>
</dict>
<key>AutoCatCore.xcscheme_^#shared#^_</key> <key>AutoCatCore.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
@ -17,59 +29,52 @@
<key>DifferenceKit (Playground) 1.xcscheme</key> <key>DifferenceKit (Playground) 1.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false /> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>3</integer> <integer>3</integer>
</dict> </dict>
<key>DifferenceKit (Playground) 2.xcscheme</key> <key>DifferenceKit (Playground) 2.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false /> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>4</integer> <integer>4</integer>
</dict> </dict>
<key>DifferenceKit (Playground).xcscheme</key> <key>DifferenceKit (Playground).xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false /> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>2</integer> <integer>2</integer>
</dict> </dict>
<key>SwiftDate (Playground) 1.xcscheme</key> <key>SwiftDate (Playground) 1.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false /> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>6</integer> <integer>6</integer>
</dict> </dict>
<key>SwiftDate (Playground) 2.xcscheme</key> <key>SwiftDate (Playground) 2.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false /> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>7</integer> <integer>7</integer>
</dict> </dict>
<key>SwiftDate (Playground).xcscheme</key> <key>SwiftDate (Playground).xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false /> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>5</integer> <integer>5</integer>
</dict> </dict>
<key>AutoCat2UITests.testExample.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<key>orderHint</key>
<integer>8</integer>
</dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>
<dict> <dict>
<key>7A49F4D627D4064500AEAAE0</key> <key>7A49F4D627D4064500AEAAE0</key>
<dict> <dict>
<key>primary</key> <key>primary</key>
<true /> <true/>
</dict> </dict>
</dict> </dict>
</dict> </dict>

View File

@ -66,6 +66,10 @@ class CoreDataSource<Item: NSManagedObject & Dated & Differentiable, Cell: Confi
} }
} }
func item(at indexPath: IndexPath) -> Item {
sections[indexPath.section].elements[indexPath.row]
}
// MARK: - NSFetchedResultsControllerDelegate // MARK: - NSFetchedResultsControllerDelegate

View File

@ -6,8 +6,7 @@ import UIKit
import PKHUD import PKHUD
import AutoCatCore import AutoCatCore
class HistoryController: UIViewController { class HistoryController: UIViewController, UITableViewDelegate {
private lazy var tableView: UITableView = { private lazy var tableView: UITableView = {
let table = UITableView() let table = UITableView()
@ -15,6 +14,7 @@ class HistoryController: UIViewController {
table.register(VehicleCell.self, forCellReuseIdentifier: cellIdentifier) table.register(VehicleCell.self, forCellReuseIdentifier: cellIdentifier)
table.translatesAutoresizingMaskIntoConstraints = false table.translatesAutoresizingMaskIntoConstraints = false
table.accessibilityIdentifier = "historyTable" table.accessibilityIdentifier = "historyTable"
table.delegate = self
return table return table
}() }()
@ -52,4 +52,18 @@ class HistoryController: UIViewController {
show(error: error) show(error: error)
} }
} }
// MARK: - UITableViewDelegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
guard let vehicle = dataSource?.item(at: indexPath) else {
return
}
let controller = ReportController(vehicle: vehicle)
controller.hidesBottomBarWhenPushed = true
navigationController?.pushViewController(controller, animated: true)
}
} }

View File

@ -0,0 +1,278 @@
//
// ReportController.swift
// AutoCat2
//
// Created by Selim Mustafaev on 13.06.2022.
//
import UIKit
import AutoCatCore
enum ReportSection: Int, CaseIterable {
case title
case general
case identifiers
case engine
// case history = 3
// case debug = 4
var name: String {
switch self {
case .title: return ""
case .general: return "General"
case .identifiers: return "Identifiers"
case .engine: return "Engine"
}
}
}
enum ReportGeneralItem: Int, CaseIterable {
case year
case color
case category
case steeringWheelPosition
case isJapanese
var name: String {
switch self {
case .year: return "Year"
case .color: return "Color"
case .category: return "Category"
case .steeringWheelPosition: return "Steering wheel position"
case .isJapanese: return "Japanese vehicle"
}
}
}
enum ReportIdentifiersItem: Int, CaseIterable {
case number
case vin
case sts
case pts
var name: String {
switch self {
case .number: return "Plate number"
case .vin: return "VIN"
case .sts: return "STS"
case .pts: return "PTS"
}
}
}
enum ReportEngineItem: Int, CaseIterable {
case number
case fuelType
case volume
case powerHp
case powerKw
var name: String {
switch self {
case .number: return "Number"
case .fuelType: return "Fuel type"
case .volume: return "Volume"
case .powerHp: return "Power (HP)"
case .powerKw: return "Power (kw)"
}
}
}
struct ReportItem {
let name: String
let value: String?
let image: UIImage?
init(name: String, value: String?) {
self.name = name
self.value = value
self.image = nil
}
init(name: String, image: UIImage?) {
self.name = name
self.value = nil
self.image = image
}
}
class ReportController: UIViewController, UICollectionViewDataSource {
private let reportTextItemId = String(describing: ReportTextItemCell.self)
private lazy var collectionView: UICollectionView = {
let collection = UICollectionView(frame: .zero, collectionViewLayout: createLayout())
collection.translatesAutoresizingMaskIntoConstraints = false
collection.register(ReportTextItemCell.self,
forCellWithReuseIdentifier: reportTextItemId)
collection.dataSource = self
return collection
}()
private let textCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, ReportItem> { cell, indexPath, item in
var config = UIListContentConfiguration.valueCell()
config.text = item.name
config.secondaryText = item.value
cell.contentConfiguration = config
}
private let titleCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, ReportItem> { cell, indexPath, item in
var config = UIListContentConfiguration.cell()
config.text = item.name
cell.contentConfiguration = config
}
private let supplementaryRegistration = UICollectionView.SupplementaryRegistration<UICollectionViewListCell>(elementKind: UICollectionView.elementKindSectionHeader) { supplementaryView, elementKind, indexPath in
guard let section = ReportSection(rawValue: indexPath.section) else {
return
}
var configutation = UIListContentConfiguration.groupedHeader()
configutation.text = section.name
supplementaryView.contentConfiguration = configutation
}
let vehicle: CDVehicle
// MARK: - Lifecycle
init(vehicle: CDVehicle) {
self.vehicle = vehicle
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
title = vehicle.number
view.addSubview(collectionView)
collectionView.pin(to: view)
}
func createLayout() -> UICollectionViewLayout {
UICollectionViewCompositionalLayout { section, env in
var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
config.headerMode = section == 0 ? .none : .supplementary
return NSCollectionLayoutSection.list(using: config, layoutEnvironment: env)
}
}
// MARK: - Getting data
func getTextData(for indexPath: IndexPath) -> ReportItem {
guard let section = ReportSection(rawValue: indexPath.section) else {
return ReportItem(name: "", value: nil)
}
switch section {
case .title: return ReportItem(name: vehicle.brand?.name?.original ?? "", image: nil)
case .general: return getGeneralValue(index: indexPath.row)
case .identifiers: return getIdentifiersValue(index: indexPath.row)
case .engine: return getEngineValue(index: indexPath.row)
}
}
func getGeneralValue(index: Int) -> ReportItem {
guard let item = ReportGeneralItem(rawValue: index) else {
return ReportItem(name: "", value: nil)
}
let value: String?
switch item {
case .year: value = String(vehicle.year)
case .color: value = vehicle.color
case .category: value = vehicle.category
case .steeringWheelPosition: value = vehicle.isRightWheel ? "Right" : "Left"
case .isJapanese: value = vehicle.isJapanese ? "Yes" : "No"
}
return ReportItem(name: item.name, value: value)
}
func getIdentifiersValue(index: Int) -> ReportItem {
guard let item = ReportIdentifiersItem(rawValue: index) else {
return ReportItem(name: "", value: nil)
}
let value: String?
switch item {
case .number: value = vehicle.number
case .vin: value = vehicle.vin1
case .sts: value = vehicle.sts
case .pts: value = vehicle.pts
}
return ReportItem(name: item.name, value: value)
}
func getEngineValue(index: Int) -> ReportItem {
guard let item = ReportEngineItem(rawValue: index) else {
return ReportItem(name: "", value: nil)
}
let value: String?
switch item {
case .number: value = vehicle.engine?.number
case .fuelType: value = vehicle.engine?.fuelType
case .volume: value = String(vehicle.engine?.volume ?? 0)
case .powerHp: value = String(vehicle.engine?.powerHp ?? 0)
case .powerKw: value = String(vehicle.engine?.powerKw ?? 0)
}
return ReportItem(name: item.name, value: value)
}
// MARK: - UICollectionViewDataSource
func numberOfSections(in collectionView: UICollectionView) -> Int {
ReportSection.allCases.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
guard let sectionEnum = ReportSection(rawValue: section) else {
return 0
}
switch sectionEnum {
case .title:
return 1
case .general:
return ReportGeneralItem.allCases.count
case .identifiers:
return ReportIdentifiersItem.allCases.count
case .engine:
return ReportEngineItem.allCases.count
}
}
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let item = getTextData(for: indexPath)
return collectionView.dequeueConfiguredReusableCell(using: textCellRegistration, for: indexPath, item: item)
}
func collectionView(_ collectionView: UICollectionView,
viewForSupplementaryElementOfKind kind: String,
at indexPath: IndexPath) -> UICollectionReusableView {
collectionView.dequeueConfiguredReusableSupplementary(using: supplementaryRegistration,
for: indexPath)
}
}