// // MatchupView.swift // FantasyWatch Watch App // // Created by Claude Code // import ComposableArchitecture import SwiftUI struct MatchupView: View { let store: StoreOf var body: some View { WithPerceptionTracking { NavigationStack { VStack(spacing: 10) { if let matchup = store.matchup { matchupContent(matchup: matchup) } else { noDataView } } .navigationTitle("Fantasy Hockey") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .topBarTrailing) { Button { store.send(.refreshTapped) } label: { if store.isRefreshing { ProgressView() } else { Image(systemName: "arrow.clockwise") } } .disabled(store.isRefreshing) } } .onAppear { store.send(.onAppear) } } } } @ViewBuilder private func matchupContent(matchup: Matchup) -> some View { ScrollView { VStack(spacing: 12) { // Week indicator Text("Week \(matchup.week)") .font(.caption) .foregroundColor(.secondary) // Score comparison VStack(spacing: 8) { HStack { Text("You") .font(.caption2) .foregroundColor(.secondary) Spacer() Text("\(matchup.userTeam.wins)-\(matchup.userTeam.losses)-\(matchup.userTeam.ties)") .font(.title3) .fontWeight(.bold) .foregroundColor(.blue) } HStack { Text("Opp") .font(.caption2) .foregroundColor(.secondary) Spacer() Text("\(matchup.opponentTeam.wins)-\(matchup.opponentTeam.losses)-\(matchup.opponentTeam.ties)") .font(.title3) .fontWeight(.semibold) } } .padding(.vertical, 8) // Category summary HStack(spacing: 8) { categoryBadge( title: "W", count: matchup.categories.filter { $0.comparison == .winning }.count, color: .green ) categoryBadge( title: "T", count: matchup.categories.filter { $0.comparison == .tied }.count, color: .orange ) categoryBadge( title: "L", count: matchup.categories.filter { $0.comparison == .losing }.count, color: .red ) } // Navigation links NavigationLink { CategoryBreakdownView(categories: matchup.categories) } label: { Label("Categories", systemImage: "list.bullet") .font(.caption) } if let roster = store.roster { NavigationLink { RosterStatusView(roster: roster) } label: { Label("Roster", systemImage: "person.3") .font(.caption) } } if let lastUpdate = store.lastUpdate { Text("Updated \(lastUpdate.formatted(date: .omitted, time: .shortened))") .font(.caption2) .foregroundColor(.secondary) .padding(.top, 4) } } .padding() } } private var noDataView: some View { VStack(spacing: 10) { Image(systemName: "hockey.puck") .font(.title) .foregroundColor(.secondary) Text("No data") .font(.caption) .foregroundColor(.secondary) Text("Open iPhone app to sync") .font(.caption2) .foregroundColor(.secondary) .multilineTextAlignment(.center) } .padding() } private func categoryBadge(title: String, count: Int, color: Color) -> some View { VStack(spacing: 2) { Text("\(count)") .font(.headline) .fontWeight(.bold) .foregroundColor(color) Text(title) .font(.caption2) .foregroundColor(.secondary) } .frame(maxWidth: .infinity) .padding(.vertical, 6) .background(color.opacity(0.15)) .cornerRadius(6) } } #Preview { MatchupView( store: Store( initialState: WatchMatchupFeature.State( matchup: Matchup( week: 10, status: "midevent", userTeam: TeamScore(teamKey: "test.l.123.t.1", teamName: "My Team", wins: 5, losses: 3, ties: 1), opponentTeam: TeamScore(teamKey: "test.l.123.t.2", teamName: "Opponent", wins: 4, losses: 4, ties: 1), categories: [ CategoryScore(statID: "1", name: "G", userValue: "10", opponentValue: "8"), CategoryScore(statID: "2", name: "A", userValue: "15", opponentValue: "18") ] ), roster: RosterStatus(activeCount: 10, benchedCount: 5, injuredReserve: 2), lastUpdate: Date() ) ) { WatchMatchupFeature() } ) }