Aug 25 - Implement new function allow Director (internal & customer) to assign and inspection to another inspector

This commit is contained in:
2026-08-25 12:30:06 -04:00
parent 3f30e2c7bd
commit ca7c09f982
3 changed files with 36 additions and 0 deletions
+9
View File
@@ -302,6 +302,12 @@ struct APIInspectionSummary: Decodable, Identifiable, Hashable, Sendable {
let followUpRequired: Bool
let followUpNote: String?
let parentInspectionId: Int?
/// phase53 who was asked to perform the follow-up. nil means it belongs
/// to the inspection's own inspector, which is what it always meant.
/// The list endpoint already returns only follow-ups this user OWNS, so
/// these are for display, not filtering.
let followUpAssignedTo: Int?
let followUpAssignedToName: String?
/// Form field values as [fieldId: stringValue] for the grid renderer.
var formValues: [String: String] {
@@ -368,6 +374,8 @@ struct APIInspectionSummary: Decodable, Identifiable, Hashable, Sendable {
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)
followUpAssignedTo = try? c.decode(Int.self, forKey: .followUpAssignedTo)
followUpAssignedToName = try? c.decode(String.self, forKey: .followUpAssignedToName)
}
private enum CodingKeys: String, CodingKey {
case id, templateId, templateName, facilityId, facilityName
@@ -376,6 +384,7 @@ struct APIInspectionSummary: Decodable, Identifiable, Hashable, Sendable {
case formData, formSchema
case formMedia
case followUpRequired, followUpNote, parentInspectionId
case followUpAssignedTo, followUpAssignedToName
}
// Explicit Hashable formDataRaw/formSchemaRaw contain JSONValue which
@@ -49,6 +49,15 @@ final class LocalFollowUpRequest {
/// Stored raw; read through `note` for the normalised form.
var followUpNote: String?
/// Display name of the inspector this follow-up was handed to, when it was
/// assigned to somebody other than whoever performed the original
/// inspection (phase53). nil = it belongs to the original inspector.
///
/// Purely for display the server only ever returns follow-ups this user
/// owns, so nothing here decides what is shown. Optional so existing
/// SwiftData stores migrate lightweight (rule 8).
var assignedToName: String?
/// Set on device the moment a re-inspection of this request is submitted, so
/// the FOLLOW-UP REQUESTED lists hide the row immediately online or
/// offline without waiting for the round trip.
@@ -128,6 +137,7 @@ final class LocalFollowUpRequest {
self.overallScore = api.overallScore
self.inspectionDateString = api.inspectionDate ?? ""
self.followUpNote = api.followUpNote
self.assignedToName = api.followUpAssignedToName
self.fulfilledLocally = false
self.parentFormDataJSON = Self.encode(api)
self.updatedAt = Date()
@@ -170,6 +180,7 @@ final class LocalFollowUpRequest {
self.overallScore = api.overallScore
self.inspectionDateString = api.inspectionDate ?? ""
self.followUpNote = api.followUpNote
self.assignedToName = api.followUpAssignedToName
self.parentFormDataJSON = Self.encode(api)
// The server is authoritative. Being returned by the pull at all means
// the follow-up is still outstanding, so any local "just did it" flag is
@@ -111,6 +111,22 @@ struct FollowUpRow: View {
}
}
// Assigned to somebody other than whoever ran the original
// inspection (phase53). The endpoint only returns follow-ups
// this user owns, so seeing this badge means "you were given
// this one" worth calling out, because it is NOT the usual
// case of re-inspecting your own work.
if request.assignedToName != nil {
HStack(spacing: 4) {
Image(systemName: "person.crop.circle.badge.checkmark")
.font(.caption2)
Text("Assigned to you")
.font(.caption2.weight(.semibold))
}
.foregroundStyle(.orange)
.padding(.top, 1)
}
// Note preview so the inspector can see there is something to
// read before committing to the tap. Truncated to one line; the
// full text is shown on the start screen. Mirrors the