Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Origin Destination Working Marker View #32

Merged
merged 4 commits into from
Jul 20, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions OTPKit/Features/MapExtension/MapMarkingView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// MapMarkingView.swift
// OTPKit
//
// Created by Hilmy Veradin on 18/07/24.
//

import SwiftUI

public struct MapMarkingView: View {
@ObservedObject private var locationManagerService = LocationManagerService.shared

public init() {}
public var body: some View {
VStack {
Spacer()

VStack(spacing: 16) {
Button(action: {
locationManagerService.toggleMapMarkingMode(false)
locationManagerService.selectCoordinate()
}, label: {
Text("Add Map Location")
})
.padding(.all)
.background(Color.gray)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @aaronbrethorst, I wonder do you have any suggestion on this color? Seems like the contrast is not good for our texts...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend a white background and a gray border for the button.

.clipShape(.rect(cornerRadius: 12))

Button(action: {
locationManagerService.toggleMapMarkingMode(false)
locationManagerService.selectCoordinate()
}, label: {
Text("Cancel Map Location")
})

.padding(.all)
.background(Color.gray)
.clipShape(.rect(cornerRadius: 12))
}
.padding(.bottom, 24)
}
}
}

#Preview {
MapMarkingView()
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,11 @@
import Foundation
import SwiftUI

/// OriginDestinationSheetState responsible for managing states of the shown `OriginDestinationSheetView`
/// - Enums:
/// - origin: This manage origin state of the trip planner
/// - destination: This manage destination state of the trip planner
public enum OriginDestinationSheetState {
case origin
case destination
}

/// OriginDestinationSheetEnvironment responsible for manage the environment of `OriginDestination` features
/// - sheetState: responsible for managing shown sheet in `OriginDestinationView`
/// - selectedValue: responsible for managing selected value when user taped the list in `OriginDestinationSheetView`
public final class OriginDestinationSheetEnvironment: ObservableObject {
@Published public var isSheetOpened = false
@Published public var sheetState: OriginDestinationSheetState = .origin
@Published public var selectedValue: String = ""

// This responsible for showing favorite locations and recent locations in sheets
Expand Down
6 changes: 4 additions & 2 deletions OTPKit/Features/OriginDestination/OriginDestinationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import SwiftUI
/// It consists a list of Origin and Destination along with the `MapKit`
public struct OriginDestinationView: View {
@EnvironmentObject private var sheetEnvironment: OriginDestinationSheetEnvironment
@ObservedObject private var locationManagerService = LocationManagerService.shared
@State private var isSheetOpened = false

// Public Initializer
Expand All @@ -22,7 +23,7 @@ public struct OriginDestinationView: View {
List {
Button(action: {
sheetEnvironment.isSheetOpened.toggle()
sheetEnvironment.sheetState = .origin
locationManagerService.originDestinationState = .origin
}, label: {
HStack(spacing: 16) {
Image(systemName: "paperplane.fill")
Expand All @@ -38,7 +39,7 @@ public struct OriginDestinationView: View {

Button(action: {
sheetEnvironment.isSheetOpened.toggle()
sheetEnvironment.sheetState = .destination
locationManagerService.originDestinationState = .destination
}, label: {
HStack(spacing: 16) {
Image(systemName: "mappin")
Expand All @@ -55,6 +56,7 @@ public struct OriginDestinationView: View {
.frame(height: 135)
.scrollContentBackground(.hidden)
.scrollDisabled(true)
.padding(.bottom, 24)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,107 +11,124 @@ import SwiftUI
/// Users can search and add their favorite locations
public struct AddFavoriteLocationsSheet: View {
@Environment(\.dismiss) var dismiss

@EnvironmentObject private var locationService: LocationService
@EnvironmentObject private var sheetEnvironment: OriginDestinationSheetEnvironment

@ObservedObject private var locationManagerService = LocationManagerService.shared

@State private var search = ""
private let userLocation = UserLocationServices.shared.currentLocation

@FocusState private var isSearchActive: Bool
@FocusState private var isSearchFocused: Bool

private var filteredCompletions: [Location] {
let favorites = sheetEnvironment.favoriteLocations
return locationService.completions.filter { completion in
return locationManagerService.completions.filter { completion in
!favorites.contains { favorite in
favorite.title == completion.title &&
favorite.subTitle == completion.subTitle
}
}
}

public var body: some View {
VStack {
HStack {
Text("Add favorite location")
private func headerView() -> some View {
HStack {
Text("Add favorite location")
.font(.title2)
.fontWeight(.bold)
Spacer()
Button(action: {
dismiss()
}, label: {
Image(systemName: "xmark.circle.fill")
.font(.title2)
.fontWeight(.bold)
Spacer()
.foregroundColor(.gray)
})
}
.padding()
}

private func searchView() -> some View {
HStack {
Image(systemName: "magnifyingglass")
TextField("Search for a place", text: $search)
.autocorrectionDisabled()
.focused($isSearchFocused)
}
.padding(.vertical, 8)
.padding(.horizontal, 12)
.background(Color.gray.opacity(0.2))
.clipShape(RoundedRectangle(cornerRadius: 12))
.padding(.horizontal, 16)
}

private func currentUserSection() -> some View {
if search.isEmpty, let userLocation = locationManagerService.currentLocation {
AnyView(
Button(action: {
dismiss()
switch UserDefaultsServices.shared.saveFavoriteLocationData(data: userLocation) {
case .success:
sheetEnvironment.refreshFavoriteLocations()
dismiss()
case let .failure(error):
print(error)
}
}, label: {
Image(systemName: "xmark.circle.fill")
.font(.title2)
.foregroundColor(.gray)
HStack {
VStack(alignment: .leading) {
Text(userLocation.title)
.font(.headline)
Text(userLocation.subTitle)
}.foregroundStyle(Color.black)

Spacer()

Image(systemName: "plus")
}

})
}
.padding()
)

HStack {
Image(systemName: "magnifyingglass")
TextField("Search for a place", text: $search)
.autocorrectionDisabled()
.focused($isSearchActive)
}
.padding(.vertical, 8)
.padding(.horizontal, 12)
.background(Color.gray.opacity(0.2))
.clipShape(.rect(cornerRadius: 12))
.padding(.horizontal, 16)
} else {
AnyView(EmptyView())
}
}

List {
if search.isEmpty, let userLocation {
Button(action: {
switch UserDefaultsServices.shared.saveFavoriteLocationData(data: userLocation) {
case .success:
sheetEnvironment.refreshFavoriteLocations()
dismiss()
case let .failure(error):
print(error)
}
}, label: {
HStack {
VStack(alignment: .leading) {
Text(userLocation.title)
.font(.headline)
Text(userLocation.subTitle)
}.foregroundStyle(Color.black)

Spacer()

Image(systemName: "plus")
}

})
private func searchedResultsSection() -> some View {
ForEach(filteredCompletions) { location in
Button(action: {
switch UserDefaultsServices.shared.saveFavoriteLocationData(data: location) {
case .success:
sheetEnvironment.refreshFavoriteLocations()
dismiss()
case let .failure(error):
print(error)
}
}, label: {
HStack {
VStack(alignment: .leading) {
Text(location.title)
.font(.headline)
Text(location.subTitle)
}.foregroundStyle(Color.black)

Spacer()

ForEach(filteredCompletions) { location in
Button(action: {
switch UserDefaultsServices.shared.saveFavoriteLocationData(data: location) {
case .success:
sheetEnvironment.refreshFavoriteLocations()
dismiss()
case let .failure(error):
print(error)
}
}, label: {
HStack {
VStack(alignment: .leading) {
Text(location.title)
.font(.headline)
Text(location.subTitle)
}.foregroundStyle(Color.black)

Spacer()

Image(systemName: "plus")
}

})
Image(systemName: "plus")
}

})
}
}

public var body: some View {
VStack {
headerView()
searchView()
List {
currentUserSection()
searchedResultsSection()
}
.onChange(of: search) { _, searchValue in
locationService.update(queryFragment: searchValue)
locationManagerService.updateQuery(queryFragment: searchValue)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ public struct OriginDestinationSheetView: View {
@Environment(\.dismiss) var dismiss
@EnvironmentObject var sheetEnvironment: OriginDestinationSheetEnvironment

@StateObject private var locationService = LocationService()
@ObservedObject private var locationManagerService = LocationManagerService.shared
aaronbrethorst marked this conversation as resolved.
Show resolved Hide resolved

@State private var search: String = ""

private let userLocation = UserLocationServices.shared.currentLocation

// Sheet States
@State private var isAddSavedLocationsSheetOpen = false
@State private var isFavoriteLocationSheetOpen = false
Expand Down Expand Up @@ -116,7 +114,6 @@ public struct OriginDestinationSheetView: View {
})
.sheet(isPresented: $isAddSavedLocationsSheetOpen, content: {
AddFavoriteLocationsSheet()
.environmentObject(locationService)
.environmentObject(sheetEnvironment)
})
.sheet(isPresented: $isFavoriteLocationSheetOpen, content: {
Expand Down Expand Up @@ -167,7 +164,7 @@ public struct OriginDestinationSheetView: View {

private func searchResultsSection() -> some View {
Group {
ForEach(locationService.completions) { location in
ForEach(locationManagerService.completions) { location in
Button(action: {
switch UserDefaultsServices.shared.saveRecentLocations(data: location) {
case .success:
Expand All @@ -190,7 +187,7 @@ public struct OriginDestinationSheetView: View {

private func currentUserSection() -> some View {
Group {
if let userLocation {
if let userLocation = locationManagerService.currentLocation {
Button(action: {
switch UserDefaultsServices.shared.saveRecentLocations(data: userLocation) {
case .success:
Expand All @@ -213,6 +210,19 @@ public struct OriginDestinationSheetView: View {
}
}

private func selectLocationBasedOnMap() -> some View {
Button(action: {
locationManagerService.toggleMapMarkingMode(true)
dismiss()
}, label: {
HStack {
Image(systemName: "mappin")
Text("Select based on Map")
}
})
.buttonStyle(PlainButtonStyle())
}

public var body: some View {
VStack {
headerView()
Expand All @@ -223,16 +233,18 @@ public struct OriginDestinationSheetView: View {

List {
if search.isEmpty, isSearchFocused {
selectLocationBasedOnMap()
currentUserSection()
} else if search.isEmpty {
favoritesSection()
recentsSection()
} else {
selectLocationBasedOnMap()
searchResultsSection()
}
}
.onChange(of: search) { _, searchValue in
locationService.update(queryFragment: searchValue)
locationManagerService.updateQuery(queryFragment: searchValue)
}

Spacer()
Expand Down
Loading
Loading