Wire onboarding task suggestions to backend, delete hardcoded catalog
Both "For You" and "Browse All" tabs are now fully server-driven on iOS and Android. No on-device task list, no client-side scoring rules. When the API fails the screen shows error + Retry + Skip so onboarding can still complete on a flaky network. Shared (KMM) - TaskCreateRequest + TaskResponse carry templateId - New BulkCreateTasksRequest/Response, TaskApi.bulkCreateTasks, APILayer.bulkCreateTasks (updates DataManager + TotalSummary) - OnboardingViewModel: templatesGroupedState + loadTemplatesGrouped; createTasks(residenceId, requests) posts once via the bulk path - Deleted regional-template plumbing: APILayer.getRegionalTemplates, OnboardingViewModel.loadRegionalTemplates, TaskTemplateApi. getTemplatesByRegion, TaskTemplate.regionId/regionName - 5 new AnalyticsEvents constants for the onboarding funnel Android (Compose) - OnboardingFirstTaskContent rewritten against the server catalog; ~70 lines of hardcoded taskCategories gone. Loading / Error / Empty panes with Retry + Skip buttons. Category icons derived from name keywords, colours from a 5-value palette keyed by category id - Browse selection carries template.id into the bulk request so task_template_id is populated server-side iOS (SwiftUI) - New OnboardingTasksViewModel (@MainActor ObservableObject) wrapping APILayer.shared for suggestions / grouped / bulk-submit with loading + error state (mirrors the TaskViewModel.swift pattern) - OnboardingFirstTaskView rewritten: buildForYouSuggestions (130 lines) and fallbackCategories (68 lines) deleted; both tabs show the same error+skip UX as Android; ForYouSuggestion/SuggestionRelevance gone - 5 new AnalyticsEvent cases with identical PostHog event names to the Kotlin constants so cross-platform funnels join cleanly - Existing TaskCreateRequest / TaskResponse call sites in TaskCard, TasksSection, TaskFormView updated for the new templateId parameter Docs - CLAUDE.md gains an "Onboarding task suggestions (server-driven)" subsection covering the data flow, key files on both platforms, and the KotlinInt(int: template.id) wrapping requirement Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
42
CLAUDE.md
42
CLAUDE.md
@@ -1219,6 +1219,48 @@ val CURRENT_ENV = Environment.DEV // or Environment.LOCAL
|
||||
3. Add method to relevant ViewModel that calls APILayer
|
||||
4. Update UI to observe the new StateFlow
|
||||
|
||||
### Onboarding task suggestions (server-driven)
|
||||
|
||||
The First-Task onboarding screen is **fully server-driven** on both
|
||||
platforms. There is no hardcoded catalog or client-side suggestion rules;
|
||||
when the API fails the screen shows error + Retry + Skip.
|
||||
|
||||
**Data flow:**
|
||||
|
||||
```
|
||||
"For You" tab → APILayer.getTaskSuggestions(residenceId)
|
||||
→ GET /api/tasks/suggestions/?residence_id=X
|
||||
→ scored against 15 home-profile fields (incl. climate zone)
|
||||
|
||||
"Browse All" tab → APILayer.getTaskTemplatesGrouped()
|
||||
→ GET /api/tasks/templates/grouped/
|
||||
→ cached on DataManager.taskTemplatesGrouped (24h TTL)
|
||||
|
||||
Submit → APILayer.bulkCreateTasks(BulkCreateTasksRequest)
|
||||
→ POST /api/tasks/bulk/
|
||||
→ single DB transaction, all-or-nothing
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
|
||||
- Shared ViewModel: `composeApp/.../viewmodel/OnboardingViewModel.kt`
|
||||
(`suggestionsState`, `templatesGroupedState`, `createTasks`)
|
||||
- Android screen: `composeApp/.../ui/screens/onboarding/OnboardingFirstTaskContent.kt`
|
||||
- iOS Swift wrapper: `iosApp/iosApp/Onboarding/OnboardingTasksViewModel.swift`
|
||||
(mirrors the Kotlin ViewModel but calls `APILayer.shared` directly in
|
||||
Swift rather than observing Kotlin StateFlows — matches the convention in
|
||||
`iosApp/iosApp/Task/TaskViewModel.swift`)
|
||||
- iOS view: `iosApp/iosApp/Onboarding/OnboardingFirstTaskView.swift`
|
||||
- Analytics: 5 shared event names in `AnalyticsEvents` (Kotlin) +
|
||||
`AnalyticsEvent` (Swift) — `onboarding_suggestions_loaded`,
|
||||
`onboarding_suggestion_accepted`, `onboarding_browse_template_accepted`,
|
||||
`onboarding_tasks_created`, `onboarding_task_step_skipped`.
|
||||
|
||||
**When selecting a template from either tab**, always populate
|
||||
`TaskCreateRequest.templateId` with the backend `TaskTemplate.id` so the
|
||||
created task carries the template backlink for reporting. Swift wraps the
|
||||
id as `KotlinInt(int: template.id)`.
|
||||
|
||||
### Handling Platform-Specific Code
|
||||
|
||||
Use `expect/actual` pattern:
|
||||
|
||||
Reference in New Issue
Block a user