diff --git a/AutoCat.xcodeproj/project.pbxproj b/AutoCat.xcodeproj/project.pbxproj index 0d6c1b7..88b6c49 100644 --- a/AutoCat.xcodeproj/project.pbxproj +++ b/AutoCat.xcodeproj/project.pbxproj @@ -151,6 +151,10 @@ 7AB587412C42FFE200FA7B66 /* ApiServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB587402C42FFE200FA7B66 /* ApiServiceProtocol.swift */; }; 7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB67E8B2435C38700258F61 /* CustomTextField.swift */; }; 7AB67E8E2435D1A000258F61 /* CustomButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB67E8D2435D1A000258F61 /* CustomButton.swift */; }; + 7AB9FE222D08C2A5005DE374 /* EventsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB9FE212D08C2A5005DE374 /* EventsScreen.swift */; }; + 7AB9FE262D08C2D7005DE374 /* EventsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB9FE252D08C2D7005DE374 /* EventsCoordinator.swift */; }; + 7AB9FE282D08C2F4005DE374 /* EventsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB9FE272D08C2F4005DE374 /* EventsViewModel.swift */; }; + 7AB9FE2A2D08CF35005DE374 /* EventsScreenMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB9FE292D08CF35005DE374 /* EventsScreenMode.swift */; }; 7ABD1B472D044A3200B43213 /* GalleryScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ABD1B462D044A3200B43213 /* GalleryScreen.swift */; }; 7ABD1B492D044A4700B43213 /* GalleryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ABD1B482D044A4700B43213 /* GalleryViewModel.swift */; }; 7ABD1B4B2D044A7D00B43213 /* GalleryCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ABD1B4A2D044A7D00B43213 /* GalleryCoordinator.swift */; }; @@ -420,6 +424,10 @@ 7AB587402C42FFE200FA7B66 /* ApiServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiServiceProtocol.swift; sourceTree = ""; }; 7AB67E8B2435C38700258F61 /* CustomTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTextField.swift; sourceTree = ""; }; 7AB67E8D2435D1A000258F61 /* CustomButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomButton.swift; sourceTree = ""; }; + 7AB9FE212D08C2A5005DE374 /* EventsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventsScreen.swift; sourceTree = ""; }; + 7AB9FE252D08C2D7005DE374 /* EventsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventsCoordinator.swift; sourceTree = ""; }; + 7AB9FE272D08C2F4005DE374 /* EventsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventsViewModel.swift; sourceTree = ""; }; + 7AB9FE292D08CF35005DE374 /* EventsScreenMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventsScreenMode.swift; sourceTree = ""; }; 7ABD1B462D044A3200B43213 /* GalleryScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GalleryScreen.swift; sourceTree = ""; }; 7ABD1B482D044A4700B43213 /* GalleryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GalleryViewModel.swift; sourceTree = ""; }; 7ABD1B4A2D044A7D00B43213 /* GalleryCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GalleryCoordinator.swift; sourceTree = ""; }; @@ -670,6 +678,7 @@ 7A1441632C297E9800E79018 /* Screens */ = { isa = PBXGroup; children = ( + 7AB9FE202D08C28E005DE374 /* EventsScreen */, 7ABD1B452D044A0900B43213 /* GalleryScreen */, 7A1E78F42CE9001A0004B740 /* ReportScreen */, 7A43228F2CB2CC5D00085CF6 /* FiltersScreen */, @@ -971,6 +980,17 @@ path = ApiService; sourceTree = ""; }; + 7AB9FE202D08C28E005DE374 /* EventsScreen */ = { + isa = PBXGroup; + children = ( + 7AB9FE212D08C2A5005DE374 /* EventsScreen.swift */, + 7AB9FE252D08C2D7005DE374 /* EventsCoordinator.swift */, + 7AB9FE272D08C2F4005DE374 /* EventsViewModel.swift */, + 7AB9FE292D08CF35005DE374 /* EventsScreenMode.swift */, + ); + path = EventsScreen; + sourceTree = ""; + }; 7ABD1B452D044A0900B43213 /* GalleryScreen */ = { isa = PBXGroup; children = ( @@ -1322,6 +1342,8 @@ 7AE26A3524F31B0700625033 /* EventsController.swift in Sources */, 7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */, 7AF860702CBAA24500954D2F /* NavigationLink.swift in Sources */, + 7AB9FE262D08C2D7005DE374 /* EventsCoordinator.swift in Sources */, + 7AB9FE282D08C2F4005DE374 /* EventsViewModel.swift in Sources */, 7A27ADF5249FD2F90035F39E /* FileManagerExt.swift in Sources */, 7A4927D52CCE438600851C01 /* OptionalBinding.swift in Sources */, 7A17CE4A2A2E820300626A6E /* UIStackView.swift in Sources */, @@ -1356,6 +1378,7 @@ 7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */, 7A64AE742469DFB600ABE48E /* MediaContentView.swift in Sources */, 7A1090EC24A4E3E100B4F0B2 /* CellProgressView.swift in Sources */, + 7AB9FE2A2D08CF35005DE374 /* EventsScreenMode.swift in Sources */, 7A96AE2D246B2B7400297C33 /* GoogleSignInController.swift in Sources */, 7A10227B2C557EE900B84627 /* LocationPickerCoordinator.swift in Sources */, 7A1090EA24A3A26300B4F0B2 /* AudioPlayer.swift in Sources */, @@ -1392,6 +1415,7 @@ 7A06E0B02C7065D8005731AC /* SettingsCoordinator.swift in Sources */, 7A91894F29A2BD8700519C74 /* GestureRecognizers.swift in Sources */, 7AFBE8CC2C3085C6003C491D /* ACProgressView.swift in Sources */, + 7AB9FE222D08C2A5005DE374 /* EventsScreen.swift in Sources */, 7ADF6C93250B954900F237B2 /* Navigation.swift in Sources */, 7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */, 7ABD1B4B2D044A7D00B43213 /* GalleryCoordinator.swift in Sources */, diff --git a/AutoCat/Screens/EventsScreen/EventsCoordinator.swift b/AutoCat/Screens/EventsScreen/EventsCoordinator.swift new file mode 100644 index 0000000..e72079b --- /dev/null +++ b/AutoCat/Screens/EventsScreen/EventsCoordinator.swift @@ -0,0 +1,30 @@ +// +// EventsCoordinator.swift +// AutoCat +// +// Created by Selim Mustafaev on 10.12.2024. +// Copyright © 2024 Selim Mustafaev. All rights reserved. +// + +import UIKit +import AutoCatCore + +@MainActor +class EventsCoordinator { + + let navController: UINavigationController + + init(navController: UINavigationController) { + + self.navController = navController + } + + func start(vehicle: VehicleDto) async -> VehicleDto { + + let viewModel = EventsViewModel(vehicle: vehicle) + let controller = CustomHostingController(rootView: EventsScreen(viewModel: viewModel)) + navController.pushViewController(controller, animated: true) + await controller.waitForDisappear() + return viewModel.vehicle + } +} diff --git a/AutoCat/Screens/EventsScreen/EventsScreen.swift b/AutoCat/Screens/EventsScreen/EventsScreen.swift new file mode 100644 index 0000000..2d398ee --- /dev/null +++ b/AutoCat/Screens/EventsScreen/EventsScreen.swift @@ -0,0 +1,49 @@ +// +// EventsScreen.swift +// AutoCat +// +// Created by Selim Mustafaev on 10.12.2024. +// Copyright © 2024 Selim Mustafaev. All rights reserved. +// + +import SwiftUI +import AutoCatCore +import MapKit + +struct EventsScreen: View { + + @State var viewModel: EventsViewModel + + init(viewModel: EventsViewModel) { + self.viewModel = viewModel + } + + var body: some View { + ZStack{ + map + .zIndex(viewModel.mode == .map ? 1 : 0) + list + .zIndex(viewModel.mode == .list ? 1 : 0) + } + .navigationTitle(viewModel.vehicle.number) + .toolbar { + ToolbarItem(placement: .primaryAction) { + Button("", systemImage: viewModel.mode.switchIcon) { + viewModel.mode.toggle() + } + } + } + } + + var map: some View { + Map {} + } + + var list: some View { + List {} + } +} + +#Preview { + EventsScreen(viewModel: .init(vehicle: .preview)) +} diff --git a/AutoCat/Screens/EventsScreen/EventsScreenMode.swift b/AutoCat/Screens/EventsScreen/EventsScreenMode.swift new file mode 100644 index 0000000..93993b4 --- /dev/null +++ b/AutoCat/Screens/EventsScreen/EventsScreenMode.swift @@ -0,0 +1,36 @@ +// +// EventsScreenMode.swift +// AutoCat +// +// Created by Selim Mustafaev on 10.12.2024. +// Copyright © 2024 Selim Mustafaev. All rights reserved. +// + +import Foundation + +enum EventsScreenMode { + + case map + case list + + var switchIcon: String { + switch self { + case .map: "list.bullet" + case .list: "map" + } + } + + var switchTitle: String { + switch self { + case .map: "Switch to list" + case .list: "Switch to map" + } + } + + mutating func toggle() { + switch self { + case .map: self = .list + case .list: self = .map + } + } +} diff --git a/AutoCat/Screens/EventsScreen/EventsViewModel.swift b/AutoCat/Screens/EventsScreen/EventsViewModel.swift new file mode 100644 index 0000000..477ddd8 --- /dev/null +++ b/AutoCat/Screens/EventsScreen/EventsViewModel.swift @@ -0,0 +1,27 @@ +// +// EventsViewModel.swift +// AutoCat +// +// Created by Selim Mustafaev on 10.12.2024. +// Copyright © 2024 Selim Mustafaev. All rights reserved. +// + +import SwiftUI +import AutoCatCore + +@MainActor +@Observable +class EventsViewModel { + + @ObservationIgnored @Service var api: ApiServiceProtocol + @ObservationIgnored @Service var storageService: StorageServiceProtocol + + var vehicle: VehicleDto + var mode: EventsScreenMode = .map + var hud: ACHud? + + init(vehicle: VehicleDto) { + + self.vehicle = vehicle + } +} diff --git a/AutoCat/Screens/ReportScreen/ReportCoordinator.swift b/AutoCat/Screens/ReportScreen/ReportCoordinator.swift index dda0619..4c22990 100644 --- a/AutoCat/Screens/ReportScreen/ReportCoordinator.swift +++ b/AutoCat/Screens/ReportScreen/ReportCoordinator.swift @@ -38,13 +38,13 @@ class ReportCoordinator: Coordinator { return viewModel.vehicle } - func openEvents(vehicle: VehicleDto, onUpdate: @escaping (VehicleDto) -> Void) { + func openEvents(vehicle: VehicleDto) async -> VehicleDto? { + guard let navController else { + return nil + } - let sb = UIStoryboard(name: "Main", bundle: nil) - let controller = sb.instantiateViewController(identifier: "EventsController") as EventsController - controller.vehicle = vehicle - controller.vehicleUpdated = onUpdate - navController?.pushViewController(controller, animated: true) + let coordinator = EventsCoordinator(navController: navController) + return await coordinator.start(vehicle: vehicle) } func openOsago(contracts: [OsagoDto]) { diff --git a/AutoCat/Screens/ReportScreen/ReportViewModel.swift b/AutoCat/Screens/ReportScreen/ReportViewModel.swift index 74ad308..7736bdd 100644 --- a/AutoCat/Screens/ReportScreen/ReportViewModel.swift +++ b/AutoCat/Screens/ReportScreen/ReportViewModel.swift @@ -92,8 +92,10 @@ class ReportViewModel: ACHudContainer { // MARK: Open detail screens func openEvents() { - coordinator?.openEvents(vehicle: vehicle) { [weak self] vehicle in - self?.vehicle = vehicle + Task { + if let vehicle = await coordinator?.openEvents(vehicle: vehicle) { + self.vehicle = vehicle + } } }