import SwiftUI struct ReadinessCardView: View { let readiness: ReadinessResponse var statusColor: Color { switch readiness.status { case "ready": return Color(hex: "00d4aa") case "moderate": return Color(hex: "ffa500") default: return Color(hex: "ff6b6b") } } var statusEmoji: String { switch readiness.status { case "ready": return "💪"; case "moderate": return "🚶"; default: return "😴" } } var body: some View { VStack(spacing: 16) { Text("Готовность").font(.headline).foregroundColor(.white.opacity(0.7)) ZStack { Circle().stroke(Color.white.opacity(0.1), lineWidth: 12).frame(width: 140, height: 140) Circle().trim(from: 0, to: CGFloat(readiness.score) / 100) .stroke(statusColor, style: StrokeStyle(lineWidth: 12, lineCap: .round)) .frame(width: 140, height: 140).rotationEffect(.degrees(-90)) .animation(.easeInOut(duration: 1), value: readiness.score) VStack(spacing: 4) { Text("\(readiness.score)").font(.system(size: 44, weight: .bold)).foregroundColor(statusColor) Text(statusEmoji).font(.title2) } } Text(readiness.recommendation).font(.subheadline).foregroundColor(.white.opacity(0.8)).multilineTextAlignment(.center).padding(.horizontal) if let f = readiness.factors { VStack(spacing: 8) { FactorRow(name: "Сон", score: f.sleep.score, value: f.sleep.value) FactorRow(name: "HRV", score: f.hrv.score, value: f.hrv.value) FactorRow(name: "Пульс", score: f.rhr.score, value: f.rhr.value) FactorRow(name: "Активность", score: f.activity.score, value: f.activity.value) }.padding(.horizontal) } } .padding(24).background(Color.white.opacity(0.05)).cornerRadius(20).padding(.horizontal) } } struct FactorRow: View { let name: String; let score: Int; let value: String var body: some View { HStack { Text(name).font(.caption).foregroundColor(.white.opacity(0.6)).frame(width: 70, alignment: .leading) GeometryReader { geo in ZStack(alignment: .leading) { RoundedRectangle(cornerRadius: 4).fill(Color.white.opacity(0.1)) RoundedRectangle(cornerRadius: 4).fill(Color(hex: "00d4aa")).frame(width: geo.size.width * CGFloat(score) / 100) } }.frame(height: 6) Text(value).font(.caption).foregroundColor(.white.opacity(0.6)).frame(width: 60, alignment: .trailing) } } }