Ir al contenido

Vista Kanban

Vista de tablero con drag & drop para gestión visual de tareas del proyecto.

  • Componente: KanbanView.tsx
  • Acceso: Toggle en pestaña “Tareas” del proyecto
  • Librería: @dnd-kit/core y @dnd-kit/sortable

El Kanban tiene 5 columnas fijas por estado de tarea:

  1. Pendiente (pending) - Gris
  2. En Progreso (in_progress) - Azul
  3. En Espera (on_hold) - Amarillo
  4. Completada (completed) - Verde
  5. Cancelada (cancelled) - Rojo

Cada columna muestra:

  • Punto de color indicativo del estado
  • Nombre del estado
  • Contador de tareas en ese estado

Activación:

  • Mouse: Arrastrar 8px mínimo antes de iniciar drag
  • Teclado: Soporte con flechas y Enter/Space

Funcionamiento:

  1. Usuario arrastra tarjeta de tarea
  2. Se muestra overlay semi-transparente de la tarea
  3. Al soltar sobre columna válida:
    • Se actualiza estado en base de datos
    • Se recalcula progreso del proyecto
    • Se invalidan queries para refrescar
  4. Animación suave de transición

Cada tarjeta muestra:

  • Título: Nombre de la tarea (truncado a 2 líneas)
  • Prioridad: Emoji indicador (🟢🟡🟠🔴)
  • Badge de vencida: Si está overdue
  • Fecha: Relativa al vencimiento
  • Progreso: Barra si progress > 0
  • Indicadores: Adjuntos, comentarios, subtareas

Acciones rápidas (hover):

  • Botón editar (Edit)
  • Botón eliminar (Trash2)
const statusConfig: Record<TaskStatus, { label: string; dotColor: string }> = {
pending: {
label: 'Pendiente',
dotColor: 'bg-gray-400',
},
in_progress: {
label: 'En Progreso',
dotColor: 'bg-blue-500',
},
on_hold: {
label: 'En Espera',
dotColor: 'bg-amber-500',
},
completed: {
label: 'Completada',
dotColor: 'bg-green-500',
},
cancelled: {
label: 'Cancelada',
dotColor: 'bg-red-500',
}
};
  • Altura mínima: 400px por columna
  • Hover state: Borde azul y fondo resaltado
  • Scroll: Automático en columnas con muchas tareas
  • Responsive: Scroll horizontal en móviles
const sensors = useSensors(
useSensor(PointerSensor, {
activationConstraint: {
distance: 8, // 8px antes de iniciar drag
},
}),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
})
);
Implementación del Drag & Drop
// KanbanView.tsx - Handler principal
const handleDragEnd = (event: DragEndEvent) => {
const { active, over } = event;
if (!over) {
setActiveId(null);
return;
}
const taskId = active.id as string;
const newStatus = over.id as TaskStatus;
if (columns.includes(newStatus)) {
onStatusChange(taskId, newStatus);
}
setActiveId(null);
};
// Actualización en base de datos
const updateTaskStatus = async (taskId: string, newStatus: TaskStatus) => {
const { error } = await supabase
.from('tasks')
.update({
status: newStatus,
completed_at: newStatus === 'completed' ? new Date().toISOString() : null
})
.eq('id', taskId);
if (!error) {
// Refrescar queries
queryClient.invalidateQueries({ queryKey: ['project', id] });
queryClient.invalidateQueries({ queryKey: ['tasks'] });
}
};