Walks users through 3-4 guided questions based on mood category: positive (great/good) gets gratitude-oriented questions, neutral (average) gets exploratory questions, and negative (bad/horrible) gets empathetic questions. Stored as JSON in MoodEntryModel, integrated into PDF reports, AI summaries, and CSV export. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
111 lines
3.3 KiB
Swift
111 lines
3.3 KiB
Swift
//
|
|
// GuidedReflection.swift
|
|
// Reflect
|
|
//
|
|
// Codable model for guided reflection responses, stored as JSON in MoodEntryModel.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
// MARK: - Mood Category
|
|
|
|
enum MoodCategory: String, Codable {
|
|
case positive // great, good → 3 questions
|
|
case neutral // average → 4 questions
|
|
case negative // bad, horrible → 4 questions
|
|
|
|
init(from mood: Mood) {
|
|
switch mood {
|
|
case .great, .good: self = .positive
|
|
case .average: self = .neutral
|
|
case .horrible, .bad: self = .negative
|
|
default: self = .neutral
|
|
}
|
|
}
|
|
|
|
var questionCount: Int {
|
|
switch self {
|
|
case .positive: return 3
|
|
case .neutral, .negative: return 4
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Guided Reflection
|
|
|
|
struct GuidedReflection: Codable, Equatable {
|
|
|
|
struct Response: Codable, Equatable, Identifiable {
|
|
var id: Int // question index (0-based)
|
|
let question: String
|
|
var answer: String
|
|
}
|
|
|
|
let moodCategory: MoodCategory
|
|
var responses: [Response]
|
|
var completedAt: Date?
|
|
|
|
// MARK: - Computed Properties
|
|
|
|
var isComplete: Bool {
|
|
responses.count == moodCategory.questionCount &&
|
|
responses.allSatisfy { !$0.answer.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }
|
|
}
|
|
|
|
var answeredCount: Int {
|
|
responses.filter { !$0.answer.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }.count
|
|
}
|
|
|
|
var totalQuestions: Int {
|
|
moodCategory.questionCount
|
|
}
|
|
|
|
// MARK: - Factory
|
|
|
|
static func createNew(for mood: Mood) -> GuidedReflection {
|
|
let category = MoodCategory(from: mood)
|
|
let questionTexts = questions(for: category)
|
|
let responses = questionTexts.enumerated().map { index, question in
|
|
Response(id: index, question: question, answer: "")
|
|
}
|
|
return GuidedReflection(moodCategory: category, responses: responses, completedAt: nil)
|
|
}
|
|
|
|
static func questions(for category: MoodCategory) -> [String] {
|
|
switch category {
|
|
case .positive:
|
|
return [
|
|
String(localized: "guided_reflection_positive_q1"),
|
|
String(localized: "guided_reflection_positive_q2"),
|
|
String(localized: "guided_reflection_positive_q3"),
|
|
]
|
|
case .neutral:
|
|
return [
|
|
String(localized: "guided_reflection_neutral_q1"),
|
|
String(localized: "guided_reflection_neutral_q2"),
|
|
String(localized: "guided_reflection_neutral_q3"),
|
|
String(localized: "guided_reflection_neutral_q4"),
|
|
]
|
|
case .negative:
|
|
return [
|
|
String(localized: "guided_reflection_negative_q1"),
|
|
String(localized: "guided_reflection_negative_q2"),
|
|
String(localized: "guided_reflection_negative_q3"),
|
|
String(localized: "guided_reflection_negative_q4"),
|
|
]
|
|
}
|
|
}
|
|
|
|
// 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) -> GuidedReflection? {
|
|
guard let data = json.data(using: .utf8) else { return nil }
|
|
return try? JSONDecoder().decode(GuidedReflection.self, from: data)
|
|
}
|
|
}
|