feat: add sorting functionality to KanbanFilters

- Enhanced `KanbanFilters` to include sorting options, allowing users to sort tasks dynamically.
- Implemented dropdown for sorting with options rendered via portal to manage z-index issues.
- Updated `TasksContext` to handle sorting preferences and apply sorting logic to both pinned and regular tasks.
- Added `sortBy` property to `KanbanFilters` and user preferences for persistent sorting settings.
This commit is contained in:
Julien Froidefond
2025-09-15 08:32:01 +02:00
parent d681a6c127
commit c8cacf1714
4 changed files with 357 additions and 17 deletions

View File

@@ -7,6 +7,7 @@ import { userPreferencesService } from '@/services/user-preferences';
import { Task, Tag } from '@/lib/types';
import { CreateTaskData, UpdateTaskData, TaskFilters } from '@/clients/tasks-client';
import { KanbanFilters } from '@/components/kanban/KanbanFilters';
import { sortTasks, getSortOption, DEFAULT_SORT, createSortKey } from '@/lib/sort-config';
interface TasksContextType {
tasks: Task[];
@@ -69,6 +70,7 @@ export function TasksProvider({ children, initialTasks, initialStats, initialTag
tags: savedFilters.tags,
priorities: savedFilters.priorities,
showCompleted: savedFilters.showCompleted,
sortBy: savedFilters.sortBy || createSortKey('priority', 'desc'), // Tri par défaut
compactView: savedViewPrefs.compactView,
swimlanesByTags: savedViewPrefs.swimlanesByTags
});
@@ -83,7 +85,8 @@ export function TasksProvider({ children, initialTasks, initialStats, initialTag
search: newFilters.search,
tags: newFilters.tags,
priorities: newFilters.priorities,
showCompleted: newFilters.showCompleted
showCompleted: newFilters.showCompleted,
sortBy: newFilters.sortBy
});
// Sauvegarder les préférences de vue
@@ -94,7 +97,7 @@ export function TasksProvider({ children, initialTasks, initialStats, initialTag
});
};
// Séparer les tâches épinglées (objectifs) des autres
// Séparer les tâches épinglées (objectifs) des autres et les trier
const { pinnedTasks, regularTasks } = useMemo(() => {
const pinnedTagNames = tags.filter(tag => tag.isPinned).map(tag => tag.name);
@@ -110,10 +113,20 @@ export function TasksProvider({ children, initialTasks, initialStats, initialTag
}
});
return { pinnedTasks: pinned, regularTasks: regular };
}, [tasksState.tasks, tags]);
// Trier les tâches épinglées avec le même tri que les autres
const sortedPinned = kanbanFilters.sortBy ?
(() => {
const sortOption = getSortOption(kanbanFilters.sortBy);
return sortOption ?
sortTasks(pinned, [{ field: sortOption.field, direction: sortOption.direction }]) :
sortTasks(pinned, DEFAULT_SORT);
})() :
sortTasks(pinned, DEFAULT_SORT);
return { pinnedTasks: sortedPinned, regularTasks: regular };
}, [tasksState.tasks, tags, kanbanFilters.sortBy]);
// Filtrage des tâches régulières (pas les épinglées)
// Filtrage et tri des tâches régulières (pas les épinglées)
const filteredTasks = useMemo(() => {
let filtered = regularTasks;
@@ -143,6 +156,20 @@ export function TasksProvider({ children, initialTasks, initialStats, initialTag
);
}
// Tri des tâches
if (kanbanFilters.sortBy) {
const sortOption = getSortOption(kanbanFilters.sortBy);
if (sortOption) {
filtered = sortTasks(filtered, [{
field: sortOption.field,
direction: sortOption.direction
}]);
}
} else {
// Tri par défaut (priorité desc + tags asc)
filtered = sortTasks(filtered, DEFAULT_SORT);
}
return filtered;
}, [regularTasks, kanbanFilters]);