E-commerce Application
Build a complete e-commerce application with product catalog, shopping cart, and checkout functionality
120 min•By Priygop Team•Last updated: Feb 2026
Project Overview
Create a full-featured e-commerce application with product management, user authentication, shopping cart, and payment integration.
Project Structure
Example
// E-commerce app structure
src/
├── components/
│ ├── layout/
│ │ ├── Header.js
│ │ ├── Footer.js
│ │ └── Navigation.js
│ ├── product/
│ │ ├── ProductCard.js
│ │ ├── ProductList.js
│ │ ├── ProductDetail.js
│ │ └── ProductFilter.js
│ ├── cart/
│ │ ├── CartItem.js
│ │ ├── CartSummary.js
│ │ └── CartDrawer.js
│ ├── auth/
│ │ ├── LoginForm.js
│ │ ├── RegisterForm.js
│ │ └── UserProfile.js
│ └── checkout/
│ ├── CheckoutForm.js
│ ├── OrderSummary.js
│ └── PaymentForm.js
├── pages/
│ ├── Home.js
│ ├── Products.js
│ ├── ProductDetail.js
│ ├── Cart.js
│ ├── Checkout.js
│ ├── Login.js
│ └── Profile.js
├── hooks/
│ ├── useCart.js
│ ├── useAuth.js
│ └── useProducts.js
├── context/
│ ├── CartContext.js
│ ├── AuthContext.js
│ └── ProductContext.js
├── utils/
│ ├── api.js
│ ├── validation.js
│ └── helpers.js
└── styles/
├── globals.css
└── components.cssKey Features Implementation
Example
// Product management with React Query
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
// Product hooks
function useProducts(filters = {}) {
return useQuery({
queryKey: ['products', filters],
queryFn: async () => {
const params = new URLSearchParams(filters);
const response = await fetch(`/api/products?${params}`);
return response.json();
},
});
}
function useProduct(productId) {
return useQuery({
queryKey: ['product', productId],
queryFn: async () => {
const response = await fetch(`/api/products/${productId}`);
return response.json();
},
enabled: !!productId,
});
}
// Shopping cart with Context API
import { createContext, useContext, useReducer } from 'react';
const CartContext = createContext();
const cartReducer = (state, action) => {
switch (action.type) {
case 'ADD_ITEM':
const existingItem = state.items.find(item => item.id === action.payload.id);
if (existingItem) {
return {
...state,
items: state.items.map(item =>
item.id === action.payload.id
? { ...item, quantity: item.quantity + 1 }
: item
)
};
}
return {
...state,
items: [...state.items, { ...action.payload, quantity: 1 }]
};
case 'REMOVE_ITEM':
return {
...state,
items: state.items.filter(item => item.id !== action.payload)
};
case 'UPDATE_QUANTITY':
return {
...state,
items: state.items.map(item =>
item.id === action.payload.id
? { ...item, quantity: action.payload.quantity }
: item
)
};
case 'CLEAR_CART':
return { ...state, items: [] };
default:
return state;
}
};
function CartProvider({ children }) {
const [state, dispatch] = useReducer(cartReducer, { items: [] });
const addItem = (product) => {
dispatch({ type: 'ADD_ITEM', payload: product });
};
const removeItem = (productId) => {
dispatch({ type: 'REMOVE_ITEM', payload: productId });
};
const updateQuantity = (productId, quantity) => {
dispatch({ type: 'UPDATE_QUANTITY', payload: { id: productId, quantity } });
};
const clearCart = () => {
dispatch({ type: 'CLEAR_CART' });
};
const getTotal = () => {
return state.items.reduce((total, item) => total + (item.price * item.quantity), 0);
};
const getItemCount = () => {
return state.items.reduce((count, item) => count + item.quantity, 0);
};
return (
<CartContext.Provider value={{
items: state.items,
addItem,
removeItem,
updateQuantity,
clearCart,
getTotal,
getItemCount
}}>
{children}
</CartContext.Provider>
);
}
function useCart() {
const context = useContext(CartContext);
if (!context) {
throw new Error('useCart must be used within a CartProvider');
}
return context;
}
// Product components
function ProductCard({ product }) {
const { addItem } = useCart();
return (
<div className="product-card">
<img src={product.image} alt={product.name} />
<h3>{product.name}</h3>
<p className="price">{product.price}</p>
<p className="description">{product.description}</p>
<button onClick={() => addItem(product)}>
Add to Cart
</button>
</div>
);
}
function ProductList({ filters }) {
const { data: products, isLoading, error } = useProducts(filters);
if (isLoading) return <div>Loading products...</div>;
if (error) return <div>Error loading products</div>;
return (
<div className="product-grid">
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
// Cart components
function CartDrawer({ isOpen, onClose }) {
const { items, removeItem, updateQuantity, getTotal } = useCart();
return (
<div className={`cart-drawer ${isOpen ? 'open' : ''}`}>
<div className="cart-header">
<h2>Shopping Cart</h2>
<button onClick={onClose}>×</button>
</div>
<div className="cart-items">
{items.map(item => (
<CartItem
key={item.id}
item={item}
onRemove={() => removeItem(item.id)}
onUpdateQuantity={(quantity) => updateQuantity(item.id, quantity)}
/>
))}
</div>
<div className="cart-footer">
<div className="cart-total">
<strong>Total: {getTotal().toFixed(2)}</strong>
</div>
<button className="checkout-btn">Proceed to Checkout</button>
</div>
</div>
);
}
function CartItem({ item, onRemove, onUpdateQuantity }) {
return (
<div className="cart-item">
<img src={item.image} alt={item.name} />
<div className="item-details">
<h4>{item.name}</h4>
<p>{item.price}</p>
<div className="quantity-controls">
<button onClick={() => onUpdateQuantity(item.quantity - 1)}>-</button>
<span>{item.quantity}</span>
<button onClick={() => onUpdateQuantity(item.quantity + 1)}>+</button>
</div>
</div>
<button onClick={onRemove} className="remove-btn">Remove</button>
</div>
);
}