// // LocationsStep.swift // SportsTime // // Start and end location selection for "By Route" planning mode. // import SwiftUI struct LocationsStep: View { @Environment(\.colorScheme) private var colorScheme @Binding var startLocation: LocationInput? @Binding var endLocation: LocationInput? @State private var showStartLocationSearch = false @State private var showEndLocationSearch = false @State private var isRoundTrip = false var body: some View { VStack(alignment: .leading, spacing: Theme.Spacing.md) { StepHeader( title: "Where are you traveling?", subtitle: "Set your start and end points" ) // Start Location locationRow( label: "Starting from", location: startLocation, placeholder: "Select start city", onTap: { showStartLocationSearch = true }, onClear: { startLocation = nil } ) // End Location if !isRoundTrip { locationRow( label: "Ending at", location: endLocation, placeholder: "Select end city", onTap: { showEndLocationSearch = true }, onClear: { endLocation = nil } ) } // Round Trip Toggle Toggle(isOn: $isRoundTrip) { HStack(spacing: Theme.Spacing.sm) { Image(systemName: "arrow.triangle.2.circlepath") .foregroundStyle(Theme.warmOrange) .accessibilityHidden(true) Text("Round trip (return to start)") .font(.subheadline) .foregroundStyle(Theme.textPrimary(colorScheme)) } } .toggleStyle(SwitchToggleStyle(tint: Theme.warmOrange)) .onChange(of: isRoundTrip) { _, newValue in if newValue { endLocation = startLocation } else { endLocation = nil } } .onChange(of: startLocation) { _, newValue in if isRoundTrip { endLocation = newValue } } } .padding(Theme.Spacing.lg) .background(Theme.cardBackground(colorScheme)) .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.large)) .overlay { RoundedRectangle(cornerRadius: Theme.CornerRadius.large) .stroke(Theme.surfaceGlow(colorScheme), lineWidth: 1) } .sheet(isPresented: $showStartLocationSearch) { LocationSearchSheet(inputType: .startLocation) { location in startLocation = location } } .sheet(isPresented: $showEndLocationSearch) { LocationSearchSheet(inputType: .endLocation) { location in endLocation = location } } } // MARK: - Location Row private func locationRow( label: String, location: LocationInput?, placeholder: String, onTap: @escaping () -> Void, onClear: @escaping () -> Void ) -> some View { VStack(alignment: .leading, spacing: Theme.Spacing.xs) { Text(label) .font(.subheadline) .fontWeight(.medium) .foregroundStyle(Theme.textSecondary(colorScheme)) if let location = location { // Selected location HStack { Image(systemName: "mappin.circle.fill") .foregroundStyle(Theme.warmOrange) .accessibilityHidden(true) VStack(alignment: .leading, spacing: 2) { Text(location.name) .font(.subheadline) .fontWeight(.medium) .foregroundStyle(Theme.textPrimary(colorScheme)) if let address = location.address, !address.isEmpty { Text(address) .font(.caption) .foregroundStyle(Theme.textMuted(colorScheme)) .lineLimit(1) } } Spacer() Button(action: onClear) { Image(systemName: "xmark.circle.fill") .foregroundStyle(Theme.textMuted(colorScheme)) } .minimumHitTarget() .accessibilityLabel("Clear location") } .padding(Theme.Spacing.sm) .background(Theme.cardBackgroundElevated(colorScheme)) .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium)) } else { // Empty state - tap to add Button(action: onTap) { HStack { Image(systemName: "plus.circle") .foregroundStyle(Theme.warmOrange) .accessibilityLabel("Add location") Text(placeholder) .font(.subheadline) .foregroundStyle(Theme.textMuted(colorScheme)) Spacer() Image(systemName: "chevron.right") .font(.caption) .foregroundStyle(Theme.textMuted(colorScheme)) .accessibilityHidden(true) } .padding(Theme.Spacing.sm) .background(Theme.cardBackgroundElevated(colorScheme)) .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium)) .overlay( RoundedRectangle(cornerRadius: Theme.CornerRadius.medium) .stroke(Theme.textMuted(colorScheme).opacity(0.3), lineWidth: 1) ) } .buttonStyle(.plain) } } } } // MARK: - Preview #Preview { LocationsStep( startLocation: .constant(nil), endLocation: .constant(nil) ) .padding() .themedBackground() }