En esta página
Proyecto final - Gestor de tareas
Descripcion del proyecto
En este proyecto final vas a construir un gestor de tareas que integra todos los conceptos del curso. El objetivo es que veas como encajan juntas todas las piezas que aprendiste.
Conceptos aplicados
| Leccion | Concepto usado en el proyecto |
|---|---|
| Variables y tipos | Tipos primitivos, const/let |
| Operadores y control | Condicionales, switch |
| Funciones modernas | Arrow functions, closures, callbacks |
| Objetos y arrays | Destructuring, spread |
| Métodos de array | filter, map, reduce, find |
| Strings | Template literals, includes, toLowerCase |
| DOM | createElement, classList, event listeners |
| Eventos | Event delegation, preventDefault |
| Promesas | Manejo de operaciones asincronas |
| Async/Await | Peticiones HTTP |
| Fetch API | CRUD con una API REST |
| Modulos ES | Organizacion en archivos |
| Patrones modernos | Map, Set, campos privados, Optional chaining |
Arquitectura
El proyecto sigue una arquitectura en capas:
1. Modelo (Task)
La clase Task encapsula los datos de una tarea con campos privados (#id, #completada). Usa el constructor para validar y inicializar, y expone getters para acceso de solo lectura.
2. Servicio (TaskStore)
El TaskStore gestiona la colección de tareas usando un Map para acceso eficiente por ID. Implementa un sistema de suscripciones (patrón Observer) para notificar cambios.
3. Vista (DOM)
La capa de vista (no incluida en el ejemplo, pero que tu construiras) usa los métodos del DOM para renderizar las tareas y event delegation para manejar las interacciones.
Desafios propuestos
Extiende el proyecto con estas mejoras progresivas:
Nivel 1 - Persistencia
Guarda las tareas en localStorage para que persistan entre recargas:
// Guardar
localStorage.setItem('tareas', JSON.stringify([...tareas]));
// Cargar
const guardadas = JSON.parse(localStorage.getItem('tareas') ?? '[]');Nivel 2 - Interfaz DOM
Renderiza las tareas en el navegador:
- Crea un formulario para agregar tareas
- Muestra la lista con filtros (todas, pendientes, completadas)
- Usa event delegation para manejar clicks en botones de eliminar y completar
Nivel 3 - API REST
Conecta el store a una API REST con fetch:
async function sincronizar() {
const res = await fetch('/api/tareas');
const datos = await res.json();
// actualizar el store local
}Nivel 4 - Busqueda avanzada
Implementa busqueda con debounce para filtrar tareas mientras el usuario escribe:
function debounce(fn, ms) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), ms);
};
}Recapitulacion del curso
Has completado JavaScript Esencial. Ahora dominas:
- Fundamentos del lenguaje (variables, tipos, operadores, control de flujo)
- Funciones modernas (arrow, closures, higher-order)
- Estructuras de datos (objetos, arrays, Map, Set)
- Manipulacion del DOM y manejo de eventos
- Programación asincrona (promesas, async/await, fetch)
- Modulos ES y patrones modernos
El siguiente paso es aprender un framework como Angular para construir aplicaciones web completas y escalables.
Has completado el curso de JavaScript Esencial. El siguiente paso recomendado es Angular para Desarrolladores.
// =============================================
// PROYECTO: Gestor de tareas con JavaScript
// =============================================
// Aplica todo lo aprendido en el curso:
// - Modulos y clases
// - Métodos de array
// - Async/await y Fetch
// - DOM y eventos
// - Patrones modernos
// =============================================
// === MODELO: Clase Task ===
class Task {
#id;
#completada;
constructor({ título, descripción = '', prioridad = 'media' }) {
this.#id = crypto.randomUUID();
this.título = título;
this.descripción = descripción;
this.prioridad = prioridad;
this.#completada = false;
this.creadaEn = new Date();
}
get id() { return this.#id; }
get completada() { return this.#completada; }
toggleCompletada() {
this.#completada = !this.#completada;
}
toJSON() {
return {
id: this.#id,
título: this.título,
descripción: this.descripción,
prioridad: this.prioridad,
completada: this.#completada,
creadaEn: this.creadaEn.toISOString(),
};
}
}
// === SERVICIO: TaskStore ===
class TaskStore {
#tareas = new Map();
#listeners = new Set();
agregar(datos) {
const tarea = new Task(datos);
this.#tareas.set(tarea.id, tarea);
this.#notificar();
return tarea;
}
eliminar(id) {
const eliminada = this.#tareas.delete(id);
if (eliminada) this.#notificar();
return eliminada;
}
toggleCompletada(id) {
const tarea = this.#tareas.get(id);
tarea?.toggleCompletada();
this.#notificar();
}
obtenerTodas(filtro = 'todas') {
const lista = [...this.#tareas.values()];
switch (filtro) {
case 'pendientes':
return lista.filter(t => !t.completada);
case 'completadas':
return lista.filter(t => t.completada);
default:
return lista;
}
}
buscar(término) {
const lower = término.toLowerCase();
return this.obtenerTodas().filter(t =>
t.título.toLowerCase().includes(lower) ||
t.descripción.toLowerCase().includes(lower)
);
}
get estadisticas() {
const todas = this.obtenerTodas();
return {
total: todas.length,
completadas: todas.filter(t => t.completada).length,
pendientes: todas.filter(t => !t.completada).length,
porPrioridad: Object.groupBy(todas, t => t.prioridad),
};
}
suscribir(callback) {
this.#listeners.add(callback);
return () => this.#listeners.delete(callback);
}
#notificar() {
this.#listeners.forEach(fn => fn(this.obtenerTodas()));
}
}
// === USO ===
const store = new TaskStore();
// Suscribirse a cambios
store.suscribir((tareas) => {
console.log(`Tareas actualizadas: ${tareas.length}`);
});
// Agregar tareas
const t1 = store.agregar({
título: 'Aprender JavaScript',
descripción: 'Completar el curso de JS Esencial',
prioridad: 'alta',
});
store.agregar({
título: 'Practicar métodos de array',
prioridad: 'media',
});
store.agregar({
título: 'Leer documentación de MDN',
prioridad: 'baja',
});
// Completar una tarea
store.toggleCompletada(t1.id);
// Ver estadisticas
console.log(store.estadisticas);
// Filtrar
console.log('Pendientes:', store.obtenerTodas('pendientes'));
// Buscar
console.log('Buscar:', store.buscar('array'));
Inicia sesión para guardar tu progreso