Enrich test data, fix multi-page PDF export, and polish UI

- Populate debug test data with random notes, guided reflections, and weather
- Fix PDF export to use UIPrintPageRenderer for proper multi-page pagination
- Add journal/reflection indicator icons to day list entry cells
- Fix weather card icon contrast by using secondarySystemBackground
- Align Generate Report and Export PDF button widths in ReportsView

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-03-11 18:19:01 -05:00
parent a9eeddf2b5
commit 6a8a66546b
5 changed files with 189 additions and 32 deletions

View File

@@ -63,15 +63,15 @@ extension DataController {
for idx in 1..<1000 {
let date = Calendar.current.date(byAdding: .day, value: -idx, to: Date())!
var moodValue = Int.random(in: 3...4)
if Int.random(in: 0...400) % 5 == 0 {
moodValue = Int.random(in: 0...4)
}
let mood = Self.randomMood()
let entry = MoodEntryModel(
forDate: date,
mood: Mood(rawValue: moodValue) ?? .average,
entryType: .listView
mood: mood,
entryType: .listView,
notes: Self.randomNotes(),
weatherJSON: Self.randomWeatherJSON(for: date),
reflectionJSON: Self.randomReflectionJSON(for: mood, on: date)
)
modelContext.insert(entry)
}
@@ -85,15 +85,15 @@ extension DataController {
for idx in 1...730 {
let date = Calendar.current.date(byAdding: .day, value: -idx, to: Date())!
var moodValue = Int.random(in: 3...4)
if Int.random(in: 0...400) % 5 == 0 {
moodValue = Int.random(in: 0...4)
}
let mood = Self.randomMood()
let entry = MoodEntryModel(
forDate: date,
mood: Mood(rawValue: moodValue) ?? .average,
entryType: .listView
mood: mood,
entryType: .listView,
notes: Self.randomNotes(),
weatherJSON: Self.randomWeatherJSON(for: date),
reflectionJSON: Self.randomReflectionJSON(for: mood, on: date)
)
modelContext.insert(entry)
}
@@ -102,6 +102,121 @@ extension DataController {
}
#endif
private static func randomMood() -> Mood {
var moodValue = Int.random(in: 3...4)
if Int.random(in: 0...400) % 5 == 0 {
moodValue = Int.random(in: 0...4)
}
return Mood(rawValue: moodValue) ?? .average
}
// ~40% of entries get notes
private static func randomNotes() -> String? {
guard Bool.random() && Bool.random() == false else { return nil }
return sampleNotes.randomElement()
}
private static let sampleNotes: [String] = [
"Had a productive morning and got a lot done.",
"Went for a long walk in the park today.",
"Feeling grateful for the little things.",
"Tough meeting at work but pushed through.",
"Spent quality time with family this evening.",
"Couldn't sleep well last night, feeling tired.",
"Great workout at the gym today!",
"Read a really interesting book chapter.",
"Cooked a new recipe and it turned out great.",
"Feeling a bit anxious about tomorrow.",
"Had coffee with an old friend, felt wonderful.",
"Rainy day but cozy inside with a good movie.",
"Got some bad news, trying to stay positive.",
"Meditation session helped clear my mind.",
"Busy day but managed to stay focused.",
"Enjoyed a quiet evening at home.",
"Felt overwhelmed by my to-do list.",
"Beautiful sunset on the drive home.",
"Tried journaling for the first time in a while.",
"Had a really meaningful conversation today.",
]
// ~25% of entries get guided reflections
private static func randomReflectionJSON(for mood: Mood, on date: Date) -> String? {
guard Int.random(in: 0...3) == 0 else { return nil }
let category = MoodCategory(from: mood)
let questions = GuidedReflection.questions(for: category)
let answers = sampleAnswers(for: category)
let responses = questions.enumerated().map { index, question in
GuidedReflection.Response(
id: index,
question: question,
answer: answers[index % answers.count]
)
}
let reflection = GuidedReflection(
moodCategory: category,
responses: responses,
completedAt: date
)
return reflection.encode()
}
private static func sampleAnswers(for category: MoodCategory) -> [String] {
switch category {
case .positive:
return [
"I felt a sense of calm and contentment throughout the day.",
"Connecting with a friend really lifted my spirits.",
"I want to keep making time for the things that bring me joy.",
]
case .neutral:
return [
"A mix of emotions today, nothing too strong in either direction.",
"Work was steady but unremarkable.",
"I'd like to be more intentional about how I spend my evenings.",
"Maybe adding a short walk after lunch could help.",
]
case .negative:
return [
"I've been worrying about things outside my control.",
"A stressful interaction this morning set the tone for the day.",
"I think I need some quiet time to recharge.",
"Taking a few deep breaths and stepping away from screens.",
]
}
}
private static let weatherConditions: [(symbol: String, condition: String)] = [
("sun.max.fill", "Clear"),
("cloud.sun.fill", "Partly Cloudy"),
("cloud.fill", "Cloudy"),
("cloud.rain.fill", "Rain"),
("cloud.heavyrain.fill", "Heavy Rain"),
("cloud.drizzle.fill", "Drizzle"),
("cloud.bolt.fill", "Thunderstorms"),
("cloud.snow.fill", "Snow"),
("cloud.fog.fill", "Foggy"),
("wind", "Windy"),
("sun.haze.fill", "Hazy"),
]
private static func randomWeatherJSON(for date: Date) -> String? {
let condition = weatherConditions.randomElement()!
let high = Double.random(in: 5...35)
let low = high - Double.random(in: 5...15)
let weather = WeatherData(
conditionSymbol: condition.symbol,
condition: condition.condition,
temperature: (high + low) / 2.0,
highTemperature: high,
lowTemperature: low,
humidity: Double.random(in: 0.2...0.95),
latitude: 37.7749,
longitude: -122.4194,
fetchedAt: date
)
return weather.encode()
}
func longestStreak() -> [MoodEntryModel] {
let descriptor = FetchDescriptor<MoodEntryModel>(
sortBy: [SortDescriptor(\.forDate, order: .forward)]