import SwiftUI struct RaceDetailView: View { let race: Race @StateObject private var viewModel = RaceDiscoveryViewModel() var body: some View { ScrollView { VStack(alignment: .leading, spacing: 16) { raceHeader raceInfoSection raceDescription actionButtons } .padding(.horizontal) .padding(.bottom, 32) } .navigationTitle(race.name) .navigationBarTitleDisplayMode(.inline) } private var raceHeader: some View { VStack(spacing: 12) { HStack { Image(systemName: race.raceType.icon) .font(.system(size: 40)) .foregroundColor(.orange) VStack(alignment: .leading, spacing: 4) { Text(race.raceType.displayName) .font(.title2) .fontWeight(.bold) Text("\(race.distanceKm) km \u2022 \(race.terrainType.displayName)") .font(.subheadline) .foregroundColor(.secondary) } Spacer() Button(action: { Task { await viewModel.toggleSaveRace(id: race.id) } }) { Image(systemName: race.isSaved ? "bookmark.fill" : "bookmark") .font(.title3) .foregroundColor(race.isSaved ? .blue : .secondary) } } Divider() HStack(spacing: 20) { infoItem(label: "Date", value: formatDate(race.raceDate)) infoItem(label: "Location", value: race.location) infoItem(label: "Days Left", value: "\(race.daysUntilRace)") } if let count = race.participantCount { HStack(spacing: 20) { infoItem(label: "Participants", value: "\(count)") infoItem(label: "Elevation", value: "\(Int(race.elevationGain))m") infoItem(label: "Terrain", value: race.terrainType.displayName) } } } .padding() .background(Color.secondary.opacity(0.1)) .cornerRadius(12) } private func infoItem(label: String, value: String) -> some View { VStack(alignment: .leading, spacing: 2) { Text(label) .font(.caption) .foregroundColor(.secondary) Text(value) .font(.subheadline) .fontWeight(.medium) } } private var raceInfoSection: some View { VStack(alignment: .leading, spacing: 8) { Text("Race Details") .font(.headline) VStack(alignment: .leading, spacing: 6) { detailRow(label: "Organizer", value: race.organizerName) detailRow(label: "Distance", value: "\(race.distanceKm) km") detailRow(label: "Elevation Gain", value: "\(Int(race.elevationGain))m") detailRow(label: "Terrain", value: race.terrainType.displayName) } } } private func detailRow(label: String, value: String) -> some View { HStack { Text(label) .font(.subheadline) .foregroundColor(.secondary) .frame(width: 120, alignment: .leading) Text(value) .font(.subheadline) .fontWeight(.medium) } } private var raceDescription: some View { VStack(alignment: .leading, spacing: 4) { Text("About This Race") .font(.headline) Text(race.description) .font(.subheadline) .foregroundColor(.secondary) } } private var actionButtons: some View { VStack(spacing: 12) { if let url = race.registrationUrl, !race.isRegistered { Button { if let registrationUrl = URL(string: url) { UIApplication.shared.open(registrationUrl) } } label: { Text("Register Now") .font(.headline) .frame(maxWidth: .infinity) .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(10) } } if race.isRegistered { HStack { Image(systemName: "checkmark.circle.fill") Text("Registered") } .font(.headline) .frame(maxWidth: .infinity) .padding() .background(Color.green.opacity(0.15)) .foregroundColor(.green) .cornerRadius(10) } } } private func formatDate(_ date: Date) -> String { let formatter = DateFormatter() formatter.dateStyle = .medium formatter.timeStyle = .none return formatter.string(from: date) } } #Preview { NavigationView { RaceDetailView(race: sampleRace) } } private var sampleRace: Race { Race( id: "1", name: "City Marathon 2026", description: "An annual marathon through the heart of the city. Features a flat, fast course suitable for all levels.", location: "Downtown", latitude: 40.7128, longitude: -74.006, raceDate: Date().addingTimeInterval(90 * 24 * 3600), distanceKm: 42.2, raceType: .road, organizerName: "City Athletics Club", registrationUrl: "https://example.com/register", imageUrl: nil, participantCount: 5000, isRegistered: false, isSaved: true, elevationGain: 120, terrainType: .flat ) }