Order Form

Sales & Marketing

Sell your products online: the user picks a product & quantity and then makes a payment, all within the form.

Build
Build on this example by creating an editable copy of this form.
// This is just a static JSON file for this example, but it _could_ be an interface
// to your backend inventory system, allowing you to provide availability estimates
// and up-to-date prices.
let inventoryEndpoint = `https://prod.static.formulate.dev/gallery/order-form/inventory.json`;

let menu = {
  Cookware: ["Saucepan", "Sauté Pan", "Skillet", "Stock Pot"],
  Bakeware: ["Cake Tin", "Cupcake Tray"],
  Tools: ["Chef's Knife", "Paring Knife"],
};

let toOptions = (items, inventory) => {
  return items.map((item) => ({
    label: `${item}: ($${inventory[item].price / 100})`,
    value: item,
    image: `https://prod.static.formulate.dev/gallery/order-form/${item}.png`,
  }));
};

export default async function () {
  await form.statement("Welcome to our kitchen supply store!", {
    buttonText: "Get started",
    banner: {
      full: true,
      imageUrl: "https://prod.static.formulate.dev/gallery/patterns/2.png",
    },
  });

  let response = await form.fetch(inventoryEndpoint);
  let inventory = JSON.parse(response.text);

  let { value: category } = await form.multi(
    "Let's get started! What are you looking for?",
    _.keys(menu),
    { single: true }
  );

  let { value: item } = await form.multi(
    "Perfect, here's what we have in stock",
    toOptions(menu[category], inventory),
    { single: true }
  );
  let { value: quantity } = await form.multi(
    `**${item}**? Great choice! How many do you want to buy?`,
    [1, 2, 3, 4, 5],
    { single: true, hideNumbers: true, name: "Quantity" }
  );
  let price = inventory[item].price;
  let total = (quantity * price) / 100;

  await form.statement(`Ok, that'll be $${total}. Please confirm below.`, {
    buttonText: "Confirm",
  });

  await form.statement("Thanks! We need to collect some details from you so can we can ship this over to you as soon as possible.");

  let { text: countries } = await form.fetch("https://prod.static.formulate.dev/gallery/countries.json");
  let countryOptions = JSON.parse(countries).map((c) => c.Name);

  await form.short("First, your email address!", { email: true });
  let streetAddress = await form.short("Your street address:");
  let city = await form.short("City:");
  let zipCode = await form.short("ZIP code:", { number: true });
  let { value: country } = await form.select("and country:", countryOptions, { single: true });

  let {status} = await form.payment("Here's a final summary of your order:", {
    description: `
- Item: ${item} ($${price / 100})
- Quantity: ${quantity}
- Address: ${streetAddress}, ${city} ${zipCode}, ${country}
    `,
    buttonText: "Purchase",
    currency: "usd",
    items: [{
      amount: price,
      name: item,
      quantity: quantity,
      imageUrls: [`https://prod.static.formulate.dev/gallery/order-form/${item}.png`],
    }],
  });

  if (status === 'successful') {
    await form.statement("Your payment was successful!", {
      description: `We'll send you an email to confirm, and you should receive the ${item} soon.`,
      buttonText: 'Submit',
    });
  } else {    
    await form.statement("Oops, looks like your payment failed! ", {
      description: `Click below to submit your order anyway, someone will be in touch within 24 hours.`,
      buttonText: 'Submit',
    });
  }
}