import SwiftUI struct RaceDiscoveryView: View { @StateObject private var viewModel = RaceDiscoveryViewModel() @State private var showingFilters = false @State private var showingSavedRaces = false var body: some View { NavigationView { Group { if viewModel.isLoading && viewModel.races.isEmpty { loadingView } else if viewModel.races.isEmpty { emptyStateView } else { raceListView } } .navigationTitle("Race Discovery") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Menu { Button { showingSavedRaces.toggle() } label: { Text("Saved Races") Image(systemName: "bookmark.fill") } } label: { Image(systemName: "ellipsis.circle") } } } .sheet(isPresented: $showingSavedRaces) { NavigationView { SavedRacesSheet(viewModel: viewModel) .navigationTitle("Saved Races") .navigationBarTitleDisplayMode(.inline) } } } .onAppear { Task { await viewModel.fetchRaces() } } } private var raceListView: some View { List { Section("Upcoming Races") { ForEach(viewModel.upcomingRaces) { race in NavigationLink(destination: RaceDetailView(race: race)) { RaceRowView(race: race) } } } } .listStyle(.insetGrouped) .refreshable { await viewModel.fetchRaces() } } private var loadingView: some View { VStack(spacing: 16) { ProgressView() Text("Loading Races...") .font(.subheadline) .foregroundColor(.secondary) } .padding(.vertical, 60) } private var emptyStateView: some View { VStack(spacing: 16) { Image(systemName: "flag.fill") .font(.system(size: 64)) .foregroundColor(.secondary) Text("No Races Found") .font(.title2) .fontWeight(.semibold) Text("Discover local races and events to train for.") .font(.subheadline) .foregroundColor(.secondary) .multilineTextAlignment(.center) .padding(.horizontal, 32) } .padding(.vertical, 60) } } struct SavedRacesSheet: View { @ObservedObject var viewModel: RaceDiscoveryViewModel var body: some View { List { if viewModel.savedRaces.isEmpty { Text("No saved races yet") .foregroundColor(.secondary) } else { ForEach(viewModel.savedRaces) { race in RaceRowView(race: race) } } } } } struct RaceRowView: View { let race: Race var body: some View { HStack(spacing: 12) { Image(systemName: race.raceType.icon) .font(.system(size: 24)) .foregroundColor(.orange) .frame(width: 44, height: 44) .background(Color.orange.opacity(0.15)) .cornerRadius(10) VStack(alignment: .leading, spacing: 4) { Text(race.name) .font(.headline) Text("\(race.location) \u2022 \(race.distanceKm) km") .font(.subheadline) .foregroundColor(.secondary) HStack(spacing: 8) { Text(formatDate(race.raceDate)) .font(.caption) .foregroundColor(.secondary) if race.isRegistered { Text("Registered") .font(.caption2) .padding(.horizontal, 6) .padding(.vertical, 2) .background(Color.green.opacity(0.2)) .cornerRadius(4) .foregroundColor(.green) } } } Spacer() if race.isSaved { Image(systemName: "bookmark.fill") .foregroundColor(.blue) } } .padding(.vertical, 4) } private func formatDate(_ date: Date) -> String { let formatter = DateFormatter() formatter.dateStyle = .short formatter.timeStyle = .none return formatter.string(from: date) } } #Preview { RaceDiscoveryView() }