Filtering vehicles history

This commit is contained in:
Selim Mustafaev 2025-01-18 17:39:07 +03:00
parent bade0d5418
commit 13a0bbe895
3 changed files with 84 additions and 7 deletions

View File

@ -11,11 +11,29 @@ enum EventAction: Equatable {
case receiveAndSend
}
enum HistoryFilter {
enum HistoryFilter: CaseIterable, Identifiable {
case all
case unrecognized
case outdated
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 {

View File

@ -12,6 +12,7 @@ import AutoCatCore
struct HistoryScreen: View {
@State var viewModel: HistoryViewModel
@State var filterSheetPresented = false
var body: some View {
List {
@ -24,8 +25,27 @@ struct HistoryScreen: View {
}
}
.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")
.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()
}
}
}
}
}

View File

@ -16,17 +16,20 @@ final class HistoryViewModel {
let apiService: ApiServiceProtocol
let storageService: StorageServiceProtocol
var vehicles: [VehicleDto] = []
var vehiclesFiltered: [VehicleDto] = []
var vehicleSections: [DateSection<VehicleDto>] = []
var vehicleSectionsFiltered: [DateSection<VehicleDto>] = []
var searchText: String = "" {
didSet {
if searchText != oldValue {
applySearchFilter(text: searchText)
applyFilters()
}
}
}
var filter: HistoryFilter = .all
init(apiService: ApiServiceProtocol, storageService: StorageServiceProtocol) {
self.apiService = apiService
@ -37,11 +40,47 @@ final class HistoryViewModel {
func loadVehicles() async {
let vehicles = await storageService.loadVehicles()
vehicleSections = vehicles.groupedByDate(type: .updatedDate)
vehicles = await storageService.loadVehicles()
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
}
}
}
}