import SwiftUI import LabWiseKit private let isoDateFormatter: ISO8601DateFormatter = { let f = ISO8601DateFormatter() f.formatOptions = [.withFullDate] return f }() private let isoTimestampFormatter: ISO8601DateFormatter = { let f = ISO8601DateFormatter() f.formatOptions = [.withInternetDateTime, .withFractionalSeconds] return f }() private let displayDateFormatter: DateFormatter = { let f = DateFormatter() f.dateStyle = .medium f.timeStyle = .none return f }() private let displayTimestampFormatter: DateFormatter = { let f = DateFormatter() f.dateStyle = .medium f.timeStyle = .short return f }() private func formatDate(_ iso: String?) -> String { guard let iso else { return "" } if let date = isoDateFormatter.date(from: iso) { return displayDateFormatter.string(from: date) } // Fallback: try full timestamp (e.g. "2025-03-01T00:00:00.000Z") if let date = isoTimestampFormatter.date(from: iso) { return displayDateFormatter.string(from: date) } return iso } private func formatTimestamp(_ iso: String?) -> String { guard let iso else { return "" } if let date = isoTimestampFormatter.date(from: iso) { return displayTimestampFormatter.string(from: date) } return iso } struct ChemicalDetailView: View { @State private var chemical: Chemical @State private var showEdit = false init(chemical: Chemical) { self._chemical = State(initialValue: chemical) } var body: some View { Form { Section("Identity") { LabeledContent("Name", value: chemical.chemicalName) LabeledContent("CAS Number", value: chemical.casNumber) if let formula = chemical.chemicalFormula { LabeledContent("Formula", value: formula) } if let mw = chemical.molecularWeight { LabeledContent("Molecular Weight", value: mw) } LabeledContent("Physical State", value: chemical.physicalState.capitalized) if let conc = chemical.concentration { LabeledContent("Concentration", value: conc) } } Section("Storage") { LabeledContent("Location", value: chemical.storageLocation) LabeledContent("Device", value: chemical.storageDevice) LabeledContent("Building", value: chemical.bldgCode) LabeledContent("Lab", value: chemical.lab) LabeledContent("Containers", value: chemical.numberOfContainers) LabeledContent("Amount / Container", value: "\(chemical.amountPerContainer) \(chemical.unitOfMeasure)") if let pct = chemical.percentageFull { LabeledContent("% Full") { HStack(spacing: 8) { PercentageBar(value: pct / 100) .frame(width: 80, height: 6) Text("\(Int(pct))%") .font(.callout) } } } } Section("Vendor") { LabeledContent("PI", value: chemical.piFirstName) if let vendor = chemical.vendor { LabeledContent("Vendor", value: vendor) } if let catalog = chemical.catalogNumber { LabeledContent("Catalog #", value: catalog) } if let lot = chemical.lotNumber { LabeledContent("Lot #", value: lot) } if let exp = chemical.expirationDate, !exp.isEmpty { LabeledContent("Expiration", value: formatDate(exp)) } if let barcode = chemical.barcode { LabeledContent("Barcode", value: barcode) } if let contact = chemical.contact { LabeledContent("Contact", value: contact) } } if let comments = chemical.comments, !comments.isEmpty { Section("Comments") { Text(comments) .font(.body) } } Section("Record") { if let created = chemical.createdAt { LabeledContent("Created", value: formatTimestamp(created)) } if let updated = chemical.updatedAt { LabeledContent("Updated", value: formatTimestamp(updated)) } } } .navigationTitle(chemical.chemicalName) .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .topBarTrailing) { Button { showEdit = true } label: { Image(systemName: "pencil") } } } .sheet(isPresented: $showEdit) { AddChemicalView(editing: chemical) { saved in showEdit = false if saved { Task { await reloadChemical() } } } } } // Reload from server so the detail view reflects the saved changes. private func reloadChemical() async { let updated = try? await ChemicalsClient().list() if let match = updated?.first(where: { $0.id == chemical.id }) { chemical = match } } }