Jul 14 - Using CDN - update

This commit is contained in:
Nguyen Ngo
2026-07-14 15:40:16 -04:00
parent 6fbd3d1437
commit 2a0b264a5c
8 changed files with 162 additions and 49 deletions
+28
View File
@@ -296,6 +296,8 @@ struct APIInspectionSummary: Decodable, Identifiable, Hashable, Sendable {
// detail view works without a local SwiftData copy (e.g. after reinstall).
let formDataRaw: [String: JSONValue]
let formSchemaRaw: [[String: JSONValue]]
/// {field_id: absolute_url} for image fields (presigned R2 / absolute static).
let formMedia: [String: String]
// Follow-up / re-inspection
let followUpRequired: Bool
let followUpNote: String?
@@ -323,6 +325,20 @@ struct APIInspectionSummary: Decodable, Identifiable, Hashable, Sendable {
formSchemaRaw.map { dict in dict.mapValues { $0.anyValue } }
}
/// {relative_path: absolute_url} for image fields, derived by joining
/// formMedia (fieldId -> url) with the form values (fieldId -> path). Lets
/// the image renderer resolve a presigned URL from just the stored path.
var mediaURLByPath: [String: String] {
var out: [String: String] = [:]
let values = formValues
for (fid, url) in formMedia {
if let path = values[fid], !path.isEmpty {
out[path] = url
}
}
return out
}
var inspectionDateParsed: Date? {
guard let str = inspectionDate else { return nil }
// Server sends "yyyy-MM-dd'T'HH:mm:ss" with no timezone suffix.
@@ -347,6 +363,7 @@ struct APIInspectionSummary: Decodable, Identifiable, Hashable, Sendable {
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)) ?? [:]
formMedia = (try? c.decode([String: String].self, forKey: .formMedia)) ?? [:]
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)
@@ -357,6 +374,7 @@ struct APIInspectionSummary: Decodable, Identifiable, Hashable, Sendable {
case areaId, areaName, status, overallScore
case inspectionDate, completedAt, mobileLocalId, inspectorNotes
case formData, formSchema
case formMedia
case followUpRequired, followUpNote, parentInspectionId
}
@@ -405,6 +423,7 @@ struct APIIssueDetail: Decodable, Sendable {
let reportedByName: String?
// Resolution photos uploaded via web or mobile resolve flow
let resultPhotos: [String]
let resultPhotoUrls: [String] // absolute display URLs (presigned R2 / static)
// Phase E area and assignee context
let areaName: String?
let assignedToName: String?
@@ -434,6 +453,7 @@ struct APIIssueDetail: Decodable, Sendable {
verificationNote = try? c.decode(String.self, forKey: .verificationNote)
reportedByName = try? c.decode(String.self, forKey: .reportedByName)
resultPhotos = (try? c.decode([String].self, forKey: .resultPhotos)) ?? []
resultPhotoUrls = (try? c.decode([String].self, forKey: .resultPhotoUrls)) ?? []
areaName = try? c.decode(String.self, forKey: .areaName)
assignedToName = try? c.decode(String.self, forKey: .assignedToName)
handlerType = try? c.decode(String.self, forKey: .handlerType)
@@ -449,6 +469,7 @@ struct APIIssueDetail: Decodable, Sendable {
case id, status, severity, description, assignedTo
case facilityId, facilityName, reportedAt, resolvedAt
case resultNotes, verifiedAt, verificationNote, reportedByName, resultPhotos
case resultPhotoUrls
case areaName, assignedToName
case handlerType, handlerLabel
case facilityHandlerName, facilityHandlerContact, facilityHandlerNotes
@@ -541,6 +562,10 @@ struct APIAssignedIssue: Decodable, Identifiable, Sendable {
let photoPath: String? // primary evidence photo
let mobilePhotoPaths: [String] // extra evidence photos from iPad
let resultPhotos: [String] // resolution photos added via web
// Absolute display URLs (presigned R2 / absolute static). photoUrls order
// mirrors the evidence merge: [photoPath] + mobilePhotoPaths.
let photoUrls: [String]
let resultPhotoUrls: [String]
// Phase A resolution details from web
let resultNotes: String?
let verifiedAt: String?
@@ -573,6 +598,8 @@ struct APIAssignedIssue: Decodable, Identifiable, Sendable {
photoPath = try? c.decode(String.self, forKey: .photoPath)
mobilePhotoPaths = (try? c.decode([String].self, forKey: .mobilePhotoPaths)) ?? []
resultPhotos = (try? c.decode([String].self, forKey: .resultPhotos)) ?? []
photoUrls = (try? c.decode([String].self, forKey: .photoUrls)) ?? []
resultPhotoUrls = (try? c.decode([String].self, forKey: .resultPhotoUrls)) ?? []
resultNotes = try? c.decode(String.self, forKey: .resultNotes)
verifiedAt = try? c.decode(String.self, forKey: .verifiedAt)
verificationNote = try? c.decode(String.self, forKey: .verificationNote)
@@ -592,6 +619,7 @@ struct APIAssignedIssue: Decodable, Identifiable, Sendable {
case id, status, severity, description, assignedTo
case facilityId, facilityName, reportedAt, mobileLocalId
case photoPath, mobilePhotoPaths, resultPhotos
case photoUrls, resultPhotoUrls
case resultNotes, verifiedAt, verificationNote, reportedByName
case areaName, assignedToName
case handlerType, handlerLabel