05/16 Fix bugs 3

This commit is contained in:
Nguyen Ngo
2026-05-16 14:56:11 -04:00
parent 9c7aa72ff3
commit f436ac2ef2
3 changed files with 93 additions and 45 deletions
+51 -8
View File
@@ -288,30 +288,63 @@ struct APIInspectionSummary: Decodable, Identifiable, Hashable, Sendable {
let inspectionDate: String?
let completedAt: String?
let mobileLocalId: String?
let inspectorNotes: String
// Form responses and schema included in every history response so the
// detail view works without a local SwiftData copy (e.g. after reinstall).
let formDataRaw: [String: JSONValue]
let formSchemaRaw: [[String: JSONValue]]
// Follow-up / re-inspection
let followUpRequired: Bool
let followUpNote: String?
let parentInspectionId: Int?
/// Form field values as [fieldId: stringValue] for the grid renderer.
var formValues: [String: String] {
var result: [String: String] = [:]
for (k, v) in formDataRaw {
switch v {
case .string(let s): result[k] = s
case .int(let n): result[k] = String(n)
case .double(let d): result[k] = String(d)
case .bool(let b): result[k] = b ? "true" : "false"
case .array(let a): result[k] = a.map { "\($0.anyValue)" }.joined(separator: ", ")
case .null: result[k] = ""
case .object: result[k] = ""
}
}
return result
}
/// Form schema as [[String: Any]] for ReadOnlyGridFormView.
var formSchema: [[String: Any]] {
formSchemaRaw.map { dict in dict.mapValues { $0.anyValue } }
}
var inspectionDateParsed: Date? {
guard let str = inspectionDate else { return nil }
return ISO8601DateFormatter().date(from: str)
// Server sends "yyyy-MM-dd'T'HH:mm:ss" with no timezone suffix.
// ISO8601DateFormatter() requires a timezone by default and returns nil
// for timezone-less strings use the shared DateFormatter instead.
return SyncManager.isoFormatter.date(from: str)
}
nonisolated init(from decoder: any Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
id = try c.decode(Int.self, forKey: .id)
templateId = try c.decode(Int.self, forKey: .templateId)
templateName = try c.decode(String.self, forKey: .templateName)
facilityId = try c.decode(Int.self, forKey: .facilityId)
facilityName = try c.decode(String.self, forKey: .facilityName)
id = try c.decode(Int.self, forKey: .id)
templateId = try c.decode(Int.self, forKey: .templateId)
templateName = try c.decode(String.self, forKey: .templateName)
facilityId = try c.decode(Int.self, forKey: .facilityId)
facilityName = try c.decode(String.self, forKey: .facilityName)
areaId = try? c.decode(Int.self, forKey: .areaId)
areaName = try? c.decode(String.self, forKey: .areaName)
status = try c.decode(String.self, forKey: .status)
status = try c.decode(String.self, forKey: .status)
overallScore = try? c.decode(Double.self, forKey: .overallScore)
inspectionDate = try? c.decode(String.self, forKey: .inspectionDate)
completedAt = try? c.decode(String.self, forKey: .completedAt)
mobileLocalId = try? c.decode(String.self, forKey: .mobileLocalId)
inspectorNotes = (try? c.decode(String.self, forKey: .inspectorNotes)) ?? ""
formDataRaw = (try? c.decode([String: JSONValue].self, forKey: .formData)) ?? [:]
formSchemaRaw = (try? c.decode([[String: JSONValue]].self, forKey: .formSchema)) ?? []
followUpRequired = (try? c.decode(Bool.self, forKey: .followUpRequired)) ?? false
followUpNote = try? c.decode(String.self, forKey: .followUpNote)
parentInspectionId = try? c.decode(Int.self, forKey: .parentInspectionId)
@@ -319,9 +352,19 @@ struct APIInspectionSummary: Decodable, Identifiable, Hashable, Sendable {
private enum CodingKeys: String, CodingKey {
case id, templateId, templateName, facilityId, facilityName
case areaId, areaName, status, overallScore
case inspectionDate, completedAt, mobileLocalId
case inspectionDate, completedAt, mobileLocalId, inspectorNotes
case formData, formSchema
case followUpRequired, followUpNote, parentInspectionId
}
// Explicit Hashable formDataRaw/formSchemaRaw contain JSONValue which
// has no Hashable conformance; identity is determined by server id alone.
static func == (lhs: APIInspectionSummary, rhs: APIInspectionSummary) -> Bool {
lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
struct InspectionHistoryResponseData: Decodable, Sendable {