diff --git a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/ui/screens/onboarding/OnboardingScreen.kt b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/ui/screens/onboarding/OnboardingScreen.kt index 3bec037..ce2aca1 100644 --- a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/ui/screens/onboarding/OnboardingScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/ui/screens/onboarding/OnboardingScreen.kt @@ -103,8 +103,7 @@ fun OnboardingScreen( if (userIntent == OnboardingIntent.JOIN_EXISTING) { viewModel.goToStep(OnboardingStep.JOIN_RESIDENCE) } else { - viewModel.createResidence() - viewModel.goToStep(OnboardingStep.RESIDENCE_LOCATION) + viewModel.goToStep(OnboardingStep.HOME_PROFILE) } } else { viewModel.nextStep() @@ -118,8 +117,7 @@ fun OnboardingScreen( if (userIntent == OnboardingIntent.JOIN_EXISTING) { viewModel.goToStep(OnboardingStep.JOIN_RESIDENCE) } else { - viewModel.createResidence() - viewModel.goToStep(OnboardingStep.RESIDENCE_LOCATION) + viewModel.goToStep(OnboardingStep.HOME_PROFILE) } } ) @@ -129,19 +127,21 @@ fun OnboardingScreen( onJoined = { viewModel.completeOnboarding() } ) - OnboardingStep.RESIDENCE_LOCATION -> OnboardingLocationContent( - viewModel = viewModel, - onLocationDetected = { zip -> - viewModel.loadRegionalTemplates(zip) - viewModel.nextStep() - }, - onSkip = { viewModel.nextStep() } - ) + OnboardingStep.RESIDENCE_LOCATION -> { + // Location step removed — skip to home profile if we land here + LaunchedEffect(Unit) { viewModel.goToStep(OnboardingStep.HOME_PROFILE) } + } OnboardingStep.HOME_PROFILE -> OnboardingHomeProfileContent( viewModel = viewModel, - onContinue = { viewModel.nextStep() }, - onSkip = { viewModel.skipStep() } + onContinue = { + viewModel.createResidence() + viewModel.nextStep() + }, + onSkip = { + viewModel.createResidence() + viewModel.skipStep() + } ) OnboardingStep.FIRST_TASK -> OnboardingFirstTaskContent( @@ -179,7 +179,6 @@ private fun OnboardingNavigationBar( val showSkipButton = when (currentStep) { OnboardingStep.VALUE_PROPS, OnboardingStep.JOIN_RESIDENCE, - OnboardingStep.RESIDENCE_LOCATION, OnboardingStep.HOME_PROFILE, OnboardingStep.FIRST_TASK, OnboardingStep.SUBSCRIPTION_UPSELL -> true diff --git a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/viewmodel/OnboardingViewModel.kt b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/viewmodel/OnboardingViewModel.kt index 373a5b4..4b16156 100644 --- a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/viewmodel/OnboardingViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/viewmodel/OnboardingViewModel.kt @@ -201,14 +201,14 @@ class OnboardingViewModel : ViewModel() { if (_userIntent.value == OnboardingIntent.JOIN_EXISTING) { OnboardingStep.JOIN_RESIDENCE } else { - OnboardingStep.RESIDENCE_LOCATION + OnboardingStep.HOME_PROFILE } } OnboardingStep.JOIN_RESIDENCE -> { completeOnboarding() OnboardingStep.JOIN_RESIDENCE } - OnboardingStep.RESIDENCE_LOCATION -> OnboardingStep.HOME_PROFILE + OnboardingStep.RESIDENCE_LOCATION -> OnboardingStep.HOME_PROFILE // Skip past if somehow reached OnboardingStep.HOME_PROFILE -> OnboardingStep.FIRST_TASK OnboardingStep.FIRST_TASK -> { completeOnboarding() @@ -253,7 +253,6 @@ class OnboardingViewModel : ViewModel() { fun skipStep() { when (_currentStep.value) { OnboardingStep.VALUE_PROPS, - OnboardingStep.RESIDENCE_LOCATION, OnboardingStep.HOME_PROFILE -> nextStep() OnboardingStep.JOIN_RESIDENCE, OnboardingStep.FIRST_TASK, diff --git a/iosApp/iosApp/Onboarding/OnboardingCoordinator.swift b/iosApp/iosApp/Onboarding/OnboardingCoordinator.swift index 1a85d41..8235438 100644 --- a/iosApp/iosApp/Onboarding/OnboardingCoordinator.swift +++ b/iosApp/iosApp/Onboarding/OnboardingCoordinator.swift @@ -64,8 +64,8 @@ struct OnboardingCoordinator: View { return } - let postalCode = onboardingState.pendingPostalCode.isEmpty ? nil : onboardingState.pendingPostalCode - print("🏠 ONBOARDING: Creating residence with name: \(onboardingState.pendingResidenceName), zip: \(postalCode ?? "none")") + let postalCode: String? = nil + print("🏠 ONBOARDING: Creating residence with name: \(onboardingState.pendingResidenceName)") isCreatingResidence = true @@ -126,7 +126,7 @@ struct OnboardingCoordinator: View { } /// Current step index for progress indicator (0-based) - /// Flow: Welcome → Features → Name → Account → Verify → Location → Home Profile → Tasks → Upsell + /// Flow: Welcome → Features → Name → Account → Verify → Home Profile → Tasks → Upsell private var currentProgressStep: Int { switch onboardingState.currentStep { case .welcome: return 0 @@ -155,7 +155,7 @@ struct OnboardingCoordinator: View { /// Whether to show the skip button private var showSkipButton: Bool { switch onboardingState.currentStep { - case .valueProps, .joinResidence, .residenceLocation, .homeProfile, .firstTask, .subscriptionUpsell: + case .valueProps, .joinResidence, .homeProfile, .firstTask, .subscriptionUpsell: return true default: return false @@ -197,9 +197,6 @@ struct OnboardingCoordinator: View { switch onboardingState.currentStep { case .valueProps: goForward() - case .residenceLocation: - // Skipping location — go to home profile - goForward(to: .homeProfile) case .homeProfile: // Skipping home profile — create residence without profile data, go to tasks createResidenceIfNeeded(thenNavigateTo: .firstTask) @@ -304,7 +301,7 @@ struct OnboardingCoordinator: View { if onboardingState.userIntent == .joinExisting { goForward(to: .joinResidence) } else { - goForward(to: .residenceLocation) + goForward(to: .homeProfile) } } else { goForward() @@ -320,7 +317,7 @@ struct OnboardingCoordinator: View { if onboardingState.userIntent == .joinExisting { goForward(to: .joinResidence) } else { - goForward(to: .residenceLocation) + goForward(to: .homeProfile) } } ) @@ -336,18 +333,10 @@ struct OnboardingCoordinator: View { .transition(navigationTransition) case .residenceLocation: - OnboardingLocationContent( - onLocationDetected: { zip in - // Load regional templates in background - onboardingState.loadRegionalTemplates(zip: zip) - // Go to home profile step (residence created after profile) - goForward() - }, - onSkip: { - // Handled by handleSkip() above - } - ) - .transition(navigationTransition) + // Location step removed — skip to home profile if we land here + EmptyView() + .onAppear { goForward(to: .homeProfile) } + .transition(navigationTransition) case .homeProfile: OnboardingHomeProfileContent( diff --git a/iosApp/iosApp/Onboarding/OnboardingFirstTaskView.swift b/iosApp/iosApp/Onboarding/OnboardingFirstTaskView.swift index ae226c8..a89dd18 100644 --- a/iosApp/iosApp/Onboarding/OnboardingFirstTaskView.swift +++ b/iosApp/iosApp/Onboarding/OnboardingFirstTaskView.swift @@ -53,12 +53,9 @@ struct OnboardingFirstTaskContent: View { /// Cached categories — computed once and stored to preserve stable UUIDs @State private var taskCategoriesCache: [OnboardingTaskCategory]? = nil - /// Uses API-driven regional templates when available, falls back to hardcoded defaults + /// Task categories for the Browse tab private var taskCategories: [OnboardingTaskCategory] { if let cached = taskCategoriesCache { return cached } - if !onboardingState.regionalTemplates.isEmpty { - return categoriesFromAPI(onboardingState.regionalTemplates) - } return fallbackCategories } @@ -297,9 +294,7 @@ struct OnboardingFirstTaskContent: View { .foregroundColor(Color.appTextPrimary) .a11yHeader() - Text(onboardingState.regionalTemplates.isEmpty - ? "Let's get you started with some tasks.\nThe more you pick, the more we'll help you remember!" - : "Here are tasks recommended for your area.\nPick the ones you'd like to track!") + Text("Let's get you started with some tasks.\nThe more you pick, the more we'll help you remember!") .font(.system(size: 15, weight: .medium)) .foregroundColor(Color.appTextSecondary) .multilineTextAlignment(.center) @@ -465,11 +460,7 @@ struct OnboardingFirstTaskContent: View { isAnimating = true // Build and cache categories once to preserve stable UUIDs if taskCategoriesCache == nil { - if !onboardingState.regionalTemplates.isEmpty { - taskCategoriesCache = categoriesFromAPI(onboardingState.regionalTemplates) - } else { - taskCategoriesCache = fallbackCategories - } + taskCategoriesCache = fallbackCategories } // Expand first category by default if let first = taskCategories.first?.name { @@ -485,23 +476,15 @@ struct OnboardingFirstTaskContent: View { private func selectPopularTasks() { withAnimation(.spring(response: 0.3)) { - if !onboardingState.regionalTemplates.isEmpty { - // API templates: select the first tasks (they're ordered by display_order) - for task in allTasks { - selectedTasks.insert(task.id) - } - } else { - // Fallback: select hardcoded popular tasks - let popularTaskTitles = [ - "Change HVAC Filter", - "Test Smoke Detectors", - "Check for Leaks", - "Clean Gutters", - "Clean Refrigerator Coils" - ] - for task in allTasks where popularTaskTitles.contains(task.title) { - selectedTasks.insert(task.id) - } + let popularTaskTitles = [ + "Change HVAC Filter", + "Test Smoke Detectors", + "Check for Leaks", + "Clean Gutters", + "Clean Refrigerator Coils" + ] + for task in allTasks where popularTaskTitles.contains(task.title) { + selectedTasks.insert(task.id) } } } diff --git a/iosApp/iosApp/Onboarding/OnboardingState.swift b/iosApp/iosApp/Onboarding/OnboardingState.swift index b0ceb98..3d5cc1b 100644 --- a/iosApp/iosApp/Onboarding/OnboardingState.swift +++ b/iosApp/iosApp/Onboarding/OnboardingState.swift @@ -36,15 +36,6 @@ class OnboardingState: ObservableObject { /// The ID of the residence created during onboarding (used for task creation) @Published var createdResidenceId: Int32? = nil - /// ZIP code entered during the location step (used for residence creation and regional templates) - @Published var pendingPostalCode: String = "" - - /// Regional task templates loaded from API based on ZIP code - @Published var regionalTemplates: [TaskTemplate] = [] - - /// Whether regional templates are currently loading - @Published var isLoadingTemplates: Bool = false - // MARK: - Home Profile State (collected during onboarding) @Published var pendingHeatingType: String? = nil @@ -80,20 +71,6 @@ class OnboardingState: ObservableObject { private init() {} - /// Load regional task templates from the backend for the given ZIP code - func loadRegionalTemplates(zip: String) { - pendingPostalCode = zip - isLoadingTemplates = true - Task { - defer { self.isLoadingTemplates = false } - let result = try await APILayer.shared.getRegionalTemplates(state: nil, zip: zip) - if let success = result as? ApiResultSuccess, - let templates = success.data as? [TaskTemplate] { - self.regionalTemplates = templates - } - } - } - /// Start the onboarding flow func startOnboarding() { isOnboardingActive = true @@ -102,7 +79,7 @@ class OnboardingState: ObservableObject { } /// Move to the next step in the flow - /// Order: Welcome → Features → Name → Account → Verify → Location → Tasks → Upsell + /// Order: Welcome → Features → Name → Account → Verify → Home Profile → Tasks → Upsell func nextStep() { switch currentStep { case .welcome: @@ -121,11 +98,12 @@ class OnboardingState: ObservableObject { if userIntent == .joinExisting { currentStep = .joinResidence } else { - currentStep = .residenceLocation + currentStep = .homeProfile } case .joinResidence: completeOnboarding() case .residenceLocation: + // Skip past this step if we somehow land here currentStep = .homeProfile case .homeProfile: currentStep = .firstTask @@ -152,8 +130,6 @@ class OnboardingState: ObservableObject { hasCompletedOnboarding = true isOnboardingActive = false pendingResidenceName = "" - pendingPostalCode = "" - regionalTemplates = [] createdResidenceId = nil userIntent = .unknown resetHomeProfile() @@ -165,8 +141,6 @@ class OnboardingState: ObservableObject { hasCompletedOnboarding = false isOnboardingActive = false pendingResidenceName = "" - pendingPostalCode = "" - regionalTemplates = [] createdResidenceId = nil userIntent = .unknown currentStep = .welcome