// Models/LocalTemplate.swift // -------------------------- // SwiftData model for locally cached inspection templates. // form_schema stored as raw JSON string, decoded on demand via formSchema property. import Foundation import SwiftData @Model final class LocalTemplate { @Attribute(.unique) var serverId: Int var name: String var templateDescription: String var frequency: String var formSchemaJSON: String var lastSyncedAt: Date var isActive: Bool = true // phase21 — false templates excluded from picker /// Timestamp of the last successful schema fetch (GET /api/v1/templates/{id}). /// Nil when the schema has never been fetched (e.g. template just inserted). /// Used to skip redundant detail calls when summary fields are unchanged. var schemaFetchedAt: Date? = nil init(from summary: APITemplateSummary) { self.serverId = summary.id self.name = summary.name self.templateDescription = summary.description self.frequency = summary.frequency self.formSchemaJSON = "[]" self.lastSyncedAt = Date() self.isActive = summary.isActive } /// Update summary fields and return whether any field changed. /// Used by pullReferenceData to skip schema re-fetching when nothing changed. @discardableResult func updateSummary(from summary: APITemplateSummary) -> Bool { let changed = name != summary.name || templateDescription != summary.description || frequency != summary.frequency || isActive != summary.isActive self.name = summary.name self.templateDescription = summary.description self.frequency = summary.frequency self.isActive = summary.isActive self.lastSyncedAt = Date() return changed } func updateSchema(from template: APITemplate) { // Convert [[String: JSONValue]] → JSON string via anyValue bridge let raw = template.formSchema.map { dict in dict.mapValues { $0.anyValue } } if let data = try? JSONSerialization.data(withJSONObject: raw), let str = String(data: data, encoding: .utf8) { self.formSchemaJSON = str } self.schemaFetchedAt = Date() self.lastSyncedAt = Date() } /// Decode stored JSON back into [[String: Any]] for the form renderer var formSchema: [[String: Any]] { guard let data = formSchemaJSON.data(using: .utf8), let array = try? JSONSerialization.jsonObject(with: data) as? [[String: Any]] else { return [] } return array } var frequencyLabel: String { switch frequency { case "daily": return "Daily" case "weekly": return "Weekly" case "monthly": return "Monthly" case "quarterly": return "Quarterly" default: return frequency.capitalized } } }