feat(ui) : add deadline/scheduled columns and sort options to Mes tâches page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -186,7 +186,11 @@
|
|||||||
"allAssignees": "Tous",
|
"allAssignees": "Tous",
|
||||||
"noTasks": "Aucune tâche",
|
"noTasks": "Aucune tâche",
|
||||||
"backlog": "Backlog",
|
"backlog": "Backlog",
|
||||||
"createTask": "Créer une tâche"
|
"createTask": "Créer une tâche",
|
||||||
|
"sortBy": "Trier par",
|
||||||
|
"sortDefault": "Par défaut",
|
||||||
|
"sortDeadline": "Échéance",
|
||||||
|
"sortScheduledStart": "Date planifiée"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Tableau de bord",
|
"title": "Tableau de bord",
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ const selectedPriorityId = ref<number | null>(null)
|
|||||||
const selectedEffortId = ref<number | null>(null)
|
const selectedEffortId = ref<number | null>(null)
|
||||||
const selectedAssigneeId = ref<number | null>(auth.user?.id ?? null)
|
const selectedAssigneeId = ref<number | null>(auth.user?.id ?? null)
|
||||||
|
|
||||||
|
// Sort
|
||||||
|
type SortOption = 'default' | 'deadline' | 'scheduledStart'
|
||||||
|
const sortBy = ref<SortOption>('default')
|
||||||
|
|
||||||
// View toggle
|
// View toggle
|
||||||
const viewMode = ref<'kanban' | 'list'>('kanban')
|
const viewMode = ref<'kanban' | 'list'>('kanban')
|
||||||
|
|
||||||
@@ -157,6 +161,11 @@ async function loadTasks() {
|
|||||||
if (selectedTagId.value) {
|
if (selectedTagId.value) {
|
||||||
params['tags[]'] = `/api/task_tags/${selectedTagId.value}`
|
params['tags[]'] = `/api/task_tags/${selectedTagId.value}`
|
||||||
}
|
}
|
||||||
|
if (sortBy.value === 'deadline') {
|
||||||
|
params['order[deadline]'] = 'asc'
|
||||||
|
} else if (sortBy.value === 'scheduledStart') {
|
||||||
|
params['order[scheduledStart]'] = 'asc'
|
||||||
|
}
|
||||||
tasks.value = await taskService.getFiltered(params)
|
tasks.value = await taskService.getFiltered(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,9 +178,9 @@ async function loadAll() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watch filters to reload tasks
|
// Watch filters and sort to reload tasks
|
||||||
watch(
|
watch(
|
||||||
[selectedProjectId, selectedGroupId, selectedTagId, selectedPriorityId, selectedEffortId, selectedAssigneeId],
|
[selectedProjectId, selectedGroupId, selectedTagId, selectedPriorityId, selectedEffortId, selectedAssigneeId, sortBy],
|
||||||
() => { loadTasks() },
|
() => { loadTasks() },
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -311,7 +320,7 @@ onMounted(async () => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="min-w-0">
|
<div class="min-w-0">
|
||||||
<!-- Header + Filters -->
|
<!-- Header + Filters -->
|
||||||
<div class="sticky top-8 z-20 bg-white pb-4 sm:top-12">
|
<div class="sticky top-8 z-20 bg-white pb-4 sm:top-12 dark:bg-dark-base">
|
||||||
<div class="flex items-center justify-between gap-3">
|
<div class="flex items-center justify-between gap-3">
|
||||||
<h1 class="text-xl font-bold text-primary-500 sm:text-2xl">{{ $t('myTasks.title') }}</h1>
|
<h1 class="text-xl font-bold text-primary-500 sm:text-2xl">{{ $t('myTasks.title') }}</h1>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@@ -390,6 +399,17 @@ onMounted(async () => {
|
|||||||
text-field="text-sm"
|
text-field="text-sm"
|
||||||
text-value="text-sm"
|
text-value="text-sm"
|
||||||
/>
|
/>
|
||||||
|
<div class="flex flex-col gap-0.5">
|
||||||
|
<span class="text-xs font-semibold text-neutral-500">{{ $t('myTasks.sortBy') }}</span>
|
||||||
|
<select
|
||||||
|
v-model="sortBy"
|
||||||
|
class="rounded-lg border border-neutral-300 bg-white px-2 py-1.5 text-sm text-neutral-700 focus:outline-none focus:ring-2 focus:ring-primary-500"
|
||||||
|
>
|
||||||
|
<option value="default">{{ $t('myTasks.sortDefault') }}</option>
|
||||||
|
<option value="deadline">{{ $t('myTasks.sortDeadline') }}</option>
|
||||||
|
<option value="scheduledStart">{{ $t('myTasks.sortScheduledStart') }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -400,7 +420,7 @@ onMounted(async () => {
|
|||||||
v-for="status in sortedStatuses"
|
v-for="status in sortedStatuses"
|
||||||
:key="status.id"
|
:key="status.id"
|
||||||
class="flex min-w-36 flex-1 flex-col rounded-lg transition-colors"
|
class="flex min-w-36 flex-1 flex-col rounded-lg transition-colors"
|
||||||
:class="dragOverStatusId === status.id ? 'bg-neutral-200' : 'bg-neutral-50'"
|
:class="dragOverStatusId === status.id ? 'bg-neutral-200 dark:bg-dark-hover' : 'bg-neutral-50 dark:bg-dark-surface/50'"
|
||||||
@dragover.prevent
|
@dragover.prevent
|
||||||
@dragenter.prevent="onDragEnter(status.id)"
|
@dragenter.prevent="onDragEnter(status.id)"
|
||||||
@dragleave="onDragLeave"
|
@dragleave="onDragLeave"
|
||||||
@@ -435,13 +455,13 @@ onMounted(async () => {
|
|||||||
<!-- Backlog below kanban -->
|
<!-- Backlog below kanban -->
|
||||||
<div
|
<div
|
||||||
class="mt-8 rounded-lg p-4 transition-colors"
|
class="mt-8 rounded-lg p-4 transition-colors"
|
||||||
:class="dragOverStatusId === 0 ? 'bg-neutral-200' : 'bg-neutral-50'"
|
:class="dragOverStatusId === 0 ? 'bg-neutral-200 dark:bg-dark-hover' : 'bg-neutral-50 dark:bg-dark-surface'"
|
||||||
@dragover.prevent
|
@dragover.prevent
|
||||||
@dragenter.prevent="onDragEnter(0)"
|
@dragenter.prevent="onDragEnter(0)"
|
||||||
@dragleave="onDragLeave"
|
@dragleave="onDragLeave"
|
||||||
@drop.prevent="onDropBacklog($event)"
|
@drop.prevent="onDropBacklog($event)"
|
||||||
>
|
>
|
||||||
<h2 class="text-lg font-bold text-neutral-900">{{ $t('myTasks.backlog') }} ({{ backlogTasks.length }})</h2>
|
<h2 class="text-lg font-bold text-neutral-900 dark:text-neutral-100">{{ $t('myTasks.backlog') }} ({{ backlogTasks.length }})</h2>
|
||||||
<div class="mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
<div class="mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||||
<TaskCard
|
<TaskCard
|
||||||
v-for="task in backlogTasks"
|
v-for="task in backlogTasks"
|
||||||
@@ -461,7 +481,7 @@ onMounted(async () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- List View -->
|
<!-- List View -->
|
||||||
<div v-if="viewMode === 'list'" class="mt-6 flex flex-col gap-2.5 rounded-[10px] bg-tertiary-500 p-2.5">
|
<div v-if="viewMode === 'list'" class="mt-6 flex flex-col gap-2.5 rounded-[10px] bg-tertiary-500 p-2.5 dark:bg-dark-surface">
|
||||||
<TaskBulkActions
|
<TaskBulkActions
|
||||||
:selected-count="selectedTaskIds.size"
|
:selected-count="selectedTaskIds.size"
|
||||||
:total-count="tasks.length"
|
:total-count="tasks.length"
|
||||||
|
|||||||
Reference in New Issue
Block a user