Has recorrido las siete primeras lecciones aprendiendo herramientas: montaste el entorno, escribiste tu primer programa, conociste la sintaxis, los tipos, los operadores y las conversiones. En cada ejemplo aparecían Marta, Iván y Lucía, y unas tareas con título, prioridad y horas estimadas. Ha llegado el momento de presentar formalmente el proyecto que atraviesa todo el curso: qué es Taller Nómada, qué problema tiene, qué aplicación vas a construir para resolverlo, cuál es el modelo de datos canónico que usarás durante los once módulos y qué parte construirás en cada uno. Esta lección es el mapa del viaje completo.
Contenido
- Taller Nómada: el contexto
- El problema que hay que resolver
- El equipo: Marta, Iván y Lucía
- Qué hará Nómada Tareas
- El modelo de datos canónico de una tarea
- El objeto de ejemplo de referencia
- Reglas de negocio del proyecto
- Mapa del curso: qué construye cada módulo
- La estructura de ficheros que irá creciendo
- Errores Comunes y Consejos
- Ejercicios
- Conclusión
- Taller Nómada: el contexto
Taller Nómada es un pequeño espacio de coworking y taller creativo situado en una nave rehabilitada. Es una empresa completamente ficticia, creada para este curso, con datos igualmente ficticios.
Su actividad tiene dos patas:
- Coworking: doce puestos de trabajo fijos y una sala polivalente que se alquila por horas para reuniones y presentaciones.
- Taller creativo: un espacio con equipamiento de serigrafía, encuadernación y pequeña carpintería, donde se imparten cursos y se acogen proyectos de residentes.
El negocio funciona, pero la gestión interna no. Y ese es el punto de partida.
- El problema que hay que resolver
Hoy, el trabajo de Taller Nómada se organiza así:
- Una pared de notas adhesivas con las tareas en curso.
- Un grupo de mensajería donde se acuerdan cosas que nadie apunta.
- Una hoja de cálculo compartida que nadie actualiza desde marzo.
Las consecuencias son las esperables:
| Síntoma | Consecuencia real |
|---|---|
| Las notas se caen o se despegan | Tareas que desaparecen sin que nadie se entere |
| Nadie sabe quién hace qué | Trabajo duplicado y trabajo sin hacer |
| Las fechas límite están en la cabeza de Marta | Se descubren tarde, siempre |
| No hay historial | Es imposible saber cuánto se tardó en algo parecido |
| No hay visión de carga | Iván acumula tres proyectos y Lucía tiene la agenda vacía |
Lo que necesitan no es una herramienta corporativa con mil opciones. Necesitan algo pequeño, rápido y suyo: una lista de tareas compartida donde se vea quién hace qué, con qué prioridad y para cuándo.
Eso es Nómada Tareas, y lo vas a construir tú.
- El equipo: Marta, Iván y Lucía
Tres personas que serán las protagonistas de todos los ejemplos y ejercicios del curso.
| Persona | Rol | Qué necesita de la aplicación |
|---|---|---|
| Marta | Coordinadora | Ver el estado global, repartir la carga, controlar fechas límite |
| Iván | Diseñador | Ver solo sus tareas, ordenadas por urgencia, y marcarlas como hechas |
| Lucía | Desarrolladora | Filtrar por etiqueta, estimar horas y consultar el histórico |
Sus necesidades no son iguales, y eso es deliberado: te obligará a pensar en filtros, ordenaciones y vistas distintas sobre los mismos datos.
- Qué hará Nómada Tareas
El alcance completo de la aplicación, en orden aproximado de construcción:
- Crear tareas con todos sus campos, validando los datos de entrada.
- Asignarlas a una persona del equipo (o dejarlas sin asignar).
- Cambiar su estado entre
pendiente,en-cursoyhecha. - Editar y eliminar tareas existentes.
- Filtrar por responsable, estado, prioridad o etiqueta.
- Ordenar por fecha límite, prioridad u horas estimadas.
- Calcular métricas: carga por persona, porcentaje de avance, tareas vencidas.
- Mostrar todo en una interfaz web usable.
- Persistir los datos en el navegador para que no se pierdan al recargar.
- Sincronizar con una API remota.
- Probar la aplicación con pruebas automáticas.
- Optimizar y desplegar la versión final.
Nada de esto se hace de golpe. Cada módulo del curso añade una capa.
- El modelo de datos canónico de una tarea
Aquí está el corazón del proyecto. Esta tabla es la referencia oficial de todo el curso: cada vez que aparezca una tarea en cualquier lección, tendrá exactamente estos campos con estos tipos.
| Campo | Tipo | Valores permitidos | Obligatorio | Ejemplo |
|---|---|---|---|---|
id |
number |
Entero positivo, único | Sí | 1 |
titulo |
string |
Texto no vacío, 1-100 caracteres | Sí | 'Rediseñar la sala polivalente' |
responsable |
string | null |
'Marta', 'Iván', 'Lucía' o null |
No | 'Iván' |
prioridad |
string |
'alta', 'media', 'baja' |
Sí | 'alta' |
estado |
string |
'pendiente', 'en-curso', 'hecha' |
Sí | 'en-curso' |
etiquetas |
string[] |
Array de textos; puede estar vacío | Sí (puede ser []) |
['diseño', 'espacio'] |
horasEstimadas |
number |
Mayor que 0, máximo 40 | Sí | 12 |
fechaLimite |
string |
Formato ISO 'yyyy-mm-dd' |
Sí | '2026-09-30' |
5.1 Por qué cada campo es como es
id es un número, no un texto. Es un identificador correlativo que asigna la aplicación. Al ser numérico, generar el siguiente es trivial.
responsable puede ser null. Aquí aplicamos lo aprendido en Variables y Tipos de Datos: null significa "deliberadamente sin asignar". No usamos '' ni undefined. Una tarea sin responsable es un estado legítimo del negocio: Marta crea la tarea primero y decide quién la hace después.
prioridad y estado son textos de un conjunto cerrado. Podríamos usar números (1, 2, 3), pero 'alta' se lee y se depura infinitamente mejor que 1. El precio es tener que validar que el valor esté entre los permitidos, algo que ya sabes hacer con ===.
etiquetas es siempre un array, nunca null. Si una tarea no tiene etiquetas, el valor es []. Esto es una decisión de diseño importante: garantiza que todo el código posterior pueda hacer tarea.etiquetas.length sin comprobar nada antes. Y recuerda de Conversión de Tipos y Comparaciones: un array vacío es truthy, así que hay que comprobar su longitud, no su existencia.
horasEstimadas admite decimales. Media hora es una unidad razonable (7.5). El máximo de 40 corresponde a una semana laboral completa.
fechaLimite es un string ISO, no un objeto Date. Esta es probablemente la decisión más discutible del proyecto, y está tomada a propósito por tres motivos:
- Se ordena solo.
'2026-09-30' < '2026-11-05'estrue, porque el orden alfabético del formato ISO coincide con el cronológico. - Se guarda y se transmite sin conversiones. Ni el almacenamiento del navegador ni una API JSON manejan objetos
Date: los convierten a texto de todos modos. - Evita las trampas de zona horaria, que son numerosas y desagradables para alguien que empieza.
Trabajaremos con fechas como texto durante todo el curso, y solo usaremos objetos Date cuando haya que calcular diferencias entre fechas.
5.2 Los estados y su ciclo de vida
Una tarea recorre siempre este camino:
stateDiagram-v2
[*] --> pendiente: Marta la crea
pendiente --> en_curso: alguien empieza
en_curso --> hecha: se termina
en_curso --> pendiente: se aparca
hecha --> en_curso: hay que retocarla
hecha --> [*]
Solo esas transiciones son válidas. Una tarea no puede pasar directamente de pendiente a hecha: alguien tiene que haberla empezado. Esta regla la implementarás en el Módulo 2, cuando aprendas condicionales.
- El objeto de ejemplo de referencia
Este es el objeto que reaparecerá una y otra vez a lo largo del curso. Todavía no has estudiado la sintaxis de objetos —eso es Introducción a los Objetos—, pero puedes leerlo perfectamente: es la agrupación de las mismas ocho variables que ya sabes declarar.
// La tarea de referencia de Nómada Tareas.
// Cada línea es un campo del modelo canónico.
const tareaEjemplo = {
id: 1,
titulo: 'Rediseñar la sala polivalente',
responsable: 'Iván',
prioridad: 'alta',
estado: 'en-curso',
etiquetas: ['diseño', 'espacio'],
horasEstimadas: 12,
fechaLimite: '2026-09-30'
};Y este es el mismo conjunto de datos expresado con lo que sí sabes hacer hoy: variables sueltas.
'use strict';
// --- Tarea 1: los mismos datos, en variables independientes -------
const id1 = 1;
const titulo1 = 'Rediseñar la sala polivalente';
const responsable1 = 'Iván';
const prioridad1 = 'alta';
let estado1 = 'en-curso';
const etiquetas1 = ['diseño', 'espacio'];
const horasEstimadas1 = 12;
const fechaLimite1 = '2026-09-30';
console.log(`[${id1}] ${titulo1} — ${responsable1} (${prioridad1})`);Compara las dos versiones. Con una tarea, las variables sueltas son manejables. Con tres, ya empiezas a numerar variables (titulo1, titulo2, titulo3), lo cual es una señal inequívoca de que falta una estructura. Con cuarenta tareas, sería inviable.
Esa incomodidad es intencionada: la sentirás en el ejercicio final de esta lección, y es exactamente la motivación para los objetos y arrays del Módulo 4.
- Reglas de negocio del proyecto
Además del modelo de datos, el proyecto tiene un conjunto de reglas fijas que se aplicarán durante todo el curso:
| Regla | Descripción |
|---|---|
| R1 | El id es único y correlativo; la aplicación lo asigna, nunca el usuario |
| R2 | El titulo no puede estar vacío ni contener solo espacios |
| R3 | horasEstimadas debe ser mayor que 0 y no superar 40 |
| R4 | fechaLimite no puede ser anterior a la fecha de creación |
| R5 | Una tarea nueva nace siempre en estado 'pendiente' |
| R6 | Solo se permiten las transiciones de estado del diagrama anterior |
| R7 | Nadie puede superar 40 horas estimadas asignadas en la misma semana |
| R8 | Una tarea sin responsable tiene responsable: null, nunca '' |
| R9 | Las etiquetas se guardan en minúsculas y sin duplicados |
| R10 | Una tarea vencida (fechaLimite pasada y estado distinto de 'hecha') se destaca |
Estas reglas aparecerán progresivamente. En este módulo ya has aplicado sin saberlo la R2, la R3 y la R8 al validar el formulario de la lección anterior.
- Mapa del curso: qué construye cada módulo
Este diagrama muestra qué parte de Nómada Tareas construye cada módulo y cómo se apoyan unos en otros.
flowchart TD
M1["Módulo 1 · Fundamentos<br/>Los datos de una tarea<br/>en variables y tipos"]
M2["Módulo 2 · Control de flujo<br/>Validar estados y recorrer<br/>varias tareas"]
M3["Módulo 3 · Funciones<br/>crearTarea, validarTarea,<br/>calcularCarga"]
M4["Módulo 4 · Objetos y arrays<br/>La tarea como objeto<br/>y la lista de tareas"]
M5["Módulo 5 · Avanzado<br/>Clase Tarea, módulos<br/>y asincronía"]
M6["Módulo 6 · DOM<br/>La interfaz: lista,<br/>formulario y eventos"]
M7["Módulo 7 · APIs<br/>Guardar en el navegador<br/>y sincronizar con la API"]
M8["Módulo 8 · Pruebas<br/>Depurar y probar<br/>toda la lógica"]
M9["Módulo 9 · Rendimiento<br/>Que responda bien<br/>con muchas tareas"]
M10["Módulo 10 · Frameworks<br/>Cómo sería con<br/>React, Vue o Angular"]
M11["Módulo 11 · Proyecto final<br/>Nómada Tareas<br/>completo y desplegado"]
M1 --> M2 --> M3 --> M4 --> M5 --> M6 --> M7 --> M8 --> M9 --> M10 --> M11
Con más detalle, módulo a módulo:
| Módulo | Qué construyes en Nómada Tareas |
|---|---|
| 1. Introducción | Los datos de una tarea en variables del tipo correcto; validación básica de un formulario |
| 2. Estructuras de control | Decidir la prioridad, validar transiciones de estado, recorrer varias tareas, capturar errores |
| 3. Funciones | Agrupar la lógica: crearTarea(), esTareaValida(), calcularCarga(), formatearResumen() |
| 4. Objetos y arrays | La tarea como objeto y la lista completa como array; filtrar, ordenar y agregar con filter, sort y reduce |
| 5. Avanzado | Una clase Tarea con validación encapsulada; separar el código en módulos; cargar datos de forma asíncrona |
| 6. El DOM | La interfaz real: pintar la lista, el formulario de alta, los botones de estado, los filtros |
| 7. APIs del navegador | Guardar en localStorage para no perder los datos; sincronizar con una API mediante fetch |
| 8. Pruebas | Depurar con las DevTools; pruebas unitarias de la lógica de tareas con Jest; pruebas de extremo a extremo con Cypress |
| 9. Rendimiento | Que la lista siga siendo fluida con cientos de tareas; renderizado eficiente |
| 10. Frameworks | Cómo se vería la misma lista de tareas en React, Vue y Angular |
| 11. Proyecto final | Ensamblar, pulir, probar y desplegar la aplicación completa |
Un detalle importante sobre cómo leer este mapa: cada módulo reescribe parte de lo anterior con mejores herramientas. Las ocho variables sueltas de hoy se convertirán en un objeto en el Módulo 4 y en una instancia de clase en el Módulo 5. No es que lo de hoy esté mal: es que aprendes el andamiaje antes que el edificio.
- La estructura de ficheros que irá creciendo
En la lección Configuración de tu Entorno de Desarrollo creaste esto:
Así quedará al final del curso:
nomada-tareas/ ├── index.html ├── css/ │ └── estilos.css ├── js/ │ ├── app.js ← punto de entrada │ ├── modelo/ │ │ ├── tarea.js ← la clase Tarea (Módulo 5) │ │ └── validacion.js ← reglas R1-R10 (Módulos 2-3) │ ├── datos/ │ │ ├── almacen.js ← localStorage (Módulo 7) │ │ └── api.js ← fetch a la API (Módulo 7) │ ├── vista/ │ │ ├── lista.js ← renderizado de la lista (Módulo 6) │ │ ├── formulario.js ← alta y edición (Módulo 6) │ │ └── filtros.js ← filtros y orden (Módulo 6) │ └── util/ │ └── fechas.js ← utilidades de fecha (Módulo 3) ├── test/ │ └── tarea.test.js ← pruebas con Jest (Módulo 8) └── package.json ← dependencias (Módulo 8)
No hace falta crear nada de esto ahora. Se muestra para que veas hacia dónde vas y entiendas la lógica de la organización: el modelo (qué es una tarea y qué reglas cumple), los datos (de dónde vienen y dónde se guardan), la vista (cómo se muestran) y las utilidades. Esa separación en capas es un principio de diseño que se aplica en proyectos de cualquier tamaño.
Errores Comunes y Consejos
Errores comunes al abordar un proyecto largo
- Querer construirlo todo de golpe. El impulso natural es abrir el editor y empezar por la interfaz. No funciona: sin lógica validada detrás, la interfaz solo esconde los problemas.
- Cambiar el modelo de datos sobre la marcha. Si en el Módulo 4 decides llamar
owneralresponsable, todos los ejemplos posteriores dejarán de encajar. Respeta la tabla del apartado 5 durante todo el curso. - Saltarse el proyecto y hacer solo los ejercicios sueltos. Lo que consolida el aprendizaje es el hilo: ver cómo el mismo problema se resuelve mejor cada vez que aprendes algo nuevo.
- Usar
''en lugar denullpara un responsable sin asignar. Rompe la R8 y provoca comprobaciones inconsistentes por todo el código. - Guardar las fechas en formato
dd/mm/yyyy. Deja de poder ordenarse como texto y complica todo lo demás. - Frustrarse porque el código de hoy es "primitivo". Ocho variables sueltas para una tarea son incómodas, y deben serlo: esa incomodidad es lo que da sentido a lo que aprenderás después.
Consejos
- Ten esta lección a mano. La tabla del modelo de datos es la referencia que consultarás durante los once módulos.
- Crea una carpeta por módulo dentro del proyecto mientras practicas (
practica/modulo-01/), y dejajs/para el código definitivo. - Haz un commit de Git al terminar cada módulo. Verás tu progreso y podrás volver atrás.
- Cuando aprendas algo nuevo, pregúntate: "¿qué parte de Nómada Tareas mejora esto?" Es la mejor forma de fijar un concepto.
- Inventa tus propias tareas para el equipo de Taller Nómada. Cuanto más juegues con los datos, más natural te resultará el dominio.
- No adelantes materia. Si un módulo posterior te tienta, resiste: el orden está pensado para que cada pieza se apoye en la anterior.
Ejercicios
Ejercicio 1: Valida tres tareas contra el modelo
Para cada una de estas tres tareas propuestas, indica qué reglas del modelo de datos o del apartado 7 incumple y cómo la corregirías:
Tarea A
id: '3' titulo: ' ' responsable: '' prioridad: 'urgente' estado: 'pendiente' etiquetas: null horasEstimadas: 0 fechaLimite: '15/10/2026'
Tarea B
id: 4 titulo: 'Inventario del almacén de serigrafía' responsable: 'Lucía' prioridad: 'baja' estado: 'hecha' etiquetas: ['Taller', 'taller', 'INVENTARIO'] horasEstimadas: 55 fechaLimite: '2026-12-01'
Tarea C
id: 5 titulo: 'Preparar la jornada de puertas abiertas' responsable: null prioridad: 'alta' estado: 'en-curso' etiquetas: [] horasEstimadas: 9.5 fechaLimite: '2026-11-20'
Ejercicio 2: Tres tareas y un resumen
Escribe un script que declare tres tareas de Taller Nómada usando solo lo aprendido en este módulo (variables, tipos, operadores, conversiones, template literals). Nada de objetos, arrays de objetos, funciones ni bucles.
Las tres tareas:
| Campo | Tarea 1 | Tarea 2 | Tarea 3 |
|---|---|---|---|
| id | 1 | 2 | 3 |
| titulo | Rediseñar la sala polivalente | Cartelería del taller de serigrafía | Actualizar la web de reservas |
| responsable | Iván | Marta | Lucía |
| prioridad | alta | media | alta |
| estado | en-curso | pendiente | pendiente |
| etiquetas | diseño, espacio | diseño, comunicación | web, desarrollo |
| horasEstimadas | 12 | 6 | 14 |
| fechaLimite | 2026-09-30 | 2026-10-15 | 2026-10-02 |
El script debe imprimir:
- Una cabecera con el nombre del proyecto.
- Una línea de resumen por tarea con el formato:
[1] Rediseñar la sala polivalente · Iván · alta · en-curso · 12 h · vence 2026-09-30 - El total de horas estimadas del equipo.
- La media de horas por tarea, redondeada a un decimal.
- Cuántas tareas son de prioridad alta.
- La tarea con la fecha límite más próxima (comparando las fechas ISO como texto).
- Un aviso con
console.warnsi el total supera las 30 horas.
Ejercicio 3: Reflexiona sobre el modelo
Responde razonadamente en tres o cuatro líneas cada pregunta:
- ¿Por qué
etiquetases siempre un array ([]cuando está vacío) en lugar denull? ¿Qué problema evita esa decisión, teniendo en cuenta lo que sabes sobre valores truthy? - ¿Qué ventaja concreta aporta guardar
fechaLimitecomo'2026-09-30'en lugar de'30/09/2026'? - Al escribir el ejercicio 2 habrás notado una incomodidad. ¿Cuál es exactamente, y qué crees que la resolverá?
Soluciones
Ejercicio 1
Tarea A — incumple siete reglas:
| Campo | Problema | Corrección |
|---|---|---|
id: '3' |
Es un string; debe ser number |
id: 3 |
titulo: ' ' |
Solo espacios: vacío tras trim() (R2) |
Un título real |
responsable: '' |
Debe ser null si no hay responsable (R8) |
responsable: null |
prioridad: 'urgente' |
No está entre los tres valores permitidos | prioridad: 'alta' |
etiquetas: null |
Debe ser siempre un array | etiquetas: [] |
horasEstimadas: 0 |
Debe ser mayor que 0 (R3) | horasEstimadas: 4 |
fechaLimite: '15/10/2026' |
No es formato ISO | fechaLimite: '2026-10-15' |
Tarea B — incumple dos reglas:
horasEstimadas: 55supera el máximo de 40 (R3). Si el trabajo realmente son 55 horas, hay que partirlo en varias tareas: es lo que la regla pretende forzar.etiquetas: ['Taller', 'taller', 'INVENTARIO']incumple la R9 por partida doble: hay mayúsculas y hay un duplicado ('Taller'y'taller'son la misma etiqueta una vez normalizadas). Lo correcto sería['taller', 'inventario'].
Tarea C — es válida. Merece la pena repasar por qué cada campo dudoso está bien:
responsable: nulles correcto: la tarea existe pero aún no se ha asignado (R8).etiquetas: []es correcto: una lista vacía, nonull.horasEstimadas: 9.5es correcto: el campo admite decimales y está dentro del rango.estado: 'en-curso'conresponsable: nulles raro desde el punto de vista del negocio (alguien la ha empezado pero no consta quién), pero no incumple ninguna regla escrita. Es justo el tipo de detalle que se descubre construyendo, y que en un proyecto real llevaría a añadir una regla nueva.
Ejercicio 2
'use strict';
// ===================================================================
// Nómada Tareas · Módulo 1 · Resumen de las tareas de Taller Nómada
// Solo con variables, operadores y template literals.
// ===================================================================
// --- Tarea 1 -------------------------------------------------------
const id1 = 1;
const titulo1 = 'Rediseñar la sala polivalente';
const responsable1 = 'Iván';
const prioridad1 = 'alta';
let estado1 = 'en-curso';
const etiquetas1 = 'diseño, espacio';
const horasEstimadas1 = 12;
const fechaLimite1 = '2026-09-30';
// --- Tarea 2 -------------------------------------------------------
const id2 = 2;
const titulo2 = 'Cartelería del taller de serigrafía';
const responsable2 = 'Marta';
const prioridad2 = 'media';
let estado2 = 'pendiente';
const etiquetas2 = 'diseño, comunicación';
const horasEstimadas2 = 6;
const fechaLimite2 = '2026-10-15';
// --- Tarea 3 -------------------------------------------------------
const id3 = 3;
const titulo3 = 'Actualizar la web de reservas';
const responsable3 = 'Lucía';
const prioridad3 = 'alta';
let estado3 = 'pendiente';
const etiquetas3 = 'web, desarrollo';
const horasEstimadas3 = 14;
const fechaLimite3 = '2026-10-02';
// --- Cálculos ------------------------------------------------------
// Total de horas
const totalHoras = horasEstimadas1 + horasEstimadas2 + horasEstimadas3;
// Media redondeada a un decimal: multiplicamos por 10, redondeamos y dividimos
const NUM_TAREAS = 3;
const mediaHoras = Math.round((totalHoras / NUM_TAREAS) * 10) / 10;
// Tareas de prioridad alta: cada comparación vale true (1) o false (0)
const tareasAlta =
Number(prioridad1 === 'alta') +
Number(prioridad2 === 'alta') +
Number(prioridad3 === 'alta');
// Fecha más próxima: las fechas ISO se comparan como texto
const fechaMasProxima1 = fechaLimite1 < fechaLimite2 ? fechaLimite1 : fechaLimite2;
const fechaMasProxima = fechaMasProxima1 < fechaLimite3 ? fechaMasProxima1 : fechaLimite3;
// Título correspondiente a esa fecha
const tituloMasUrgente =
fechaMasProxima === fechaLimite1 ? titulo1 :
fechaMasProxima === fechaLimite2 ? titulo2 :
titulo3;
// --- Salida --------------------------------------------------------
console.log('=========================================');
console.log(' NÓMADA TAREAS · Taller Nómada');
console.log('=========================================');
console.log(
`[${id1}] ${titulo1} · ${responsable1} · ${prioridad1} · ${estado1} · ${horasEstimadas1} h · vence ${fechaLimite1}`
);
console.log(
`[${id2}] ${titulo2} · ${responsable2} · ${prioridad2} · ${estado2} · ${horasEstimadas2} h · vence ${fechaLimite2}`
);
console.log(
`[${id3}] ${titulo3} · ${responsable3} · ${prioridad3} · ${estado3} · ${horasEstimadas3} h · vence ${fechaLimite3}`
);
console.log('-----------------------------------------');
console.log(`Total de horas estimadas: ${totalHoras} h`);
console.log(`Media por tarea: ${mediaHoras} h`);
console.log(`Tareas de prioridad alta: ${tareasAlta} de ${NUM_TAREAS}`);
console.log(`Vence antes: ${tituloMasUrgente} (${fechaMasProxima})`);
const LIMITE_AVISO = 30;
totalHoras > LIMITE_AVISO &&
console.warn(`Atención: el equipo acumula ${totalHoras} h estimadas.`);Salida:
========================================= NÓMADA TAREAS · Taller Nómada ========================================= [1] Rediseñar la sala polivalente · Iván · alta · en-curso · 12 h · vence 2026-09-30 [2] Cartelería del taller de serigrafía · Marta · media · pendiente · 6 h · vence 2026-10-15 [3] Actualizar la web de reservas · Lucía · alta · pendiente · 14 h · vence 2026-10-02 ----------------------------------------- Total de horas estimadas: 32 h Media por tarea: 10.7 h Tareas de prioridad alta: 2 de 3 Vence antes: Rediseñar la sala polivalente (2026-09-30) ⚠ Atención: el equipo acumula 32 h estimadas.
Técnicas del módulo que aparecen aquí:
Number(prioridad === 'alta')convierte un booleano a1o0para poder sumarlos. Es una aplicación directa de la conversión explícita de Conversión de Tipos y Comparaciones.Math.round(x * 10) / 10redondea a un decimal sin usartoFixed, que devolvería un string.- La comparación de fechas ISO como texto funciona porque el orden alfabético coincide con el cronológico.
- Los ternarios encadenados eligen la fecha menor y su título asociado.
- El cortocircuito
&&dispara el aviso solo cuando se supera el umbral.
Ejercicio 3
1. ¿Por qué etiquetas es siempre un array?
Porque permite que todo el código posterior trate el campo de la misma forma, sin comprobaciones previas: etiquetas.length funciona siempre, tanto si hay tres etiquetas como si no hay ninguna. Si el valor fuese null cuando está vacío, cada lugar que consultase el campo tendría que preguntar antes si existe, y olvidarlo provocaría un TypeError. Además, como aprendiste en la lección anterior, un array vacío es truthy, de modo que if (etiquetas) no distingue una lista llena de una vacía: la comprobación correcta es siempre etiquetas.length === 0, y esa comprobación solo es posible si el campo es siempre un array.
2. ¿Qué ventaja aporta el formato ISO?
Que su orden alfabético coincide con su orden cronológico, porque los componentes van de mayor a menor magnitud (año, mes, día) y llevan ceros a la izquierda. Eso permite ordenar y comparar fechas con los operadores < y > sin ninguna conversión ni librería, tal y como se hace en el ejercicio 2. Con '30/09/2026' la comparación de texto sería absurda: '30/09/2026' < '15/10/2026' sería false, porque compararía '3' con '1'. El formato ISO también es el estándar internacional, el que usan las APIs JSON y el que espera el campo <input type="date"> del navegador.
3. ¿Qué incomodidad has notado?
Que cada tarea necesita ocho variables numeradas (titulo1, titulo2, titulo3...), y que cualquier cálculo sobre el conjunto —sumar horas, contar prioridades, buscar la más urgente— hay que escribirlo repitiendo manualmente los tres casos. Con tres tareas es tedioso; con cuarenta sería imposible. Faltan dos cosas: una manera de agrupar los ocho campos de una tarea en una sola unidad (los objetos, Módulo 4), una manera de agrupar todas las tareas en una sola colección (los arrays, Módulo 4), y una manera de repetir una operación sobre todas ellas sin copiar y pegar (los bucles, Módulo 2). Esa necesidad, sentida en tus propias manos, es exactamente el motivo por el que existen esas herramientas.
Conclusión
Ya conoces el proyecto completo. Sabes qué es Taller Nómada, cuál es su problema real y qué necesitan Marta, Iván y Lucía de la aplicación. Tienes el modelo de datos canónico de una tarea, con sus ocho campos, sus tipos y sus valores permitidos, y entiendes las decisiones de diseño que hay detrás: por qué responsable puede ser null, por qué etiquetas es siempre un array y por qué fechaLimite es un texto en formato ISO. Conoces las diez reglas de negocio que irás implementando, el ciclo de vida de una tarea, el mapa de qué construye cada módulo y la estructura de ficheros hacia la que avanzas.
Con esto cierras el Módulo 1. Empezaste sin haber escrito una línea de JavaScript y terminas con un entorno de desarrollo montado, un proyecto en marcha y la capacidad de declarar, calcular, convertir y comparar los datos de una tarea real. No es poco.
Pero has terminado el módulo con una frustración muy concreta y muy productiva: puedes describir tres tareas, pero no puedes decidir ni repetir. No sabes hacer que el programa compruebe por sí mismo si una transición de estado es válida, ni recorrer una lista de cuarenta tareas sin escribir cuarenta veces lo mismo. Todo tu código se ejecuta de arriba abajo, en línea recta, sin tomar ni una sola decisión.
Eso cambia en el Módulo 2: Estructuras de Control. Empezarás con Sentencias Condicionales, donde aprenderás a que el programa elija un camino u otro —clasificar la prioridad de una tarea, detectar si está vencida, permitir o rechazar un cambio de estado—, y seguirás con los bucles, que te permitirán aplicar esa lógica a todas las tareas de Taller Nómada de una sola vez. Es el momento en el que tu código deja de ser una lista de instrucciones y empieza a comportarse como un programa.
Curso de JavaScript: De Principiante a Avanzado
Módulo 1: Introducción a JavaScript
- ¿Qué es JavaScript?
- Configuración de tu Entorno de Desarrollo
- Tu Primer Programa en JavaScript
- Sintaxis y Conceptos Básicos de JavaScript
- Variables y Tipos de Datos
- Operadores Básicos
- Conversión de Tipos y Comparaciones
- El Proyecto del Curso: Nómada Tareas
Módulo 2: Estructuras de Control
- Sentencias Condicionales
- Bucles: for, while, do-while
- Sentencias Switch
- Control del Flujo: break, continue y Bucles Anidados
- Manejo de Errores con try-catch
Módulo 3: Funciones
- Definición y Llamada de Funciones
- Expresiones de Función y Funciones Flecha
- Parámetros y Valores de Retorno
- Ámbito y Closures
- Hoisting y el Contexto de Ejecución
- Funciones de Orden Superior
- Recursividad
Módulo 4: Objetos y Arrays
- Introducción a los Objetos
- Métodos de Objeto y la Palabra Clave
this - Arrays: Conceptos Básicos y Métodos
- Iteración sobre Arrays
- Buscar, Ordenar y Agregar Datos: find, sort y reduce
- Desestructuración de Arrays
- Desestructuración de Objetos, Spread y Rest
- JSON y Copias de Objetos
Módulo 5: Objetos y Funciones Avanzadas
- Prototipos y Herencia
- Clases y Programación Orientada a Objetos
- Encapsulación: Getters, Setters y Campos Privados
- Módulos e Importación/Exportación
- JavaScript Asíncrono: Callbacks
- Promesas y Async/Await
- El Bucle de Eventos y la Cola de Microtareas
- Iteradores y Generadores
Módulo 6: El Modelo de Objetos del Documento (DOM)
- Introducción al DOM
- Selección y Manipulación de Elementos del DOM
- Manejo de Eventos
- Propagación, Delegación y Eventos Personalizados
- Creación y Eliminación de Elementos del DOM
- Renderizado de Listas y Plantillas HTML
- Manejo y Validación de Formularios
Módulo 7: APIs del Navegador y Temas Avanzados
- Almacenamiento Local y de Sesión
- Fetch API y AJAX
- Peticiones Robustas: Errores, Timeouts y AbortController
- WebSockets
- Service Workers y Aplicaciones Web Progresivas (PWAs)
- APIs del Navegador Esenciales
- Introducción a WebAssembly
Módulo 8: Pruebas y Depuración
- Depuración de JavaScript
- Calidad de Código: ESLint, Prettier y Convenciones
- Pruebas Unitarias con Jest
- Dobles de Prueba: Mocks, Stubs y Spies
- Pruebas de Integración
- Pruebas de Extremo a Extremo con Cypress
Módulo 9: Rendimiento y Optimización
- Medir Antes de Optimizar: DevTools y Web Vitals
- Optimización del Rendimiento de JavaScript
- Gestión de Memoria
- Manipulación Eficiente del DOM
- Carga Perezosa y División de Código
Módulo 10: Frameworks y Librerías de JavaScript
- Por Qué Existen los Frameworks
- Introducción a React
- Gestión de Estado con Redux
- Conceptos Básicos de Vue.js
- Conceptos Básicos de Angular
- Elegir el Framework Adecuado
