Build a Fully Functional Shopping Cart in Next.js + Chatgpt Using Context API

Building an e-commerce site in Next.js? You need a cart system that can:
✅ Add, remove, and update items
✅ Calculate total price
✅ Persist data using localStorage
✅ Support a clean and scalable architecture

https://www.youtube.com/watch?v=D2ZcEHXI7RI

🛠️ Step 1: Create the Cart Context

"use client";
import { createContext, useContext, useEffect, useState } from "react";

const CartContext = createContext();

export const CartProvider = ({ children }) => {
  const [cart, setCart] = useState([]);

  useEffect(() => {
    const savedCart = JSON.parse(localStorage.getItem("cart")) || [];
    setCart(savedCart);
  }, []);

  useEffect(() => {
    localStorage.setItem("cart", JSON.stringify(cart));
  }, [cart]);

  const addToCart = (product) => {
    setCart((prevCart) => {
      const existingItem = prevCart.find((item) => item.id === product.id);
      if (existingItem) {
        return prevCart.map((item) =>
          item.id === product.id ? { ...item, quantity: item.quantity + 1 } : item
        );
      } else {
        return [...prevCart, { ...product, quantity: 1 }];
      }
    });
  };

  const removeFromCart = (id) => {
    setCart((prevCart) => prevCart.filter((item) => item.id !== id));
  };

  const updateQuantity = (id, quantity) => {
    setCart((prevCart) =>
      prevCart.map((item) => (item.id === id ? { ...item, quantity } : item))
    );
  };

  const totalPrice = cart.reduce((total, item) => total + item.price * item.quantity, 0);

  const clearCart = () => setCart([]);

  return (
    <CartContext.Provider value={{ cart, addToCart, removeFromCart, updateQuantity, totalPrice, clearCart }}>
      {children}
    </CartContext.Provider>
  );
};

export const useCart = () => useContext(CartContext);

📌 Step 2: Wrap the Application with CartProvider

🛒 Step 3: Add an "Add to Cart" Button to Your Products

'use client';
import Image from 'next/image';

const products = [
  {
    id: 1,
    name: 'Wireless Headphones',
    price: '$99.99',
    image: 'https://via.placeholder.com/150',
  },
  {
    id: 2,
    name: 'Smart Watch',
    price: '$149.99',
    image: 'https://via.placeholder.com/150',
  },
  {
    id: 3,
    name: 'Gaming Mouse',
    price: '$49.99',
    image: 'https://via.placeholder.com/150',
  },
  {
    id: 4,
    name: 'Mechanical Keyboard',
    price: '$129.99',
    image: 'https://via.placeholder.com/150',
  },
];

const ProductCard = () => {
const { addToCart } = useCart();
  return (
    <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6 p-6">
      {products.map((product) => (
        <div key={product.id} className="border rounded-lg p-4 shadow-lg bg-white">
          <Image
            src={product.image}
            alt={product.name}
            width={150}
            height={150}
            className="w-full h-40 object-cover rounded-md"
          />
          <h2 className="text-lg font-semibold mt-2">{product.name}</h2>
          <p className="text-gray-600">{product.price}</p>
          <button onClick={() => addToCart(product)} className="mt-3 bg-blue-500 text-white px-4 py-2 rounded-lg hover:bg-blue-600">
            Add to Cart
          </button>
        </div>
      ))}
    </div>
  );
};

export default ProductCard;

🛍️ Step 4: Create the Cart Page

"use client";
import { useCart } from "../../context/CartContext";

const CartPage = () => {
  const { cart, removeFromCart, updateQuantity, totalPrice, clearCart } = useCart();

  return (
    <div className="p-6">
      <h1 className="text-2xl font-bold mb-4">Shopping Cart</h1>
      {cart.length === 0 ? (
        <p>Your cart is empty</p>
      ) : (
        <>
          {cart.map((item) => (
            <div key={item.id} className="flex justify-between items-center border-b py-2">
              <div>
                <h2>{item.name}</h2>
                <p>${item.price}</p>
                <input
                  type="number"
                  value={item.quantity}
                  min="1"
                  className="border p-1 w-16"
                  onChange={(e) => updateQuantity(item.id, parseInt(e.target.value))}
                />
              </div>
              <button className="bg-red-500 text-white px-3 py-1 rounded" onClick={() => removeFromCart(item.id)}>
                Remove
              </button>
            </div>
          ))}
          <h2 className="text-lg font-bold mt-4">Total: ${totalPrice.toFixed(2)}</h2>
          <button className="bg-green-500 text-white px-4 py-2 mt-4 rounded" onClick={clearCart}>
            Clear Cart
          </button>
        </>
      )}
    </div>
  );
};

export default CartPage;