import Foundation struct MonthlyCheckInEntry: Codable, Equatable { var note: String? var rating: Int? var mood: MonthlyCheckInMood? var completionTime: Double? var createdAt: Double var completionDate: Date? { completionTime.map { Date(timeIntervalSince1970: $0) } } } enum MonthlyCheckInMood: String, Codable, CaseIterable, Identifiable { case energized case confident case balanced case cautious case stressed var id: String { rawValue } var title: String { switch self { case .energized: return String(localized: "mood_energized_title") case .confident: return String(localized: "mood_confident_title") case .balanced: return String(localized: "mood_balanced_title") case .cautious: return String(localized: "mood_cautious_title") case .stressed: return String(localized: "mood_stressed_title") } } var iconName: String { switch self { case .energized: return "flame.fill" case .confident: return "hand.thumbsup.fill" case .balanced: return "leaf.fill" case .cautious: return "exclamationmark.triangle.fill" case .stressed: return "exclamationmark.octagon.fill" } } var detail: String { switch self { case .energized: return String(localized: "mood_energized_detail") case .confident: return String(localized: "mood_confident_detail") case .balanced: return String(localized: "mood_balanced_detail") case .cautious: return String(localized: "mood_cautious_detail") case .stressed: return String(localized: "mood_stressed_detail") } } } struct MonthlyCheckInAchievement: Identifiable, Equatable { let key: String let title: String let detail: String let icon: String var id: String { key } } struct MonthlyCheckInAchievementStatus: Identifiable, Equatable { let achievement: MonthlyCheckInAchievement let isUnlocked: Bool var id: String { achievement.key } } struct MonthlyCheckInStats: Equatable { let currentStreak: Int let bestStreak: Int let onTimeCount: Int let totalCheckIns: Int let averageDaysBeforeDeadline: Double? let closestCutoffDays: Double? let recentMood: MonthlyCheckInMood? let achievements: [MonthlyCheckInAchievement] static var empty: MonthlyCheckInStats { MonthlyCheckInStats( currentStreak: 0, bestStreak: 0, onTimeCount: 0, totalCheckIns: 0, averageDaysBeforeDeadline: nil, closestCutoffDays: nil, recentMood: nil, achievements: [] ) } var onTimeRate: Double { guard totalCheckIns > 0 else { return 0 } return Double(onTimeCount) / Double(totalCheckIns) } }