import SwiftUI struct DashboardView: View { @EnvironmentObject var authManager: AuthManager @StateObject private var healthKit = HealthKitService() @State private var readiness: ReadinessResponse? @State private var latest: LatestHealthResponse? @State private var isLoading = true var body: some View { ZStack { LinearGradient(colors: [Color(hex: "1a1a2e"), Color(hex: "16213e")], startPoint: .top, endPoint: .bottom) .ignoresSafeArea() ScrollView { VStack(spacing: 20) { HStack { Text("Привет, \(authManager.userName) 👋").font(.title2.bold()).foregroundColor(.white) Spacer() Button(action: { authManager.logout() }) { Image(systemName: "rectangle.portrait.and.arrow.right").foregroundColor(.white.opacity(0.5)) } }.padding(.horizontal).padding(.top) if isLoading { ProgressView().tint(Color(hex: "00d4aa")).padding(.top, 60) } else { if let r = readiness { ReadinessCardView(readiness: r) } if let l = latest { LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 16) { if let sleep = l.sleep { MetricCardView(icon: "moon.fill", title: "Сон", value: String(format: "%.1f ч", sleep.totalSleep ?? 0), subtitle: "Глубокий: \(String(format: "%.0f мин", (sleep.deep ?? 0) * 60))", color: Color(hex: "6c63ff")) } if let rhr = l.restingHeartRate { MetricCardView(icon: "heart.fill", title: "Пульс покоя", value: "\(Int(rhr.value ?? 0)) уд/мин", subtitle: "Resting HR", color: Color(hex: "ff6b6b")) } if let hrv = l.hrv { MetricCardView(icon: "waveform.path.ecg", title: "HRV", value: "\(Int(hrv.avg ?? 0)) мс", subtitle: "Вариабельность", color: Color(hex: "00d4aa")) } if let steps = l.steps { MetricCardView(icon: "figure.walk", title: "Шаги", value: "\(steps.total ?? 0)", subtitle: "Сегодня", color: Color(hex: "ffa500")) } }.padding(.horizontal) } } Spacer(minLength: 20) } } } .task { await loadData() } } func loadData() async { isLoading = true async let r = APIService.shared.getReadiness(token: authManager.token) async let l = APIService.shared.getLatest(token: authManager.token) readiness = try? await r latest = try? await l isLoading = false } }