feat(gamification): integrate gamification into app — badge celebration overlay, history stats+badges tabs
This commit is contained in:
parent
58dde35cc9
commit
40fd63e748
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user