package com.taskttl.data.viewmodel import androidx.lifecycle.viewModelScope import com.taskttl.core.viewmodel.BaseViewModel import com.taskttl.data.local.model.Category import com.taskttl.data.local.model.CategoryType import com.taskttl.data.local.model.Countdown import com.taskttl.data.repository.CategoryRepository import com.taskttl.data.repository.CountdownRepository import com.taskttl.data.state.CountdownEffect import com.taskttl.data.state.CountdownIntent import com.taskttl.data.state.CountdownState import kotlinx.coroutines.launch import org.jetbrains.compose.resources.getString import taskttl.composeapp.generated.resources.Res import taskttl.composeapp.generated.resources.countdown_add_failed import taskttl.composeapp.generated.resources.countdown_add_success import taskttl.composeapp.generated.resources.countdown_delete_failed import taskttl.composeapp.generated.resources.countdown_delete_success import taskttl.composeapp.generated.resources.countdown_load_failed import taskttl.composeapp.generated.resources.countdown_query_failed import taskttl.composeapp.generated.resources.countdown_update_failed import taskttl.composeapp.generated.resources.countdown_update_success /** * 倒计时视图模型 * @author admin * @date 2025/10/04 * @constructor 创建[CountdownViewModel] * @param [countdownRepository] 倒计时存储库 */ class CountdownViewModel( private val countdownRepository: CountdownRepository, private val categoryRepository: CategoryRepository, ) : BaseViewModel(CountdownState()) { init { processIntent(CountdownIntent.LoadCountdowns) } public override fun handleIntent(intent: CountdownIntent) { when (intent) { is CountdownIntent.LoadCountdowns -> loadCountdowns() is CountdownIntent.GetCountdownById -> getCountdownById(intent.countdownId) is CountdownIntent.AddCountdown -> addCountdown(intent.countdown) is CountdownIntent.UpdateCountdown -> updateCountdown(intent.countdown) is CountdownIntent.DeleteCountdown -> deleteCountdown(intent.countdownId) is CountdownIntent.FilterByCategory -> filterByCategory(intent.category) is CountdownIntent.ClearError -> clearError() } } private fun loadCountdowns() { viewModelScope.launch { updateState { copy(isLoading = true) } try { launch { categoryRepository.getCategoriesByType(CategoryType.COUNTDOWN) .collect { categories -> updateState { copy(categories = categories) } } } launch { countdownRepository.getAllCountdowns().collect { countdowns -> updateState { copy( countdowns = countdowns, filteredCountdowns = filterCountdowns(countdowns) ) } } } } catch (e: Exception) { val errStr = getString(Res.string.countdown_load_failed) updateState { copy(isLoading = false, error = e.message ?: errStr) } } finally { updateState { copy(isLoading = false) } } } } private fun getCountdownById(countdownId: String) { viewModelScope.launch { try { val countdown = countdownRepository.getCountdownById(countdownId) updateState { copy(editingCountdown = countdown) } } catch (e: Exception) { val errStr = getString(Res.string.countdown_query_failed) updateState { copy(isLoading = false, error = e.message ?: errStr) } } } } private fun addCountdown(countdown: Countdown) { viewModelScope.launch { try { if (state.value.isProcessing) return@launch updateState { copy(isLoading = false, isProcessing = true) } countdownRepository.insertCountdown(countdown) sendEvent(CountdownEffect.ShowMessage(getString(Res.string.countdown_add_success))) sendEvent(CountdownEffect.NavigateBack) } catch (e: Exception) { val errStr = getString(Res.string.countdown_add_failed) updateState { copy(error = e.message ?: errStr) } } finally { updateState { copy(isLoading = false, isProcessing = false) } } } } private fun updateCountdown(countdown: Countdown) { viewModelScope.launch { try { if (state.value.isProcessing) return@launch updateState { copy(isLoading = false, isProcessing = true) } countdownRepository.updateCountdown(countdown) sendEvent(CountdownEffect.ShowMessage(getString(Res.string.countdown_update_success))) sendEvent(CountdownEffect.NavigateBack) } catch (e: Exception) { val errStr = getString(Res.string.countdown_update_failed) updateState { copy(error = e.message ?: errStr) } } finally { updateState { copy(isLoading = false, isProcessing = false) } } } } private fun deleteCountdown(countdownId: String) { viewModelScope.launch { try { if (state.value.isProcessing) return@launch updateState { copy(isLoading = false, isProcessing = true) } countdownRepository.deleteCountdown(countdownId) sendEvent(CountdownEffect.ShowMessage(getString(Res.string.countdown_delete_success))) } catch (e: Exception) { val errStr = getString(Res.string.countdown_delete_failed) updateState { copy(error = e.message ?: errStr) } } finally { updateState { copy(isLoading = false, isProcessing = false) } } } } private fun filterByCategory(category: Category?) { updateState { copy( selectedCategory = category, filteredCountdowns = filterCountdowns(state.value.countdowns) ) } } private fun clearError() { updateState { copy(error = null) } } private fun filterCountdowns(countdowns: List): List { val currentState = state.value return countdowns.filter { countdown -> currentState.selectedCategory?.let { countdown.category == it } ?: true } } }