import SwiftUI struct ProductCard: View { let product: Product var body: some View { HStack(spacing: 12) { // Product Image if let imageURL = product.imageURL { AsyncImage(url: imageURL) { phase in switch phase { case .success(let image): image .resizable() .aspectRatio(contentMode: .fill) case .failure: imagePlaceholder default: ProgressView() } } .frame(width: 70, height: 70) .background(Color(.systemGray6)) .cornerRadius(12) .clipped() } else { imagePlaceholder .frame(width: 70, height: 70) } // Product Info VStack(alignment: .leading, spacing: 6) { Text(product.brand) .font(.caption) .foregroundColor(.secondary) Text(product.name) .font(.subheadline.bold()) .lineLimit(2) HStack(spacing: 12) { // Score HStack(spacing: 4) { Circle() .fill(scoreColor) .frame(width: 10, height: 10) Text("\(product.score)") .font(.caption.bold()) } // NOVA Text("NOVA \(product.novaGroup)") .font(.caption) .padding(.horizontal, 6) .padding(.vertical, 2) .background(novaColor.opacity(0.2)) .foregroundColor(novaColor) .cornerRadius(4) } } Spacer() // Score Ring (mini) ZStack { Circle() .stroke(lineWidth: 4) .opacity(0.2) .foregroundColor(scoreColor) Circle() .trim(from: 0, to: Double(product.score) / 100.0) .stroke(style: StrokeStyle(lineWidth: 4, lineCap: .round)) .foregroundColor(scoreColor) .rotationEffect(.degrees(-90)) Text("\(product.score)") .font(.caption2.bold()) } .frame(width: 40, height: 40) } .padding() .background(Color(.secondarySystemBackground)) .cornerRadius(16) } private var imagePlaceholder: some View { ZStack { Color(.systemGray5) Image(systemName: "carrot.fill") .foregroundColor(.gray) } .cornerRadius(12) } private var scoreColor: Color { switch product.score { case 80...100: return .green case 50..<80: return .yellow case 30..<50: return .orange default: return .red } } private var novaColor: Color { switch product.novaGroup { case 1: return .green case 2: return .yellow case 3: return .orange default: return .red } } }