The Power of Promises with Next.js: Building a Pizza Delivery App 🍕
Tags: javascript, tutorial, nextjs, beginners
Published: 2023-06-06 16:45:54

## The Power of Promises with Next.js: Building a Pizza Delivery App

In this blog post, we'll explore the power of promises in Next.js by building a Pizza Delivery App. Promises allow us to handle asynchronous operations in a more elegant and structured way, making our code more readable and maintainable. We'll dive into each function of the code and understand how promises are utilized to simulate API calls for adding, editing, and deleting orders.

---

The full code for our Pizza Delivery App component can be found on [GitHub](https://github.com/bobbyhalljr/pizza-ordering-app).

**Live Demo**: 
Check it for yourself here: [Pizza Ordering App Demo](pizza-ordering-app-mu.vercel.app)

---

## The PizzaOrder Component

The core of our Pizza Delivery App is the `PizzaOrder` component. This component handles the pizza order functionality, including selecting pizzas, placing orders, displaying order status, and managing the order history. Let's break down each function and understand how promises are used.

### takeOrder Function

The `takeOrder` function is responsible for adding a pizza to the cart. Here's the code:

```javascript
const takeOrder = (pizza) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const isAvailable = checkAvailability(pizza);

      if (isAvailable) {
        const updatedCart = [...cart, pizza];
        setCart(updatedCart);
        resolve(pizza);
      } else {
        reject(new Error('Sorry, the pizza is not available.'));
      }
    }, 2000);
  });
};
```

Here, we create a new promise that wraps the asynchronous operation of adding a pizza to the cart. We simulate this operation using `setTimeout()` for a delay of 2000 milliseconds (2 seconds). Inside the timeout function, we check the availability of the pizza using the `checkAvailability` function. If the pizza is available, we update the cart and resolve the promise with the added pizza. Otherwise, we reject the promise with an error message.

### checkAvailability Function

The `checkAvailability` function simply checks if the selected pizza is available. Here's the code:

```javascript
const checkAvailability = (pizza) => {
  const availablePizzas = ['Margherita', 'Pepperoni', 'Vegetarian'];
  return availablePizzas.includes(pizza);
};
```

In this function, we define an array of available pizzas and check if the selected pizza exists in the array using the `includes` method. The function returns a boolean value indicating the availability of the pizza.

### processOrder Function

The `processOrder` function handles the processing of the order. It checks if the cart is empty and resolves the promise with the cart items if it's not empty. Here's the code:

```javascript
const processOrder = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (cart.length >= 0) {
        resolve(cart);
      } else {
        reject(new Error('Cart is empty. Please add pizzas to your order.'));
      }
    }, 1500);
  });
};
```

Similar to the `takeOrder` function, we create a promise and simulate an API call using `setTimeout()`. Inside the timeout function, we check if the cart has any items. If it does, we resolve the promise with the cart items. Otherwise, we reject the promise with an error message.

### handleOrder Function

The `handleOrder` function is the event handler for placing an order. It utilizes the `takeOrder` and `processOrder` functions to add the selected pizza to the cart and process the order. Here's the code:

```javascript
const handleOrder = async () => {
  try {
    setOrderStatus('Placing order...');

    const order = await takeOrder(selectedPizza);
    console.log(`Successfully added ${order} to the cart.`);

    const processedOrder = await processOrder();
    console.log('Your order is ready!');
    console.log('Ordered Pizzas:', processedOrder);

    setOrderStatus('Order placed successfully!');
  } catch (error) {
    console.error(error.message);
    setOrderStatus('Failed to place order.');
  }
};
```

In this function, we set the order status to "Placing order..." to indicate the ongoing process. We then use `await` to call the `takeOrder` function and add the selected pizza to the cart. Once the pizza is added, we log a success message and call the `processOrder` function to process the order. Finally, we update the order status based on the outcome of the order placement.

### handleEditOrder Function

The `handleEditOrder` function is triggered when the user clicks the "Edit" button for a specific order. It opens a modal to edit the pizza name. Here's the code:

```javascript
const handleEditOrder = (index) => {
  setEditIndex(index);
  setNewPizzaName(cart[index]);
  setEditModalOpen(true);
};
```

In this function, we set the `editIndex` state to the index of the order being edited. We also set the `newPizzaName` state to the current pizza name, and open the edit modal by setting the `editModalOpen` state to `true`.

### handleDeleteOrder Function

The `handleDeleteOrder` function is triggered when the user clicks the "Delete" button for a specific order. It opens a confirmation modal before deleting the order. Here's the code:

```javascript
const handleDeleteOrder = (index) => {
  setEditIndex(index);
  setDeleteModalOpen(true);
};
```

Similar to the `handleEditOrder` function, we set the `editIndex` state to the index of the order being deleted and open the delete modal by setting the `deleteModalOpen` state to `true`.

### handleConfirmEdit Function

The `handleConfirmEdit` function is called when the user confirms the edit in the edit modal. It updates the cart with the new pizza name. Here's the code:

```javascript
const handleConfirmEdit = () => {
  try {
    const updatedCart = [...cart];
    updatedCart[editIndex] = newPizzaName;
    setCart(updatedCart);
    setEditModalOpen(false);
    setOrderStatus('Order edited successfully!');
  } catch (error) {
    console.error(error.message);
    setOrderStatus('Failed to edit order.');
  }
};
```

In this function, we create a new array `updatedCart` using the spread operator to copy the existing cart. We update the pizza name at the specified index with the `newPizzaName` state. Finally, we update the cart, close the edit modal, and set the order status accordingly.

### handleConfirmDelete Function

The `handleConfirmDelete` function is called when the user confirms the deletion in the delete modal. It removes the order from the cart. Here's the code:

```javascript
const handleConfirmDelete = () => {
  try {
    const updatedCart = [...cart];
    updatedCart.splice(editIndex, 1);
    setCart(updatedCart);
    setDeleteModalOpen(false);
    setOrderStatus('Order deleted successfully!');
  } catch (error) {
    console.error(error.message);
    setOrderStatus('Failed to delete order.');
  }
};
```

In this function, we create a new array `updatedCart` using the spread operator to copy the existing cart. We use the `splice` method to remove the order at the specified index. Finally, we update the cart, close the delete modal, and set the order status accordingly.

## Conclusion

In this blog post, we explored the power of promises in Next.js by building a Pizza Delivery App. We learned how promises can be used to handle asynchronous operations in a structured and readable manner. By using promises and simulating API calls with `setTimeout()`, we were able to add, edit, and delete orders seamlessly. Leveraging promises helps improve code organization, maintainability, and overall developer experience.

---

The full code for our Pizza Delivery App component can be found on [GitHub](https://github.com/bobbyhalljr/pizza-ordering-app).

**Live Demo**: 
Check it for yourself here: [Pizza Ordering App Demo](pizza-ordering-app-mu.vercel.app)

--- 

### **Subscribe to my newsletter where you will get tips, tricks and challenges to keep your skills sharp. [Subscribe to newsletter](https://prodigious-innovator-1238.ck.page/25e4b3fdce)**