AutoCat/AutoCat/Screens/SearchScreen/SearchScreen.swift

127 lines
3.8 KiB
Swift

//
// SearchScreen.swift
// AutoCat
//
// Created by Selim Mustafaev on 17.02.2025.
// Copyright © 2025 Selim Mustafaev. All rights reserved.
//
import SwiftUI
import AutoCatCore
struct SearchScreen: View {
enum Screen: Hashable {
case filter(Filter)
case map(Filter)
}
@State var viewModel: SearchViewModel
init(viewModel: SearchViewModel) {
self.viewModel = viewModel
}
var body: some View {
List(selection: $viewModel.selectedVehicleId) {
vehicles
if viewModel.hasMoreData && !viewModel.vehicleSections.isEmpty {
progressCell
}
}
.listStyle(.plain)
.hud($viewModel.hud)
.searchable(text: $viewModel.searchText, prompt: "Search plate numbers")
.searchPresentationToolbarBehavior(.avoidHidingContent)
.makeTextFieldDumb()
.titleModeInline()
.navigationTitle(String.localizedStringWithFormat(NSLocalizedString("vehicles found", comment: ""),
viewModel.vehiclesCount))
.onAppear {
Task { await viewModel.onAppear() }
}
.refreshable {
Task { await viewModel.reloadData() }
}
.toolbar {
ToolbarItem(placement: .primaryAction) {
toolbarMenu
}
}
.navigationDestination(for: Screen.self) { screen in
switch screen {
case .filter(let filter):
FiltersScreen(filter: filter, onUpdate: viewModel.onFilterChanged)
case .map(let filter):
MapScreen(mapInput: .filter(filter))
}
}
.navigationDestination(for: VehicleDto.self) { vehicle in
return ReportScreen(vehicle: vehicle, isPersistent: false, onUpdate: viewModel.onVehicleChanged)
}
}
var vehicles: some View {
ForEach(viewModel.vehicleSections) { section in
Section(header: Text(section.header)) {
ForEach(section.elements) { vehicle in
if Device.isIPhone {
NavigationLink(value: vehicle) {
vehicleCell(vehicle)
}
} else {
vehicleCell(vehicle)
}
}
}
}
}
func vehicleCell(_ vehicle: VehicleDto) -> some View {
VehicleCellView(vehicle: vehicle)
.swipeActions(allowsFullSwipe: false) {
makeActions(for: vehicle)
}
.contextMenu {
makeActions(for: vehicle, useLabels: true)
}
}
var progressCell: some View {
HStack {
Spacer()
ProgressView()
.id(UUID())
Spacer()
}
.onAppear {
Task { await viewModel.loadMoreData() }
}
}
var toolbarMenu: some View {
Menu("", systemImage: "ellipsis") {
NavigationLink(value: Screen.filter(viewModel.filter)) {
Label("Filter results", systemImage: "line.horizontal.3.decrease")
}
NavigationLink(value: Screen.map(viewModel.filter)) {
Label("Show on map", systemImage: "map")
}
ShareLink(item: viewModel.vehiclesArchive, preview: SharePreview(VehiclesArchive.fileName))
//ShareLink(items: [viewModel.vehiclesArchive])
}
}
@ViewBuilder
func makeActions(for vehicle: VehicleDto, useLabels: Bool = false) -> some View {
Button {
Task { await viewModel.updateVehicle(vehicle) }
} label: {
Label(useLabels ? "Update" : "", systemImage: "arrow.2.circlepath")
}
}
}