JavaScript de Cero a Experto / DOM a fondo
Reto: Mi Bolsillo en pantalla
Seis módulos viviendo en la consola se acabaron hoy: vas a renderizar "Mi Bolsillo" en una página de verdad — la lista de gastos construida desde el array, con formato colombiano, clases según el dato y total calculado. El mismo patrón con el que se pinta cualquier app del mundo real.
Reto
Mi Bolsillo en pantalla
Qué debes construir
Con estos datos de partida:
const gastos = [
{ nombre: "Almuerzo", valor: 18000, categoria: "comida" },
{ nombre: "Bus", valor: 5800, categoria: "transporte" },
{ nombre: "Café", valor: 4500, categoria: "comida" },
{ nombre: "Cine", valor: 25000, categoria: "ocio" },
{ nombre: "Mercado", valor: 92000, categoria: "comida" },
];Debes producir exactamente esta página (los gastos que superan $ 20.000 van resaltados en ámbar):
<h1 id="titulo"></h1>
<ul id="lista"></ul>
<p class="resumen">Total: <strong id="total"></strong></p>
<p class="resumen" id="nota"></p>body { font-family: system-ui; padding: 24px; background: #0b1120; color: #f1f5f9; }
h1 { font-size: 24px; margin: 0 0 14px; }
li { margin: 6px 0; color: #cbd5e1; }
.caro { color: #f59e0b; font-weight: 700; }
.resumen { color: #94a3b8; }
.resumen strong { color: #f1f5f9; }const gastos = [
{ nombre: "Almuerzo", valor: 18000, categoria: "comida" },
{ nombre: "Bus", valor: 5800, categoria: "transporte" },
{ nombre: "Café", valor: 4500, categoria: "comida" },
{ nombre: "Cine", valor: 25000, categoria: "ocio" },
{ nombre: "Mercado", valor: 92000, categoria: "comida" },
];
const cop = new Intl.NumberFormat("es-CO", {
style: "currency",
currency: "COP",
maximumFractionDigits: 0,
});
document.querySelector("#titulo").textContent = "Mi Bolsillo";
const items = gastos.map((gasto) => {
const item = document.createElement("li");
item.textContent = `${gasto.nombre} — ${cop.format(gasto.valor)}`;
item.dataset.categoria = gasto.categoria;
if (gasto.valor > 20000) item.classList.add("caro");
return item;
});
document.querySelector("#lista").append(...items);
const total = gastos.reduce((acum, gasto) => acum + gasto.valor, 0);
document.querySelector("#total").textContent = cop.format(total);
const caros = document.querySelectorAll(".caro").length;
document.querySelector("#nota").textContent = `Gastos por encima de $ 20.000: ${caros}`;El HTML de partida ya trae los contenedores vacíos (#titulo, #lista,
#total, #nota) y el CSS ya define la clase .caro. TODO lo demás sale
de JavaScript. Requisitos:
- El
h1#titulodice "Mi Bolsillo" puesto contextContent. - Un formateador
Intl.NumberFormatde pesos colombianos (es-CO,COP, sin decimales) creado UNA sola vez. - Cada gasto se convierte en un
liconcreateElement: textonombre — valor formateado. - Cada
lilleva sudataset.categoria, y la clasecaro(conclassList) SOLO si el valor supera 20000. - Los
lientran a la lista con UNA sola inserción:append(...items)oDocumentFragment— nada deappenddentro del bucle. - El total se calcula con
reducey se pinta formateado en#total. #notamuestra cuántos gastos quedaron resaltados — contándolos en el DOM conquerySelectorAll(".caro"), no en el array.
Reglas
- Cero
innerHTML: todo entra concreateElement+textContent(los datos podrían venir de un usuario mañana). - La plata solo la formatea
Intl— nunca a mano. - El estilo del resaltado vive en el CSS (
.caro); JS solo pone la clase. - Usa el patrón
iniciarpara esperar el DOM.
30:00
Cuando estés listo, arranca el reloj.
Qué sigue
Tu página ya se pinta sola desde los datos… pero es una foto: no reacciona a nada. El módulo 8 le da vida de verdad: eventos y listeners — clicks, teclas, formularios — para que "Mi Bolsillo" deje de ser un reporte y se vuelva una aplicación que responde al usuario.