Remove CFB/NASCAR/PGA and streamline to 8 supported sports
- Remove College Football, NASCAR, and PGA from scraper and app - Clean all data files (stadiums, games, pipeline reports) - Update Sport.swift enum and all UI components - Add sportstime.py CLI tool for pipeline management - Add DATA_SCRAPING.md documentation - Add WNBA/MLS/NWSL implementation documentation - Scraper now supports: NBA, MLB, NHL, NFL, WNBA, MLS, NWSL, CBB Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -524,22 +524,36 @@ struct TripCreationView: View {
|
||||
}
|
||||
|
||||
private var sportsSection: some View {
|
||||
ThemedSection(title: "Sports") {
|
||||
HStack(spacing: Theme.Spacing.sm) {
|
||||
ForEach(Sport.supported) { sport in
|
||||
SportSelectionChip(
|
||||
sport: sport,
|
||||
isSelected: viewModel.selectedSports.contains(sport),
|
||||
onTap: {
|
||||
if viewModel.selectedSports.contains(sport) {
|
||||
viewModel.selectedSports.remove(sport)
|
||||
} else {
|
||||
viewModel.selectedSports.insert(sport)
|
||||
let sports = Sport.supported
|
||||
let rows = sports.chunked(into: 4)
|
||||
|
||||
return ThemedSection(title: "Sports") {
|
||||
VStack(spacing: Theme.Spacing.sm) {
|
||||
ForEach(Array(rows.enumerated()), id: \.offset) { _, row in
|
||||
HStack(spacing: Theme.Spacing.sm) {
|
||||
ForEach(row) { sport in
|
||||
SportSelectionChip(
|
||||
sport: sport,
|
||||
isSelected: viewModel.selectedSports.contains(sport),
|
||||
onTap: {
|
||||
if viewModel.selectedSports.contains(sport) {
|
||||
viewModel.selectedSports.remove(sport)
|
||||
} else {
|
||||
viewModel.selectedSports.insert(sport)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
// Fill remaining space if row has fewer than 4 items
|
||||
if row.count < 4 {
|
||||
ForEach(0..<(4 - row.count), id: \.self) { _ in
|
||||
Color.clear.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.vertical, Theme.Spacing.xs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2139,27 +2153,45 @@ struct SportSelectionChip: View {
|
||||
let isSelected: Bool
|
||||
let onTap: () -> Void
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
@State private var isPressed = false
|
||||
|
||||
var body: some View {
|
||||
Button(action: onTap) {
|
||||
VStack(spacing: Theme.Spacing.xs) {
|
||||
VStack(spacing: 6) {
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(isSelected ? sport.themeColor : sport.themeColor.opacity(0.15))
|
||||
.frame(width: 44, height: 44)
|
||||
.frame(width: 48, height: 48)
|
||||
.overlay {
|
||||
if isSelected {
|
||||
Circle()
|
||||
.stroke(sport.themeColor.opacity(0.3), lineWidth: 3)
|
||||
.frame(width: 54, height: 54)
|
||||
}
|
||||
}
|
||||
|
||||
Image(systemName: sport.iconName)
|
||||
.font(.title3)
|
||||
.font(.system(size: 20))
|
||||
.foregroundStyle(isSelected ? .white : sport.themeColor)
|
||||
}
|
||||
|
||||
Text(sport.rawValue)
|
||||
.font(.system(size: Theme.FontSize.micro, weight: .medium))
|
||||
.font(.system(size: 10, weight: isSelected ? .semibold : .medium))
|
||||
.foregroundStyle(isSelected ? Theme.textPrimary(colorScheme) : Theme.textSecondary(colorScheme))
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.scaleEffect(isPressed ? 0.9 : 1.0)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.simultaneousGesture(
|
||||
DragGesture(minimumDistance: 0)
|
||||
.onChanged { _ in
|
||||
withAnimation(Theme.Animation.spring) { isPressed = true }
|
||||
}
|
||||
.onEnded { _ in
|
||||
withAnimation(Theme.Animation.spring) { isPressed = false }
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user