fix: use LocationSearchSheet for Start/End Location fields
Replaces inline text fields with buttons that open LocationSearchSheet, matching the must-stop location picker UI for consistency. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,8 @@ struct TripCreationView: View {
|
||||
case mustStop
|
||||
case preferred
|
||||
case homeLocation
|
||||
case startLocation
|
||||
case endLocation
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@@ -122,9 +124,12 @@ struct TripCreationView: View {
|
||||
viewModel.addMustStopLocation(location)
|
||||
case .preferred:
|
||||
viewModel.addPreferredCity(location.name)
|
||||
case .homeLocation:
|
||||
case .homeLocation, .startLocation:
|
||||
viewModel.startLocationText = location.name
|
||||
viewModel.startLocation = location
|
||||
case .endLocation:
|
||||
viewModel.endLocationText = location.name
|
||||
viewModel.endLocation = location
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,71 +245,68 @@ struct TripCreationView: View {
|
||||
|
||||
private var locationSection: some View {
|
||||
ThemedSection(title: "Locations") {
|
||||
// Start Location with suggestions
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
ThemedTextField(
|
||||
label: "Start Location",
|
||||
placeholder: "Where are you starting from?",
|
||||
text: $viewModel.startLocationText,
|
||||
icon: "location.circle.fill"
|
||||
)
|
||||
.onChange(of: viewModel.startLocationText) { _, newValue in
|
||||
searchLocation(query: newValue, isStart: true)
|
||||
}
|
||||
|
||||
// Suggestions for start location
|
||||
if !startLocationSuggestions.isEmpty {
|
||||
locationSuggestionsList(
|
||||
suggestions: startLocationSuggestions,
|
||||
isLoading: isSearchingStart
|
||||
) { result in
|
||||
viewModel.startLocationText = result.name
|
||||
viewModel.startLocation = result.toLocationInput()
|
||||
startLocationSuggestions = []
|
||||
}
|
||||
} else if isSearchingStart {
|
||||
HStack {
|
||||
ThemedSpinnerCompact(size: 14)
|
||||
Text("Searching...")
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Theme.textMuted(colorScheme))
|
||||
}
|
||||
.padding(.top, Theme.Spacing.xs)
|
||||
}
|
||||
// Start Location - opens search sheet
|
||||
locationButton(
|
||||
label: "Start Location",
|
||||
icon: "location.circle.fill",
|
||||
location: viewModel.startLocation,
|
||||
placeholder: "Where are you starting from?"
|
||||
) {
|
||||
cityInputType = .startLocation
|
||||
showCityInput = true
|
||||
}
|
||||
|
||||
// End Location with suggestions
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
ThemedTextField(
|
||||
label: "End Location",
|
||||
placeholder: "Where do you want to end up?",
|
||||
text: $viewModel.endLocationText,
|
||||
icon: "mappin.circle.fill"
|
||||
)
|
||||
.onChange(of: viewModel.endLocationText) { _, newValue in
|
||||
searchLocation(query: newValue, isStart: false)
|
||||
}
|
||||
// End Location - opens search sheet
|
||||
locationButton(
|
||||
label: "End Location",
|
||||
icon: "mappin.circle.fill",
|
||||
location: viewModel.endLocation,
|
||||
placeholder: "Where do you want to end up?"
|
||||
) {
|
||||
cityInputType = .endLocation
|
||||
showCityInput = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Suggestions for end location
|
||||
if !endLocationSuggestions.isEmpty {
|
||||
locationSuggestionsList(
|
||||
suggestions: endLocationSuggestions,
|
||||
isLoading: isSearchingEnd
|
||||
) { result in
|
||||
viewModel.endLocationText = result.name
|
||||
viewModel.endLocation = result.toLocationInput()
|
||||
endLocationSuggestions = []
|
||||
}
|
||||
} else if isSearchingEnd {
|
||||
HStack {
|
||||
ThemedSpinnerCompact(size: 14)
|
||||
Text("Searching...")
|
||||
.font(.subheadline)
|
||||
private func locationButton(
|
||||
label: String,
|
||||
icon: String,
|
||||
location: LocationInput?,
|
||||
placeholder: String,
|
||||
action: @escaping () -> Void
|
||||
) -> some View {
|
||||
VStack(alignment: .leading, spacing: Theme.Spacing.xs) {
|
||||
Text(label)
|
||||
.font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
.foregroundStyle(Theme.warmOrange)
|
||||
|
||||
Button(action: action) {
|
||||
HStack(spacing: Theme.Spacing.md) {
|
||||
Image(systemName: icon)
|
||||
.foregroundStyle(Theme.warmOrange)
|
||||
.frame(width: 24)
|
||||
|
||||
if let location = location {
|
||||
Text(location.name)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
} else {
|
||||
Text(placeholder)
|
||||
.foregroundStyle(Theme.textMuted(colorScheme))
|
||||
}
|
||||
.padding(.top, Theme.Spacing.xs)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(systemName: "chevron.right")
|
||||
.font(.caption)
|
||||
.foregroundStyle(Theme.textMuted(colorScheme))
|
||||
}
|
||||
.padding(Theme.Spacing.md)
|
||||
.background(Theme.cardBackgroundElevated(colorScheme))
|
||||
.clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user