# General Guidelines ## Technology Stack Technology stack is described in TECH.md file. ## Data Model Data model is defined in MODEL.md file. ## Persistence When implementing an edit form for a SwiftData model, ensure proper loading: 1. BEFORE PRESENTING THE FORM: - Ensure the model is fully loaded with all its relationships - Use a deep fetch pattern to eagerly load all relationships - Access each property to force SwiftData to materialize lazy-loaded relationships - Consider creating a deep copy of the model if relationships are complex 2. IN THE EDIT VIEW: - Accept the model as a @State parameter (e.g., @State var modelObject: ModelType) - Create separate @State variables for each editable field - Initialize each state variable in the init() method using State(initialValue:) - Use the modelContext for persisting changes back to the data store 3. SAVING CHANGES: - When saving, update the model object properties from state variables - Use modelContext.save() to persist changes - Handle errors appropriately ## User Interface and User Experience Each view struct should be placed in its own file under "Views" directory. The user interface and user experience should follow Apple's Human Interface Guidelines (HIG) and best practices for iOS development. Avoid custom UI components, instead rely on available SwiftUI views and modifiers. When creating a add/edit functionality for a model, unless otherwise instructed use a single Add/Edit View for both add and edit functionality. Unless otherwise instructed, use a sheet to present both add and edit views. Whenever a list view has no entries, show a placeholder view with text "No [ListName] yet." and a button "Add [ListName]". Before presenting an add/edit view, ensure the model is fully loaded with all its relationships. Make use of async/await mechanism to load the model. Show an overlay with a loading indicator while the model is being loaded. ## Logger Use custom logger instead of print statements. Make a custom logger as follows: ```swift import OSLog struct AppLogger { private let logger: Logger private let subsystem: String private let category: String init(subsystem: String, category: String) { self.subsystem = subsystem self.category = category self.logger = Logger(subsystem: subsystem, category: category) } func timestamp () -> String { Date.now.formatDateET(format: "yyyy-MM-dd HH:mm:ss") } func formattedMessage (_ message: String) -> String { "\(timestamp()) [\(subsystem):\(category)] \(message)" } func debug(_ message: String) { logger.debug("\(formattedMessage(message))") } func info(_ message: String) { logger.info("\(formattedMessage(message))") } func warning(_ message: String) { logger.warning("\(formattedMessage(message))") } func error(_ message: String) { logger.error("\(formattedMessage(message))") } } ``` ```swift extension Date { func formatDateET(format: String = "MMMM, d yyyy @ h:mm a z") -> String { let formatter = DateFormatter() formatter.timeZone = TimeZone(identifier: "America/New_York") formatter.dateFormat = format return formatter.string(from: self) } static var ISO8601: String { "yyyy-MM-dd'T'HH:mm:ssZ" } } ```