Skip to main content

Overview

The Shopping Cart API provides comprehensive cart management functionality for customers. Each customer can have multiple carts (one per store) with real-time synchronization across devices.

Add to Cart

Add a product to the customer’s shopping cart for a specific store.
customerId
Id<'customers'>
required
Customer ID
storeId
Id<'stores'>
required
Store ID
productId
Id<'products'>
required
Product ID to add
quantity
number
required
Quantity to add (must be positive)
await convex.mutation(api.customers.cart.addToCart, {
  customerId: "c123456789",
  storeId: "j123456789",
  productId: "p123456789",
  quantity: 2
});
null

Update Cart Item Quantity

Update the quantity of a specific item in the cart. Set quantity to 0 to remove the item.
customerId
Id<'customers'>
required
Customer ID
storeId
Id<'stores'>
required
Store ID
productId
Id<'products'>
required
Product ID to update
quantity
number
required
New quantity (0 to remove item)
await convex.mutation(api.customers.cart.updateCartItemQuantity, {
  customerId: "c123456789",
  storeId: "j123456789",
  productId: "p123456789",
  quantity: 3
});

Remove from Cart

Remove a specific item from the cart completely.
customerId
Id<'customers'>
required
Customer ID
storeId
Id<'stores'>
required
Store ID
productId
Id<'products'>
required
Product ID to remove
await convex.mutation(api.customers.cart.removeFromCart, {
  customerId: "c123456789",
  storeId: "j123456789",
  productId: "p123456789"
});

Clear Cart

Clear all items from the cart for a specific store.
customerId
Id<'customers'>
required
Customer ID
storeId
Id<'stores'>
required
Store ID
await convex.mutation(api.customers.cart.clearCart, {
  customerId: "c123456789",
  storeId: "j123456789"
});

Get Cart

Retrieve the cart for a specific customer and store with current product information and pricing.
customerId
Id<'customers'>
required
Customer ID
storeId
Id<'stores'>
required
Store ID
const cart = await convex.query(api.customers.cart.getCart, {
  customerId: "c123456789",
  storeId: "j123456789"
});
{
  "_id": "cart123456789",
  "customerId": "c123456789",
  "storeId": "j123456789",
  "items": [
    {
      "productId": "p123456789",
      "productName": "Pizza Margherita",
      "productPrice": 15.99,
      "quantity": 2,
      "subtotal": 31.98,
      "productImage": "https://storage.convex.dev/...",
      "isAvailable": true,
      "stockAvailable": 100
    },
    {
      "productId": "p987654321",
      "productName": "Garlic Bread",
      "productPrice": 6.99,
      "quantity": 1,
      "subtotal": 6.99,
      "productImage": "https://storage.convex.dev/...",
      "isAvailable": true,
      "stockAvailable": 50
    }
  ],
  "itemsCount": 3,
  "subtotal": 38.97,
  "store": {
    "id": "j123456789",
    "name": "Mario's Pizza",
    "logo": "https://storage.convex.dev/...",
    "isActive": true
  },
  "_creationTime": 1640995200000,
  "lastUpdated": 1640995800000
}

Get Customer Carts

Retrieve all carts for a customer across all stores.
customerId
Id<'customers'>
required
Customer ID
const carts = await convex.query(api.customers.cart.getCustomerCarts, {
  customerId: "c123456789"
});
[
  {
    "_id": "cart123456789",
    "storeId": "j123456789",
    "storeName": "Mario's Pizza",
    "itemsCount": 3,
    "subtotal": 38.97,
    "lastUpdated": 1640995800000
  },
  {
    "_id": "cart987654321", 
    "storeId": "j987654321",
    "storeName": "Tech Store",
    "itemsCount": 1,
    "subtotal": 299.99,
    "lastUpdated": 1640995600000
  }
]

Get Cart Summary

Get a summary of all cart activity for a customer.
customerId
Id<'customers'>
required
Customer ID
const summary = await convex.query(api.customers.cart.getCartSummary, {
  customerId: "c123456789"
});
{
  "totalItems": 4,
  "totalStores": 2,
  "totalAmount": 338.96
}

Get Cart for Checkout

🆕 New Function - Get cart with checkout calculations and validation in one call.
customerId
Id<'customers'>
required
Customer ID
storeId
Id<'stores'>
required
Store ID
deliveryType
string
required
Delivery method: delivery or pickup
deliveryFee
number
Delivery fee (defaults to 5.99 for delivery, 0 for pickup)
const checkoutData = await convex.query(api.customers.cart.getCartForCheckout, {
  customerId: "c123456789",
  storeId: "j123456789",
  deliveryType: "delivery",
  deliveryFee: 5.00
});
{
  "cart": {
    "_id": "cart123456789",
    "items": [...],
    "itemsCount": 3,
    "subtotal": 38.97
  },
  "checkoutTotals": {
    "subtotal": 38.97,
    "deliveryFee": 5.00,
    "platformCommission": 2.85,
    "totalAmount": 43.97,
    "itemsCount": 3
  },
  "isValidForCheckout": true,
  "validationIssues": []
}

Real-time Updates

The cart system supports real-time updates across all devices. Use the React hooks for automatic synchronization:
import { useQuery, useMutation } from "convex/react";
import { api } from "./convex/_generated/api";

function CartComponent({ customerId, storeId }) {
  // Real-time cart data
  const cart = useQuery(api.customers.cart.getCart, {
    customerId,
    storeId
  });
  
  // Mutation for adding items
  const addToCart = useMutation(api.customers.cart.addToCart);
  
  const handleAddItem = async (productId: string, quantity: number) => {
    await addToCart({
      customerId,
      storeId,
      productId,
      quantity
    });
  };
  
  if (cart === undefined) return <div>Loading cart...</div>;
  if (cart === null) return <div>Cart is empty</div>;
  
  return (
    <div>
      <h2>Cart ({cart.itemsCount} items)</h2>
      <p>Subtotal: ${cart.subtotal}</p>
      {cart.items.map(item => (
        <div key={item.productId}>
          {item.productName} x {item.quantity} = ${item.subtotal}
        </div>
      ))}
    </div>
  );
}

Error Handling

Error: Product is inactive or out of stock
{
  "error": "Product is not available for purchase",
  "code": "PRODUCT_UNAVAILABLE",
  "productId": "p123456789"
}
Error: Not enough stock for requested quantity
{
  "error": "Insufficient stock available",
  "code": "INSUFFICIENT_STOCK", 
  "available": 5,
  "requested": 10
}
Error: Store is not accepting orders
{
  "error": "Store is currently not accepting orders",
  "code": "STORE_INACTIVE",
  "storeId": "j123456789"
}

Best Practices

Real-time Sync

Use React hooks for automatic cart synchronization across devices and tabs.

Validation

Always validate cart contents before checkout to handle stock changes.

Performance

Use getCartForCheckout for checkout flows to reduce API calls.

User Experience

Show loading states and handle errors gracefully for better UX.
Cart items are automatically validated for availability and stock levels. Unavailable items are marked but not removed automatically.
Use the getCartForCheckout function for checkout flows as it provides cart data, validation, and totals calculation in a single optimized call.