Files
Sportstime/SportsTime/Features/Progress/Views/StadiumVisitHistoryView.swift
Trey t c0f1645434 feat(ui): replace loading indicators with Apple-style LoadingSpinner
- Add LoadingSpinner component with small/medium/large sizes using system gray color
- Add LoadingPlaceholder for skeleton loading states
- Add LoadingSheet for full-screen blocking overlays
- Replace ThemedSpinner/ThemedSpinnerCompact across all views
- Remove deprecated loading components from AnimatedComponents.swift
- Delete LoadingTextGenerator.swift
- Fix PhotoImportView layout to fill full width

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 22:43:33 -06:00

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 {
LoadingSpinner(size: .medium)
} 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()
}
}