diff --git a/components/kanban/ColumnVisibilityToggle.tsx b/components/kanban/ColumnVisibilityToggle.tsx
index fc25c29..0b6ebb1 100644
--- a/components/kanban/ColumnVisibilityToggle.tsx
+++ b/components/kanban/ColumnVisibilityToggle.tsx
@@ -1,37 +1,38 @@
'use client';
import { TaskStatus } from '@/lib/types';
+import { getAllStatuses } from '@/lib/status-config';
interface ColumnVisibilityToggleProps {
- statuses: { id: TaskStatus; title: string; color: string }[];
hiddenStatuses: Set
;
onToggleStatus: (status: TaskStatus) => void;
className?: string;
}
export function ColumnVisibilityToggle({
- statuses,
hiddenStatuses,
onToggleStatus,
className = ""
}: ColumnVisibilityToggleProps) {
+ const statuses = getAllStatuses();
+
return (
Colonnes :
- {statuses.map(status => (
+ {statuses.map(statusConfig => (
))}
diff --git a/components/kanban/SwimlanesBoard.tsx b/components/kanban/SwimlanesBoard.tsx
index 56e2dc2..1bbc475 100644
--- a/components/kanban/SwimlanesBoard.tsx
+++ b/components/kanban/SwimlanesBoard.tsx
@@ -6,6 +6,7 @@ import { useMemo, useState } from 'react';
import { useTasksContext } from '@/contexts/TasksContext';
import { useColumnVisibility } from '@/hooks/useColumnVisibility';
import { ColumnVisibilityToggle } from './ColumnVisibilityToggle';
+import { getAllStatuses } from '@/lib/status-config';
import {
DndContext,
DragEndEvent,
@@ -101,12 +102,14 @@ export function SwimlanesBoard({
})
);
- const statuses: { id: TaskStatus; title: string; color: string }[] = [
- { id: 'todo', title: 'À faire', color: 'gray' },
- { id: 'in_progress', title: 'En cours', color: 'blue' },
- { id: 'done', title: 'Terminé', color: 'green' },
- { id: 'cancelled', title: 'Annulé', color: 'red' }
- ];
+ // Configuration des statuts basée sur la config centralisée
+ const statuses = useMemo(() => {
+ return getAllStatuses().map(statusConfig => ({
+ id: statusConfig.key,
+ title: statusConfig.label,
+ color: statusConfig.color
+ }));
+ }, []);
// Handlers pour le drag & drop
const handleDragStart = (event: DragStartEvent) => {
@@ -195,7 +198,6 @@ export function SwimlanesBoard({
{/* Headers des colonnes avec boutons toggle */}
diff --git a/hooks/useColumnVisibility.ts b/hooks/useColumnVisibility.ts
index e621de6..e25175c 100644
--- a/hooks/useColumnVisibility.ts
+++ b/hooks/useColumnVisibility.ts
@@ -1,6 +1,7 @@
import { useState, useEffect } from 'react';
import { TaskStatus } from '@/lib/types';
import { userPreferencesService } from '@/services/user-preferences';
+import { getAllStatuses } from '@/lib/status-config';
export function useColumnVisibility() {
const [hiddenStatuses, setHiddenStatuses] = useState>(new Set());
@@ -37,10 +38,15 @@ export function useColumnVisibility() {
return !hiddenStatuses.has(status);
};
+ const getAllAvailableStatuses = () => {
+ return getAllStatuses();
+ };
+
return {
hiddenStatuses,
toggleStatusVisibility,
getVisibleStatuses,
- isStatusVisible
+ isStatusVisible,
+ getAllAvailableStatuses
};
}
diff --git a/hooks/useTasks.ts b/hooks/useTasks.ts
index 543a186..67fca2c 100644
--- a/hooks/useTasks.ts
+++ b/hooks/useTasks.ts
@@ -11,6 +11,8 @@ interface UseTasksState {
completed: number;
inProgress: number;
todo: number;
+ cancelled: number;
+ freeze: number;
completionRate: number;
};
loading: boolean;
@@ -41,6 +43,8 @@ export function useTasks(
completed: 0,
inProgress: 0,
todo: 0,
+ cancelled: 0,
+ freeze: 0,
completionRate: 0
},
loading: false,
@@ -147,6 +151,8 @@ export function useTasks(
completed: updatedTasks.filter(t => t.status === 'done').length,
inProgress: updatedTasks.filter(t => t.status === 'in_progress').length,
todo: updatedTasks.filter(t => t.status === 'todo').length,
+ cancelled: updatedTasks.filter(t => t.status === 'cancelled').length,
+ freeze: updatedTasks.filter(t => t.status === 'freeze').length,
completionRate: updatedTasks.length > 0
? Math.round((updatedTasks.filter(t => t.status === 'done').length / updatedTasks.length) * 100)
: 0
@@ -188,6 +194,8 @@ export function useTasks(
completed: currentTasks.filter(t => t.status === 'done').length,
inProgress: currentTasks.filter(t => t.status === 'in_progress').length,
todo: currentTasks.filter(t => t.status === 'todo').length,
+ cancelled: currentTasks.filter(t => t.status === 'cancelled').length,
+ freeze: currentTasks.filter(t => t.status === 'freeze').length,
completionRate: currentTasks.length > 0
? Math.round((currentTasks.filter(t => t.status === 'done').length / currentTasks.length) * 100)
: 0
diff --git a/lib/status-config.ts b/lib/status-config.ts
new file mode 100644
index 0000000..7d4713f
--- /dev/null
+++ b/lib/status-config.ts
@@ -0,0 +1,116 @@
+import { TaskStatus } from './types';
+
+export interface StatusConfig {
+ key: TaskStatus;
+ label: string;
+ icon: string;
+ color: 'gray' | 'blue' | 'green' | 'red' | 'purple';
+ order: number;
+}
+
+export const STATUS_CONFIG: Record = {
+ todo: {
+ key: 'todo',
+ label: 'À faire',
+ icon: '⚡',
+ color: 'gray',
+ order: 1
+ },
+ in_progress: {
+ key: 'in_progress',
+ label: 'En cours',
+ icon: '🔄',
+ color: 'blue',
+ order: 2
+ },
+ freeze: {
+ key: 'freeze',
+ label: 'Gelé',
+ icon: '🧊',
+ color: 'purple',
+ order: 3
+ },
+ done: {
+ key: 'done',
+ label: 'Terminé',
+ icon: '✓',
+ color: 'green',
+ order: 4
+ },
+ cancelled: {
+ key: 'cancelled',
+ label: 'Annulé',
+ icon: '✕',
+ color: 'red',
+ order: 5
+ }
+} as const;
+
+// Utilitaires pour récupérer facilement les infos
+export const getStatusConfig = (status: TaskStatus): StatusConfig => {
+ return STATUS_CONFIG[status];
+};
+
+export const getAllStatuses = (): StatusConfig[] => {
+ return Object.values(STATUS_CONFIG).sort((a, b) => a.order - b.order);
+};
+
+export const getStatusLabel = (status: TaskStatus): string => {
+ return STATUS_CONFIG[status].label;
+};
+
+export const getStatusIcon = (status: TaskStatus): string => {
+ return STATUS_CONFIG[status].icon;
+};
+
+export const getStatusColor = (status: TaskStatus): StatusConfig['color'] => {
+ return STATUS_CONFIG[status].color;
+};
+
+// Configuration des couleurs tech/cyberpunk
+export const TECH_STYLES = {
+ gray: {
+ border: 'border-slate-700',
+ glow: 'shadow-slate-500/20',
+ accent: 'text-slate-400',
+ badge: 'bg-slate-800 text-slate-300 border border-slate-600'
+ },
+ blue: {
+ border: 'border-cyan-500/30',
+ glow: 'shadow-cyan-500/20',
+ accent: 'text-cyan-400',
+ badge: 'bg-cyan-950 text-cyan-300 border border-cyan-500/30'
+ },
+ green: {
+ border: 'border-emerald-500/30',
+ glow: 'shadow-emerald-500/20',
+ accent: 'text-emerald-400',
+ badge: 'bg-emerald-950 text-emerald-300 border border-emerald-500/30'
+ },
+ red: {
+ border: 'border-red-500/30',
+ glow: 'shadow-red-500/20',
+ accent: 'text-red-400',
+ badge: 'bg-red-950 text-red-300 border border-red-500/30'
+ },
+ purple: {
+ border: 'border-purple-500/30',
+ glow: 'shadow-purple-500/20',
+ accent: 'text-purple-400',
+ badge: 'bg-purple-950 text-purple-300 border border-purple-500/30'
+ }
+} as const;
+
+export const getTechStyle = (color: StatusConfig['color']) => {
+ return TECH_STYLES[color];
+};
+
+export const getBadgeVariant = (color: StatusConfig['color']): 'success' | 'primary' | 'danger' | 'default' => {
+ switch (color) {
+ case 'green': return 'success';
+ case 'blue':
+ case 'purple': return 'primary';
+ case 'red': return 'danger';
+ default: return 'default';
+ }
+};
diff --git a/lib/types.ts b/lib/types.ts
index b2c1efc..49e3912 100644
--- a/lib/types.ts
+++ b/lib/types.ts
@@ -1,5 +1,6 @@
// Types de base pour les tâches
-export type TaskStatus = 'todo' | 'in_progress' | 'done' | 'cancelled';
+// Note: TaskStatus est maintenant géré par la configuration centralisée dans lib/status-config.ts
+export type TaskStatus = 'todo' | 'in_progress' | 'done' | 'cancelled' | 'freeze';
export type TaskPriority = 'low' | 'medium' | 'high' | 'urgent';
export type TaskSource = 'reminders' | 'jira' | 'manual';
diff --git a/services/tasks.ts b/services/tasks.ts
index 4943ddd..85967b4 100644
--- a/services/tasks.ts
+++ b/services/tasks.ts
@@ -189,12 +189,13 @@ export class TasksService {
* Récupère les statistiques des tâches
*/
async getTaskStats() {
- const [total, completed, inProgress, todo, cancelled] = await Promise.all([
+ const [total, completed, inProgress, todo, cancelled, freeze] = await Promise.all([
prisma.task.count(),
prisma.task.count({ where: { status: 'done' } }),
prisma.task.count({ where: { status: 'in_progress' } }),
prisma.task.count({ where: { status: 'todo' } }),
- prisma.task.count({ where: { status: 'cancelled' } })
+ prisma.task.count({ where: { status: 'cancelled' } }),
+ prisma.task.count({ where: { status: 'freeze' } })
]);
return {
@@ -203,6 +204,7 @@ export class TasksService {
inProgress,
todo,
cancelled,
+ freeze,
completionRate: total > 0 ? Math.round((completed / total) * 100) : 0
};
}
diff --git a/src/contexts/TasksContext.tsx b/src/contexts/TasksContext.tsx
index 8f88049..3f8303c 100644
--- a/src/contexts/TasksContext.tsx
+++ b/src/contexts/TasksContext.tsx
@@ -15,6 +15,8 @@ interface TasksContextType {
completed: number;
inProgress: number;
todo: number;
+ cancelled: number;
+ freeze: number;
completionRate: number;
};
loading: boolean;