En esta página
Proyecto Final — Kanban Board
¡Felicitaciones por llegar al proyecto final!
Has completado todas las lecciones del curso y ahora es momento de aplicar todo lo aprendido en un proyecto real y complejo: un tablero Kanban completamente funcional.
¿Qué construirás?
El tablero Kanban incluye:
- 4 columnas: Pendiente → En Progreso → En Revisión → Completada
- Tarjetas de tarea con título, descripción, prioridad, asignado, etiquetas y fecha de vencimiento
- Drag & Drop nativo con HTML5 para mover tarjetas entre columnas
- Límites WIP (Work In Progress) por columna
- Filtrado por texto y prioridad en tiempo real
- Persistencia en localStorage con Zustand persist
- Modal para crear nuevas tareas
- Accesibilidad con ARIA roles y labels correctos
Arquitectura del proyecto
src/
├── components/
│ ├── TarjetaTarea.tsx — Tarjeta draggable con prioridad y metadatos
│ ├── ColumnaKanban.tsx — Drop zone con límite WIP
│ ├── TableroKanban.tsx — Tablero raíz con estado de arrastre
│ ├── BotonAgregarTarea.tsx — Modal de creación
│ └── FiltroTablero.tsx — Barra de filtros
├── store/
│ └── kanbanStore.ts — Zustand store con devtools + persist
├── hooks/
│ └── useDragDrop.ts — Hook personalizado para drag & drop
├── types/
│ └── kanban.ts — Interfaces TypeScript
└── App.tsx — Router con rutas Inicio y TableroTecnologías utilizadas
| Tecnología | Uso en el proyecto |
|---|---|
| React 19.2 | Componentes y hooks |
| TypeScript | Tipado estricto de todo el dominio |
| Zustand | Estado global con persist + devtools |
| React Router v7 | Navegación (Inicio / Tablero) |
| HTML5 Drag & Drop | Mover tarjetas entre columnas |
| CSS personalizado | Glassmorphism cards y grid layout |
Cómo extender el proyecto
Una vez que el tablero básico funcione, practica estas extensiones:
Extensión 1 — TanStack Query para datos del servidor
// Obtener tareas desde una API real en lugar de localStorage
const { data: tareas } = useQuery({
queryKey: ['tareas-kanban'],
queryFn: () => fetch('/api/tareas').then(r => r.json()) as Promise<Tarea[]>,
});
const moverMutation = useMutation({
mutationFn: ({ id, estado }: { id: string; estado: string }) =>
fetch(`/api/tareas/${id}`, {
method: 'PATCH',
body: JSON.stringify({ estado }),
}),
onSuccess: () => void queryClient.invalidateQueries({ queryKey: ['tareas-kanban'] }),
});Extensión 2 — Autenticación con Context
function KanbanConAuth(): React.JSX.Element {
const { usuario } = useAuth();
return usuario ? <TableroKanban /> : <PaginaLogin />;
}Extensión 3 — React Router para detalle de tarea
// Ruta de detalle /tablero/tareas/:tareaId
function DetalleTarea(): React.JSX.Element {
const { tareaId } = useParams<{ tareaId: string }>();
const tarea = useKanban((s) => s.tareas.find((t) => t.id === tareaId));
if (!tarea) return <Navigate to="/tablero" replace />;
return (
<article>
<h1>{tarea.titulo}</h1>
<p>{tarea.descripcion}</p>
{/* Editor completo de la tarea */}
</article>
);
}Extensión 4 — Testing del tablero
describe('TableroKanban', () => {
it('mueve una tarea al columna En Progreso', async () => {
const usuario = userEvent.setup();
render(<TableroKanban />);
// Verificar que la tarea existe en Pendiente
const columnasPendiente = screen.getByRole('region', { name: /pendiente/i });
expect(within(columnasPendiente).getAllByRole('article').length).toBeGreaterThan(0);
});
it('crea una nueva tarea correctamente', async () => {
const usuario = userEvent.setup();
render(<TableroKanban />);
await usuario.click(screen.getByRole('button', { name: /nueva tarea/i }));
const dialog = screen.getByRole('dialog');
await usuario.type(within(dialog).getByLabelText(/título/i), 'Mi nueva tarea');
await usuario.click(within(dialog).getByRole('button', { name: /agregar/i }));
expect(screen.getByText('Mi nueva tarea')).toBeInTheDocument();
});
});Reflexión final
Este tablero Kanban integra todos los conceptos del curso:
- Componentes y JSX — TarjetaTarea, ColumnaKanban, TableroKanban
- Props y children — comunicación entre componentes del tablero
- useState — estado local del modal, drag, expansión de tarjetas
- useEffect — podría integrarse para sincronización con API
- useRef — referencia al ID de tarea arrastrada (no causa render)
- useCallback — callbacks estables para drag handlers
- Hooks personalizados — useDragDrop, useKanbanFilters
- Context API — podría usarse para auth
- React Router — navegación entre tableros o detalle de tarea
- Zustand — store global con persist y devtools
- TypeScript — todos los tipos del dominio Kanban bien definidos
¡El tablero está listo para escalar! Puedes agregar colaboración en tiempo real con WebSockets, sub-tareas, adjuntos, comentarios, notificaciones y mucho más. El conocimiento que adquiriste en este curso te da todas las herramientas para construir aplicaciones React profesionales y escalables.
Inicia sesión para guardar tu progreso