Skip to content

Cart

A headless shopping cart implementation using Recoil.

Overview

Cart is based off of a git branch model and has 3 main states, staged, cart and items.

staged

staged is where the current product the user is editing is stored. This product is preformatted to include actions such as add, remove and select.

cart

cart is the main branch that staged products get comitted to. cart also comes with actions.

items

items is the final master branch that is trimmed to include only critical information (no display data). This is what we send to all other services (APIs, SDKs etc).

Usage

The useCart hook returns 5 items.

js
const { stage, staged, commit, cart, items } = useCart();

stage

js
const { stage } = useCart();

stage({ product }); // Product must be a fully hydrated menu product

staged

js
const { staged } = useCart();

console.log(staged);
// {
//     id: 30456,
//     price: 1600,
//     selected: true,
//     uid: "sj234ifeuj8s",
//     name: { text: "Burger" },
//     imageUrl: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
//     count: { current: 1, min: 0, max: 0 },
//     add () => {},
//     remove: () => {},
//     select: () => {},
//     options: [...],
//     customisations: [...],
// }

commit

js
const { commit } = useCart();

commit(); // moves and appends `staged` to `cart`

cart

js
const { cart } = useCart();

console.log(cart); // array of actionable products (see `staged` for example)

items

js
const { items } = useCart();

console.log(items);
//  [
//    {
//         "id": "30733",
//         "price": 13.95,
//         "quantity": 1,
//         "product": {
//           "id": "30733",
//           "type": "combo",
//           "price": 11.45,
//           "name": "Zinger Burger Box",
//           "customisations": [
//             {
//               "productId": "554357",
//               "categoryId": "90115",
//               "name": "Lettuce",
//               "price": 0,
//               "defaultQuantity": 1,
//               "quantity": 1,
//               "providerData": {
//                 "DefaultReason": 1,
//                 "ModifierAction": 0
//               }
//             }
//           ],
//           "comboProducts": [
//             {
//               "id": "40956",
//               "name": "Zinger Burger",
//               "price": 5.95,
//               "customisations": [],
//               "providerData": {}
//             }
//           ],
//           "providerData": {
//             "PromoId": 4002,
//             "MenuItemId": 30733,
//             "SalesItemId": 0
//           }
//         }
//       }
// ]

Lifecycle

The current lifecycle for a hydrated product (product that is passed into stage) to a trimmed product (items) is as follows.

  • Product is formatted to include minimal display information and self updating functions (see notes for more).
  • Product is added to staged

If a user actions a staged product

  • The entire product tree is traversed and changes are made to product based on uid
  • The current tree is replaced by the new, updated tree
  • The tree is re-evaluated for new display information (count updates etc)

When the staged product is commited

  • The staged product is reformatted to include the correct update functions (cart setter instead of staged setter)
  • The staged product is appended to the cart
  • Recoil selector trims the cart and produces items