More filters screen code
This commit is contained in:
parent
8718042f1d
commit
ba09884a65
@ -49,6 +49,7 @@
|
|||||||
7A27ADF5249FD2F90035F39E /* FileManagerExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A27ADF4249FD2F90035F39E /* FileManagerExt.swift */; };
|
7A27ADF5249FD2F90035F39E /* FileManagerExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A27ADF4249FD2F90035F39E /* FileManagerExt.swift */; };
|
||||||
7A27ADF7249FEF690035F39E /* Recorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A27ADF6249FEF690035F39E /* Recorder.swift */; };
|
7A27ADF7249FEF690035F39E /* Recorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A27ADF6249FEF690035F39E /* Recorder.swift */; };
|
||||||
7A2C96122C3B155B00AE46B5 /* NoteAlertModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2C96112C3B155B00AE46B5 /* NoteAlertModifier.swift */; };
|
7A2C96122C3B155B00AE46B5 /* NoteAlertModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2C96112C3B155B00AE46B5 /* NoteAlertModifier.swift */; };
|
||||||
|
7A2E11292CCE395300E5CA17 /* OptionalDatePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2E11282CCE395300E5CA17 /* OptionalDatePicker.swift */; };
|
||||||
7A2E6FA72C42B3AD00C40DA7 /* AutoCatCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AF6D1EF2677C03B0086EA64 /* AutoCatCore.framework */; };
|
7A2E6FA72C42B3AD00C40DA7 /* AutoCatCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AF6D1EF2677C03B0086EA64 /* AutoCatCore.framework */; };
|
||||||
7A33381124990DAE00D878F1 /* FiltersController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A33381024990DAE00D878F1 /* FiltersController.swift */; };
|
7A33381124990DAE00D878F1 /* FiltersController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A33381024990DAE00D878F1 /* FiltersController.swift */; };
|
||||||
7A3399AB299063370087DF98 /* SearchControllerExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3399AA299063370087DF98 /* SearchControllerExt.swift */; };
|
7A3399AB299063370087DF98 /* SearchControllerExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3399AA299063370087DF98 /* SearchControllerExt.swift */; };
|
||||||
@ -61,6 +62,8 @@
|
|||||||
7A4322932CB2CCAA00085CF6 /* FiltersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4322922CB2CCAA00085CF6 /* FiltersViewModel.swift */; };
|
7A4322932CB2CCAA00085CF6 /* FiltersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4322922CB2CCAA00085CF6 /* FiltersViewModel.swift */; };
|
||||||
7A4322952CB2CD0F00085CF6 /* FiltersCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4322942CB2CD0F00085CF6 /* FiltersCoordinator.swift */; };
|
7A4322952CB2CD0F00085CF6 /* FiltersCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4322942CB2CD0F00085CF6 /* FiltersCoordinator.swift */; };
|
||||||
7A45FB382C27073700618694 /* StorageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A45FB372C27073700618694 /* StorageService.swift */; };
|
7A45FB382C27073700618694 /* StorageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A45FB372C27073700618694 /* StorageService.swift */; };
|
||||||
|
7A4927D52CCE438600851C01 /* OptionalBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4927D42CCE438600851C01 /* OptionalBinding.swift */; };
|
||||||
|
7A4927D72CCEA6DC00851C01 /* VMResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4927D62CCEA6DC00851C01 /* VMResult.swift */; };
|
||||||
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7924001D3300CBFE6E /* CheckController.swift */; };
|
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7924001D3300CBFE6E /* CheckController.swift */; };
|
||||||
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */; };
|
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */; };
|
||||||
7A599C362C18AC7F00D47C18 /* ApiError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A599C352C18AC7F00D47C18 /* ApiError.swift */; };
|
7A599C362C18AC7F00D47C18 /* ApiError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A599C352C18AC7F00D47C18 /* ApiError.swift */; };
|
||||||
@ -306,6 +309,7 @@
|
|||||||
7A27ADF824A09CAD0035F39E /* CocoaError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CocoaError.swift; sourceTree = "<group>"; };
|
7A27ADF824A09CAD0035F39E /* CocoaError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CocoaError.swift; sourceTree = "<group>"; };
|
||||||
7A2C96112C3B155B00AE46B5 /* NoteAlertModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteAlertModifier.swift; sourceTree = "<group>"; };
|
7A2C96112C3B155B00AE46B5 /* NoteAlertModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteAlertModifier.swift; sourceTree = "<group>"; };
|
||||||
7A2DE69725868AC800A113FC /* VehicleAd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleAd.swift; sourceTree = "<group>"; };
|
7A2DE69725868AC800A113FC /* VehicleAd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleAd.swift; sourceTree = "<group>"; };
|
||||||
|
7A2E11282CCE395300E5CA17 /* OptionalDatePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionalDatePicker.swift; sourceTree = "<group>"; };
|
||||||
7A2E6FA32C42B3AD00C40DA7 /* AutoCatCoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AutoCatCoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
7A2E6FA32C42B3AD00C40DA7 /* AutoCatCoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AutoCatCoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
7A33381024990DAE00D878F1 /* FiltersController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersController.swift; sourceTree = "<group>"; };
|
7A33381024990DAE00D878F1 /* FiltersController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersController.swift; sourceTree = "<group>"; };
|
||||||
7A333813249A532400D878F1 /* Filter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filter.swift; sourceTree = "<group>"; };
|
7A333813249A532400D878F1 /* Filter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filter.swift; sourceTree = "<group>"; };
|
||||||
@ -319,6 +323,8 @@
|
|||||||
7A4322942CB2CD0F00085CF6 /* FiltersCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersCoordinator.swift; sourceTree = "<group>"; };
|
7A4322942CB2CD0F00085CF6 /* FiltersCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersCoordinator.swift; sourceTree = "<group>"; };
|
||||||
7A43F9F7246C8A6200BA5B49 /* JWT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = "<group>"; };
|
7A43F9F7246C8A6200BA5B49 /* JWT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = "<group>"; };
|
||||||
7A45FB372C27073700618694 /* StorageService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageService.swift; sourceTree = "<group>"; };
|
7A45FB372C27073700618694 /* StorageService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageService.swift; sourceTree = "<group>"; };
|
||||||
|
7A4927D42CCE438600851C01 /* OptionalBinding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionalBinding.swift; sourceTree = "<group>"; };
|
||||||
|
7A4927D62CCEA6DC00851C01 /* VMResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMResult.swift; sourceTree = "<group>"; };
|
||||||
7A52AB292580112E002CD910 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
7A52AB292580112E002CD910 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
7A530B7924001D3300CBFE6E /* CheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckController.swift; sourceTree = "<group>"; };
|
7A530B7924001D3300CBFE6E /* CheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckController.swift; sourceTree = "<group>"; };
|
||||||
7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleCell.swift; sourceTree = "<group>"; };
|
7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleCell.swift; sourceTree = "<group>"; };
|
||||||
@ -615,6 +621,7 @@
|
|||||||
7AC3554B29696A1C00889457 /* MainTabController.swift */,
|
7AC3554B29696A1C00889457 /* MainTabController.swift */,
|
||||||
7AC3554D29696C4500889457 /* DummyNewController.swift */,
|
7AC3554D29696C4500889457 /* DummyNewController.swift */,
|
||||||
7AC3554F29696D5A00889457 /* NewNumberController.swift */,
|
7AC3554F29696D5A00889457 /* NewNumberController.swift */,
|
||||||
|
7A4927D62CCEA6DC00851C01 /* VMResult.swift */,
|
||||||
);
|
);
|
||||||
path = Controllers;
|
path = Controllers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1038,6 +1045,8 @@
|
|||||||
7A1022712C554A1300B84627 /* CustomHostingController.swift */,
|
7A1022712C554A1300B84627 /* CustomHostingController.swift */,
|
||||||
7A5D7E0B2C71EB25002C17E7 /* ToggleRowView.swift */,
|
7A5D7E0B2C71EB25002C17E7 /* ToggleRowView.swift */,
|
||||||
7AF8606F2CBAA24500954D2F /* NavigationLink.swift */,
|
7AF8606F2CBAA24500954D2F /* NavigationLink.swift */,
|
||||||
|
7A2E11282CCE395300E5CA17 /* OptionalDatePicker.swift */,
|
||||||
|
7A4927D42CCE438600851C01 /* OptionalBinding.swift */,
|
||||||
);
|
);
|
||||||
path = SwiftUI;
|
path = SwiftUI;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1290,14 +1299,17 @@
|
|||||||
7AFBE8C02C3024E5003C491D /* ACHud.swift in Sources */,
|
7AFBE8C02C3024E5003C491D /* ACHud.swift in Sources */,
|
||||||
7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */,
|
7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */,
|
||||||
7AABDE26253350C30041AFC6 /* RxSectionedDataSource.swift in Sources */,
|
7AABDE26253350C30041AFC6 /* RxSectionedDataSource.swift in Sources */,
|
||||||
|
7A4927D72CCEA6DC00851C01 /* VMResult.swift in Sources */,
|
||||||
7AAAFADA2C4D1AFE0050410D /* Zoomable.swift in Sources */,
|
7AAAFADA2C4D1AFE0050410D /* Zoomable.swift in Sources */,
|
||||||
7A6DD90C24335A6D009DE740 /* FlagLayer.swift in Sources */,
|
7A6DD90C24335A6D009DE740 /* FlagLayer.swift in Sources */,
|
||||||
|
7A2E11292CCE395300E5CA17 /* OptionalDatePicker.swift in Sources */,
|
||||||
7A761C0B267E8FF90005F28F /* Error.swift in Sources */,
|
7A761C0B267E8FF90005F28F /* Error.swift in Sources */,
|
||||||
7AC3555029696D5A00889457 /* NewNumberController.swift in Sources */,
|
7AC3555029696D5A00889457 /* NewNumberController.swift in Sources */,
|
||||||
7AE26A3524F31B0700625033 /* EventsController.swift in Sources */,
|
7AE26A3524F31B0700625033 /* EventsController.swift in Sources */,
|
||||||
7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */,
|
7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */,
|
||||||
7AF860702CBAA24500954D2F /* NavigationLink.swift in Sources */,
|
7AF860702CBAA24500954D2F /* NavigationLink.swift in Sources */,
|
||||||
7A27ADF5249FD2F90035F39E /* FileManagerExt.swift in Sources */,
|
7A27ADF5249FD2F90035F39E /* FileManagerExt.swift in Sources */,
|
||||||
|
7A4927D52CCE438600851C01 /* OptionalBinding.swift in Sources */,
|
||||||
7A17CE4A2A2E820300626A6E /* UIStackView.swift in Sources */,
|
7A17CE4A2A2E820300626A6E /* UIStackView.swift in Sources */,
|
||||||
7A1DC38E2517ED98002E9C99 /* BlockBarButtonItem.swift in Sources */,
|
7A1DC38E2517ED98002E9C99 /* BlockBarButtonItem.swift in Sources */,
|
||||||
7AE26A3324EEF9EC00625033 /* UIViewControllerExt.swift in Sources */,
|
7AE26A3324EEF9EC00625033 /* UIViewControllerExt.swift in Sources */,
|
||||||
|
|||||||
@ -134,7 +134,7 @@ class FiltersController: FormViewController {
|
|||||||
row.title = NSLocalizedString("Added by", comment: "")
|
row.title = NSLocalizedString("Added by", comment: "")
|
||||||
row.selectorTitle = NSLocalizedString("Added by", comment: "")
|
row.selectorTitle = NSLocalizedString("Added by", comment: "")
|
||||||
row.options = AddedBy.allCases.map { $0.description }
|
row.options = AddedBy.allCases.map { $0.description }
|
||||||
row.value = self.filter.addedBy?.description ?? AddedBy.anyone.description
|
row.value = self.filter.addedBy.description
|
||||||
}
|
}
|
||||||
.onChange { row in
|
.onChange { row in
|
||||||
if let index = row.options?.firstIndex(of: row.value ?? "") {
|
if let index = row.options?.firstIndex(of: row.value ?? "") {
|
||||||
@ -144,7 +144,7 @@ class FiltersController: FormViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.cellUpdate { cell, row in
|
.cellUpdate { cell, row in
|
||||||
row.value = self.filter.addedBy?.description ?? AddedBy.anyone.description
|
row.value = self.filter.addedBy.description
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,14 +210,14 @@ class FiltersController: FormViewController {
|
|||||||
row.value = self.filter.sortBy
|
row.value = self.filter.sortBy
|
||||||
row.options = SortParameter.allCases
|
row.options = SortParameter.allCases
|
||||||
}
|
}
|
||||||
.onChange { self.filter.sortBy = $0.value }
|
.onChange { self.filter.sortBy = $0.value ?? .updatedDate }
|
||||||
.cellUpdate { $1.value = self.filter.sortBy }
|
.cellUpdate { $1.value = self.filter.sortBy }
|
||||||
<<< SegmentedRow<AutoCatCore.SortOrder>("SortOrder") { row in
|
<<< SegmentedRow<AutoCatCore.SortOrder>("SortOrder") { row in
|
||||||
row.title = NSLocalizedString("Order", comment: "sort order")
|
row.title = NSLocalizedString("Order", comment: "sort order")
|
||||||
row.value = self.filter.sortOrder
|
row.value = self.filter.sortOrder
|
||||||
row.options = AutoCatCore.SortOrder.allCases
|
row.options = AutoCatCore.SortOrder.allCases
|
||||||
}
|
}
|
||||||
.onChange { self.filter.sortOrder = $0.value }
|
.onChange { self.filter.sortOrder = $0.value ?? .descending }
|
||||||
.cellUpdate { $1.value = self.filter.sortOrder }
|
.cellUpdate { $1.value = self.filter.sortOrder }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -184,26 +184,28 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func showFilter() async throws {
|
func showFilter() async throws {
|
||||||
let sb = UIStoryboard(name: "Main", bundle: nil)
|
// let sb = UIStoryboard(name: "Main", bundle: nil)
|
||||||
let controller = sb.instantiateViewController(identifier: "FiltersController") as FiltersController
|
// let controller = sb.instantiateViewController(identifier: "FiltersController") as FiltersController
|
||||||
controller.filter = self.filter
|
// controller.filter = self.filter
|
||||||
controller.onDone = {
|
// controller.onDone = {
|
||||||
self.filter = controller.filter
|
// self.filter = controller.filter
|
||||||
self.datasource.setSortParameter(self.filter.sortBy ?? .updatedDate)
|
// self.datasource.setSortParameter(self.filter.sortBy ?? .updatedDate)
|
||||||
self.filter.needReset = true
|
// self.filter.needReset = true
|
||||||
self.filter.scope = SearchScope(rawValue: self.searchController.searchBar.selectedScopeButtonIndex) ?? .plateNumber
|
// self.filter.scope = SearchScope(rawValue: self.searchController.searchBar.selectedScopeButtonIndex) ?? .plateNumber
|
||||||
self.updateSearchResults(with: self.filter)
|
// self.updateSearchResults(with: self.filter)
|
||||||
}
|
|
||||||
self.navigationController?.pushViewController(controller, animated: true)
|
|
||||||
|
|
||||||
// if let navigationController = self.navigationController {
|
|
||||||
// let coordinator = FiltersCoordinator(navController: navigationController, filter: filter)
|
|
||||||
// filter = try await coordinator.start()
|
|
||||||
// datasource.setSortParameter(self.filter.sortBy ?? .updatedDate)
|
|
||||||
// filter.needReset = true
|
|
||||||
// filter.scope = SearchScope(rawValue: self.searchController.searchBar.selectedScopeButtonIndex) ?? .plateNumber
|
|
||||||
// updateSearchResults(with: self.filter)
|
|
||||||
// }
|
// }
|
||||||
|
// self.navigationController?.pushViewController(controller, animated: true)
|
||||||
|
|
||||||
|
if let navigationController = self.navigationController {
|
||||||
|
let coordinator = FiltersCoordinator(navController: navigationController, filter: filter)
|
||||||
|
if let newFilter = try await coordinator.start() {
|
||||||
|
filter = newFilter
|
||||||
|
datasource.setSortParameter(self.filter.sortBy)
|
||||||
|
filter.needReset = true
|
||||||
|
filter.scope = SearchScope(rawValue: self.searchController.searchBar.selectedScopeButtonIndex) ?? .plateNumber
|
||||||
|
updateSearchResults(with: self.filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func showOnMap() {
|
func showOnMap() {
|
||||||
|
|||||||
39
AutoCat/Controllers/VMResult.swift
Normal file
39
AutoCat/Controllers/VMResult.swift
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
//
|
||||||
|
// VMResult.swift
|
||||||
|
// AutoCat
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 27.10.2024.
|
||||||
|
// Copyright © 2024 Selim Mustafaev. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@Observable
|
||||||
|
class VMResult<T> {
|
||||||
|
|
||||||
|
var value: T
|
||||||
|
var isDone: Bool
|
||||||
|
|
||||||
|
init(value: T) {
|
||||||
|
|
||||||
|
self.value = value
|
||||||
|
self.isDone = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func done() {
|
||||||
|
isDone = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func cancel() {
|
||||||
|
isDone = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func set(_ value: T) {
|
||||||
|
self.value = value
|
||||||
|
isDone = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func get() -> T? {
|
||||||
|
isDone ? value : nil
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,11 +21,11 @@ class FiltersCoordinator: Coordinator {
|
|||||||
self.filter = filter
|
self.filter = filter
|
||||||
}
|
}
|
||||||
|
|
||||||
func start() async throws -> Filter {
|
func start() async throws -> Filter? {
|
||||||
let viewModel = FiltersViewModel(filter: filter)
|
let viewModel = FiltersViewModel(filter: filter)
|
||||||
let controller = CustomHostingController(rootView: FiltersScreen(viewModel: viewModel))
|
let controller = CustomHostingController(rootView: FiltersScreen(viewModel: viewModel))
|
||||||
viewController?.pushViewController(controller, animated: true)
|
viewController?.pushViewController(controller, animated: true)
|
||||||
await controller.waitForDisappear()
|
await controller.waitForDisappear()
|
||||||
return viewModel.filter
|
return viewModel.filterResult
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,11 +41,75 @@ struct FiltersScreen: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.pickerStyle(.navigationLink)
|
.pickerStyle(.navigationLink)
|
||||||
|
|
||||||
|
Section {
|
||||||
|
Picker("Added by", selection: $viewModel.filter.addedBy) {
|
||||||
|
ForEach(AddedBy.allCases, id: \.self) {
|
||||||
|
Text($0.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Section("Update time") {
|
||||||
|
OptionalDatePicker(label: "From",
|
||||||
|
defaultValue: "Beginning",
|
||||||
|
date: $viewModel.filter.fromDateUpdated)
|
||||||
|
OptionalDatePicker(label: "To",
|
||||||
|
defaultValue: "Now",
|
||||||
|
date: $viewModel.filter.toDateUpdated)
|
||||||
|
}
|
||||||
|
|
||||||
|
Section("Added time") {
|
||||||
|
OptionalDatePicker(label: "From",
|
||||||
|
defaultValue: "Beginning",
|
||||||
|
date: $viewModel.filter.fromDate)
|
||||||
|
OptionalDatePicker(label: "To",
|
||||||
|
defaultValue: "Now",
|
||||||
|
date: $viewModel.filter.toDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
Section("Location adding time") {
|
||||||
|
OptionalDatePicker(label: "From",
|
||||||
|
defaultValue: "Beginning",
|
||||||
|
date: $viewModel.filter.fromLocationDate)
|
||||||
|
OptionalDatePicker(label: "To",
|
||||||
|
defaultValue: "Now",
|
||||||
|
date: $viewModel.filter.toLocationDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
Section("Sort") {
|
||||||
|
Section {
|
||||||
|
Picker("Sort by", selection: $viewModel.filter.sortBy) {
|
||||||
|
ForEach(SortParameter.allCases, id: \.self) {
|
||||||
|
Text($0.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Picker("Order", selection: $viewModel.filter.sortOrder) {
|
||||||
|
ForEach(SortOrder.allCases, id: \.self) {
|
||||||
|
Text($0.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Section {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
Button("Clear all filters") {
|
||||||
|
viewModel.clearAllFilters()
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("Filters")
|
.navigationTitle("Filters")
|
||||||
.navigationBarItems(trailing: Button("Done", action: {
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .topBarTrailing) {
|
||||||
}))
|
Button("Done") {
|
||||||
|
viewModel.applyFilters()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.task {
|
.task {
|
||||||
await viewModel.loadData()
|
await viewModel.loadData()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,8 @@ class FiltersViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ObservationIgnored var filterResult: Filter?
|
||||||
|
|
||||||
var models: [StringOption] = [.any]
|
var models: [StringOption] = [.any]
|
||||||
var brands: [StringOption] = [.any]
|
var brands: [StringOption] = [.any]
|
||||||
var colors: [StringOption] = [.any]
|
var colors: [StringOption] = [.any]
|
||||||
@ -51,4 +53,12 @@ class FiltersViewModel {
|
|||||||
models = [.any] + ((try? await api.getModels(of: brand)) ?? []).map { .value($0) }
|
models = [.any] + ((try? await api.getModels(of: brand)) ?? []).map { .value($0) }
|
||||||
filter.model = .any
|
filter.model = .any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func clearAllFilters() {
|
||||||
|
filter.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyFilters() {
|
||||||
|
filterResult = filter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,23 +14,19 @@ struct LinkRowView: View {
|
|||||||
let value: String?
|
let value: String?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if #available(iOS 16.0, *) {
|
ViewThatFits(in: .horizontal) {
|
||||||
ViewThatFits(in: .horizontal) {
|
SimpleLinkRowView(title: title, value: value)
|
||||||
SimpleLinkRowView(title: title, value: value)
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
VStack(alignment: .leading, spacing: 8) {
|
Text(title)
|
||||||
Text(title)
|
HStack {
|
||||||
HStack {
|
Spacer()
|
||||||
Spacer()
|
if let url = URL(string: value ?? "") {
|
||||||
if let url = URL(string: value ?? "") {
|
Link(url.absoluteString, destination: url)
|
||||||
Link(url.absoluteString, destination: url)
|
.multilineTextAlignment(.trailing)
|
||||||
.multilineTextAlignment(.trailing)
|
.padding(.leading)
|
||||||
.padding(.leading)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
SimpleLinkRowView(title: title, value: value)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
AutoCat/SwiftUI/OptionalBinding.swift
Normal file
16
AutoCat/SwiftUI/OptionalBinding.swift
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// OptionalBinding.swift
|
||||||
|
// AutoCat
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 27.10.2024.
|
||||||
|
// Copyright © 2024 Selim Mustafaev. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
public func ??<T>(lhs: Binding<Optional<T>>, rhs: T) -> Binding<T> where T: Sendable {
|
||||||
|
Binding(
|
||||||
|
get: { lhs.wrappedValue ?? rhs },
|
||||||
|
set: { lhs.wrappedValue = $0 }
|
||||||
|
)
|
||||||
|
}
|
||||||
49
AutoCat/SwiftUI/OptionalDatePicker.swift
Normal file
49
AutoCat/SwiftUI/OptionalDatePicker.swift
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// OptionalDatePicker.swift
|
||||||
|
// AutoCat
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 27.10.2024.
|
||||||
|
// Copyright © 2024 Selim Mustafaev. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct OptionalDatePicker: View {
|
||||||
|
|
||||||
|
let label: LocalizedStringKey
|
||||||
|
let defaultValue: LocalizedStringKey
|
||||||
|
@Binding var date: Date?
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
Text(label)
|
||||||
|
Spacer(minLength: 0)
|
||||||
|
if date != nil {
|
||||||
|
HStack {
|
||||||
|
DatePicker("", selection: $date ?? Date(), displayedComponents: [.date])
|
||||||
|
.labelsHidden()
|
||||||
|
Image(systemName: "xmark.circle.fill")
|
||||||
|
.onTapGesture {
|
||||||
|
date = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Text(defaultValue)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.onTapGesture {
|
||||||
|
if date == nil {
|
||||||
|
date = Date()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
VStack {
|
||||||
|
OptionalDatePicker(label: "From", defaultValue: "Beginning", date: .constant(nil))
|
||||||
|
OptionalDatePicker(label: "To", defaultValue: "Now", date: .constant(Date()))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,27 +21,23 @@ struct TextRowView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if #available(iOS 16.0, *) {
|
ViewThatFits(in: .horizontal) {
|
||||||
ViewThatFits(in: .horizontal) {
|
SimpleTextRowView(title: title, value: value, showArrow: showArrow)
|
||||||
SimpleTextRowView(title: title, value: value, showArrow: showArrow)
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
VStack(alignment: .leading, spacing: 8) {
|
Text(title)
|
||||||
Text(title)
|
HStack {
|
||||||
HStack {
|
Spacer()
|
||||||
Spacer()
|
Text(value ?? "")
|
||||||
Text(value ?? "")
|
.foregroundStyle(.secondary)
|
||||||
|
.multilineTextAlignment(.trailing)
|
||||||
|
.padding(.leading)
|
||||||
|
if showArrow {
|
||||||
|
Image(systemName: "chevron.right")
|
||||||
|
.padding(.leading, 8)
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
.multilineTextAlignment(.trailing)
|
|
||||||
.padding(.leading)
|
|
||||||
if showArrow {
|
|
||||||
Image(systemName: "chevron.right")
|
|
||||||
.padding(.leading, 8)
|
|
||||||
.foregroundStyle(.secondary)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
SimpleTextRowView(title: title, value: value, showArrow: showArrow)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,9 +95,9 @@ public struct Filter: Sendable {
|
|||||||
public var color: StringOption = .any
|
public var color: StringOption = .any
|
||||||
public var year: StringOption = .any
|
public var year: StringOption = .any
|
||||||
public var regions: [Int]?
|
public var regions: [Int]?
|
||||||
public var addedBy: AddedBy?
|
public var addedBy: AddedBy = .anyone
|
||||||
public var sortBy: SortParameter? = .updatedDate
|
public var sortBy: SortParameter = .updatedDate
|
||||||
public var sortOrder: SortOrder? = .descending
|
public var sortOrder: SortOrder = .descending
|
||||||
public var fromDate: Date?
|
public var fromDate: Date?
|
||||||
public var toDate: Date?
|
public var toDate: Date?
|
||||||
public var fromDateUpdated: Date?
|
public var fromDateUpdated: Date?
|
||||||
@ -116,7 +116,7 @@ public struct Filter: Sendable {
|
|||||||
self.color = .any
|
self.color = .any
|
||||||
self.year = .any
|
self.year = .any
|
||||||
self.regions = nil
|
self.regions = nil
|
||||||
self.addedBy = nil
|
self.addedBy = .anyone
|
||||||
self.sortBy = .updatedDate
|
self.sortBy = .updatedDate
|
||||||
self.sortOrder = .descending
|
self.sortOrder = .descending
|
||||||
self.fromDate = nil
|
self.fromDate = nil
|
||||||
@ -129,7 +129,12 @@ public struct Filter: Sendable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func queryDictionary() -> [String: String] {
|
public func queryDictionary() -> [String: String] {
|
||||||
var dict: [String: String] = ["query": self.searchString]
|
var dict: [String: String] = [
|
||||||
|
"query": self.searchString,
|
||||||
|
"addedBy": addedBy.rawValue,
|
||||||
|
"sortBy": sortBy.rawValue,
|
||||||
|
"sortOrder": sortOrder.rawValue
|
||||||
|
]
|
||||||
|
|
||||||
if case let .value(brand) = brand {
|
if case let .value(brand) = brand {
|
||||||
dict["brand"] = brand
|
dict["brand"] = brand
|
||||||
@ -146,15 +151,6 @@ public struct Filter: Sendable {
|
|||||||
if let regions = self.regions {
|
if let regions = self.regions {
|
||||||
dict["regions"] = regions.map(String.init).joined(separator: ",")
|
dict["regions"] = regions.map(String.init).joined(separator: ",")
|
||||||
}
|
}
|
||||||
if let addedBy = self.addedBy {
|
|
||||||
dict["addedBy"] = addedBy.rawValue
|
|
||||||
}
|
|
||||||
if let sortBy = self.sortBy {
|
|
||||||
dict["sortBy"] = sortBy.rawValue
|
|
||||||
}
|
|
||||||
if let sortOrder = self.sortOrder {
|
|
||||||
dict["sortOrder"] = sortOrder.rawValue
|
|
||||||
}
|
|
||||||
if let fromDate = self.fromDate {
|
if let fromDate = self.fromDate {
|
||||||
dict["fromDate"] = String(fromDate.timeIntervalSince1970)
|
dict["fromDate"] = String(fromDate.timeIntervalSince1970)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user