//
// OnboardingContainerView.swift
// Worko
//
// Created by Rodrigo Soares on 20/12/25.
//
import SwiftUI
import SwiftData
/// Container que gerencia todo o fluxo de navegação do onboarding
struct OnboardingContainerView: View {
// MARK: - Properties
@Environment(AppStateManager.self) private var appState
@Environment(\.modelContext) private var modelContext
@State private var viewModel = OnboardingViewModel()
@State private var isHealthKitReady = false
// MARK: - Body
var body: some View {
ZStack {
WorkoColors.background.ignoresSafeArea()
// Content com transições
ZStack {
currentStepView
.transition(.creativeSlide(direction: viewModel.navigationDirection))
}
.animation(.spring(response: 0.6, dampingFraction: 0.8, blendDuration: 0), value: viewModel.currentStep)
// Controles fixos (header + botão)
if viewModel.currentStep != .completion {
controlsOverlay
}
}
.task {
await viewModel.requestHealthKitAuthorization()
isHealthKitReady = true
}
}
// MARK: - Current Step View
@ViewBuilder
private var currentStepView: some View {
switch viewModel.currentStep {
case .welcome:
WelcomeView()
case .gender:
GenderView(viewModel: viewModel)
case .age:
AgePickerView(viewModel: viewModel)
case .height:
HeightPickerView(viewModel: viewModel)
case .weight:
WeightPickerView(viewModel: viewModel)
case .objective:
ObjectiveView(viewModel: viewModel)
case .activityLevel:
ActivityLevelView(viewModel: viewModel)
case .trainingExperience:
TrainingExperienceView(viewModel: viewModel)
case .completion:
CompletionView(onFinishTapped: finishOnboarding)
}
}
// MARK: - Controls Overlay
@ViewBuilder
private var controlsOverlay: some View {
VStack {
// Header com botão voltar e progresso
if viewModel.currentStep != .welcome {
OnboardingHeaderView(
currentStep: viewModel.currentDisplayStep,
totalSteps: viewModel.totalSteps,
onBack: {
withAnimation {
viewModel.goBack()
}
}
)
}
Spacer()
// Botão de ação - desabilitado até HealthKit estar pronto na tela welcome
PrimaryButton(
title: viewModel.currentStep == .welcome ? "COMEÇAR" : "PRÓXIMO",
action: handleNextAction,
isEnabled: canProceed
)
.padding(.horizontal, WorkoSpacing.horizontalPadding)
.padding(.bottom, WorkoSpacing.bottomButtonPadding)
}
}
// MARK: - Computed Properties
/// Só permite prosseguir se HealthKit já carregou (na tela welcome)
private var canProceed: Bool {
if viewModel.currentStep == .welcome {
return isHealthKitReady
}
return viewModel.canProceedFromStep
}
// MARK: - Actions
private func handleNextAction() {
withAnimation {
if viewModel.currentStep == .welcome {
viewModel.startOnboarding()
} else {
viewModel.goToNext()
}
}
}
private func finishOnboarding() {
let profile = viewModel.saveProfile(modelContext: modelContext)
appState.completeOnboarding(profile: profile, modelContext: modelContext)
}
}
// MARK: - Preview
#Preview {
OnboardingContainerView()
.environment(AppStateManager())
.modelContainer(for: UserProfile.self, inMemory: true)
}
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags: