AutoCat/AutoCat/Screens/HistoryScreen/HistoryViewModel.swift

117 lines
3.1 KiB
Swift

//
// HistoryViewModel.swift
// AutoCat
//
// Created by Selim Mustafaev on 15.01.2025.
// Copyright © 2025 Selim Mustafaev. All rights reserved.
//
import SwiftUI
import AutoCatCore
@MainActor
@Observable
final class HistoryViewModel: ACHudContainer {
let apiService: ApiServiceProtocol
let storageService: StorageServiceProtocol
let vehicleService: VehicleServiceProtocol
let coordinator: HistoryCoordinator?
var hud: ACHud?
var vehicles: [VehicleDto] = []
var vehiclesFiltered: [VehicleDto] = []
var vehicleSections: [DateSection<VehicleDto>] = []
var searchText: String = "" {
didSet {
if searchText != oldValue {
applyFilters()
}
}
}
var filter: HistoryFilter = .all
var vehiclesArchive: VehiclesArchive {
VehiclesArchive(vehiles: vehiclesFiltered)
}
var vehiclesCount: Int {
vehicleSections.reduce(0, { $0 + $1.elements.count })
}
var dbFileURL: URL?
init(apiService: ApiServiceProtocol,
storageService: StorageServiceProtocol,
vehicleService: VehicleServiceProtocol,
coordinator: HistoryCoordinator) {
self.apiService = apiService
self.storageService = storageService
self.vehicleService = vehicleService
self.coordinator = coordinator
Task { await loadVehicles() }
Task { dbFileURL = await storageService.dbFileURL }
}
func loadVehicles() async {
vehicles = await storageService.loadVehicles()
applyFilters()
}
func openReport(vehicle: VehicleDto) async {
await coordinator?.openReport(vehicle: vehicle)
await loadVehicles()
}
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
}
}
}
func checkNewNumber(_ number: String) async {
await wrapWithToast { [weak self] in
try await self?.vehicleService.checkAndStore(number: number)
}
}
}