javascript 46 lines · 8 steps

How a cart total is calculated with discounts

A single function turns line items and an optional promo code into a rounded, itemized total.

Explained by highlit
1const DISCOUNT_CODES = {
2 SAVE10: { type: 'percent', value: 0.1 },
3 WELCOME5: { type: 'fixed', value: 5 },
4 FREESHIP: { type: 'shipping', value: Infinity },
5};
6 
7function calculateCart(items, { taxRate = 0.08, shipping = 0, code = null } = {}) {
8 const subtotal = items.reduce(
9 (sum, item) => sum + item.price * item.quantity,
10 0
11 );
12 
13 let discount = 0;
14 let shippingCost = shipping;
15 const promo = code ? DISCOUNT_CODES[code.trim().toUpperCase()] : null;
16 
17 if (code && !promo) {
18 throw new Error(`Invalid discount code: ${code}`);
19 }
20 
21 if (promo) {
22 if (promo.type === 'percent') {
23 discount = subtotal * promo.value;
24 } else if (promo.type === 'fixed') {
25 discount = Math.min(promo.value, subtotal);
26 } else if (promo.type === 'shipping') {
27 shippingCost = Math.max(0, shipping - promo.value);
28 }
29 }
30 
31 const discountedSubtotal = subtotal - discount;
32 const tax = discountedSubtotal * taxRate;
33 const total = discountedSubtotal + tax + shippingCost;
34 
35 const round = (n) => Math.round(n * 100) / 100;
36 
37 return {
38 subtotal: round(subtotal),
39 discount: round(discount),
40 tax: round(tax),
41 shipping: round(shippingCost),
42 total: round(total),
43 };
44}
45 
46export { calculateCart, DISCOUNT_CODES };
01 / 01
STEP 01

Walkthrough

Space play ←→ step click any line
Three takeaways
  1. 1A lookup table keyed by code lets you add promo types without touching the calculation logic.
  2. 2Validating unknown codes early with a thrown error keeps invalid state out of the math.
  3. 3Rounding only at the output boundary avoids compounding floating-point drift across intermediate sums.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How a cart total is calculated with discounts — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code