Add weather feature with WeatherKit integration for mood entries
Fetch and display weather data (temp, condition, hi/lo, humidity) when users log a mood. Weather is stored as JSON on MoodEntryModel and shown as a card in EntryDetailView. Premium-gated with location permission prompt. Includes BGTask retry for failed fetches and full analytics. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,9 @@ final class MoodEntryModel {
|
||||
var notes: String?
|
||||
var photoID: UUID?
|
||||
|
||||
// Weather
|
||||
var weatherJSON: String?
|
||||
|
||||
// Computed properties
|
||||
var mood: Mood {
|
||||
Mood(rawValue: moodValue) ?? .missing
|
||||
@@ -58,7 +61,8 @@ final class MoodEntryModel {
|
||||
canEdit: Bool = true,
|
||||
canDelete: Bool = true,
|
||||
notes: String? = nil,
|
||||
photoID: UUID? = nil
|
||||
photoID: UUID? = nil,
|
||||
weatherJSON: String? = nil
|
||||
) {
|
||||
self.forDate = forDate
|
||||
self.moodValue = mood.rawValue
|
||||
@@ -69,6 +73,7 @@ final class MoodEntryModel {
|
||||
self.canDelete = canDelete
|
||||
self.notes = notes
|
||||
self.photoID = photoID
|
||||
self.weatherJSON = weatherJSON
|
||||
}
|
||||
|
||||
// Convenience initializer for raw values
|
||||
@@ -81,7 +86,8 @@ final class MoodEntryModel {
|
||||
canEdit: Bool = true,
|
||||
canDelete: Bool = true,
|
||||
notes: String? = nil,
|
||||
photoID: UUID? = nil
|
||||
photoID: UUID? = nil,
|
||||
weatherJSON: String? = nil
|
||||
) {
|
||||
self.forDate = forDate
|
||||
self.moodValue = moodValue
|
||||
@@ -92,5 +98,6 @@ final class MoodEntryModel {
|
||||
self.canDelete = canDelete
|
||||
self.notes = notes
|
||||
self.photoID = photoID
|
||||
self.weatherJSON = weatherJSON
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +207,7 @@ class UserDefaultsStore {
|
||||
case lockScreenStyle
|
||||
case celebrationAnimation
|
||||
case hapticFeedbackEnabled
|
||||
case weatherEnabled
|
||||
|
||||
case contentViewCurrentSelectedHeaderViewBackDays
|
||||
case contentViewHeaderTag
|
||||
|
||||
32
Shared/Models/WeatherData.swift
Normal file
32
Shared/Models/WeatherData.swift
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// WeatherData.swift
|
||||
// Reflect
|
||||
//
|
||||
// Codable weather model stored as JSON string in MoodEntryModel.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct WeatherData: Codable {
|
||||
let conditionSymbol: String // SF Symbol from WeatherKit (e.g. "cloud.sun.fill")
|
||||
let condition: String // "Partly Cloudy"
|
||||
let temperature: Double // Current/average in Celsius
|
||||
let highTemperature: Double // Day high in Celsius
|
||||
let lowTemperature: Double // Day low in Celsius
|
||||
let humidity: Double // 0.0–1.0
|
||||
let latitude: Double
|
||||
let longitude: Double
|
||||
let fetchedAt: Date
|
||||
|
||||
// MARK: - JSON Helpers
|
||||
|
||||
func encode() -> String? {
|
||||
guard let data = try? JSONEncoder().encode(self) else { return nil }
|
||||
return String(data: data, encoding: .utf8)
|
||||
}
|
||||
|
||||
static func decode(from json: String) -> WeatherData? {
|
||||
guard let data = json.data(using: .utf8) else { return nil }
|
||||
return try? JSONDecoder().decode(WeatherData.self, from: data)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user