Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/alex-pizza-assistant/llms.txt

Use this file to discover all available pages before exploring further.

The Alex Pizza Assistant drives every conversation through a linear sequence of named steps defined in the steps[] array inside app.js. The app starts at index 0 and advances one step at a time via advanceStep(), but it is not purely sequential — three branching points exist: the addAnother loop that sends the user back to size for a second pizza, the paymentMethod fork that routes cash orders directly to completion, and the cardCvv fork that only asks for a tip on delivery orders. Understanding this array is the foundation for understanding everything else in the app.

The Steps Array

The following array is defined at the top of app.js and contains every question the chatbot will ever ask, along with its validator and error message.
const steps = [
  { id: "userName",       label: "Enter your name:", ... },
  { id: "size",           label: "What size pizza do you want? Enter small, medium, or large:", ... },
  { id: "toppings",       label: "Enter any toppings you want on your pizza...", ... },
  { id: "crustType",      label: "Enter the type of crust you want: thin, thick, pan, or deep dish:", ... },
  { id: "quantity",       label: "How many of these pizzas do you want to order? Enter a numeric value:", ... },
  { id: "addAnother",     label: "Would you like to order a different pizza or add another one?", ... },
  { id: "method",         label: "Is this carry out or delivery?", ... },
  { id: "paymentMethod",  label: "Will you be paying with cash or card?", ... },
  { id: "cardNumber",     label: "Enter your credit/debit card number for this demo payment:", ... },
  { id: "cardExpiration", label: "Enter the card expiration date as MM/YY:", ... },
  { id: "cardCvv",        label: "Enter the 3 or 4 digit security code:", ... },
  { id: "tip",            label: "Would you like to add a tip for your delivery driver?...", ... }
];

Step Sequence

The logical path through the steps, including all branch points, is shown below.
1

userName

Alex greets the customer by name. The conversation cannot begin with a blank name.
2

size → toppings → crustType → quantity

The four pizza-building questions run in sequence. When quantity is answered, addCurrentPizzaToOrder() pushes the completed pizza into order.pizzas[] and the bot confirms what was added.
3

addAnother (branch)

Yesorder.currentPizza is reset to a blank pizza and currentStep jumps back to size. The pizza-building loop repeats.NocurrentStep advances to method.
4

method

The customer chooses carry out or delivery. This choice is recorded once and applies to every pizza already in the order.
5

paymentMethod (branch)

Card — advances to cardNumber.Cash — the bot shows the appropriate pickup or delivery message and finishOrder() is called immediately. Card steps are skipped entirely.
6

cardNumber → cardExpiration → cardCvv

The three card fields are collected in sequence. After cardCvv, the bot displays a simulated approval using the last four digits of the card number.
7

tip (delivery + card only)

Only reached when order.method === "delivery" after cardCvv. For carry out card orders, finishOrder() is called right after cardCvv.
8

finishOrder()

Totals are calculated, thank-you bubbles are shown, the coupon threshold is checked, and the ETA countdown runs.
The order method (carry out or delivery) is chosen a single time — after all pizzas have been added — and it applies uniformly to every pizza in the order. There is no per-pizza delivery option.

State Object

All data collected during a session lives in the order object. It is declared at the top of app.js and mutated in place throughout the conversation.
const order = {
  userName: "",          // customer's name (string)
  pizzas: [],            // completed pizza objects pushed by addCurrentPizzaToOrder()
  currentPizza: {        // working pizza being built (reset on each addAnother loop)
    size: "",
    toppings: "",
    crustType: "",
    quantity: ""
  },
  addAnother: "",        // "yes" | "no" — normalized by normalizeValue()
  method: "",            // "carry out" | "delivery"
  paymentMethod: "",     // "cash" | "card"
  cardLastFour: "",      // last 4 digits of entered card number
  tip: 0,                // numeric dollar amount (delivery + card only)
  subtotal: 0,           // sum of price × quantity for all pizzas
  tax: 0,                // subtotal × 0.10
  deliveryFee: 0,        // $5.00 for delivery, $0 for carry out
  total: 0               // subtotal + tax + deliveryFee + tip
};

Branching Logic

The advanceStep() function is the sole place where currentStep is mutated. It reads the step id and the normalized value to decide which step to jump to next.
function advanceStep(id, value) {
  if (id === "quantity") {
    currentStep = getStepIndex("addAnother");

  } else if (id === "addAnother") {
    if (value === "yes") {
      order.currentPizza = createBlankPizza();
      order.addAnother = "";
      currentStep = getStepIndex("size");   // loop back
    } else {
      currentStep = getStepIndex("method"); // proceed to checkout
    }

  } else if (id === "method") {
    currentStep = getStepIndex("paymentMethod");

  } else if (id === "paymentMethod") {
    if (value === "card") {
      currentStep = getStepIndex("cardNumber");
    } else {
      finishOrder(); // cash path — end immediately
      return;
    }

  } else if (id === "cardCvv") {
    if (order.method === "delivery") {
      currentStep = getStepIndex("tip");    // ask for tip
    } else {
      finishOrder(); // carry out card — end after CVV
      return;
    }

  } else if (id === "tip") {
    finishOrder();
    return;

  } else {
    currentStep += 1; // default: move one step forward
  }

  showCurrentStep();
}
addAnother loop — when the user answers yes (or y), currentPizza is wiped clean and the step pointer rewinds to size. This can repeat as many times as the customer wants. Cash vs card branch — when paymentMethod normalizes to "cash", no card fields are ever shown. finishOrder() fires immediately, skipping cardNumber, cardExpiration, cardCvv, and tip. Delivery tip branch — after cardCvv, the app checks order.method. Only a "delivery" order proceeds to tip; a carry out card order ends at CVV.

Completion

finishOrder() is called from three places in advanceStep(): after paymentMethod (cash), after cardCvv (carry out + card), and after tip (delivery + card).
function finishOrder() {
  calculateTotals();
  updateReceipt();

  addBubble(`Thank you, ${order.userName}, for your order.`, "bot");
  addBubble(`Your order total is ${formatMoney(order.total)}.`, "result");

  if (order.paymentMethod === "card") {
    addBubble("Your card payment has been processed for this demo order.", "bot");
  }

  if (order.total >= 50) {
    addBubble("Congratulations! You've been awarded a $10 off coupon for your next order.", "bot");
  } else {
    addBubble("Orders over $50 receive a free $10 off coupon.", "bot");
  }

  runFastEta();

  chatInput.disabled = true;
  chatForm.querySelector("button").disabled = true;
  questionLabel.textContent = "Order complete. Start over if you want to place another order.";
  orderStatus.textContent = "Complete";
}
finishOrder() performs these actions in order:
  1. Calls calculateTotals() one final time to ensure the receipt is up to date.
  2. Adds a thank-you bubble with the customer name and a result bubble showing the grand total.
  3. For card orders, adds a simulated “payment processed” confirmation.
  4. Coupon check — if order.total >= 50, the customer is awarded a $10 off coupon message; otherwise, the app displays a reminder that the threshold has not been reached.
  5. Calls runFastEta(), which uses setTimeout to inject a series of ETA countdown bubbles at 450 ms intervals, ending with either “Your driver is on the way!” (delivery) or “Order is ready for pickup!” (carry out).
  6. Disables the input and submit button, locking the chat for the completed session.

Build docs developers (and LLMs) love