import SwiftUI struct CommunityEventsView: View { @StateObject private var viewModel = CommunityEventViewModel() @State private var showingCreateSheet = false @State private var selectedTab: EventTab = .upcoming enum EventTab: String, CaseIterable { case upcoming, ongoing, past } var body: some View { NavigationView { Group { if viewModel.isLoading && viewModel.events.isEmpty { loadingView } else if currentEvents.isEmpty { emptyStateView } else { eventListView } } .navigationTitle("Community Events") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { showingCreateSheet = true } label: { Image(systemName: "plus") } } } .sheet(isPresented: $showingCreateSheet) { CreateEventSheet() } } .onAppear { Task { await viewModel.fetchEvents() } } } private var currentEvents: [CommunityEvent] { switch selectedTab { case .upcoming: return viewModel.upcomingEvents case .ongoing: return viewModel.ongoingEvents case .past: return viewModel.pastEvents } } private var eventListView: some View { List { Picker("Events", selection: $selectedTab) { ForEach(EventTab.allCases, id: \.self) { tab in Text(tab.rawValue.capitalized).tag(tab) } } .pickerStyle(.segmented) .padding(.top, 8) Section(currentSectionTitle) { ForEach(currentEvents) { event in NavigationLink(destination: CommunityEventDetailView(event: event)) { EventRowView(event: event) } } } } .listStyle(.insetGrouped) .refreshable { await viewModel.fetchEvents() } } private var currentSectionTitle: String { switch selectedTab { case .upcoming: return "Upcoming" case .ongoing: return "Happening Now" case .past: return "Past Events" } } private var loadingView: some View { VStack(spacing: 16) { ProgressView() Text("Loading Events...") .font(.subheadline) .foregroundColor(.secondary) } .padding(.vertical, 60) } private var emptyStateView: some View { VStack(spacing: 16) { Image(systemName: "person.3.fill") .font(.system(size: 64)) .foregroundColor(.secondary) Text("No \(selectedTab.rawValue) Events") .font(.title2) .fontWeight(.semibold) Text("Create or discover community running events in your area.") .font(.subheadline) .foregroundColor(.secondary) .multilineTextAlignment(.center) .padding(.horizontal, 32) } .padding(.vertical, 60) } } struct CreateEventSheet: View { @Environment(\.dismiss) var dismiss @State private var title = "" @State private var description = "" @State private var eventType: EventType = .groupRun @State private var location = "" @State private var distanceKm = "" @State private var maxParticipants = "" var body: some View { NavigationView { Form { Section("Event Details") { TextField("Event Title", text: $title) TextField("Description", text: $description) TextField("Location", text: $location) } Section("Type") { Picker("Event Type", selection: $eventType) { ForEach(EventType.allCases, id: \.self) { type in Text(type.displayName).tag(type) } } } Section("Optional") { TextField("Distance (km)", text: $distanceKm) .keyboardType(.decimalPad) TextField("Max Participants", text: $maxParticipants) .keyboardType(.numberPad) } } .navigationTitle("Create Event") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button("Cancel") { dismiss() } } ToolbarItem(placement: .navigationBarTrailing) { Button("Create") { let request = CreateEventRequest( title: title, description: description, eventType: eventType, location: location, latitude: 0, longitude: 0, startDate: Date(), endDate: Date().addingTimeInterval(3600), distanceKm: Double(distanceKm), maxParticipants: Int(maxParticipants), difficulty: nil ) dismiss() } .disabled(title.isEmpty || location.isEmpty) } } } } } struct EventRowView: View { let event: CommunityEvent var body: some View { HStack(spacing: 12) { Image(systemName: event.eventType.icon) .font(.system(size: 24)) .foregroundColor(event.eventType.color) .frame(width: 44, height: 44) .background(event.eventType.color.opacity(0.15)) .cornerRadius(10) VStack(alignment: .leading, spacing: 4) { Text(event.title) .font(.headline) Text("\(event.location) \u2022 \(event.organizerName)") .font(.subheadline) .foregroundColor(.secondary) HStack(spacing: 8) { Text(formatDate(event.startDate)) .font(.caption) .foregroundColor(.secondary) if let spots = event.availableSpots, spots > 0 { Text("\(spots) spots left") .font(.caption2) .foregroundColor(.green) } } } Spacer() switch event.rsvpStatus { case .going: Image(systemName: "checkmark.circle.fill") .foregroundColor(.green) case .maybe: Image(systemName: "questionmark.circle.fill") .foregroundColor(.orange) case .notGoing: Image(systemName: "xmark.circle.fill") .foregroundColor(.red) case .pending: Image(systemName: "circle") .foregroundColor(.secondary) } } .padding(.vertical, 4) } private func formatDate(_ date: Date) -> String { let formatter = DateFormatter() formatter.dateStyle = .short formatter.timeStyle = .short return formatter.string(from: date) } } #Preview { CommunityEventsView() }