05/21 Fix issue's photo problems

This commit is contained in:
Nguyen Ngo
2026-05-21 13:24:10 -04:00
parent 437ed913cd
commit 6aa3b74e61
8 changed files with 602 additions and 103 deletions
+32 -3
View File
@@ -309,8 +309,23 @@ class SyncManager: ObservableObject {
let issueId = try await APIClient.shared.submitIssue(issue)
issue.serverId = issueId
issue.syncStatus = "synced"
// Photos are now represented by photoServerPaths on the server.
// Clear the local file paths so IssueDetailView doesn't render
// a duplicate "local photos" section alongside the server section.
issue.photoLocalPaths = []
try? context.save()
// If there are additional photos beyond the first (which was sent
// as photo_path on create), PATCH them to result_photos now.
// The server create endpoint only stores photo_path; result_photos
// must be set via a separate PATCH call.
let extras = Array(issue.photoServerPaths.dropFirst())
if !extras.isEmpty {
try? await APIClient.shared.updateIssuePhotos(
issueId: issueId, resultPhotos: extras
)
}
} catch {
issue.syncRetryCount += 1
issue.syncErrorMessage = error.localizedDescription
@@ -339,7 +354,17 @@ class SyncManager: ObservableObject {
uniquingKeysWith: { a, _ in a }
)
for apiFacility in facilitiesData.facilities {
// Deduplicate the server response by id before upserting.
// The server may return the same facility id more than once
// (e.g. one row per contract assignment), which would insert
// duplicate LocalFacility records and show buildings twice in
// every picker. Keep only the first occurrence of each id.
var seenFacilityIds = Set<Int>()
let uniqueFacilities = facilitiesData.facilities.filter {
seenFacilityIds.insert($0.id).inserted
}
for apiFacility in uniqueFacilities {
if let existing = facilityMap[apiFacility.id] {
existing.update(from: apiFacility)
} else {
@@ -446,9 +471,12 @@ class SyncManager: ObservableObject {
existing.issueDescription = api.description
if let fid = api.facilityId { existing.facilityServerId = fid }
// Refresh photos in case they were added after first pull
// photoServerPaths = evidence photos only (photo_path + mobile_photo_paths).
// result_photos are resolution photos shown separately on the web,
// not displayed on the iPad issues list.
var serverPaths: [String] = []
if let p = api.photoPath, !p.isEmpty { serverPaths.append(p) }
serverPaths.append(contentsOf: api.resultPhotos)
serverPaths.append(contentsOf: api.mobilePhotoPaths)
existing.photoServerPaths = serverPaths
} else {
// Insert new server-pulled issue
@@ -462,9 +490,10 @@ class SyncManager: ObservableObject {
local.issueStatus = api.status
local.syncStatus = "synced" // never re-submit
// Store server photos so IssueDetailView can show them
// photoServerPaths = evidence photos only (photo_path + mobile_photo_paths).
var serverPaths: [String] = []
if let p = api.photoPath, !p.isEmpty { serverPaths.append(p) }
serverPaths.append(contentsOf: api.resultPhotos)
serverPaths.append(contentsOf: api.mobilePhotoPaths)
local.photoServerPaths = serverPaths
if let ts = api.reportedAt,
let date = Self.isoFormatter.date(from: ts) {