feat(gamification): integrate gamification into app — badge celebration overlay, history stats+badges tabs

This commit is contained in:
saravanakumardb1 2026-02-27 22:13:50 -08:00
parent 58dde35cc9
commit 40fd63e748
2 changed files with 57 additions and 10 deletions

View File

@ -7,20 +7,34 @@ import WidgetKit
struct ChronoMindApp: App {
@StateObject private var timerStore = TimerStore()
@StateObject private var notificationManager = CMNotificationManager.shared
@StateObject private var gamification = GamificationStore.shared
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(timerStore)
.environmentObject(notificationManager)
.preferredColorScheme(.dark)
.task {
notificationManager.registerCategories()
await notificationManager.requestPermission()
}
.onReceive(NotificationCenter.default.publisher(for: .chronoMindTimersDidChange)) { _ in
WidgetCenter.shared.reloadAllTimelines()
ZStack {
ContentView()
.environmentObject(timerStore)
.environmentObject(notificationManager)
.environmentObject(gamification)
.preferredColorScheme(.dark)
.task {
notificationManager.registerCategories()
await notificationManager.requestPermission()
}
.onReceive(NotificationCenter.default.publisher(for: .chronoMindTimersDidChange)) { _ in
WidgetCenter.shared.reloadAllTimelines()
}
// Badge celebration overlay
if let badge = gamification.newBadge {
BadgeCelebrationOverlay(badge: badge) {
gamification.clearNewBadge()
}
.transition(.opacity)
.zIndex(100)
}
}
.animation(.easeInOut, value: gamification.newBadge != nil)
}
}
}

View File

@ -10,6 +10,7 @@ struct HistoryView: View {
enum HistorySegment: String, CaseIterable {
case recent = "Recent"
case stats = "Stats"
case badges = "Badges"
}
private var completedTimers: [CMTimer] {
@ -39,6 +40,8 @@ struct HistoryView: View {
recentList
case .stats:
statsView
case .badges:
badgesView
}
}
}
@ -87,6 +90,20 @@ struct HistoryView: View {
private var statsView: some View {
ScrollView {
VStack(spacing: CMSpacing.lg) {
// Streak card
StreakCard()
// Focus score
let focusScore = GamificationEngine.calculateFocusScore(timers: store.timers)
FocusScoreCard(score: focusScore)
// Weekly summary card (shareable)
let summary = GamificationEngine.generateWeeklySummary(
timers: store.timers,
streak: GamificationStore.shared.streak
)
WeeklySummaryCard(summary: summary)
// Summary cards
let allTimers = store.timers
let completed = allTimers.filter { $0.state == .completed }.count
@ -166,6 +183,22 @@ struct HistoryView: View {
.padding(.bottom, CMSpacing.xxl)
}
}
// MARK: - Badges View
private var badgesView: some View {
ScrollView {
VStack(spacing: CMSpacing.lg) {
// Streak card (compact)
StreakCard()
// Badge grid
BadgeGridView()
}
.padding(.horizontal, CMSpacing.lg)
.padding(.bottom, CMSpacing.xxl)
}
}
}
// MARK: - Stat Card