Ejercicio: Catálogo y carrito
Objetivo
Escribir tu propio carrito de compras como funciones puras e inmutables (como src/carrito.js): agregar productos, cambiar cantidades, calcular el total en céntimos sin errores de decimales y armar el resumen que verá el cliente.
Cómo se trabaja
La parte A se hace en tu terminal con el código de referencia y te ayuda a ver el problema de los decimales con tus propios ojos. La parte B son cinco funciones de JavaScript puro que se comprueban en esta página.
Una línea del carrito es { id, nombre, precio, cantidad } (el precio en soles). Un carrito es un arreglo de líneas. Reglas:
agregar(carrito, producto, cantidad): si el producto ya está, suma la cantidad a su línea; si no, añade una línea nueva conid,nombre,precioycantidad. La cantidad por defecto es 1. Devuelve un carrito nuevo y no modifica el recibido.cambiarCantidad(carrito, id, cantidad): fija la cantidad de una línea; con 0 o menos, la línea desaparece. Devuelve un carrito nuevo.total(carrito): sumaprecio * cantidaden céntimos enteros (Math.round(precio * 100)) y devuelve el resultado en soles.formatoSoles(monto): devuelve el texto"S/ 12.50"(siempre dos decimales).resumen(carrito): una línea por producto con el formato- 2 x Leche entera 1 L: S/ 8.60, y al finalSubtotal: S/ 12.80. Con el carrito vacío devuelveTu carrito está vacío.
💡 Reto extra
Añade faltaParaDelivery(carrito, minimo) que devuelva cuántos soles faltan para llegar al mínimo de delivery (0 si ya lo alcanzó), calculado en céntimos. Con el mínimo de S/ 25.00 y un carrito de S/ 21.30 debe dar 3.7. Es la cuenta que usa el bot en el mensaje «Te faltan S/ 3.70» (lección 8).
Pasos
Marca cada paso a medida que lo completes. Tu avance se guarda en este navegador.
💡 Pista 1: Inmutable significa copiar
Para agregar una línea nueva usa [...carrito, nueva]. Para cambiar una línea existente usa carrito.map(...) y devuelve { ...linea, cantidad: ... } solo en la que coincide. Nunca hagas carrito.push(...) ni linea.cantidad += ....
💡 Pista 2: Céntimos enteros
Math.round(4.3 * 100) da 430: un entero seguro. Suma todos los centimos * cantidad y divide entre 100 solo al final. Así 0.1 + 0.2 termina siendo 0.3.
💡 Pista 3: toFixed
(12.5).toFixed(2) devuelve "12.50". El subtotal de cada línea también debe salir de céntimos: Math.round(precio * 100) * cantidad / 100.
🔎 Comprueba tu trabajo
Pega tu código y pulsa Comprobar. La revisión ocurre en tu navegador; nada se envía a ningún sitio. Cada punto en rojo incluye una pista. Pega solo el JavaScript, sin las etiquetas <script>.
✅ Ver una solución posible
Intenta resolverlo antes de mirar. Tu versión puede ser distinta y también correcta.
const aCentimos = (soles) => Math.round(soles * 100);
function formatoSoles(monto) {
return `S/ ${monto.toFixed(2)}`;
}
function agregar(carrito, producto, cantidad = 1) {
if (carrito.some((l) => l.id === producto.id)) {
return carrito.map((l) =>
l.id === producto.id ? { ...l, cantidad: l.cantidad + cantidad } : l,
);
}
return [...carrito, { id: producto.id, nombre: producto.nombre, precio: producto.precio, cantidad }];
}
function cambiarCantidad(carrito, id, cantidad) {
if (cantidad <= 0) return carrito.filter((l) => l.id !== id);
return carrito.map((l) => (l.id === id ? { ...l, cantidad } : l));
}
function total(carrito) {
const centimos = carrito.reduce((suma, l) => suma + aCentimos(l.precio) * l.cantidad, 0);
return centimos / 100;
}
function resumen(carrito) {
if (carrito.length === 0) return "Tu carrito está vacío.";
const lineas = carrito.map((l) => {
const subtotal = (aCentimos(l.precio) * l.cantidad) / 100;
return `- ${l.cantidad} x ${l.nombre}: ${formatoSoles(subtotal)}`;
});
return `${lineas.join("\n")}\nSubtotal: ${formatoSoles(total(carrito))}`;
}