Smart onboarding: home profile, tabbed tasks, free app

New onboarding step: "Tell us about your home" with chip-based pickers
for systems (heating/cooling/water heater), features (pool, fireplace,
garage, etc.), exterior (roof, siding), interior (flooring, landscaping).
All optional, skippable.

Tabbed task selection: "For You" tab shows personalized suggestions
based on home profile, "Browse All" has existing category browser.
Removed 5-task limit — users can add unlimited tasks.

Removed subscription upsell from onboarding flow — app is free.
Fixed picker capsule squishing bug with .fixedSize() modifier.

Both iOS and Compose implementations updated.
This commit is contained in:
Trey T
2026-03-30 09:02:27 -05:00
parent 8f86fa2cd0
commit 4609d5a953
18 changed files with 2293 additions and 266 deletions

View File

@@ -53,6 +53,20 @@ data class ResidenceResponse(
@SerialName("is_active") val isActive: Boolean = true,
@SerialName("overdue_count") val overdueCount: Int = 0,
@SerialName("completion_summary") val completionSummary: CompletionSummary? = null,
@SerialName("heating_type") val heatingType: String? = null,
@SerialName("cooling_type") val coolingType: String? = null,
@SerialName("water_heater_type") val waterHeaterType: String? = null,
@SerialName("roof_type") val roofType: String? = null,
@SerialName("has_pool") val hasPool: Boolean = false,
@SerialName("has_sprinkler_system") val hasSprinklerSystem: Boolean = false,
@SerialName("has_septic") val hasSeptic: Boolean = false,
@SerialName("has_fireplace") val hasFireplace: Boolean = false,
@SerialName("has_garage") val hasGarage: Boolean = false,
@SerialName("has_basement") val hasBasement: Boolean = false,
@SerialName("has_attic") val hasAttic: Boolean = false,
@SerialName("exterior_type") val exteriorType: String? = null,
@SerialName("flooring_primary") val flooringPrimary: String? = null,
@SerialName("landscaping_type") val landscapingType: String? = null,
@SerialName("created_at") val createdAt: String,
@SerialName("updated_at") val updatedAt: String
) {
@@ -94,7 +108,21 @@ data class ResidenceCreateRequest(
val description: String? = null,
@SerialName("purchase_date") val purchaseDate: String? = null,
@SerialName("purchase_price") val purchasePrice: Double? = null,
@SerialName("is_primary") val isPrimary: Boolean? = null
@SerialName("is_primary") val isPrimary: Boolean? = null,
@SerialName("heating_type") val heatingType: String? = null,
@SerialName("cooling_type") val coolingType: String? = null,
@SerialName("water_heater_type") val waterHeaterType: String? = null,
@SerialName("roof_type") val roofType: String? = null,
@SerialName("has_pool") val hasPool: Boolean? = null,
@SerialName("has_sprinkler_system") val hasSprinklerSystem: Boolean? = null,
@SerialName("has_septic") val hasSeptic: Boolean? = null,
@SerialName("has_fireplace") val hasFireplace: Boolean? = null,
@SerialName("has_garage") val hasGarage: Boolean? = null,
@SerialName("has_basement") val hasBasement: Boolean? = null,
@SerialName("has_attic") val hasAttic: Boolean? = null,
@SerialName("exterior_type") val exteriorType: String? = null,
@SerialName("flooring_primary") val flooringPrimary: String? = null,
@SerialName("landscaping_type") val landscapingType: String? = null
)
/**
@@ -118,7 +146,21 @@ data class ResidenceUpdateRequest(
val description: String? = null,
@SerialName("purchase_date") val purchaseDate: String? = null,
@SerialName("purchase_price") val purchasePrice: Double? = null,
@SerialName("is_primary") val isPrimary: Boolean? = null
@SerialName("is_primary") val isPrimary: Boolean? = null,
@SerialName("heating_type") val heatingType: String? = null,
@SerialName("cooling_type") val coolingType: String? = null,
@SerialName("water_heater_type") val waterHeaterType: String? = null,
@SerialName("roof_type") val roofType: String? = null,
@SerialName("has_pool") val hasPool: Boolean? = null,
@SerialName("has_sprinkler_system") val hasSprinklerSystem: Boolean? = null,
@SerialName("has_septic") val hasSeptic: Boolean? = null,
@SerialName("has_fireplace") val hasFireplace: Boolean? = null,
@SerialName("has_garage") val hasGarage: Boolean? = null,
@SerialName("has_basement") val hasBasement: Boolean? = null,
@SerialName("has_attic") val hasAttic: Boolean? = null,
@SerialName("exterior_type") val exteriorType: String? = null,
@SerialName("flooring_primary") val flooringPrimary: String? = null,
@SerialName("landscaping_type") val landscapingType: String? = null
)
/**