feat: enforce custom Theme colors app-wide, add debug sample trips and poll
Replace all system colors (.secondary, Color(.secondarySystemBackground), etc.) with Theme.textPrimary/textSecondary/textMuted/cardBackground/ surfaceGlow across 13 views. Remove PostHog debug logging. Add debug settings for sample trips and hardcoded group poll preview. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import SwiftUI
|
||||
|
||||
struct GamesHistoryRow: View {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
let visit: StadiumVisit
|
||||
let stadium: Stadium?
|
||||
|
||||
@@ -20,16 +21,17 @@ struct GamesHistoryRow: View {
|
||||
// Date
|
||||
Text(visit.visitDate.formatted(date: .abbreviated, time: .omitted))
|
||||
.font(.subheadline.bold())
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
|
||||
// Teams (if game)
|
||||
if let matchup = visit.matchupDescription {
|
||||
Text(matchup)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
} else {
|
||||
Text(visit.stadiumNameAtVisit)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +40,11 @@ struct GamesHistoryRow: View {
|
||||
// Chevron
|
||||
Image(systemName: "chevron.right")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.tertiary)
|
||||
.foregroundStyle(Theme.textMuted(colorScheme))
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
.padding()
|
||||
.background(Color(.systemBackground))
|
||||
.background(Theme.cardBackground(colorScheme))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 10))
|
||||
.accessibilityElement(children: .combine)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftUI
|
||||
|
||||
struct VisitListCard: View {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
let visit: StadiumVisit
|
||||
@State private var isExpanded = false
|
||||
|
||||
@@ -17,9 +18,10 @@ struct VisitListCard: View {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(visit.visitDate.formatted(date: .abbreviated, time: .omitted))
|
||||
.font(.subheadline.bold())
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
Text(visit.visitType.displayName)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
}
|
||||
|
||||
Spacer()
|
||||
@@ -28,14 +30,14 @@ struct VisitListCard: View {
|
||||
if let matchup = visit.matchupDescription {
|
||||
Text(matchup)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
.lineLimit(1)
|
||||
}
|
||||
|
||||
// Chevron
|
||||
Image(systemName: "chevron.right")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.foregroundStyle(Theme.textMuted(colorScheme))
|
||||
.rotationEffect(.degrees(isExpanded ? 90 : 0))
|
||||
.accessibilityLabel(isExpanded ? "Collapse details" : "Expand details")
|
||||
}
|
||||
@@ -79,12 +81,13 @@ struct VisitListCard: View {
|
||||
.transition(.opacity.combined(with: .move(edge: .top)))
|
||||
}
|
||||
}
|
||||
.background(Color(.systemBackground))
|
||||
.background(Theme.cardBackground(colorScheme))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 12))
|
||||
}
|
||||
}
|
||||
|
||||
private struct GameInfoRow: View {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
let matchup: String
|
||||
let score: String?
|
||||
|
||||
@@ -93,11 +96,12 @@ private struct GameInfoRow: View {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text(matchup)
|
||||
.font(.subheadline.bold())
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
|
||||
if let score {
|
||||
Text("Final: \(score)")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +111,7 @@ private struct GameInfoRow: View {
|
||||
}
|
||||
|
||||
private struct InfoRow: View {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
let icon: String
|
||||
let label: String
|
||||
let value: String
|
||||
@@ -115,16 +120,17 @@ private struct InfoRow: View {
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: icon)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.foregroundStyle(Theme.textMuted(colorScheme))
|
||||
.frame(width: 16)
|
||||
.accessibilityHidden(true)
|
||||
|
||||
Text(label)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
|
||||
Text(value)
|
||||
.font(.caption)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
.lineLimit(2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ struct GamesHistoryView: View {
|
||||
}
|
||||
|
||||
private struct GamesHistoryContent: View {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
@Bindable var viewModel: GamesHistoryViewModel
|
||||
@Binding var selectedVisit: StadiumVisit?
|
||||
|
||||
@@ -50,6 +51,7 @@ private struct GamesHistoryContent: View {
|
||||
HStack {
|
||||
Text("\(viewModel.totalGamesCount) Games")
|
||||
.font(.headline)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
Spacer()
|
||||
|
||||
if !viewModel.selectedSports.isEmpty {
|
||||
@@ -68,9 +70,10 @@ private struct GamesHistoryContent: View {
|
||||
)
|
||||
}
|
||||
.padding()
|
||||
.background(Color(.systemBackground))
|
||||
.background(Theme.cardBackground(colorScheme))
|
||||
|
||||
Divider()
|
||||
.overlay(Theme.surfaceGlow(colorScheme))
|
||||
|
||||
// Games list grouped by year
|
||||
if viewModel.filteredVisits.isEmpty {
|
||||
@@ -85,7 +88,7 @@ private struct GamesHistoryContent: View {
|
||||
)
|
||||
}
|
||||
}
|
||||
.background(Color(.systemGroupedBackground))
|
||||
.background(Theme.backgroundGradient(colorScheme))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +114,7 @@ private struct SportFilterChips: View {
|
||||
}
|
||||
|
||||
private struct SportChip: View {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
let sport: Sport
|
||||
let isSelected: Bool
|
||||
let onTap: () -> Void
|
||||
@@ -124,12 +128,12 @@ private struct SportChip: View {
|
||||
Text(sport.rawValue)
|
||||
.font(.caption.bold())
|
||||
}
|
||||
.foregroundStyle(isSelected ? .white : .primary)
|
||||
.foregroundStyle(isSelected ? .white : Theme.textPrimary(colorScheme))
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 6)
|
||||
.background(
|
||||
Capsule()
|
||||
.fill(isSelected ? sport.themeColor : Color(.systemGray5))
|
||||
.fill(isSelected ? sport.themeColor : Theme.cardBackgroundElevated(colorScheme))
|
||||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
@@ -185,33 +189,38 @@ private struct GamesListByYear: View {
|
||||
}
|
||||
|
||||
private struct YearHeader: View {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
let year: Int
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Text(String(year))
|
||||
.font(.title3.bold())
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
Spacer()
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.vertical, 8)
|
||||
.background(Color(.systemGroupedBackground))
|
||||
.background(Theme.backgroundGradient(colorScheme))
|
||||
}
|
||||
}
|
||||
|
||||
private struct EmptyGamesView: View {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 16) {
|
||||
Image(systemName: "ticket")
|
||||
.font(.largeTitle)
|
||||
.foregroundStyle(.secondary)
|
||||
.foregroundStyle(Theme.textMuted(colorScheme))
|
||||
|
||||
Text("No games recorded yet")
|
||||
.font(.headline)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
|
||||
Text("Add your first stadium visit to see it here!")
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
.multilineTextAlignment(.center)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
|
||||
@@ -65,6 +65,7 @@ struct StadiumVisitHistoryView: View {
|
||||
}
|
||||
|
||||
private struct VisitHistoryList: View {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
let visits: [StadiumVisit]
|
||||
|
||||
var body: some View {
|
||||
@@ -74,6 +75,7 @@ private struct VisitHistoryList: View {
|
||||
HStack {
|
||||
Text("\(visits.count) Visit\(visits.count == 1 ? "" : "s")")
|
||||
.font(.headline)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
Spacer()
|
||||
}
|
||||
.padding(.horizontal)
|
||||
@@ -86,23 +88,26 @@ private struct VisitHistoryList: View {
|
||||
}
|
||||
.padding(.vertical)
|
||||
}
|
||||
.background(Color(.systemGroupedBackground))
|
||||
.background(Theme.backgroundGradient(colorScheme))
|
||||
}
|
||||
}
|
||||
|
||||
private struct EmptyVisitHistoryView: View {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 16) {
|
||||
Image(systemName: "calendar.badge.plus")
|
||||
.font(.largeTitle)
|
||||
.foregroundStyle(.secondary)
|
||||
.foregroundStyle(Theme.textMuted(colorScheme))
|
||||
|
||||
Text("No visits recorded")
|
||||
.font(.headline)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
|
||||
Text("Tap + to add your first visit to this stadium")
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
.multilineTextAlignment(.center)
|
||||
}
|
||||
.padding()
|
||||
|
||||
Reference in New Issue
Block a user