Filtering vehicles history
This commit is contained in:
parent
bade0d5418
commit
13a0bbe895
@ -11,11 +11,29 @@ enum EventAction: Equatable {
|
|||||||
case receiveAndSend
|
case receiveAndSend
|
||||||
}
|
}
|
||||||
|
|
||||||
enum HistoryFilter {
|
enum HistoryFilter: CaseIterable, Identifiable {
|
||||||
case all
|
case all
|
||||||
case unrecognized
|
case unrecognized
|
||||||
case outdated
|
case outdated
|
||||||
case notSynced
|
case notSynced
|
||||||
|
|
||||||
|
var title: String {
|
||||||
|
switch self {
|
||||||
|
case .all: return NSLocalizedString("All", comment: "");
|
||||||
|
case .unrecognized: return NSLocalizedString("Unrecognized", comment: "");
|
||||||
|
case .outdated: return NSLocalizedString("Outdated", comment: "");
|
||||||
|
case .notSynced: return NSLocalizedString("Not updated", comment: "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var id: Int {
|
||||||
|
switch self {
|
||||||
|
case .all: return 0;
|
||||||
|
case .unrecognized: return 1;
|
||||||
|
case .outdated: return 2;
|
||||||
|
case .notSynced: return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension String.StringInterpolation {
|
extension String.StringInterpolation {
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import AutoCatCore
|
|||||||
struct HistoryScreen: View {
|
struct HistoryScreen: View {
|
||||||
|
|
||||||
@State var viewModel: HistoryViewModel
|
@State var viewModel: HistoryViewModel
|
||||||
|
@State var filterSheetPresented = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List {
|
List {
|
||||||
@ -24,8 +25,27 @@ struct HistoryScreen: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.listStyle(.plain)
|
.listStyle(.plain)
|
||||||
.navigationTitle(String.localizedStringWithFormat(NSLocalizedString("vehicles found", comment: ""), viewModel.vehicleSections.reduce(0, { $0 + $1.elements.count })))
|
.navigationTitle(String.localizedStringWithFormat(NSLocalizedString("vehicles found", comment: ""),
|
||||||
|
viewModel.vehicleSections.reduce(0, { $0 + $1.elements.count })))
|
||||||
.searchable(text: $viewModel.searchText, prompt: "Search plate numbers")
|
.searchable(text: $viewModel.searchText, prompt: "Search plate numbers")
|
||||||
|
.autocorrectionDisabled()
|
||||||
|
.textInputAutocapitalization(.never)
|
||||||
|
.keyboardType(.asciiCapable)
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .primaryAction) {
|
||||||
|
Button("", systemImage: "line.horizontal.3.decrease") {
|
||||||
|
filterSheetPresented = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.confirmationDialog("Filter check history", isPresented: $filterSheetPresented, titleVisibility: .visible) {
|
||||||
|
ForEach(HistoryFilter.allCases) { filter in
|
||||||
|
Button(filter.title) {
|
||||||
|
viewModel.filter = filter
|
||||||
|
viewModel.applyFilters()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,17 +16,20 @@ final class HistoryViewModel {
|
|||||||
let apiService: ApiServiceProtocol
|
let apiService: ApiServiceProtocol
|
||||||
let storageService: StorageServiceProtocol
|
let storageService: StorageServiceProtocol
|
||||||
|
|
||||||
|
var vehicles: [VehicleDto] = []
|
||||||
|
var vehiclesFiltered: [VehicleDto] = []
|
||||||
var vehicleSections: [DateSection<VehicleDto>] = []
|
var vehicleSections: [DateSection<VehicleDto>] = []
|
||||||
var vehicleSectionsFiltered: [DateSection<VehicleDto>] = []
|
|
||||||
|
|
||||||
var searchText: String = "" {
|
var searchText: String = "" {
|
||||||
didSet {
|
didSet {
|
||||||
if searchText != oldValue {
|
if searchText != oldValue {
|
||||||
applySearchFilter(text: searchText)
|
applyFilters()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var filter: HistoryFilter = .all
|
||||||
|
|
||||||
init(apiService: ApiServiceProtocol, storageService: StorageServiceProtocol) {
|
init(apiService: ApiServiceProtocol, storageService: StorageServiceProtocol) {
|
||||||
|
|
||||||
self.apiService = apiService
|
self.apiService = apiService
|
||||||
@ -37,11 +40,47 @@ final class HistoryViewModel {
|
|||||||
|
|
||||||
func loadVehicles() async {
|
func loadVehicles() async {
|
||||||
|
|
||||||
let vehicles = await storageService.loadVehicles()
|
vehicles = await storageService.loadVehicles()
|
||||||
vehicleSections = vehicles.groupedByDate(type: .updatedDate)
|
vehiclesFiltered = vehicles
|
||||||
|
vehicleSections = vehiclesFiltered.groupedByDate(type: .updatedDate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func applySearchFilter(text: String) {
|
func applyFilters() {
|
||||||
|
vehiclesFiltered = filterType(vehicles)
|
||||||
|
vehiclesFiltered = filterSearch(vehiclesFiltered)
|
||||||
|
vehicleSections = vehiclesFiltered.groupedByDate(type: .updatedDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterSearch(_ vehicles: [VehicleDto]) -> [VehicleDto] {
|
||||||
|
guard !searchText.isEmpty else {
|
||||||
|
return vehicles
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = searchText.uppercased()
|
||||||
|
let regex = try? Regex(text)
|
||||||
|
|
||||||
|
return vehicles.filter { vehicle in
|
||||||
|
let number = vehicle.getNumber()
|
||||||
|
if let regex {
|
||||||
|
return number.contains(regex)
|
||||||
|
} else {
|
||||||
|
return number.contains(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterType(_ vehicles: [VehicleDto]) -> [VehicleDto] {
|
||||||
|
guard filter != .all else {
|
||||||
|
return vehicles
|
||||||
|
}
|
||||||
|
|
||||||
|
return vehicles.filter { vehicle in
|
||||||
|
switch filter {
|
||||||
|
case .unrecognized: vehicle.unrecognized
|
||||||
|
case .outdated: vehicle.outdated
|
||||||
|
case .notSynced: vehicle.needSync
|
||||||
|
case .all: true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user