Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
b444e85b04
commit
5f3f79e6be
@ -1053,10 +1053,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Last 7 days average" : {
|
||||
"comment" : "Explanation of the \"Weekly trend\" insight card, describing how the user's average completion rate over the last 7 days is displayed.",
|
||||
"isCommentAutoGenerated" : true
|
||||
},
|
||||
"Last synced %@" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
@ -2060,10 +2056,6 @@
|
||||
"comment" : "An accessibility label for the weekly completion chart in the insight detail sheet.",
|
||||
"isCommentAutoGenerated" : true
|
||||
},
|
||||
"Weekly trend" : {
|
||||
"comment" : "Title of an insight card that shows the user their average completion rate over the last 7 days.",
|
||||
"isCommentAutoGenerated" : true
|
||||
},
|
||||
"What this means" : {
|
||||
"comment" : "A label displayed above the explanation text in the insight detail sheet.",
|
||||
"isCommentAutoGenerated" : true
|
||||
@ -2134,12 +2126,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Your average completion rate over the last 7 days. This shows how consistent you've been recently and helps identify patterns." : {
|
||||
"comment" : "Text for the \"Weekly trend\" insight card, describing its purpose and functionality.",
|
||||
"isCommentAutoGenerated" : true
|
||||
},
|
||||
"Your completion percentage for today across all rituals. This resets each morning, giving you a fresh start every day." : {
|
||||
"comment" : "Explanation of the insight card that shows the user their completion percentage for today across all their active rituals. This percentage resets each morning, providing a fresh start every day.",
|
||||
"Your completion percentage for today across all rituals. The chart shows your last 7 days—this helps you spot patterns and stay consistent." : {
|
||||
"comment" : "Explanation of the insight card that shows the user their completion percentage for today across all their active rituals, with a chart displaying their last 7 days.",
|
||||
"isCommentAutoGenerated" : true
|
||||
},
|
||||
"Your current streak of consecutive days with 100% habit completion. Complete all your habits today to keep the streak going!" : {
|
||||
|
||||
@ -243,8 +243,11 @@ final class RitualStore: RitualStoreProviding {
|
||||
let completedToday = rituals.flatMap { $0.habits }.filter { isHabitCompletedToday($0) }.count
|
||||
let completionRate = totalHabits == 0 ? 0 : Int((Double(completedToday) / Double(totalHabits)) * 100)
|
||||
|
||||
// Build per-ritual breakdowns
|
||||
let ritualDaysBreakdown = rituals.map { ritual in
|
||||
// Days active = unique calendar days with at least one check-in
|
||||
let daysActiveCount = datesWithActivity().count
|
||||
|
||||
// Build per-ritual progress breakdown
|
||||
let ritualProgressBreakdown = rituals.map { ritual in
|
||||
BreakdownItem(
|
||||
label: ritual.title,
|
||||
value: ritualDayLabel(for: ritual)
|
||||
@ -259,7 +262,6 @@ final class RitualStore: RitualStoreProviding {
|
||||
)
|
||||
}
|
||||
|
||||
let activeDays = rituals.map { ritualDayIndex(for: $0) }.reduce(0, +)
|
||||
|
||||
// Streak tracking
|
||||
let current = currentStreak()
|
||||
@ -305,26 +307,18 @@ final class RitualStore: RitualStoreProviding {
|
||||
title: String(localized: "Completion"),
|
||||
value: "\(completionRate)%",
|
||||
caption: String(localized: "Today's progress"),
|
||||
explanation: String(localized: "Your completion percentage for today across all rituals. This resets each morning, giving you a fresh start every day."),
|
||||
explanation: String(localized: "Your completion percentage for today across all rituals. The chart shows your last 7 days—this helps you spot patterns and stay consistent."),
|
||||
symbolName: "chart.bar.fill",
|
||||
breakdown: nil
|
||||
),
|
||||
InsightCard(
|
||||
title: String(localized: "Days"),
|
||||
value: "\(activeDays)",
|
||||
caption: String(localized: "Days on your journey"),
|
||||
explanation: String(localized: "The total number of days you've been working on your rituals. This shows your progress through each arc, combining all active rituals."),
|
||||
symbolName: "calendar",
|
||||
breakdown: ritualDaysBreakdown
|
||||
),
|
||||
InsightCard(
|
||||
title: String(localized: "Weekly trend"),
|
||||
value: "\(weeklyAverage)%",
|
||||
caption: String(localized: "Last 7 days average"),
|
||||
explanation: String(localized: "Your average completion rate over the last 7 days. This shows how consistent you've been recently and helps identify patterns."),
|
||||
symbolName: "chart.line.uptrend.xyaxis",
|
||||
breakdown: trendBreakdown,
|
||||
trendData: trendData
|
||||
),
|
||||
InsightCard(
|
||||
title: String(localized: "Days Active"),
|
||||
value: "\(daysActiveCount)",
|
||||
caption: String(localized: "Days you checked in"),
|
||||
explanation: String(localized: "The number of days you've completed at least one habit. Each day you check in counts toward your journey."),
|
||||
symbolName: "calendar",
|
||||
breakdown: ritualProgressBreakdown
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
@ -20,12 +20,10 @@ struct InsightCardView: View {
|
||||
|
||||
private var cardContent: some View {
|
||||
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
||||
HStack(spacing: Design.Spacing.small) {
|
||||
Image(systemName: card.symbolName)
|
||||
.foregroundStyle(AppAccent.primary)
|
||||
.accessibilityHidden(true)
|
||||
HStack {
|
||||
Text(card.title)
|
||||
.font(.subheadline)
|
||||
.bold()
|
||||
.foregroundStyle(AppTextColors.secondary)
|
||||
|
||||
Spacer()
|
||||
@ -37,49 +35,39 @@ struct InsightCardView: View {
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
|
||||
// Show mini sparkline if trend data is available
|
||||
if let trendData = card.trendData, !trendData.isEmpty {
|
||||
HStack(alignment: .bottom, spacing: Design.Spacing.medium) {
|
||||
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
||||
Text(card.value)
|
||||
.font(.title)
|
||||
.foregroundStyle(AppTextColors.primary)
|
||||
.bold()
|
||||
Text(card.caption)
|
||||
.font(.caption)
|
||||
.foregroundStyle(AppTextColors.secondary)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
// Mini sparkline chart
|
||||
Chart(trendData) { point in
|
||||
BarMark(
|
||||
x: .value("Day", point.label),
|
||||
y: .value("Completion", point.value)
|
||||
)
|
||||
.foregroundStyle(
|
||||
point.value >= 1.0 ? AppStatus.success :
|
||||
point.value >= 0.5 ? AppAccent.primary :
|
||||
AppTextColors.tertiary
|
||||
)
|
||||
.cornerRadius(2)
|
||||
}
|
||||
.chartYScale(domain: 0...1)
|
||||
.chartXAxis(.hidden)
|
||||
.chartYAxis(.hidden)
|
||||
.frame(width: 80, height: 40)
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
} else {
|
||||
Text(card.value)
|
||||
.font(.title)
|
||||
.foregroundStyle(AppTextColors.primary)
|
||||
.bold()
|
||||
// Show value prominently
|
||||
Text(card.value)
|
||||
.font(.title)
|
||||
.foregroundStyle(AppTextColors.primary)
|
||||
.bold()
|
||||
|
||||
// Show caption if present (non-chart cards)
|
||||
if !card.caption.isEmpty {
|
||||
Text(card.caption)
|
||||
.font(.caption)
|
||||
.foregroundStyle(AppTextColors.secondary)
|
||||
}
|
||||
|
||||
// Show full-width mini bar chart at bottom (Athlytic style)
|
||||
if let trendData = card.trendData, !trendData.isEmpty {
|
||||
Chart(trendData) { point in
|
||||
BarMark(
|
||||
x: .value("Day", point.label),
|
||||
y: .value("Completion", point.value)
|
||||
)
|
||||
.foregroundStyle(
|
||||
point.value >= 1.0 ? AppStatus.success :
|
||||
point.value >= 0.5 ? AppAccent.primary :
|
||||
AppTextColors.tertiary
|
||||
)
|
||||
.cornerRadius(2)
|
||||
}
|
||||
.chartYScale(domain: 0...1)
|
||||
.chartXAxis(.hidden)
|
||||
.chartYAxis(.hidden)
|
||||
.frame(height: 20)
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
}
|
||||
.padding(Design.Spacing.large)
|
||||
.background(AppSurface.card)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user