diff --git a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/viewmodel/ResidenceViewModel.kt b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/viewmodel/ResidenceViewModel.kt index 0991226..7fcea30 100644 --- a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/viewmodel/ResidenceViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/viewmodel/ResidenceViewModel.kt @@ -2,6 +2,7 @@ package com.tt.honeyDue.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.tt.honeyDue.data.DataManager import com.tt.honeyDue.models.Residence import com.tt.honeyDue.models.ResidenceCreateRequest import com.tt.honeyDue.models.TotalSummary @@ -11,7 +12,10 @@ import com.tt.honeyDue.models.ContractorSummary import com.tt.honeyDue.network.ApiResult import com.tt.honeyDue.network.APILayer import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch class ResidenceViewModel : ViewModel() { @@ -28,8 +32,24 @@ class ResidenceViewModel : ViewModel() { private val _updateResidenceState = MutableStateFlow>(ApiResult.Idle) val updateResidenceState: StateFlow> = _updateResidenceState - private val _residenceTasksState = MutableStateFlow>(ApiResult.Idle) - val residenceTasksState: StateFlow> = _residenceTasksState + /// Residence-scoped kanban derived from `DataManager.allTasks` filtered + /// by `_currentResidenceId`. Re-emits whenever either upstream changes, + /// so the residence detail screen reacts to new tasks (created or + /// completed elsewhere) without manual refresh. Replaces the previous + /// imperative `_residenceTasksState` that was only written by + /// loadResidenceTasks's API result and stayed stale otherwise. + private val _currentResidenceId = MutableStateFlow(null) + val residenceTasksState: StateFlow> = + combine(DataManager.allTasks, _currentResidenceId) { all, id -> + when { + id == null -> ApiResult.Idle + all == null -> ApiResult.Loading + else -> { + val filtered = DataManager.getTasksForResidence(id) + if (filtered != null) ApiResult.Success(filtered) else ApiResult.Loading + } + } + }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), ApiResult.Idle) private val _myResidencesState = MutableStateFlow>(ApiResult.Idle) val myResidencesState: StateFlow> = _myResidencesState @@ -85,13 +105,16 @@ class ResidenceViewModel : ViewModel() { } fun resetResidenceTasksState() { - _residenceTasksState.value = ApiResult.Idle + _currentResidenceId.value = null } - fun loadResidenceTasks(residenceId: Int) { + fun loadResidenceTasks(residenceId: Int, forceRefresh: Boolean = false) { + _currentResidenceId.value = residenceId + // Trigger an _allTasks refresh in the background. The combine flow + // above re-emits Success when allTasks lands, so the screen + // re-renders without needing the result here. viewModelScope.launch { - _residenceTasksState.value = ApiResult.Loading - _residenceTasksState.value = APILayer.getTasksByResidence(residenceId) + APILayer.getTasks(forceRefresh = forceRefresh) } }