Files
towercontrol/lib/sort-config.ts
Julien Froidefond c8cacf1714 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.
2025-09-15 08:32:01 +02:00

201 lines
4.5 KiB
TypeScript

import { Task, TaskPriority } from './types';
import { getPriorityConfig } from './status-config';
export type SortField = 'priority' | 'tags' | 'createdAt' | 'updatedAt' | 'dueDate' | 'title';
export type SortDirection = 'asc' | 'desc';
export interface SortConfig {
field: SortField;
direction: SortDirection;
}
export interface SortOption {
key: string;
label: string;
field: SortField;
direction: SortDirection;
icon: string;
}
// Configuration des options de tri disponibles
export const SORT_OPTIONS: SortOption[] = [
{
key: 'priority-desc',
label: 'Priorité (Urgente → Faible)',
field: 'priority',
direction: 'desc',
icon: '🔥'
},
{
key: 'priority-asc',
label: 'Priorité (Faible → Urgente)',
field: 'priority',
direction: 'asc',
icon: '🔵'
},
{
key: 'tags-asc',
label: 'Tags (A → Z)',
field: 'tags',
direction: 'asc',
icon: '🏷️'
},
{
key: 'title-asc',
label: 'Titre (A → Z)',
field: 'title',
direction: 'asc',
icon: '📝'
},
{
key: 'title-desc',
label: 'Titre (Z → A)',
field: 'title',
direction: 'desc',
icon: '📝'
},
{
key: 'createdAt-desc',
label: 'Date création (Récent → Ancien)',
field: 'createdAt',
direction: 'desc',
icon: '📅'
},
{
key: 'createdAt-asc',
label: 'Date création (Ancien → Récent)',
field: 'createdAt',
direction: 'asc',
icon: '📅'
},
{
key: 'dueDate-asc',
label: 'Échéance (Proche → Lointaine)',
field: 'dueDate',
direction: 'asc',
icon: '⏰'
},
{
key: 'dueDate-desc',
label: 'Échéance (Lointaine → Proche)',
field: 'dueDate',
direction: 'desc',
icon: '⏰'
}
];
// Tri par défaut : Priorité (desc) puis Tags (asc)
export const DEFAULT_SORT: SortConfig[] = [
{ field: 'priority', direction: 'desc' },
{ field: 'tags', direction: 'asc' }
];
/**
* Compare deux valeurs selon la direction de tri
*/
function compareValues<T>(a: T, b: T, direction: SortDirection): number {
if (a === b) return 0;
if (a == null) return 1;
if (b == null) return -1;
const result = a < b ? -1 : 1;
return direction === 'asc' ? result : -result;
}
/**
* Obtient la valeur de priorité numérique pour le tri
*/
function getPriorityValue(priority: TaskPriority): number {
return getPriorityConfig(priority).order;
}
/**
* Obtient le premier tag pour le tri (ou chaîne vide si pas de tags)
*/
function getFirstTag(task: Task): string {
return task.tags?.[0]?.toLowerCase() || '';
}
/**
* Compare deux tâches selon un critère de tri
*/
function compareTasksByField(a: Task, b: Task, sortConfig: SortConfig): number {
const { field, direction } = sortConfig;
switch (field) {
case 'priority':
return compareValues(
getPriorityValue(a.priority),
getPriorityValue(b.priority),
direction
);
case 'tags':
return compareValues(
getFirstTag(a),
getFirstTag(b),
direction
);
case 'title':
return compareValues(
a.title.toLowerCase(),
b.title.toLowerCase(),
direction
);
case 'createdAt':
return compareValues(
new Date(a.createdAt).getTime(),
new Date(b.createdAt).getTime(),
direction
);
case 'updatedAt':
return compareValues(
new Date(a.updatedAt).getTime(),
new Date(b.updatedAt).getTime(),
direction
);
case 'dueDate':
return compareValues(
a.dueDate ? new Date(a.dueDate).getTime() : null,
b.dueDate ? new Date(b.dueDate).getTime() : null,
direction
);
default:
return 0;
}
}
/**
* Trie un tableau de tâches selon une configuration de tri multiple
*/
export function sortTasks(tasks: Task[], sortConfigs: SortConfig[] = DEFAULT_SORT): Task[] {
return [...tasks].sort((a, b) => {
for (const sortConfig of sortConfigs) {
const result = compareTasksByField(a, b, sortConfig);
if (result !== 0) {
return result;
}
}
return 0;
});
}
/**
* Utilitaire pour obtenir une option de tri par sa clé
*/
export function getSortOption(key: string): SortOption | undefined {
return SORT_OPTIONS.find(option => option.key === key);
}
/**
* Utilitaire pour créer une clé de tri
*/
export function createSortKey(field: SortField, direction: SortDirection): string {
return `${field}-${direction}`;
}