Add featured trips carousel on home screen
- Generate 8 suggested trips on app launch (2 per region: East, Central, West, Cross-Country) - Each region has single-sport and multi-sport trip options - Region classification based on stadium longitude - Animated loading state with shimmer placeholders - Loading messages use Foundation Models when available, fallback otherwise - Tap card to view trip details in sheet - Refresh button to regenerate trips - Fixed-height cards with aligned top/bottom layout New files: - Region.swift: Geographic region enum with longitude classification - LoadingTextGenerator.swift: On-device AI loading messages - SuggestedTripsGenerator.swift: Trip generation service - SuggestedTripCard.swift: Carousel card component - LoadingTripsView.swift: Animated loading state 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
54
SportsTime/Core/Models/Domain/Region.swift
Normal file
54
SportsTime/Core/Models/Domain/Region.swift
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Region.swift
|
||||
// SportsTime
|
||||
//
|
||||
// Geographic regions for trip classification.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum Region: String, CaseIterable, Identifiable {
|
||||
case east = "East Coast"
|
||||
case central = "Central"
|
||||
case west = "West Coast"
|
||||
case crossCountry = "Cross-Country"
|
||||
|
||||
var id: String { rawValue }
|
||||
|
||||
var displayName: String { rawValue }
|
||||
|
||||
var shortName: String {
|
||||
switch self {
|
||||
case .east: return "East"
|
||||
case .central: return "Central"
|
||||
case .west: return "West"
|
||||
case .crossCountry: return "Coast to Coast"
|
||||
}
|
||||
}
|
||||
|
||||
var iconName: String {
|
||||
switch self {
|
||||
case .east: return "building.2"
|
||||
case .central: return "building"
|
||||
case .west: return "sun.max"
|
||||
case .crossCountry: return "arrow.left.arrow.right"
|
||||
}
|
||||
}
|
||||
|
||||
/// Classifies a stadium's region based on longitude.
|
||||
///
|
||||
/// Longitude boundaries:
|
||||
/// - East: > -85 (NYC, Boston, Miami, Toronto, Montreal, Atlanta)
|
||||
/// - Central: -110 to -85 (Chicago, Houston, Dallas, Minneapolis, Denver)
|
||||
/// - West: < -110 (LA, SF, Seattle, Phoenix, Las Vegas)
|
||||
static func classify(longitude: Double) -> Region {
|
||||
switch longitude {
|
||||
case _ where longitude > -85:
|
||||
return .east
|
||||
case -110...(-85):
|
||||
return .central
|
||||
default:
|
||||
return .west
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,10 @@ struct Stadium: Identifiable, Codable, Hashable {
|
||||
"\(city), \(state)"
|
||||
}
|
||||
|
||||
var region: Region {
|
||||
Region.classify(longitude: longitude)
|
||||
}
|
||||
|
||||
func distance(to other: Stadium) -> CLLocationDistance {
|
||||
location.distance(from: other.location)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user