feat: [#22] vue Scheduled (tâches planifiées groupées par date : aujourd'hui, demain, cette semaine, plus tard)
This commit is contained in:
@@ -0,0 +1,56 @@
|
|||||||
|
package com.planify.mobile.ui.scheduled
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.CalendarMonth
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
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 ScheduledScreen(
|
||||||
|
onTaskClick: (Task) -> Unit,
|
||||||
|
viewModel: ScheduledViewModel = hiltViewModel(),
|
||||||
|
) {
|
||||||
|
val groups by viewModel.groups.collectAsState()
|
||||||
|
|
||||||
|
if (groups.isEmpty()) {
|
||||||
|
EmptyState(
|
||||||
|
icon = Icons.Outlined.CalendarMonth,
|
||||||
|
title = "Aucune tâche planifiée",
|
||||||
|
subtitle = "Les tâches avec une date d'échéance apparaîtront ici",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
||||||
|
groups.forEach { group ->
|
||||||
|
item(key = group.label) {
|
||||||
|
Text(
|
||||||
|
text = group.label,
|
||||||
|
style = MaterialTheme.typography.titleSmall,
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
items(group.tasks, key = { it.id }) { task ->
|
||||||
|
TaskRow(
|
||||||
|
task = task,
|
||||||
|
onClick = { onTaskClick(task) },
|
||||||
|
onCheckedChange = { viewModel.toggleTask(task) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package com.planify.mobile.ui.scheduled
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.planify.mobile.domain.model.Task
|
||||||
|
import com.planify.mobile.domain.repository.TaskRepository
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import java.time.LocalDate
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
data class ScheduledGroup(val label: String, val tasks: List<Task>)
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class ScheduledViewModel @Inject constructor(
|
||||||
|
private val taskRepository: TaskRepository,
|
||||||
|
) : ViewModel() {
|
||||||
|
|
||||||
|
val groups = taskRepository.getScheduledTasks()
|
||||||
|
.map { tasks -> groupByDate(tasks) }
|
||||||
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), emptyList())
|
||||||
|
|
||||||
|
private fun groupByDate(tasks: List<Task>): List<ScheduledGroup> {
|
||||||
|
val today = LocalDate.now()
|
||||||
|
val tomorrow = today.plusDays(1)
|
||||||
|
val endOfWeek = today.plusDays(7)
|
||||||
|
|
||||||
|
val buckets = linkedMapOf(
|
||||||
|
"Aujourd'hui" to mutableListOf<Task>(),
|
||||||
|
"Demain" to mutableListOf(),
|
||||||
|
"Cette semaine" to mutableListOf(),
|
||||||
|
"Plus tard" to mutableListOf(),
|
||||||
|
)
|
||||||
|
|
||||||
|
for (task in tasks) {
|
||||||
|
val date = runCatching { LocalDate.parse(task.dueDate?.date ?: "") }.getOrNull() ?: continue
|
||||||
|
when {
|
||||||
|
date == today -> buckets["Aujourd'hui"]!!.add(task)
|
||||||
|
date == tomorrow -> buckets["Demain"]!!.add(task)
|
||||||
|
date <= endOfWeek -> buckets["Cette semaine"]!!.add(task)
|
||||||
|
else -> buckets["Plus tard"]!!.add(task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buckets.entries
|
||||||
|
.filter { it.value.isNotEmpty() }
|
||||||
|
.map { ScheduledGroup(it.key, it.value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toggleTask(task: Task) {
|
||||||
|
viewModelScope.launch { taskRepository.checkTask(task.id, !task.checked) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteTask(task: Task) {
|
||||||
|
viewModelScope.launch { taskRepository.deleteTask(task.id) }
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user