DMarlon Studio

Lección 20 · 20 de 20

Proyecto: carrito de la compra · Dart

Un proyecto en Dart que reúne el curso: un carrito de la compra con mapas, funciones, excepciones, null safety, fold y una expresión switch para el descuento.

Dart · Proyecto: carrito de la compra en DMarlon Studio: el código del ejemplo y su salida en la terminal

Este programa junta lo aprendido en el curso. Los precios de la tienda están en un mapa `const` fuera de main, porque no cambian. El carrito es una lista de líneas producto,unidades, tal como llegarían de un formulario o de un archivo, y tres de ellas tienen errores a propósito.

La función lineCost calcula el coste de una línea. split(',') separa el producto de las unidades; prices[parts[0]] da un double?, porque el producto puede no existir, e int.tryParse da un int?, porque el texto puede no ser un número. Si falta alguno de los dos, o la cantidad no es positiva, `throw` lanza un ArgumentError con un mensaje claro; si no, devuelve precio por unidades. Tras esos if, Dart sabe que ninguno es null.

En main, el bucle suma el coste de cada línea en el mapa totals con (totals[product] ?? 0) + ..., de modo que la leche, que aparece dos veces, se acumula. El `try` con `on ArgumentError catch (e)` atiende las líneas incorrectas: se escriben con Skipped: y el carrito sigue.

Para el tique, forEach escribe cada producto con la función de flecha row, que alinea las columnas con padRight y padLeft. `fold` suma los valores del mapa y una expresión `switch` con patrones >= 20 y >= 10 elige el descuento: con 17,60 euros toca un 5 %, y el total queda en 16.72.

Un buen siguiente paso es darle una pantalla: en DMarlon Studio puede diseñar en el lienzo de teléfono una aplicación Flutter con la lista de productos y un botón de pagar, y reutilizar estas mismas funciones de Dart.

Código · main.dart

const prices = {'bread': 1.20, 'milk': 0.95, 'cheese': 4.50, 'apples': 2.30};// Gives the cost of one "product,units" line, or throws an error.double lineCost(String line) {  var parts = line.split(',');  double? price = prices[parts[0]];  int? units = int.tryParse(parts[1]);  if (price == null) throw ArgumentError('${parts[0]} is not sold here');  if (units == null || units <= 0) throw ArgumentError('bad quantity in "$line"');  return price * units;}String row(String label, double euros) =>    label.padRight(14) + euros.toStringAsFixed(2).padLeft(7);void main() {  var cart = ['bread,2', 'cheese,1', 'milk,x', 'apples,3', 'ham,1', 'milk,4', 'bread,0'];  var totals = <String, double>{};  for (var line in cart) {    var product = line.split(',')[0];    try {      totals[product] = (totals[product] ?? 0) + lineCost(line);    } on ArgumentError catch (e) {      print('Skipped: ${e.message}');    }  }  totals.forEach((product, cost) => print(row(product, cost)));  double subtotal = totals.values.fold(0, (a, b) => a + b);  double rate = switch (subtotal) { >= 20 => 0.10, >= 10 => 0.05, _ => 0.0 };  print('-' * 21);  print(row('Subtotal', subtotal));  print(row('Discount (${(rate * 100).round()}%)', -subtotal * rate));  print(row('TOTAL', subtotal * (1 - rate)));}

Salida · dart run main.dart

Skipped: bad quantity in "milk,x"
Skipped: ham is not sold here
Skipped: bad quantity in "bread,0"
bread            2.40
cheese           4.50
apples           6.90
milk             3.80
---------------------
Subtotal        17.60
Discount (5%)   -0.88
TOTAL           16.72

Para recordar

  • Los datos fijos van en un const fuera de main.
  • double? e int? obligan a pensar en lo que puede faltar.
  • throw en la función y try en el bucle separan el error de su tratamiento.
  • fold suma los valores de un mapa.
  • Una expresión switch convierte el subtotal en un descuento.

Ejercicio

Añada un mapa con el IVA de cada producto (4 para el pan y la leche, 10 para el resto) y escriba en el tique una línea VAT con el impuesto incluido en el total.