Add CBT-based guided reflection questions with clinical info sheet

Replace generic journaling prompts with evidence-based therapeutic
techniques: CBT thought record for negative moods, ACT cognitive
defusion for neutral, and behavioral activation for positive. Each
question now shows a clinical step label (e.g. SITUATION, REFRAME).
Added info button linking to a new sheet explaining the techniques
with citations to Beck, Harris, and Martell/Dimidjian.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-03-17 22:39:30 -05:00
parent 916be6a1e0
commit 99314b8e6a
4 changed files with 15582 additions and 15260 deletions

View File

@@ -753,18 +753,18 @@
"comment" : "A subheading that describes the type of report and the number of entries it contains. The first argument is the type of report (e.g., \"Mood Log\"). The second argument is the count of valid entries in the report.",
"isCommentAutoGenerated" : true,
"localizations" : {
"en": {
"stringUnit": {
"state": "new",
"value": "%1$@ with %2$lld entries"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "%@ mit %lld Einträgen"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "%1$@ with %2$lld entries"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
@@ -1213,18 +1213,18 @@
"comment" : "A text label displaying the number of days selected in the date range picker. The argument is the count of selected days.",
"isCommentAutoGenerated" : true,
"localizations" : {
"en": {
"stringUnit": {
"state": "new",
"value": "%1$lld day%2$@ selected"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld Tag%@ ausgewählt"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "%1$lld day%2$@ selected"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
@@ -2253,6 +2253,10 @@
}
}
},
"Activity" : {
"comment" : "Question text for the first question in the \"Behavioral Activation\" section of the guided reflection.",
"isCommentAutoGenerated" : true
},
"Add" : {
"comment" : "A button that allows the user to add or edit a journal note.",
"isCommentAutoGenerated" : true,
@@ -3482,6 +3486,14 @@
}
}
},
"Automatic Thought" : {
"comment" : "Question text for the \"Automatic Thought\" step in the CBT Thought Record technique.",
"isCommentAutoGenerated" : true
},
"Awareness" : {
"comment" : "The order of these step labels is the same as in the original app.",
"isCommentAutoGenerated" : true
},
"Browse Themes" : {
"comment" : "A suggestion to the user to explore different color and layout combinations.",
"isCommentAutoGenerated" : true,
@@ -6509,6 +6521,10 @@
}
}
},
"Defusion" : {
"comment" : "The fourth step label in the \"Acceptance & Commitment Therapy\" section of the Guided Reflection.",
"isCommentAutoGenerated" : true
},
"Delete" : {
"comment" : "The text on a button that deletes a mood entry.",
"isCommentAutoGenerated" : true,
@@ -9021,18 +9037,18 @@
"comment" : "Progress message displayed in the UI during detailed report generation. The number in parentheses represents the number of sections that have been completed out of the total number of sections.",
"isCommentAutoGenerated" : true,
"localizations" : {
"en": {
"stringUnit": {
"state": "new",
"value": "Generating weekly summary %1$lld of %2$lld..."
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Wöchentliche Zusammenfassung %lld von %lld wird erstellt …"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Generating weekly summary %1$lld of %2$lld..."
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
@@ -9401,6 +9417,106 @@
}
}
},
"guided_reflection_about_act_body" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "On neutral days, Reflect draws on cognitive defusion — an ACT technique that helps you notice thoughts as mental events rather than facts, creating distance between you and unhelpful thinking patterns."
}
}
}
},
"guided_reflection_about_act_title" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Acceptance & Commitment Therapy (ACT)"
}
}
}
},
"guided_reflection_about_ba_body" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "On good days, Reflect uses behavioral activation principles to help you identify which activities and behaviors contributed to your mood, so you can intentionally build more of them into your routine."
}
}
}
},
"guided_reflection_about_ba_title" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Behavioral Activation"
}
}
}
},
"guided_reflection_about_body" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "These questions are guided by evidence-based therapeutic techniques used by mental health professionals worldwide."
}
}
}
},
"guided_reflection_about_cbt_body" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "When you're feeling low, Reflect uses a simplified thought record — a core CBT technique developed by Dr. Judith Beck. It helps you separate what happened from how you interpreted it, then find a more balanced perspective."
}
}
}
},
"guided_reflection_about_cbt_title" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cognitive Behavioral Therapy (CBT)"
}
}
}
},
"guided_reflection_about_disclaimer" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Reflect is not a substitute for professional mental health care. If you are in crisis, please contact a mental health professional or crisis helpline."
}
}
}
},
"guided_reflection_about_learn_more" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Learn More"
}
}
}
},
"guided_reflection_about_title" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "About These Questions"
}
}
}
},
"guided_reflection_answered_count %lld %lld" : {
"localizations" : {
"de" : {
@@ -9688,7 +9804,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value": "What's weighing on you today?"
"value" : "What happened today that affected your mood?"
}
},
"es" : {
@@ -9734,7 +9850,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value": "If you could change how you're feeling, what would you want instead?"
"value" : "What thought kept coming back about it?"
}
},
"es" : {
@@ -9780,7 +9896,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value": "Why is feeling that way important to you?"
"value" : "What would you tell a friend who had that same thought?"
}
},
"es" : {
@@ -9826,7 +9942,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value": "What's one small thing that might help shift things?"
"value" : "What's a more balanced way to see the situation?"
}
},
"es" : {
@@ -9872,7 +9988,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value": "What feelings came up for you today?"
"value" : "What feeling has been sitting with you today?"
}
},
"es" : {
@@ -9918,7 +10034,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value": "Is there a feeling you wish had been stronger?"
"value" : "What thought is connected to that feeling?"
}
},
"es" : {
@@ -9964,7 +10080,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value": "Why does that feeling matter to you?"
"value" : "Is that thought something you know to be true, or something your mind is telling you?"
}
},
"es" : {
@@ -10010,7 +10126,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value": "What's one thing that could help you get closer to that?"
"value" : "What matters to you about tomorrow?"
}
},
"es" : {
@@ -10102,7 +10218,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value": "What feelings stood out to you today?"
"value" : "What did you do today that contributed to this feeling?"
}
},
"es" : {
@@ -10148,7 +10264,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value": "What do you think helped you feel this way?"
"value" : "What thought or moment stands out the most?"
}
},
"es" : {
@@ -10194,7 +10310,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value": "How can you bring more of this into your days?"
"value" : "How could you create more days like this?"
}
},
"es" : {
@@ -11470,6 +11586,46 @@
}
}
},
"Location Access Required" : {
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Standortzugriff erforderlich"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Acceso a ubicación requerido"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Accès à la localisation requis"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "位置情報のアクセスが必要です"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "위치 접근 권한 필요"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Acesso à localização necessário"
}
}
}
},
"Log" : {
"localizations" : {
"de" : {
@@ -11796,46 +11952,6 @@
}
}
},
"Location Access Required": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "Standortzugriff erforderlich"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "Acceso a ubicación requerido"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Accès à la localisation requis"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "位置情報のアクセスが必要です"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "위치 접근 권한 필요"
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "Acesso à localização necessário"
}
}
}
},
"Longest Streak" : {
"localizations" : {
"de" : {
@@ -14494,6 +14610,10 @@
}
}
},
"Perspective Check" : {
"comment" : "Short CBT step label shown above the \"Perspective Check\" question in Guided Reflection.",
"isCommentAutoGenerated" : true
},
"Photo" : {
"comment" : "A label displayed next to the \"Photo\" button.",
"isCommentAutoGenerated" : true,
@@ -14704,6 +14824,10 @@
}
}
},
"Planning" : {
"comment" : "Step label in the Guided Reflection for the \"Activity\" question.",
"isCommentAutoGenerated" : true
},
"Populate with sample mood entries" : {
"comment" : "A description of what the \"Add Test Data\" button does.",
"isCommentAutoGenerated" : true,
@@ -16216,6 +16340,10 @@
}
}
},
"Reframe" : {
"comment" : "The fourth step label for the CBT Thought Record technique.",
"isCommentAutoGenerated" : true
},
"Reminder time" : {
"comment" : "An accessibility label for the time picker in the onboarding flow.",
"isCommentAutoGenerated" : true,
@@ -18853,6 +18981,10 @@
}
}
},
"Situation" : {
"comment" : "The first question in the Cognitive Behavioral Therapy (CBT) Thought Record step.",
"isCommentAutoGenerated" : true
},
"Skip subscription and complete setup" : {
"comment" : "A button label that says \"Skip subscription and complete setup\". It's used in the \"OnboardingSubscription\" view.",
"isCommentAutoGenerated" : true,
@@ -20325,6 +20457,10 @@
}
}
},
"Thought" : {
"comment" : "The fourth step label in the \"Cognitive Behavioral Therapy\" section of the guided reflection.",
"isCommentAutoGenerated" : true
},
"Tip: \"Today\" works great for evening reminders" : {
"comment" : "A tip displayed below the day rating option, providing guidance on how to use the \"Today\" option effectively.",
"localizations" : {
@@ -21622,6 +21758,10 @@
}
}
},
"Values" : {
"comment" : "Label for the last question in the \"Acceptance & Commitment Therapy\" section of the guided reflection.",
"isCommentAutoGenerated" : true
},
"Vibrate when logging mood" : {
"comment" : "A description of the feature that lets users know when their device vibrates when they log a mood.",
"isCommentAutoGenerated" : true,

View File

@@ -10,9 +10,9 @@ 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
case positive // great, good 3 questions (Behavioral Activation)
case neutral // average 4 questions (ACT Cognitive Defusion)
case negative // bad, horrible 4 questions (CBT Thought Record)
init(from mood: Mood) {
switch mood {
@@ -29,6 +29,41 @@ enum MoodCategory: String, Codable {
case .neutral, .negative: return 4
}
}
/// The therapeutic technique name for display purposes.
var techniqueName: String {
switch self {
case .positive: return "Behavioral Activation"
case .neutral: return "Acceptance & Commitment Therapy"
case .negative: return "Cognitive Behavioral Therapy"
}
}
/// Short CBT step labels shown above each question.
var stepLabels: [String] {
switch self {
case .negative:
return [
String(localized: "Situation"),
String(localized: "Automatic Thought"),
String(localized: "Perspective Check"),
String(localized: "Reframe"),
]
case .neutral:
return [
String(localized: "Awareness"),
String(localized: "Thought"),
String(localized: "Defusion"),
String(localized: "Values"),
]
case .positive:
return [
String(localized: "Activity"),
String(localized: "Awareness"),
String(localized: "Planning"),
]
}
}
}
// MARK: - Guided Reflection

View File

@@ -0,0 +1,124 @@
//
// GuidedReflectionInfoView.swift
// Reflect
//
// Explains the clinical techniques behind the guided reflection questions.
//
import SwiftUI
struct GuidedReflectionInfoView: View {
@Environment(\.dismiss) private var dismiss
private let cbtURL = URL(string: "https://www.ncbi.nlm.nih.gov/books/NBK470241/")!
private let actURL = URL(string: "https://link.springer.com/article/10.1007/s40732-017-0254-z")!
private let baURL = URL(string: "https://www.psychologytools.com/self-help/behavioral-activation")!
var body: some View {
NavigationStack {
ScrollView {
VStack(alignment: .leading, spacing: 28) {
// Intro
Text(String(localized: "guided_reflection_about_body"))
.font(.body)
.foregroundStyle(.secondary)
// CBT
techniqueSection(
icon: "brain.head.profile",
color: .red,
title: String(localized: "guided_reflection_about_cbt_title"),
body: String(localized: "guided_reflection_about_cbt_body"),
citation: "Beck, J. S. (2020). Cognitive Behavior Therapy: Basics and Beyond, 3rd ed.",
url: cbtURL
)
// ACT
techniqueSection(
icon: "eye",
color: .orange,
title: String(localized: "guided_reflection_about_act_title"),
body: String(localized: "guided_reflection_about_act_body"),
citation: "Harris, R. (2009). ACT Made Simple. New Harbinger Publications.",
url: actURL
)
// BA
techniqueSection(
icon: "figure.walk",
color: .green,
title: String(localized: "guided_reflection_about_ba_title"),
body: String(localized: "guided_reflection_about_ba_body"),
citation: "Martell, C. R., Dimidjian, S., & Herman-Dunn, R. (2010). Behavioral Activation for Depression.",
url: baURL
)
// Disclaimer
Text(String(localized: "guided_reflection_about_disclaimer"))
.font(.footnote)
.foregroundStyle(.tertiary)
.padding(.top, 8)
}
.padding()
}
.navigationTitle(String(localized: "guided_reflection_about_title"))
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button(String(localized: "Done")) {
dismiss()
}
}
}
}
}
// MARK: - Technique Section
@ViewBuilder
private func techniqueSection(
icon: String,
color: Color,
title: String,
body: String,
citation: String,
url: URL
) -> some View {
VStack(alignment: .leading, spacing: 12) {
HStack(spacing: 10) {
Image(systemName: icon)
.font(.title3)
.foregroundStyle(color)
.frame(width: 32)
Text(title)
.font(.headline)
}
Text(body)
.font(.subheadline)
.foregroundStyle(.secondary)
VStack(alignment: .leading, spacing: 4) {
Text(citation)
.font(.caption)
.foregroundStyle(.tertiary)
.italic()
Link(destination: url) {
HStack(spacing: 4) {
Text(String(localized: "guided_reflection_about_learn_more"))
Image(systemName: "arrow.up.right")
}
.font(.caption)
}
}
}
.padding()
.background(
RoundedRectangle(cornerRadius: 16)
.fill(Color(.systemGray6))
)
}
}

View File

@@ -20,6 +20,7 @@ struct GuidedReflectionView: View {
@State private var currentStep: Int = 0
@State private var isSaving = false
@State private var showDiscardAlert = false
@State private var showInfoSheet = false
@FocusState private var isTextFieldFocused: Bool
/// Snapshot of the initial state to detect unsaved changes
@@ -83,6 +84,15 @@ struct GuidedReflectionView: View {
.accessibilityIdentifier(AccessibilityID.GuidedReflection.cancelButton)
}
ToolbarItem(placement: .primaryAction) {
Button {
showInfoSheet = true
} label: {
Image(systemName: "info.circle")
}
.accessibilityLabel(String(localized: "guided_reflection_about_title"))
}
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("Done") {
@@ -102,6 +112,9 @@ struct GuidedReflectionView: View {
Text(String(localized: "guided_reflection_unsaved_message"))
}
.trackScreen(.guidedReflection)
.sheet(isPresented: $showInfoSheet) {
GuidedReflectionInfoView()
}
}
}
@@ -153,6 +166,16 @@ struct GuidedReflectionView: View {
VStack(alignment: .leading, spacing: 16) {
if currentStep < reflection.responses.count {
let response = reflection.responses[currentStep]
let stepLabels = reflection.moodCategory.stepLabels
// CBT step label
if currentStep < stepLabels.count {
Text(stepLabels[currentStep].uppercased())
.font(.caption)
.fontWeight(.semibold)
.foregroundStyle(.secondary)
.tracking(1.5)
}
Text(response.question)
.font(.title3)