Files
LabWiseiOS/LabWise/ChemicalsListView.swift

106 lines
2.9 KiB
Swift
Raw Normal View History

import SwiftUI
import LabWiseKit
2026-03-20 02:30:15 -05:00
// MARK: - Chemical row
struct ChemicalRowView: View {
let chemical: Chemical
var body: some View {
VStack(alignment: .leading, spacing: 4) {
HStack {
2026-05-01 13:54:05 -05:00
Text(chemical.displayName)
.font(.headline)
Spacer()
2026-05-01 13:54:05 -05:00
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)
}
}
2026-03-20 02:30:15 -05:00
// 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())
}
}
2026-05-01 13:54:05 -05:00
// 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())
}
}
2026-03-20 02:30:15 -05:00
// MARK: - Percentage bar
struct PercentageBar: View {
2026-03-20 02:30:15 -05:00
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
}
}