feat(sharing): implement unified sharing system for social media

Replace old ProgressCardGenerator with protocol-based sharing architecture
supporting trips, achievements, and stadium progress. Features 8 color
themes, Instagram Stories optimization (1080x1920), and reusable card
components with map snapshots.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-14 08:54:37 -06:00
parent 2b16420fb4
commit fe36f99bca
13 changed files with 1775 additions and 636 deletions

View File

@@ -108,6 +108,12 @@ final class ProgressViewModel {
leagueProgress.stadiumsRemaining
}
/// Count of trips for the selected sport (stub - can be enhanced)
var tripCount: Int {
// TODO: Fetch saved trips count from SwiftData
0
}
/// Recent visits sorted by date
var recentVisits: [VisitSummary] {
visits

View File

@@ -36,6 +36,20 @@ struct AchievementsListView: View {
}
.themedBackground()
.navigationTitle("Achievements")
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
if !earnedAchievements.isEmpty {
ShareButton(
content: AchievementCollectionContent(
achievements: earnedAchievements,
year: Calendar.current.component(.year, from: Date())
),
style: .icon
)
.foregroundStyle(Theme.warmOrange)
}
}
}
.task {
await loadAchievements()
}
@@ -184,6 +198,10 @@ struct AchievementsListView: View {
}
}
private var earnedAchievements: [AchievementProgress] {
achievements.filter { $0.isEarned }
}
private var filteredAchievements: [AchievementProgress] {
let filtered: [AchievementProgress]

View File

@@ -15,7 +15,6 @@ struct ProgressTabView: View {
@State private var viewModel = ProgressViewModel()
@State private var showVisitSheet = false
@State private var showPhotoImport = false
@State private var showShareSheet = false
@State private var selectedStadium: Stadium?
@State private var selectedVisitId: UUID?
@@ -65,12 +64,12 @@ struct ProgressTabView: View {
.themedBackground()
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button {
showShareSheet = true
} label: {
Image(systemName: "square.and.arrow.up")
.foregroundStyle(Theme.warmOrange)
}
ShareButton(
progress: viewModel.leagueProgress,
tripCount: viewModel.tripCount,
style: .icon
)
.foregroundStyle(Theme.warmOrange)
}
ToolbarItem(placement: .primaryAction) {
@@ -125,9 +124,6 @@ struct ProgressTabView: View {
)
.presentationDetents([.medium])
}
.sheet(isPresented: $showShareSheet) {
ProgressShareView(progress: viewModel.leagueProgress)
}
}
// MARK: - League Selector