AutoCat/AutoCat/Screens/EventsScreen/EventsScreen.swift

146 lines
4.3 KiB
Swift

//
// 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
@State var selectedEvent: EventModel?
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)
}
.hud($viewModel.hud)
.navigationTitle(viewModel.vehicle.number)
.toolbar {
if viewModel.isPasteAvailable {
ToolbarItem(placement: .primaryAction) {
Button("", systemImage: "document.on.clipboard") {
viewModel.confirmPaste()
}
}
}
ToolbarItem(placement: .primaryAction) {
Button("", systemImage: "plus") {
Task { await viewModel.addNewEvent() }
}
}
ToolbarItem(placement: .primaryAction) {
Button("", systemImage: viewModel.mode.switchIcon) {
viewModel.mode.toggle()
}
}
}
.alert("Paste event",
isPresented: $viewModel.showPasteAlert,
presenting: viewModel.pastedEvent) { event in
Button("Cancel", role: .cancel, action: {})
Button("OK") {
Task { await viewModel.addEvent(event) }
}
.keyboardShortcut(.defaultAction)
} message: { event in
Text(viewModel.getConfirmMessge(from: event))
}
}
var map: some View {
Map(selection: $selectedEvent) {
ForEach(viewModel.events) {
Marker($0.date, coordinate: $0.coordinate)
.tag($0)
}
}
}
var list: some View {
List {
ForEach(viewModel.events) { event in
makeEventCell(for: event)
.contentShape(Rectangle())
.onTapGesture {
viewModel.mode = .map
selectedEvent = event
}
.swipeActions(allowsFullSwipe: false) {
makeActions(for: event)
}
.contextMenu {
makeActions(for: event, useLabels: true)
}
}
}
.listStyle(.inset)
}
func makeEventCell(for event: EventModel) -> some View {
HStack {
VStack(alignment: .leading, spacing: 4) {
Text(event.address)
Text(event.date)
.foregroundStyle(.secondary)
}
Spacer()
Image(systemName: event.isMe ? "person.fill" : "person")
.foregroundStyle(event.isMe ? Color.accentColor : .secondary)
}
}
@ViewBuilder
func makeActions(for event: EventModel, useLabels: Bool = false) -> some View {
Button(role: .destructive) {
Task { await viewModel.deleteEvent(event) }
} label: {
Label(useLabels ? "Delete" : "", systemImage: "trash")
}
Button() {
Task { await viewModel.editEvent(event) }
} label: {
Label(useLabels ? "Edit" : "", systemImage: "pencil")
}
Button() {
viewModel.copyEvent(event)
} label: {
Label(useLabels ? "Copy" : "", systemImage: "doc.on.doc")
}
if useLabels {
Button() {
viewModel.openMaps(event)
} label: {
Label("Open in Maps", systemImage: "map")
}
if let link = viewModel.getMapLink(for: event) {
ShareLink(item: link)
}
}
}
}
#Preview {
EventsScreen(viewModel: .init(apiService: MockApiServiceProtocol(),
storageService: MockStorageServiceProtocol(),
settingsService: MockSettingsServiceProtocol(),
vehicle: .preview))
}