06/22 Fix Low impact items

This commit is contained in:
Nguyen Ngo
2026-06-22 13:45:32 -04:00
parent 93ee02ea18
commit 072ea13b53
8 changed files with 1810 additions and 1701 deletions
@@ -65,6 +65,44 @@ struct ExecuteInspectionView: View {
private var formSchema: [[String: Any]] { template?.formSchema ?? [] }
/// Live score computed directly from `formValues` (in-memory SwiftUI state)
/// so it updates as the inspector fills in each field without waiting for
/// `saveDraft()` to flush to SwiftData and `computeScore()` to run.
/// Returns nil when the schema has no scoreable fields.
private var liveScore: Double? {
let scoreable = formSchema.filter {
["rating", "checkbox", "radio", "pass_fail"].contains($0["type"] as? String ?? "")
}
guard !scoreable.isEmpty else { return nil }
var total = 0; var earned = 0
for field in scoreable {
let fid: String
if let s = field["id"] as? String { fid = s }
else if let n = field["id"] as? Int { fid = String(n) }
else { continue }
guard let ftype = field["type"] as? String else { continue }
let val = formValues[fid] ?? ""
switch ftype {
case "rating":
if let v = Int(val), v > 0 { earned += v; total += field["max"] as? Int ?? 5 }
case "checkbox":
total += 1; if val == "true" { earned += 1 }
case "radio":
total += 1
if ["pass","yes","ok","good","acceptable","compliant"].contains(val.lowercased()) { earned += 1 }
case "pass_fail":
guard !val.isEmpty else { continue }
total += 1
if ["pass","yes","ok","good","acceptable","compliant"].contains(val.lowercased()) { earned += 1 }
default: break
}
}
guard total > 0 else { return nil }
return (Double(earned) / Double(total) * 100).rounded(toPlaces: 2)
}
// Body
var body: some View {
@@ -83,7 +121,25 @@ struct ExecuteInspectionView: View {
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
ConnectivityBadge()
HStack(spacing: 10) {
// Live score updates on every field change via formValues binding.
// Only shown when the schema has at least one scoreable field.
if let score = liveScore {
let color: Color = score >= 80 ? .green : score >= 60 ? .orange : .red
HStack(spacing: 4) {
Image(systemName: "chart.bar.fill")
.font(.caption2)
.foregroundStyle(color)
Text(String(format: "%.0f%%", score))
.font(.system(size: 13, weight: .semibold, design: .rounded))
.foregroundStyle(color)
}
.padding(.horizontal, 8).padding(.vertical, 4)
.background(color.opacity(0.12))
.clipShape(Capsule())
}
ConnectivityBadge()
}
}
}
.onAppear {