Back to Top

How to create Odoo cart page using ReactJS

Updated 1 October 2024

To create a cart page for an Odoo-based headless eCommerce app using ReactJS. Below is a high-level overview to develop cart page and example code snippets to guide you through the process.

First, add the product to the cart from the Odoo product page for a seamless shopping experience.

Introduction

Odoo offers a range of API endpoints that allow you to perform different actions like ‘products’‘category-list’, and ‘cart’ but we’ll work with the ‘cart’ endpoint.

Basically, the Odoo API is normally the Rest API which provides the Odoo headless eCommerce services and serves as the bridge between your application and the Odoo Platform.

Getting Start

We will guide you through this blog step-by-step that how to create product page using Odoo API.

Searching for an experienced
Odoo Company ?
Find out More
  1. Setup ReactJs Project
  2. Setup Tailwind CSS
  3. Setup React Router
  4. Create Cart Page
  5. Mount Cart Page
  6. Run React App

Step 1. Set Up your ReactJs Project

First, you need a solid foundation for your React application. Use Create React App to bootstrap your project easily. This tool configures everything you need to start building a React app.

Open your terminal and type below the command.

npx create-react-app odoo-cart-page

Navigate the Project Directory.

After the setup is complete, navigate into your project folder:

cd odoo-cart-page

Step 2: Setup Tailwind CSS

You need to implement the Tailwind CSS to effective cart page design and its Dev dependencies. Use the following command:

npm install -D tailwindcss postcss autoprefixer

Run the following command to generate the tailwind.config.js and postcss.config.js files:

npx tailwindcss init -p

Configure Tailwind CSS

Open tailwind.config.js and update the content array to include paths to your template files. This allows Tailwind to purge unused styles in production:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}", // Adjust if needed
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

In the src directory, open the index.css file and add the following lines to import tailwind’s base, components, and utilities styles:

@tailwind base;
@tailwind components;
@tailwind utilities;

Over all setup the project, and you can see the final folder structure.

.
├── src/
│   ├── App.js
│   ├── App.css
│   ├── App.test.js
|   ├── index.js
|   ├── index.css
│   └── logo.svg
├── public/
│   ├── index.html
│   ├── logo.svg
│   ├── robots.txt
│   └── manifest.json
├── package-lock.json
├── package.json
├── tailwind.config.js
└── README.md

Step 3: Setup the React Router

React Router is used to define multiple routes in the application, so you need to install the react router library. Run the following command in your project directory.

npm install react-router-dom

Open App.js File and replace the code to import BrowserRouterRoute, and Routes for displaying the router component.

import "./App.css";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Layout from "./pages/Layout";

function App() {
  return (
    <>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Layout />}>
            <Route index element={<h1> Render home page </h1>} />
          </Route>
        </Routes>
      </BrowserRouter>
    </>
  );
}

export default App;

After this you can create the layout for cart page and other pages like Home and product page.

We’ll start by creating a file named Layout.js in the src/pages folder.

import { Outlet, Link } from "react-router-dom";

const Layout = () => {
  return (
    <>
       {/* You can add the Header Here */}
      <div className="container mx-auto min-h-[50vh]">
        <Outlet />
      </div>
      {/* You can add the Footer Here */}
    </>
  );
};

export default Layout;

Step 4: Create the Cart Page Component

We’ll start by creating a file named Cart.js in the src/pages folder.

This component in React displays the product details, including the image, description, quantity, and total price. Users can choose to proceed to checkout or continue shopping.

import { useEffect, useState } from "react";
import { Link } from "react-router-dom";

const Cart = () => {
  const [cart, setCart] = useState();
  const oddApi="<Odoo-API-Domain>";
  const authenticate ="<API-Authenticate-Key>";
  const cartId = "<Cart-Id>";

  const postData = () => {
    fetch(`${odooAPI}`, {
      method: "GET",
      headers: {
        "Content-Type": "application/json; charset=utf-8",
        Authenticate: authenticate,
        cartid: cartId,
      },
    })
      .then((response) => {
        if (!response.ok) {
          throw new Error("Network response was not ok");
        }
        return response.json();
      })
      .then((data) => {
        console.log("Response Data:", data);
        setCart(data);
      })
      .catch((error) => {
        console.error("Response Error:", error);
      });
  };

  useEffect(() => {
    postData();
  }, []);
  const cartData = cart?.customerCart?.items;
  const prices = cart?.customerCart?.prices;
  const stepperCls =
    "flex w-full items-center text-teal-600 after:inline-block after:h-0.5 after:w-full after:border after:border-b after:border-gray-200 after:content-['']";
  const stepCls =
    "flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 border-solid border-gray-200";
  return (
    <div>
      <ol className="mx-auto flex max-w-[86%] items-center py-6">
        <li className={stepperCls}>
          <span className={stepCls}>
            <div className="h-2.5 w-2.5 rounded-full bg-teal-600"></div>
          </span>
        </li>
        <li className={stepperCls}>
          <span className={stepCls}>
            <div className="h-2.5 w-2.5 rounded-full bg-white"></div>
          </span>
        </li>

        <li className={stepperCls}>
          <span className={stepCls}>
            <div className="h-2.5 w-2.5 rounded-full bg-white"></div>
          </span>
        </li>
      </ol>
      <div className="mx-auto max-w-[86%] pb-8">
        <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
          <div className="lg:col-span-2">
            <table className="w-full border-collapse text-left">
              <thead>
                <tr className="border-b">
                  <th className="pb-2">Product</th>
                  <th className="pb-2">Quantity</th>
                  <th className="pb-2">Price</th>
                </tr>
              </thead>
              <tbody>
                {Array.isArray(cartData) &&
                  cartData.length > 0 &&
                  cartData.map((value, index) => (
                    <tr key={index} className="border-b">
                      <td className="flex items-start py-2">
                        <img
                          src={value?.product?.thumbnail.url}
                          alt="Warranty"
                          className="mr-4 h-16 w-16"
                        />
                        <div>
                          <div className="line-clamp-2 font-semibold text-teal-700">
                            {value.product.name}
                          </div>
                          <p className="line-clamp-2 text-sm text-gray-600">
                            {value.product.short_description}
                          </p>
                        </div>
                      </td>
                      <td className="py-2">
                        <div className="flex items-center">
                          <button className="rounded border px-4 py-0.5">
                            -
                          </button>
                          <span className="mx-2">{value?.quantity}</span>
                          <button className="rounded border px-4 py-0.5">
                            +
                          </button>
                        </div>
                      </td>
                      <td className="py-2 text-right">
                        ${value?.product?.prices?.price?.value.toFixed(2)}
                      </td>
                    </tr>
                  ))}
              </tbody>
            </table>
            <div className="flex justify-between gap-2">
              <button className="mt-6 rounded bg-gray-700 px-6 py-2 text-white shadow-lg">
                <Link to="shop"> Continue Shopping</Link>
              </button>
              <button className="mt-6 rounded bg-teal-700 px-6 py-2 text-white shadow-lg">
                <Link to="checkout"> Proceed to Checkout</Link>
              </button>
            </div>
          </div>

          <div className="max-h-fit rounded border bg-white p-6 shadow-sm lg:col-span-1">
            <h3 className="mb-4 text-lg font-semibold">Order Total</h3>
            <div className="mb-2 flex justify-between">
              <span>Subtotal:</span>
              <span>${prices?.subtotal_excluding_tax?.value.toFixed(2)}</span>
            </div>
            {Array.isArray(prices?.applied_taxes) &&
              prices?.applied_taxes.length > 0 &&
              prices?.applied_taxes.map((price, index) => (
                <div key={index} className="mb-2 flex justify-between">
                  <span>Taxes:</span>
                  <span>${price?.value.toFixed(2)}</span>
                </div>
              ))}

            <div className="flex justify-between border-t py-2 text-lg font-semibold">
              <span>Total:</span>
              <span>${prices?.grand_total?.value.toFixed(2)}</span>
            </div>

            <div className="mt-4">
              <a href="#" className="text-sm text-teal-700 underline">
                Discount code or gift card
              </a>
            </div>
            <button className="mt-4 w-full rounded bg-teal-700 px-6 py-3 text-white shadow-lg">
              <Link to="checkout"> Proceed to Checkout</Link>
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};

export default Cart;

Step 5: Mount Cart Page.

Open App.js File and Mention the component in the routes to navigate and displaying the cart page.

import "./App.css";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Layout from "./pages/Layout";
import Cart from "./pages/Shop/Cart";

function App() {
  return (
    <>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Layout />}>
            <Route index element={<h1> Render home page </h1>} />
            <Route path="shop/cart" element={<Cart />} />
          </Route>
        </Routes>
      </BrowserRouter>
    </>
  );
}

Step 6: Run your React app.

Run the following command to see the cart page in the terminal, and then check the React app in your browser.

npm run start
The final of the terminal of launch the app.

Note:- Navigate the cart page at http://localhost:3000/shop/cart

The final output of the cart page.
Mobile view for cart page output.

Conclusion

Congratulations! You’ve successfully learn how to create an odoo Cart page in React JS.

Start your Headless Development with Webkul.

Thanks for reading this blog.

Hope this blog helped you to better understand how to create an odoo Cart page in React Js.

Happy Coding!!

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home