diff --git a/composeApp/src/androidUnitTest/roborazzi/animation_testing_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/animation_testing_empty_dark.png index 0b96c48..15c4e71 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/animation_testing_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/animation_testing_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/animation_testing_empty_light.png b/composeApp/src/androidUnitTest/roborazzi/animation_testing_empty_light.png index 94db015..5d048ac 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/animation_testing_empty_light.png and b/composeApp/src/androidUnitTest/roborazzi/animation_testing_empty_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/animation_testing_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/animation_testing_populated_dark.png index 0b96c48..15c4e71 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/animation_testing_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/animation_testing_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/animation_testing_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/animation_testing_populated_light.png index 94db015..5d048ac 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/animation_testing_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/animation_testing_populated_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/biometric_lock_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/biometric_lock_empty_dark.png index 127d3fb..cc67f43 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/biometric_lock_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/biometric_lock_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/biometric_lock_empty_light.png b/composeApp/src/androidUnitTest/roborazzi/biometric_lock_empty_light.png index 3976d77..b06c5f1 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/biometric_lock_empty_light.png and b/composeApp/src/androidUnitTest/roborazzi/biometric_lock_empty_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/biometric_lock_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/biometric_lock_populated_dark.png index 127d3fb..cc67f43 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/biometric_lock_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/biometric_lock_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/biometric_lock_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/biometric_lock_populated_light.png index 3976d77..b06c5f1 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/biometric_lock_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/biometric_lock_populated_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/contractor_detail_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/contractor_detail_empty_dark.png index 1f45c42..b66067c 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/contractor_detail_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/contractor_detail_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/contractor_detail_empty_light.png b/composeApp/src/androidUnitTest/roborazzi/contractor_detail_empty_light.png index 3e26a74..7565e8d 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/contractor_detail_empty_light.png and b/composeApp/src/androidUnitTest/roborazzi/contractor_detail_empty_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/contractor_detail_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/contractor_detail_populated_dark.png index 1f45c42..b66067c 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/contractor_detail_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/contractor_detail_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/contractor_detail_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/contractor_detail_populated_light.png index d8d8520..907ce8b 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/contractor_detail_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/contractor_detail_populated_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/contractors_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/contractors_empty_dark.png index 3e649b9..9d8f964 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/contractors_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/contractors_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/contractors_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/contractors_populated_dark.png index 9736a1c..9d8f964 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/contractors_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/contractors_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/contractors_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/contractors_populated_light.png index ac404c6..61eb47a 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/contractors_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/contractors_populated_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/document_detail_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/document_detail_empty_dark.png index f0bbe76..997472d 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/document_detail_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/document_detail_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/document_detail_empty_light.png b/composeApp/src/androidUnitTest/roborazzi/document_detail_empty_light.png index 03e6454..f9ffae1 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/document_detail_empty_light.png and b/composeApp/src/androidUnitTest/roborazzi/document_detail_empty_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/document_detail_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/document_detail_populated_dark.png index f0bbe76..997472d 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/document_detail_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/document_detail_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/document_detail_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/document_detail_populated_light.png index 3d2b509..30e401b 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/document_detail_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/document_detail_populated_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/documents_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/documents_empty_dark.png index 47082ea..1048884 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/documents_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/documents_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/documents_empty_light.png b/composeApp/src/androidUnitTest/roborazzi/documents_empty_light.png index 10421a9..7c02b7c 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/documents_empty_light.png and b/composeApp/src/androidUnitTest/roborazzi/documents_empty_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/documents_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/documents_populated_dark.png index 47082ea..b431721 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/documents_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/documents_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/documents_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/documents_populated_light.png index 10421a9..23deac3 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/documents_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/documents_populated_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/feature_comparison_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/feature_comparison_empty_dark.png index b976804..35d72c0 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/feature_comparison_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/feature_comparison_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/feature_comparison_empty_light.png b/composeApp/src/androidUnitTest/roborazzi/feature_comparison_empty_light.png index 9e8d9ea..bd7b912 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/feature_comparison_empty_light.png and b/composeApp/src/androidUnitTest/roborazzi/feature_comparison_empty_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/feature_comparison_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/feature_comparison_populated_dark.png index b976804..35d72c0 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/feature_comparison_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/feature_comparison_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/feature_comparison_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/feature_comparison_populated_light.png index 9e8d9ea..bd7b912 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/feature_comparison_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/feature_comparison_populated_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/notification_preferences_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/notification_preferences_empty_dark.png index 711911b..a6ae19f 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/notification_preferences_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/notification_preferences_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/notification_preferences_empty_light.png b/composeApp/src/androidUnitTest/roborazzi/notification_preferences_empty_light.png index 30bac63..73a8dfd 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/notification_preferences_empty_light.png and b/composeApp/src/androidUnitTest/roborazzi/notification_preferences_empty_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/notification_preferences_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/notification_preferences_populated_dark.png index 711911b..a6ae19f 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/notification_preferences_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/notification_preferences_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/notification_preferences_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/notification_preferences_populated_light.png index 30bac63..73a8dfd 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/notification_preferences_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/notification_preferences_populated_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/profile_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/profile_empty_dark.png index b5d7938..4042051 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/profile_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/profile_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/profile_empty_light.png b/composeApp/src/androidUnitTest/roborazzi/profile_empty_light.png index a737531..5707abb 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/profile_empty_light.png and b/composeApp/src/androidUnitTest/roborazzi/profile_empty_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/profile_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/profile_populated_dark.png index d92bbb4..3075ec6 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/profile_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/profile_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/profile_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/profile_populated_light.png index 56797bd..895d773 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/profile_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/profile_populated_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/residence_detail_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/residence_detail_empty_dark.png index 67823da..9acadc1 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/residence_detail_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/residence_detail_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/residence_detail_empty_light.png b/composeApp/src/androidUnitTest/roborazzi/residence_detail_empty_light.png index f7c9caa..5b1fce5 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/residence_detail_empty_light.png and b/composeApp/src/androidUnitTest/roborazzi/residence_detail_empty_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/residence_detail_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/residence_detail_populated_dark.png index 67823da..35ad299 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/residence_detail_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/residence_detail_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/residence_detail_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/residence_detail_populated_light.png index ddd4871..d900ce5 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/residence_detail_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/residence_detail_populated_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/residences_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/residences_populated_dark.png index c752182..b19ec2b 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/residences_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/residences_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/residences_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/residences_populated_light.png index ac41106..c29cd95 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/residences_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/residences_populated_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/task_templates_browser_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/task_templates_browser_empty_dark.png index 7c94bc7..f2db3fb 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/task_templates_browser_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/task_templates_browser_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/task_templates_browser_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/task_templates_browser_populated_dark.png index 6258ce1..303cb99 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/task_templates_browser_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/task_templates_browser_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/tasks_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/tasks_empty_dark.png index 9d6e389..4cac08b 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/tasks_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/tasks_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/tasks_empty_light.png b/composeApp/src/androidUnitTest/roborazzi/tasks_empty_light.png index 5e9f392..4909bb7 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/tasks_empty_light.png and b/composeApp/src/androidUnitTest/roborazzi/tasks_empty_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/tasks_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/tasks_populated_light.png index 5dd4bd0..4909bb7 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/tasks_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/tasks_populated_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/theme_selection_empty_dark.png b/composeApp/src/androidUnitTest/roborazzi/theme_selection_empty_dark.png index f6504ec..4bb2b38 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/theme_selection_empty_dark.png and b/composeApp/src/androidUnitTest/roborazzi/theme_selection_empty_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/theme_selection_empty_light.png b/composeApp/src/androidUnitTest/roborazzi/theme_selection_empty_light.png index 69dfc93..2e75add 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/theme_selection_empty_light.png and b/composeApp/src/androidUnitTest/roborazzi/theme_selection_empty_light.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/theme_selection_populated_dark.png b/composeApp/src/androidUnitTest/roborazzi/theme_selection_populated_dark.png index f6504ec..4bb2b38 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/theme_selection_populated_dark.png and b/composeApp/src/androidUnitTest/roborazzi/theme_selection_populated_dark.png differ diff --git a/composeApp/src/androidUnitTest/roborazzi/theme_selection_populated_light.png b/composeApp/src/androidUnitTest/roborazzi/theme_selection_populated_light.png index 69dfc93..2e75add 100644 Binary files a/composeApp/src/androidUnitTest/roborazzi/theme_selection_populated_light.png and b/composeApp/src/androidUnitTest/roborazzi/theme_selection_populated_light.png differ diff --git a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/data/DataManager.kt b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/data/DataManager.kt index c59f629..ae49278 100644 --- a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/data/DataManager.kt +++ b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/data/DataManager.kt @@ -141,6 +141,9 @@ object DataManager : IDataManager { private val _tasksByResidence = MutableStateFlow>(emptyMap()) override val tasksByResidence: StateFlow> = _tasksByResidence.asStateFlow() + private val _taskCompletions = MutableStateFlow>>(emptyMap()) + override val taskCompletions: StateFlow>> = _taskCompletions.asStateFlow() + // ==================== DOCUMENTS ==================== private val _documents = MutableStateFlow>(emptyList()) @@ -149,12 +152,21 @@ object DataManager : IDataManager { private val _documentsByResidence = MutableStateFlow>>(emptyMap()) override val documentsByResidence: StateFlow>> = _documentsByResidence.asStateFlow() + private val _documentDetail = MutableStateFlow>(emptyMap()) + override val documentDetail: StateFlow> = _documentDetail.asStateFlow() + // ==================== CONTRACTORS ==================== // Stores ContractorSummary for list views (lighter weight than full Contractor) private val _contractors = MutableStateFlow>(emptyList()) override val contractors: StateFlow> = _contractors.asStateFlow() + private val _contractorsByResidence = MutableStateFlow>>(emptyMap()) + override val contractorsByResidence: StateFlow>> = _contractorsByResidence.asStateFlow() + + private val _contractorDetail = MutableStateFlow>(emptyMap()) + override val contractorDetail: StateFlow> = _contractorDetail.asStateFlow() + // ==================== SUBSCRIPTION ==================== private val _subscription = MutableStateFlow(null) @@ -451,6 +463,11 @@ object DataManager : IDataManager { persistToDisk() } + /** Populate the per-task completion cache (used by TaskViewModel's derived flow). */ + fun setTaskCompletions(taskId: Int, completions: List) { + _taskCompletions.value = _taskCompletions.value + (taskId to completions) + } + /** * Filter cached allTasks by residence ID to avoid separate API call. * Returns null if allTasks not cached. @@ -557,6 +574,12 @@ object DataManager : IDataManager { persistToDisk() } + /** Populate the per-document detail cache (used by DocumentViewModel's derived flow). */ + fun setDocumentDetail(document: Document) { + val id = document.id ?: return + _documentDetail.value = _documentDetail.value + (id to document) + } + /** * Add a new document to the cache. * Caches affected: _documents, _documentsByResidence[residenceId] @@ -606,6 +629,16 @@ object DataManager : IDataManager { persistToDisk() } + /** Populate the per-residence contractor cache. */ + fun setContractorsForResidence(residenceId: Int, contractors: List) { + _contractorsByResidence.value = _contractorsByResidence.value + (residenceId to contractors) + } + + /** Populate the per-contractor detail cache (used by ContractorViewModel's derived flow). */ + fun setContractorDetail(contractor: com.tt.honeyDue.models.Contractor) { + _contractorDetail.value = _contractorDetail.value + (contractor.id to contractor) + } + fun addContractor(contractor: ContractorSummary) { _contractors.value = _contractors.value + contractor persistToDisk() diff --git a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/data/IDataManager.kt b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/data/IDataManager.kt index e924085..930eea6 100644 --- a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/data/IDataManager.kt +++ b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/data/IDataManager.kt @@ -65,16 +65,28 @@ interface IDataManager { /** Kanban board cache keyed by residence id. */ val tasksByResidence: StateFlow> + /** Task completions keyed by task id. Populated by APILayer.getTaskCompletions. */ + val taskCompletions: StateFlow>> + // ==================== DOCUMENTS ==================== val documents: StateFlow> val documentsByResidence: StateFlow>> + /** Document detail (full Document with user+images) cached by id. Populated by APILayer.getDocument. */ + val documentDetail: StateFlow> + // ==================== CONTRACTORS ==================== val contractors: StateFlow> + /** Contractor list per residence id (from residence-scoped fetches). */ + val contractorsByResidence: StateFlow>> + + /** Contractor detail (full Contractor with user association) cached by id. Populated by APILayer.getContractor. */ + val contractorDetail: StateFlow> + // ==================== SUBSCRIPTION ==================== /** Observed by [com.tt.honeyDue.ui.screens.ProfileScreen]. */ diff --git a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/network/APILayer.kt b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/network/APILayer.kt index 5c81c83..3c22dd9 100644 --- a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/network/APILayer.kt +++ b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/network/APILayer.kt @@ -844,7 +844,11 @@ object APILayer { */ suspend fun getTaskCompletions(taskId: Int): ApiResult> { val token = getToken() ?: return ApiResult.Error("Not authenticated", 401) - return taskApi.getTaskCompletions(token, taskId) + val result = taskApi.getTaskCompletions(token, taskId) + if (result is ApiResult.Success) { + DataManager.setTaskCompletions(taskId, result.data) + } + return result } // ==================== Document Operations ==================== @@ -903,6 +907,7 @@ object APILayer { // Update DataManager on success if (result is ApiResult.Success) { DataManager.updateDocument(result.data) + DataManager.setDocumentDetail(result.data) } return result @@ -1069,6 +1074,7 @@ object APILayer { // Update the summary in DataManager on success if (result is ApiResult.Success) { DataManager.updateContractor(result.data) + DataManager.setContractorDetail(result.data) } return result @@ -1127,6 +1133,7 @@ object APILayer { if (!forceRefresh && DataManager.isCacheValid(DataManager.contractorsCacheTime)) { val cachedContractors = DataManager.contractors.value val filtered = cachedContractors.filter { it.residenceId == residenceId } + DataManager.setContractorsForResidence(residenceId, filtered) return ApiResult.Success(filtered) } @@ -1138,6 +1145,7 @@ object APILayer { DataManager.setContractors(result.data) // Now filter from the fresh cache val filtered = result.data.filter { it.residenceId == residenceId } + DataManager.setContractorsForResidence(residenceId, filtered) return ApiResult.Success(filtered) } return result as ApiResult> @@ -1145,6 +1153,7 @@ object APILayer { // Fallback: filter from cache val filtered = DataManager.contractors.value.filter { it.residenceId == residenceId } + DataManager.setContractorsForResidence(residenceId, filtered) return ApiResult.Success(filtered) } diff --git a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/testing/FixtureDataManager.kt b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/testing/FixtureDataManager.kt index 31b5ca8..714ce53 100644 --- a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/testing/FixtureDataManager.kt +++ b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/testing/FixtureDataManager.kt @@ -82,7 +82,13 @@ object FixtureDataManager { }, documents = Fixtures.documents, documentsByResidence = Fixtures.documentsByResidence, + documentDetail = Fixtures.documents.associateBy { it.id ?: 0 }.filterKeys { it != 0 }, contractors = Fixtures.contractorSummaries, + contractorsByResidence = Fixtures.residences.associate { r -> + r.id to Fixtures.contractorSummaries.filter { it.residenceId == r.id } + }, + contractorDetail = Fixtures.contractors.associateBy { it.id }, + taskCompletions = emptyMap(), // Fixtures doesn't define task completions; leave empty subscription = Fixtures.premiumSubscription, upgradeTriggers = emptyMap(), featureBenefits = Fixtures.featureBenefits, diff --git a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/testing/InMemoryDataManager.kt b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/testing/InMemoryDataManager.kt index bac8038..c9645a6 100644 --- a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/testing/InMemoryDataManager.kt +++ b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/testing/InMemoryDataManager.kt @@ -43,9 +43,13 @@ class InMemoryDataManager( residenceSummaries: Map = emptyMap(), allTasks: TaskColumnsResponse? = null, tasksByResidence: Map = emptyMap(), + taskCompletions: Map> = emptyMap(), documents: List = emptyList(), documentsByResidence: Map> = emptyMap(), + documentDetail: Map = emptyMap(), contractors: List = emptyList(), + contractorsByResidence: Map> = emptyMap(), + contractorDetail: Map = emptyMap(), subscription: SubscriptionStatus? = null, upgradeTriggers: Map = emptyMap(), featureBenefits: List = emptyList(), @@ -74,15 +78,19 @@ class InMemoryDataManager( override val allTasks: StateFlow = MutableStateFlow(allTasks) override val tasksByResidence: StateFlow> = MutableStateFlow(tasksByResidence) + override val taskCompletions: StateFlow>> = MutableStateFlow(taskCompletions) // ==================== DOCUMENTS ==================== override val documents: StateFlow> = MutableStateFlow(documents) override val documentsByResidence: StateFlow>> = MutableStateFlow(documentsByResidence) + override val documentDetail: StateFlow> = MutableStateFlow(documentDetail) // ==================== CONTRACTORS ==================== override val contractors: StateFlow> = MutableStateFlow(contractors) + override val contractorsByResidence: StateFlow>> = MutableStateFlow(contractorsByResidence) + override val contractorDetail: StateFlow> = MutableStateFlow(contractorDetail) // ==================== SUBSCRIPTION ====================