import SwiftUI import LabWiseKit // MARK: - Chemical row struct ChemicalRowView: View { let chemical: Chemical var body: some View { VStack(alignment: .leading, spacing: 4) { HStack { Text(chemical.displayName) .font(.headline) Spacer() if let state = chemical.physicalState, !state.isEmpty { PhysicalStateBadge(state: state) } } HStack(spacing: 6) { if let cas = chemical.casNumber, !cas.isEmpty { Text("CAS: \(cas)") .font(.caption) .foregroundStyle(.secondary) } if chemical.isMissingKeyInfo { MissingInfoBadge() } } if let pct = chemical.percentageFull { PercentageBar(value: pct / 100) .frame(height: 4) .padding(.top, 2) } } .padding(.vertical, 2) } } // MARK: - Physical state badge struct PhysicalStateBadge: View { let state: String var color: Color { switch state.lowercased() { case "liquid": return Color(.brandPrimary) case "solid": return Color(red: 0.42, green: 0.30, blue: 0.18) case "gas": return Color(red: 0.22, green: 0.56, blue: 0.52) default: return Color(.brandMutedForeground) } } var body: some View { Text(state.capitalized) .font(.caption2.weight(.semibold)) .padding(.horizontal, 8) .padding(.vertical, 3) .background(color.opacity(0.15)) .foregroundStyle(color) .clipShape(Capsule()) } } // MARK: - Missing info badge /// Mirrors the web "Missing info" pill — amber, with a warning glyph. struct MissingInfoBadge: View { var body: some View { HStack(spacing: 3) { Image(systemName: "exclamationmark.triangle.fill") .font(.caption2) Text("Missing info") .font(.caption2.weight(.semibold)) } .padding(.horizontal, 6) .padding(.vertical, 2) .background(Color.orange.opacity(0.15)) .foregroundStyle(Color.orange) .clipShape(Capsule()) } } // MARK: - Percentage bar struct PercentageBar: View { let value: Double // 0.0 – 1.0 var body: some View { GeometryReader { geo in ZStack(alignment: .leading) { RoundedRectangle(cornerRadius: 2) .fill(Color.secondary.opacity(0.2)) RoundedRectangle(cornerRadius: 2) .fill(barColor) .frame(width: geo.size.width * max(0, min(1, value))) } } } var barColor: Color { if value > 0.6 { return .green } if value > 0.25 { return .yellow } return .red } }