Saltar al contenido
Chatbots de WhatsApp desde cero
Temario

Ejercicio: Catálogo y carrito

  • ⏱ 50 minutos
  • 📶 Nivel: intermedio

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:

💡 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).

▶ Prueba tu código aquí (opcional)
Consola

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.

    carrito.js
    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))}`;
    }