import SwiftUI /// Onboarding "aha moment" step: shows the freshly auto-filled first week and /// asks for the weekly reminder with context (instead of a cold OS prompt on Home). struct WeekReadyStepView: View { let filledCount: Int var onContinue: () -> Void @State private var isRequestingPermission = false @State private var reminderGranted = false var body: some View { VStack(spacing: 24) { VStack(spacing: 16) { ZStack { Circle() .fill(Color.mealMoodCoral.opacity(0.12)) .frame(width: 88, height: 88) Image(systemName: filledCount > 0 ? "checkmark.circle.fill" : "calendar.badge.checkmark") .font(.system(size: 44, weight: .semibold)) .foregroundColor(.mealMoodCoral) } .padding(.top, 24) Text("onboarding_week_ready_title") .font(.mealMoodH1) .foregroundColor(.mealMoodTextPrimary) .multilineTextAlignment(.center) .accessibilityIdentifier("onboarding_week_ready_title") Text(subtitleText) .font(.mealMoodBody) .foregroundColor(.mealMoodTextSecondary) .multilineTextAlignment(.center) } .padding(.horizontal, 24) VStack(alignment: .leading, spacing: 12) { HStack(spacing: 12) { Image(systemName: "bell.badge.fill") .font(.system(size: 22)) .foregroundColor(.mealMoodCoral) Text("onboarding_reminder_pitch") .font(.mealMoodSmall) .foregroundColor(.mealMoodTextPrimary) .fixedSize(horizontal: false, vertical: true) } } .padding(16) .frame(maxWidth: .infinity, alignment: .leading) .background(Color.mealMoodSurface) .cornerRadius(14) .overlay( RoundedRectangle(cornerRadius: 14) .stroke(Color(hex: "#F0F0F0"), lineWidth: 1) ) .padding(.horizontal, 24) Spacer(minLength: 0) VStack(spacing: 12) { PrimaryButton( title: reminderGranted ? String(localized: "onboarding_continue") : String(localized: "onboarding_reminder_allow"), action: { if reminderGranted { onContinue() } else { enableReminders() } } ) .disabled(isRequestingPermission) if !reminderGranted { Button { onContinue() } label: { Text("onboarding_reminder_skip") .font(.mealMoodSmall) .foregroundColor(.mealMoodTextSecondary) } .buttonStyle(.plain) .accessibilityIdentifier("onboarding_cta_week_ready_skip") } } .padding(.horizontal, 24) .padding(.bottom, 40) } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) } private var subtitleText: String { if filledCount > 0 { return String(format: String(localized: "onboarding_week_ready_subtitle"), filledCount) } return String(localized: "onboarding_week_ready_subtitle_empty") } private func enableReminders() { isRequestingPermission = true Task { let granted = await NotificationService.shared.requestPermission() NotificationService.shared.remindersEnabled = true AnalyticsService.logNotificationsToggled(enabled: granted) isRequestingPermission = false if granted { reminderGranted = true HapticManager.shared.notification(type: .success) // Small beat so the user sees the button flip before moving on. try? await Task.sleep(nanoseconds: 600_000_000) } onContinue() } } }