From 1146b146c0c0e7562fc67643fb8f6291343a9619 Mon Sep 17 00:00:00 2001 From: Gato Date: Sat, 6 Jun 2026 06:39:03 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20[#23]=20vue=20Labels=20(toutes=20les=20?= =?UTF-8?q?t=C3=A2ches=20associ=C3=A9es=20=C3=A0=20un=20label)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../planify/mobile/ui/label/LabelScreen.kt | 46 ++++++++++++++++ .../planify/mobile/ui/label/LabelViewModel.kt | 52 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 app/src/main/java/com/planify/mobile/ui/label/LabelScreen.kt create mode 100644 app/src/main/java/com/planify/mobile/ui/label/LabelViewModel.kt diff --git a/app/src/main/java/com/planify/mobile/ui/label/LabelScreen.kt b/app/src/main/java/com/planify/mobile/ui/label/LabelScreen.kt new file mode 100644 index 0000000..332abd1 --- /dev/null +++ b/app/src/main/java/com/planify/mobile/ui/label/LabelScreen.kt @@ -0,0 +1,46 @@ +package com.planify.mobile.ui.label + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Label +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.hilt.navigation.compose.hiltViewModel +import com.planify.mobile.domain.model.Task +import com.planify.mobile.ui.components.EmptyState +import com.planify.mobile.ui.components.TaskRow + +@Composable +fun LabelScreen( + labelId: String, + onTaskClick: (Task) -> Unit, + viewModel: LabelViewModel = hiltViewModel(), +) { + LaunchedEffect(labelId) { viewModel.init(labelId) } + + val tasks by viewModel.tasks.collectAsState() + + if (tasks.isEmpty()) { + EmptyState( + icon = Icons.Outlined.Label, + title = "Aucune tâche", + subtitle = "Aucune tâche n'est associée à ce label", + ) + return + } + + LazyColumn(modifier = Modifier.fillMaxSize()) { + items(tasks, key = { it.id }) { task -> + TaskRow( + task = task, + onClick = { onTaskClick(task) }, + onCheckedChange = { viewModel.toggleTask(task) }, + ) + } + } +} diff --git a/app/src/main/java/com/planify/mobile/ui/label/LabelViewModel.kt b/app/src/main/java/com/planify/mobile/ui/label/LabelViewModel.kt new file mode 100644 index 0000000..d89c67d --- /dev/null +++ b/app/src/main/java/com/planify/mobile/ui/label/LabelViewModel.kt @@ -0,0 +1,52 @@ +package com.planify.mobile.ui.label + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.planify.mobile.domain.model.Label +import com.planify.mobile.domain.model.Task +import com.planify.mobile.domain.repository.LabelRepository +import com.planify.mobile.domain.repository.TaskRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class LabelViewModel @Inject constructor( + private val taskRepository: TaskRepository, + private val labelRepository: LabelRepository, +) : ViewModel() { + + private val _labelId = MutableStateFlow(null) + + @OptIn(ExperimentalCoroutinesApi::class) + val label = _labelId.flatMapLatest { id -> + if (id == null) flowOf(null) + else labelRepository.getAllLabels().flatMapLatest { labels -> + flowOf(labels.find { it.id == id }) + } + }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null) + + @OptIn(ExperimentalCoroutinesApi::class) + val tasks = label.flatMapLatest { lbl -> + if (lbl == null) flowOf(emptyList()) + else taskRepository.getTasksByLabel(lbl.name) + }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), emptyList()) + + fun init(labelId: String) { + _labelId.value = labelId + } + + fun toggleTask(task: Task) { + viewModelScope.launch { taskRepository.checkTask(task.id, !task.checked) } + } + + fun deleteTask(task: Task) { + viewModelScope.launch { taskRepository.deleteTask(task.id) } + } +}