Build a comprehensive shopping cart system with product management, inventory tracking, payment integration, and order processing. Master complex state management and e-commerce workflows.
E-commerce applications require sophisticated state management, secure payment processing, and seamless user experiences. Building a shopping cart system teaches you to handle complex data relationships, implement business logic, and create secure transaction flows.
This project covers everything from product catalog management to payment processing, giving you hands-on experience with the technologies and patterns used in real e-commerce applications.
A robust e-commerce system requires comprehensive product management with categories, variants, and inventory tracking.
Product Data Model:
1class Product {
2 constructor(data) {
3 this.id = data.id || this.generateId();
4 this.name = data.name;
5 this.description = data.description;
6 this.price = data.price;
7 this.images = data.images || [];
8 this.category = data.category;
9 this.tags = data.tags || [];
10 this.variants = data.variants || [];
11 this.stock = data.stock || 0;
12 this.isActive = data.isActive !== false;
13 this.ratings = data.ratings || [];
14 this.createdAt = new Date(data.createdAt || Date.now());
15 }
16
17 getAverageRating() {
18 if (this.ratings.length === 0) return 0;
19 const sum = this.ratings.reduce((acc, rating) => acc + rating.score, 0);
20 return sum / this.ratings.length;
21 }
22
23 isInStock(quantity = 1) {
24 return this.stock >= quantity;
25 }
26
27 updateStock(quantity) {
28 this.stock = Math.max(0, this.stock + quantity);
29 }
30}
31
32class ProductCatalog {
33 constructor() {
34 this.products = new Map();
35 this.categories = new Map();
36 this.searchIndex = new Map();
37 }
38
39 addProduct(productData) {
40 const product = new Product(productData);
41 this.products.set(product.id, product);
42 this.updateSearchIndex(product);
43 return product;
44 }
45
46 searchProducts(query, filters = {}) {
47 let results = Array.from(this.products.values());
48
49 // Text search
50 if (query) {
51 const terms = query.toLowerCase().split(' ');
52 results = results.filter(product => {
53 const searchText = `${product.name} ${product.description} ${product.tags.join(' ')}`.toLowerCase();
54 return terms.every(term => searchText.includes(term));
55 });
56 }
57
58 // Apply filters
59 if (filters.category) {
60 results = results.filter(p => p.category === filters.category);
61 }
62
63 if (filters.priceMin !== undefined) {
64 results = results.filter(p => p.price >= filters.priceMin);
65 }
66
67 if (filters.priceMax !== undefined) {
68 results = results.filter(p => p.price <= filters.priceMax);
69 }
70
71 if (filters.inStock) {
72 results = results.filter(p => p.stock > 0);
73 }
74
75 // Sort results
76 const sortBy = filters.sortBy || 'name';
77 results.sort((a, b) => {
78 switch (sortBy) {
79 case 'price_asc': return a.price - b.price;
80 case 'price_desc': return b.price - a.price;
81 case 'rating': return b.getAverageRating() - a.getAverageRating();
82 case 'newest': return new Date(b.createdAt) - new Date(a.createdAt);
83 default: return a.name.localeCompare(b.name);
84 }
85 });
86
87 return results;
88 }
89}This system provides comprehensive product management with search, filtering, and inventory tracking capabilities.
The shopping cart is the heart of any e-commerce application, requiring careful state management and business logic.
Advanced Shopping Cart System:
1class ShoppingCart {
2 constructor() {
3 this.items = new Map();
4 this.discounts = [];
5 this.shipping = null;
6 this.listeners = new Set();
7 }
8
9 addItem(productId, quantity = 1, variant = null) {
10 const key = this.getItemKey(productId, variant);
11 const existingItem = this.items.get(key);
12
13 if (existingItem) {
14 this.updateQuantity(key, existingItem.quantity + quantity);
15 } else {
16 this.items.set(key, {
17 productId,
18 variant,
19 quantity,
20 addedAt: new Date()
21 });
22 }
23
24 this.notifyListeners('item_added', { productId, quantity, variant });
25 this.saveToStorage();
26 }
27
28 updateQuantity(itemKey, newQuantity) {
29 if (newQuantity <= 0) {
30 this.items.delete(itemKey);
31 this.notifyListeners('item_removed', { itemKey });
32 } else {
33 const item = this.items.get(itemKey);
34 if (item) {
35 item.quantity = newQuantity;
36 this.notifyListeners('quantity_updated', { itemKey, quantity: newQuantity });
37 }
38 }
39
40 this.saveToStorage();
41 }
42
43 calculateTotals(productCatalog) {
44 let subtotal = 0;
45 let totalItems = 0;
46
47 for (const [key, item] of this.items) {
48 const product = productCatalog.getProduct(item.productId);
49 if (product) {
50 subtotal += product.price * item.quantity;
51 totalItems += item.quantity;
52 }
53 }
54
55 const discountAmount = this.calculateDiscounts(subtotal);
56 const shippingCost = this.calculateShipping(subtotal, totalItems);
57 const tax = this.calculateTax(subtotal - discountAmount);
58 const total = subtotal - discountAmount + shippingCost + tax;
59
60 return {
61 subtotal,
62 discountAmount,
63 shippingCost,
64 tax,
65 total,
66 itemCount: totalItems
67 };
68 }
69
70 applyDiscount(discountCode) {
71 // Simulate discount validation
72 const validDiscounts = {
73 'SAVE10': { type: 'percentage', value: 10, minOrder: 50 },
74 'FREESHIP': { type: 'free_shipping', minOrder: 25 },
75 'WELCOME20': { type: 'percentage', value: 20, maxDiscount: 50, newCustomerOnly: true }
76 };
77
78 const discount = validDiscounts[discountCode];
79 if (!discount) {
80 throw new Error('Invalid discount code');
81 }
82
83 // Check if already applied
84 if (this.discounts.some(d => d.code === discountCode)) {
85 throw new Error('Discount already applied');
86 }
87
88 this.discounts.push({
89 code: discountCode,
90 ...discount,
91 appliedAt: new Date()
92 });
93
94 this.notifyListeners('discount_applied', { code: discountCode });
95 this.saveToStorage();
96 }
97
98 getItemKey(productId, variant) {
99 return variant ? `${productId}_${JSON.stringify(variant)}` : productId;
100 }
101
102 saveToStorage() {
103 const cartData = {
104 items: Array.from(this.items.entries()),
105 discounts: this.discounts,
106 shipping: this.shipping,
107 lastUpdated: new Date().toISOString()
108 };
109
110 localStorage.setItem('shopping_cart', JSON.stringify(cartData));
111 }
112
113 loadFromStorage() {
114 try {
115 const saved = localStorage.getItem('shopping_cart');
116 if (saved) {
117 const cartData = JSON.parse(saved);
118 this.items = new Map(cartData.items);
119 this.discounts = cartData.discounts || [];
120 this.shipping = cartData.shipping;
121 }
122 } catch (error) {
123 console.error('Failed to load cart from storage:', error);
124 }
125 }
126}This cart system handles complex scenarios like variants, discounts, and persistent storage while maintaining clean state management.
Your progress is saved in this browser, on this device only.