Add Android onboarding flow matching iOS implementation

Implement complete onboarding experience for Android with the following screens:
- Welcome screen with "Start Fresh" and "Join Existing Home" options
- Value props carousel showcasing app features (Tasks, Documents, Contractors, Family)
- Residence naming screen for new property setup
- Account creation with email registration (no Apple Sign In on Android)
- Email verification with 6-digit code
- Join residence screen for share code entry
- First task selection with 6 category templates
- Subscription upsell with monthly/yearly plans

Key implementation details:
- OnboardingViewModel manages all state and API integration
- AnimatedContent provides smooth screen transitions
- HorizontalPager for feature carousel
- Onboarding completion persisted in DataManager
- New users start at onboarding, returning users go to login

Files added:
- OnboardingViewModel.kt
- OnboardingScreen.kt (coordinator)
- OnboardingWelcomeContent.kt
- OnboardingValuePropsContent.kt
- OnboardingNameResidenceContent.kt
- OnboardingCreateAccountContent.kt
- OnboardingVerifyEmailContent.kt
- OnboardingJoinResidenceContent.kt
- OnboardingFirstTaskContent.kt
- OnboardingSubscriptionContent.kt

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-03 17:21:44 -06:00
parent 63a54434ed
commit 43f5b9514f
15 changed files with 3323 additions and 0 deletions

View File

@@ -91,6 +91,11 @@ object DataManager {
private val _themeId = MutableStateFlow("default")
val themeId: StateFlow<String> = _themeId.asStateFlow()
// ==================== ONBOARDING ====================
private val _hasCompletedOnboarding = MutableStateFlow(false)
val hasCompletedOnboarding: StateFlow<Boolean> = _hasCompletedOnboarding.asStateFlow()
// ==================== RESIDENCES ====================
private val _residences = MutableStateFlow<List<Residence>>(emptyList())
@@ -256,6 +261,13 @@ object DataManager {
themeManager?.saveThemeId(id)
}
// ==================== ONBOARDING UPDATE METHODS ====================
fun setHasCompletedOnboarding(completed: Boolean) {
_hasCompletedOnboarding.value = completed
persistenceManager?.save(KEY_HAS_COMPLETED_ONBOARDING, completed.toString())
}
// ==================== RESIDENCE UPDATE METHODS ====================
fun setResidences(residences: List<Residence>) {
@@ -668,6 +680,11 @@ object DataManager {
manager.load(KEY_CURRENT_USER)?.let { data ->
_currentUser.value = json.decodeFromString<User>(data)
}
// Load onboarding completion flag
manager.load(KEY_HAS_COMPLETED_ONBOARDING)?.let { data ->
_hasCompletedOnboarding.value = data.toBooleanStrictOrNull() ?: false
}
} catch (e: Exception) {
println("DataManager: Error loading from disk: ${e.message}")
}
@@ -677,4 +694,5 @@ object DataManager {
// Only user data is persisted - all other data fetched fresh from API
private const val KEY_CURRENT_USER = "dm_current_user"
private const val KEY_HAS_COMPLETED_ONBOARDING = "dm_has_completed_onboarding"
}