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