Skip to content

Commit

Permalink
feat: add interactive view on origin/destination data
Browse files Browse the repository at this point in the history
  • Loading branch information
hilmyveradin committed Jul 30, 2024
1 parent c21df65 commit 44b336b
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 181 deletions.
2 changes: 2 additions & 0 deletions OTPKit/Features/MapExtension/MapMarkingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public struct MapMarkingView: View {
Button {
locationManagerService.toggleMapMarkingMode(false)
locationManagerService.selectAndRefreshCoordinate()
locationManagerService.removeOriginDestinationData()
} label: {
Text("Cancel")
.padding(8)
Expand All @@ -33,6 +34,7 @@ public struct MapMarkingView: View {

Button {
locationManagerService.toggleMapMarkingMode(false)
locationManagerService.addOriginDestinationData()
locationManagerService.selectAndRefreshCoordinate()
} label: {
Text("Add Pin")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public struct OriginDestinationSheetView: View {
ForEach(locationManagerService.completions) { location in
Button(action: {
locationManagerService.appendMarker(location: location)

locationManagerService.addOriginDestinationData()
switch UserDefaultsServices.shared.saveRecentLocations(data: location) {
case .success:
dismiss()
Expand All @@ -192,6 +192,7 @@ public struct OriginDestinationSheetView: View {
if let userLocation = locationManagerService.currentLocation {
Button(action: {
locationManagerService.appendMarker(location: userLocation)
locationManagerService.addOriginDestinationData()
switch UserDefaultsServices.shared.saveRecentLocations(data: userLocation) {
case .success:
dismiss()
Expand Down
76 changes: 76 additions & 0 deletions OTPKit/Features/TripPlanner/TripPlannerSheetView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//
// TripPlannerSheetView.swift
// OTPKit
//
// Created by Hilmy Veradin on 25/07/24.
//

import SwiftUI

public struct TripPlannerSheetView: View {
@ObservedObject private var locationManagerService = LocationManagerService.shared
@Environment(\.dismiss) var dismiss

public init() {}

private func formatTimeDuration(_ duration: Int) -> String {
if duration < 60 {
return "Total duration: \(duration) second\(duration > 1 ? "s" : "")"
} else if duration < 3600 {
let minutes = Double(duration) / 60
return String(format: "Total duration: %.1f minutes", minutes)
} else {
let hours = Double(duration) / 3600
return String(format: "Total duration: %.1f hours", hours)
}
}

private func formatDistance(_ distance: Int) -> String {
if distance < 1000 {
return "Total distance: \(distance) meters"
} else {
let miles = Double(distance) / 1609.34
return String(format: "Total distance: %.1f miles", miles)
}
}

public var body: some View {
VStack {
if let itineraries = locationManagerService.planResponse?.plan?.itineraries {
List(itineraries, id: \.self) { itinerary in
let distance = itinerary.legs.map(\.distance).reduce(0, +)
Button(action: {
locationManagerService.selectedIternary = itinerary
locationManagerService.planResponse = nil
dismiss()
}, label: {
VStack(alignment: .leading) {
Text(formatTimeDuration(itinerary.duration))
Text(formatDistance(Int(distance)))
}

})
}
} else {
Text("Can't find trip planner. Please try another pin point")
}

Button(action: {
locationManagerService.resetTripPlanner()
dismiss()
}, label: {
Text("Cancel")
.frame(maxWidth: .infinity)
.padding()
.background(Color.gray)
.foregroundStyle(Color.white)
.clipShape(RoundedRectangle(cornerRadius: 12))
.padding(.horizontal, 16)
})
}
}
}

#Preview {
TripPlannerSheetView()
}
39 changes: 25 additions & 14 deletions OTPKit/Features/TripPlanner/TripPlannerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,41 @@
// TripPlannerView.swift
// OTPKit
//
// Created by Hilmy Veradin on 25/07/24.
// Created by Hilmy Veradin on 30/07/24.
//

import SwiftUI

public struct TripPlannerView: View {
@ObservedObject private var locationManagerService = LocationManagerService.shared
@Environment(\.dismiss) var dismiss

public init() {}

public var body: some View {
if let itineraries = locationManagerService.planResponse?.plan?.itineraries {
List(itineraries, id: \.self) { itinerary in
Button(action: {
locationManagerService.selectedIternary = itinerary
VStack {
Button(action: {
locationManagerService.resetTripPlanner()
}, label: {
Text("Start")
})
.frame(maxWidth: .infinity)
.padding()
.background(Color.gray)
.foregroundStyle(Color.white)
.clipShape(RoundedRectangle(cornerRadius: 12))
.padding(.horizontal, 16)

locationManagerService.planResponse = nil
dismiss()
}, label: {
Text("Total Duration: \(itinerary.duration)")
})
}
} else {
Text("Can't find location")
Button(action: {
locationManagerService.resetTripPlanner()
}, label: {
Text("Cancel")
})
.frame(maxWidth: .infinity)
.padding()
.background(Color.gray)
.foregroundStyle(Color.white)
.clipShape(RoundedRectangle(cornerRadius: 12))
.padding(.horizontal, 16)
}
}
}
Expand Down
39 changes: 27 additions & 12 deletions OTPKit/Services/LocationManagerService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,38 @@ public final class LocationManagerService: NSObject, ObservableObject {
case .origin:
selectedMapPoint["origin"] = markerItem
changeMapCamera(mapItem)
originName = mapItem.name ?? "Location unknown"
originCoordinate = coordinate
case .destination:
selectedMapPoint["destination"] = markerItem
changeMapCamera(mapItem)
destinationName = mapItem.name ?? "Location unknown"
destinationCoordinate = coordinate
}
}

public func addOriginDestinationData() {
switch originDestinationState {
case .origin:
originName = selectedMapPoint["origin"]??.item.name ?? "Location unknown"
originCoordinate = selectedMapPoint["origin"]??.item.placemark.coordinate
case .destination:
destinationName = selectedMapPoint["destination"]??.item.name ?? "Location unknown"
destinationCoordinate = selectedMapPoint["destination"]??.item.placemark.coordinate
}

checkAndFetchTripPlanner()
}

public func removeOriginDestinationData() {
switch originDestinationState {
case .origin:
originName = "Origin"
originCoordinate = nil
selectedMapPoint["origin"] = nil
case .destination:
destinationName = "Destination"
destinationCoordinate = nil
selectedMapPoint["destination"] = nil
}
}

public func toggleMapMarkingMode(_ isMapMarking: Bool) {
isMapMarkingMode = isMapMarking
}
Expand All @@ -142,21 +162,16 @@ public final class LocationManagerService: NSObject, ObservableObject {
public func generateMapPolyline() -> MapPolyline? {
guard let itinerary = selectedIternary else { return nil }

// Experiment on using steps compactmap
// Use steps to calculate the Location Coordinate
let coordinates = itinerary.legs.flatMap { leg in
leg.steps?.compactMap { step in
CLLocationCoordinate2D(latitude: step.lat, longitude: step.lon)
} ?? []
}

// let coordinates = itinerary.legs.flatMap { leg in
// [CLLocationCoordinate2D(latitude: leg.from.lat, longitude: leg.from.lon),
// CLLocationCoordinate2D(latitude: leg.to.lat, longitude: leg.to.lon)]
// }

print("---", coordinates, "---")
let coodinateExists = !coordinates.isEmpty

guard !coordinates.isEmpty else { return nil }
guard coodinateExists else { return nil }

return MapPolyline(coordinates: coordinates)
}
Expand Down
18 changes: 12 additions & 6 deletions OTPKitDemo/MapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,23 @@ public struct MapView: View {
OriginDestinationSheetView()
.environmentObject(sheetEnvironment)
}
.sheet(isPresented: isPlanResponsePresented, onDismiss: {
// locationManagerService.resetTripPlanner()
// locationManagerService.planResponse = nil
}, content: {
TripPlannerView()
.sheet(isPresented: isPlanResponsePresented, content: {
TripPlannerSheetView()
.presentationDetents([.medium, .large])
// .interactiveDismissDisabled()
})
}

if locationManagerService.isFetchingResponse {
ProgressView()
}

if locationManagerService.isMapMarkingMode {
MapMarkingView()
} else if locationManagerService.selectedIternary != nil {
VStack {
Spacer()
TripPlannerView()
}
} else {
VStack {
Spacer()
Expand Down
73 changes: 0 additions & 73 deletions OTPKitDemo/TripPlannerView.swift

This file was deleted.

Loading

0 comments on commit 44b336b

Please sign in to comment.