- Enable zoom/pan on progress map with reset button - Add visit count badges to stadium chips - Create GamesHistoryView with year grouping and sport filters - Create StadiumVisitHistoryView for viewing all visits to a stadium - Add VisitListCard and GamesHistoryRow components - Add "See All" navigation from Recent Visits to Games History - Add tests for map interactions, visit lists, and games history Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
110 lines
3.1 KiB
Swift
110 lines
3.1 KiB
Swift
import SwiftUI
|
|
import SwiftData
|
|
|
|
struct StadiumVisitHistoryView: View {
|
|
let stadium: Stadium
|
|
@Environment(\.modelContext) private var modelContext
|
|
@Environment(\.dismiss) private var dismiss
|
|
|
|
@State private var visits: [StadiumVisit] = []
|
|
@State private var isLoading = true
|
|
@State private var showingAddVisit = false
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
Group {
|
|
if isLoading {
|
|
ProgressView()
|
|
} else if visits.isEmpty {
|
|
EmptyVisitHistoryView()
|
|
} else {
|
|
VisitHistoryList(visits: visits)
|
|
}
|
|
}
|
|
.navigationTitle(stadium.name)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbar {
|
|
ToolbarItem(placement: .cancellationAction) {
|
|
Button("Done") { dismiss() }
|
|
}
|
|
|
|
ToolbarItem(placement: .primaryAction) {
|
|
Button {
|
|
showingAddVisit = true
|
|
} label: {
|
|
Image(systemName: "plus")
|
|
}
|
|
}
|
|
}
|
|
.sheet(isPresented: $showingAddVisit) {
|
|
StadiumVisitSheet(initialStadium: stadium)
|
|
}
|
|
}
|
|
.task {
|
|
await loadVisits()
|
|
}
|
|
}
|
|
|
|
private func loadVisits() async {
|
|
isLoading = true
|
|
defer { isLoading = false }
|
|
|
|
let stadiumId = stadium.id
|
|
let descriptor = FetchDescriptor<StadiumVisit>(
|
|
predicate: #Predicate { $0.stadiumId == stadiumId },
|
|
sortBy: [SortDescriptor(\.visitDate, order: .reverse)]
|
|
)
|
|
|
|
do {
|
|
visits = try modelContext.fetch(descriptor)
|
|
} catch {
|
|
visits = []
|
|
}
|
|
}
|
|
}
|
|
|
|
private struct VisitHistoryList: View {
|
|
let visits: [StadiumVisit]
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
VStack(spacing: 12) {
|
|
// Visit count header
|
|
HStack {
|
|
Text("\(visits.count) Visit\(visits.count == 1 ? "" : "s")")
|
|
.font(.headline)
|
|
Spacer()
|
|
}
|
|
.padding(.horizontal)
|
|
|
|
// Visit cards
|
|
ForEach(visits, id: \.id) { visit in
|
|
VisitListCard(visit: visit)
|
|
.padding(.horizontal)
|
|
}
|
|
}
|
|
.padding(.vertical)
|
|
}
|
|
.background(Color(.systemGroupedBackground))
|
|
}
|
|
}
|
|
|
|
private struct EmptyVisitHistoryView: View {
|
|
var body: some View {
|
|
VStack(spacing: 16) {
|
|
Image(systemName: "calendar.badge.plus")
|
|
.font(.system(size: 48))
|
|
.foregroundStyle(.secondary)
|
|
|
|
Text("No visits recorded")
|
|
.font(.headline)
|
|
|
|
Text("Tap + to add your first visit to this stadium")
|
|
.font(.subheadline)
|
|
.foregroundStyle(.secondary)
|
|
.multilineTextAlignment(.center)
|
|
}
|
|
.padding()
|
|
}
|
|
}
|