06/22 Fix High impact items

This commit is contained in:
Nguyen Ngo
2026-06-22 11:10:37 -04:00
parent 6c48a38743
commit e68a702bf9
4 changed files with 309 additions and 48 deletions
@@ -23,10 +23,12 @@ struct ExecuteInspectionView: View {
let inspection: LocalInspection
@State private var formValues: [String: String] = [:]
@State private var showFlagIssue = false
@State private var showSubmitAlert = false
@State private var showNoGPSAlert = false
@State private var isSaving = false
@State private var showFlagIssue = false
@State private var showSubmitAlert = false
@State private var showNoGPSAlert = false
@State private var showValidationAlert = false
@State private var missingFields: [String] = []
@State private var isSaving = false
@State private var isSubmitting = false
@State private var submitResult: SubmitResult?
@@ -125,6 +127,15 @@ struct ExecuteInspectionView: View {
} message: {
Text("This inspection's location could not be recorded — Location permission may be denied, or no GPS signal is available right now. You can submit without it, or wait a moment and try again.")
}
.alert("Required Fields Missing", isPresented: $showValidationAlert) {
Button("OK", role: .cancel) {}
} message: {
let list = missingFields.prefix(5).joined(separator: "\n")
let suffix = missingFields.count > 5
? "\n…and \(missingFields.count - 5) more."
: ""
Text("Please fill in the following required fields before submitting:\n\n\(list)\(suffix)")
}
.onChange(of: showSubmitAlert) { _, showing in
// Begin acquiring a GPS fix the moment the confirm dialog appears
// so a location is likely ready by the time the inspector taps Submit.
@@ -284,7 +295,16 @@ struct ExecuteInspectionView: View {
.disabled(isSaving)
Button {
showSubmitAlert = true
// Validate required fields before showing the confirm dialog.
// Collects every unfilled required field's label so the alert
// can name them specifically rather than just saying "missing fields".
let missing = missingRequiredFields()
if missing.isEmpty {
showSubmitAlert = true
} else {
missingFields = missing
showValidationAlert = true
}
} label: {
Group {
if isSubmitting {
@@ -380,6 +400,43 @@ struct ExecuteInspectionView: View {
// Submit (async shows result, then dismisses)
/// Returns the labels of required fields that have no value in formValues.
/// Skips structural fields (section, label, buttons) and image/signature
/// fields since those have complex "filled" semantics (local:// counts as
/// filled the photo exists even if not yet uploaded to the server).
private func missingRequiredFields() -> [String] {
let skipTypes: Set<String> = ["section", "label",
"button_submit", "button_print", "button_email"]
var missing: [String] = []
for field in formSchema {
guard let ftype = field["type"] as? String,
!skipTypes.contains(ftype),
field["required"] as? Bool == true
else { continue }
let fid = field["id"] as? String ?? (field["id"] as? Int).map(String.init) ?? ""
let val = formValues[fid] ?? ""
let isFilled: Bool
switch ftype {
case "rating":
isFilled = (Int(val) ?? 0) > 0
case "image", "signature":
isFilled = !val.isEmpty // local:// or uploads/ both count
case "checkbox":
isFilled = val == "true"
default:
isFilled = !val.trimmingCharacters(in: .whitespaces).isEmpty
}
if !isFilled {
let label = field["label"] as? String ?? "Field \(fid)"
missing.append(label.isEmpty ? "Field \(fid)" : label)
}
}
return missing
}
private func submitInspection() async {
isSubmitting = true