| struct WatchEntry: Identifiable, Codable, Equatable {
var id: UUID
var playName: String
var dateTime: Date
var cuisine: String
var address: String
var phone: String
var neighborhood: String
var rating: Int
var beenThere: Bool
var starRating: Int
var latitude: Double?
var longitude: Double?
var entryMode: WatchEntryMode
var consider: Bool // shows only: true = "Consider" (no firm date)
var isPast: Bool { dateTime < Date() }
var formattedDate: String {
let f = DateFormatter()
f.dateFormat = "MM/dd/yy h:mma"
f.amSymbol = "am"
f.pmSymbol = "pm"
return f.string(from: dateTime)
}
var daysUntil: Int? {
guard !isPast else { return nil }
return Calendar.current.dateComponents([.day], from: Calendar.current.startOfDay(for: Date()),
to: Calendar.current.startOfDay(for: dateTime)).day
}
// MARK: - Codable (explicit so new fields degrade gracefully with old cached data)
private enum CodingKeys: String, CodingKey {
case id, playName, dateTime, cuisine, address, phone, neighborhood, rating, beenThere, starRating, latitude, longitude, entryMode, consider
}
init(id: UUID, playName: String, dateTime: Date, cuisine: String, address: String,
phone: String = "", neighborhood: String, rating: Int, beenThere: Bool = false, starRating: Int = 0,
latitude: Double? = nil, longitude: Double? = nil,
entryMode: WatchEntryMode = .food, consider: Bool = false) {
self.id = id
self.playName = playName
self.dateTime = dateTime
self.cuisine = cuisine
self.address = address
self.phone = phone
self.neighborhood = neighborhood
self.rating = rating
self.beenThere = beenThere
self.starRating = starRating
self.latitude = latitude
self.longitude = longitude
self.entryMode = entryMode
self.consider = consider
}
init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
id = try c.decode(UUID.self, forKey: .id)
playName = try c.decode(String.self, forKey: .playName)
dateTime = try c.decode(Date.self, forKey: .dateTime)
cuisine = try c.decode(String.self, forKey: .cuisine)
address = try c.decode(String.self, forKey: .address)
phone = try c.decodeIfPresent(String.self, forKey: .phone) ?? ""
neighborhood = try c.decodeIfPresent(String.self, forKey: .neighborhood) ?? ""
rating = try c.decodeIfPresent(Int.self, forKey: .rating) ?? 0
beenThere = try c.decodeIfPresent(Bool.self, forKey: .beenThere) ?? false
starRating = try c.decodeIfPresent(Int.self, forKey: .starRating) ?? 0
latitude = try c.decodeIfPresent(Double.self, forKey: .latitude)
longitude = try c.decodeIfPresent(Double.self, forKey: .longitude)
entryMode = try c.decodeIfPresent(WatchEntryMode.self, forKey: .entryMode) ?? .food
consider = try c.decodeIfPresent(Bool.self, forKey: .consider) ?? false
}
} | `WatchEntry` struct | Defines the `WatchEntry` struct. Conforms to Identifiable, Codable, Equatable. |