aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
525 lines (522 loc) • 17.4 kB
JavaScript
'use client';
import { jsx } from 'react/jsx-runtime';
import { useState, useCallback, createContext, useContext } from 'react';
const EcommerceContext = /*#__PURE__*/createContext(null);
// Mock AI recommendation engine
const mockRecommendationEngine = {
async generateRecommendations(productId, products) {
await new Promise(resolve => setTimeout(resolve, 1000)); // Simulate API call
const product = products.find(p => p.id === productId);
if (!product) return [];
// Generate different types of recommendations
const recommendations = [];
// Similar products (same category)
const similarProducts = products.filter(p => p.id !== productId && p.category === product.category && Math.abs(p.price - product.price) / product.price < 0.5).slice(0, 3);
similarProducts.forEach(p => {
recommendations.push({
productId: p.id,
product: p,
score: 0.8 + Math.random() * 0.2,
reason: 'similar',
explanation: `Similar to ${product.name} in ${product.category} category`,
confidence: 0.75 + Math.random() * 0.2
});
});
// Trending products
const trendingProducts = products.filter(p => p.id !== productId && (p.isBestseller || p.isNew)).slice(0, 2);
trendingProducts.forEach(p => {
recommendations.push({
productId: p.id,
product: p,
score: 0.7 + Math.random() * 0.2,
reason: 'trending',
explanation: p.isBestseller ? 'Bestseller in our store' : 'New arrival that\'s gaining popularity',
confidence: 0.8 + Math.random() * 0.15
});
});
// Frequently bought together (mock)
const complementaryProducts = products.filter(p => p.id !== productId && p.category !== product.category && p.price < product.price * 0.5).slice(0, 2);
complementaryProducts.forEach(p => {
recommendations.push({
productId: p.id,
product: p,
score: 0.6 + Math.random() * 0.3,
reason: 'bought-together',
explanation: `Frequently purchased with ${product.name}`,
confidence: 0.6 + Math.random() * 0.3
});
});
return recommendations.sort((a, b) => b.score - a.score).slice(0, 8);
}
};
const EcommerceProvider = ({
children
}) => {
const [products, setProducts] = useState([]);
const [cart, setCart] = useState([]);
const [wishlist, setWishlist] = useState([]);
const [recommendations, setRecommendations] = useState({});
const [comparisons, setComparisons] = useState([]);
const [reviews, setReviews] = useState({});
const [priceHistory, setPriceHistory] = useState({});
const [searchQuery, setSearchQuery] = useState('');
const [filters, setFilters] = useState({});
const [sortBy, setSortBy] = useState('relevance');
const [selectedShipping, setSelectedShipping] = useState();
const [selectedPayment, setSelectedPayment] = useState();
// Mock shipping and payment options
const shippingOptions = [{
id: 'standard',
name: 'Standard Shipping',
description: 'Free shipping on orders over $50',
price: 0,
estimatedDays: 5,
trackingAvailable: true,
insuranceIncluded: false
}, {
id: 'express',
name: 'Express Shipping',
description: 'Fast delivery with tracking',
price: 9.99,
estimatedDays: 2,
trackingAvailable: true,
insuranceIncluded: true
}, {
id: 'overnight',
name: 'Overnight Delivery',
description: 'Next business day delivery',
price: 24.99,
estimatedDays: 1,
trackingAvailable: true,
insuranceIncluded: true
}];
const paymentMethods = [{
id: 'credit-card',
type: 'credit-card',
name: 'Credit Card',
icon: '💳',
acceptedCurrencies: ['USD', 'EUR', 'GBP']
}, {
id: 'paypal',
type: 'paypal',
name: 'PayPal',
icon: '🅿️',
acceptedCurrencies: ['USD', 'EUR', 'GBP']
}, {
id: 'apple-pay',
type: 'apple-pay',
name: 'Apple Pay',
icon: '🍎',
acceptedCurrencies: ['USD', 'EUR', 'GBP']
}];
// Cart calculations
const cartSubtotal = cart.reduce((total, item) => total + item.product.price * item.quantity, 0);
const cartTax = cartSubtotal * 0.08; // 8% tax
const cartShipping = selectedShipping?.price || 0;
const cartTotal = cartSubtotal + cartTax + cartShipping;
const addProduct = useCallback(product => {
setProducts(prev => [...prev, product]);
}, []);
const updateProduct = useCallback((id, updates) => {
setProducts(prev => prev.map(product => product.id === id ? {
...product,
...updates
} : product));
}, []);
const removeProduct = useCallback(id => {
setProducts(prev => prev.filter(product => product.id !== id));
}, []);
const getProduct = useCallback(id => {
return products.find(product => product.id === id);
}, [products]);
const getProductsByCategory = useCallback(category => {
return products.filter(product => product.category === category);
}, [products]);
const searchProducts = useCallback((query, searchFilters) => {
let filtered = products;
// Text search
if (query) {
const lowercaseQuery = query.toLowerCase();
filtered = filtered.filter(product => product.name.toLowerCase().includes(lowercaseQuery) || product.description.toLowerCase().includes(lowercaseQuery) || product.tags.some(tag => tag.toLowerCase().includes(lowercaseQuery)) || product.brand?.toLowerCase().includes(lowercaseQuery));
}
// Apply filters
const activeFilters = searchFilters || filters;
if (activeFilters.category?.length) {
filtered = filtered.filter(product => activeFilters.category.includes(product.category));
}
if (activeFilters.brand?.length) {
filtered = filtered.filter(product => product.brand && activeFilters.brand.includes(product.brand));
}
if (activeFilters.priceRange) {
const [min, max] = activeFilters.priceRange;
filtered = filtered.filter(product => product.price >= min && product.price <= max);
}
if (activeFilters.rating) {
filtered = filtered.filter(product => product.rating >= activeFilters.rating);
}
if (activeFilters.onSale) {
filtered = filtered.filter(product => product.isOnSale);
}
if (activeFilters.inStock) {
filtered = filtered.filter(product => product.availability === 'in-stock');
}
// Apply sorting
switch (sortBy) {
case 'price-low-high':
filtered.sort((a, b) => a.price - b.price);
break;
case 'price-high-low':
filtered.sort((a, b) => b.price - a.price);
break;
case 'rating':
filtered.sort((a, b) => b.rating - a.rating);
break;
case 'name-az':
filtered.sort((a, b) => a.name.localeCompare(b.name));
break;
case 'name-za':
filtered.sort((a, b) => b.name.localeCompare(a.name));
break;
case 'bestseller':
filtered.sort((a, b) => (b.isBestseller ? 1 : 0) - (a.isBestseller ? 1 : 0));
break;
}
return filtered;
}, [products, filters, sortBy]);
const addToCart = useCallback((productId, quantity = 1, variants) => {
const product = getProduct(productId);
if (!product) return;
setCart(prev => {
const existingItem = prev.find(item => item.productId === productId && JSON.stringify(item.selectedVariants) === JSON.stringify(variants));
if (existingItem) {
return prev.map(item => item.id === existingItem.id ? {
...item,
quantity: item.quantity + quantity
} : item);
} else {
const newItem = {
id: `cart_${Date.now()}_${Math.random()}`,
productId,
product,
quantity,
selectedVariants: variants,
addedAt: new Date()
};
return [...prev, newItem];
}
});
}, [getProduct]);
const updateCartItem = useCallback((itemId, quantity) => {
if (quantity <= 0) {
removeFromCart(itemId);
return;
}
setCart(prev => prev.map(item => item.id === itemId ? {
...item,
quantity
} : item));
}, []);
const removeFromCart = useCallback(itemId => {
setCart(prev => prev.filter(item => item.id !== itemId));
}, []);
const clearCart = useCallback(() => {
setCart([]);
}, []);
const getCartTotal = useCallback(() => {
return cart.reduce((total, item) => total + item.product.price * item.quantity, 0);
}, [cart]);
const getCartItemCount = useCallback(() => {
return cart.reduce((count, item) => count + item.quantity, 0);
}, [cart]);
const addToWishlist = useCallback((productId, priority = 'medium') => {
const product = getProduct(productId);
if (!product) return;
const existingItem = wishlist.find(item => item.productId === productId);
if (existingItem) return;
const newItem = {
id: `wishlist_${Date.now()}_${Math.random()}`,
productId,
product,
addedAt: new Date(),
priority
};
setWishlist(prev => [...prev, newItem]);
}, [getProduct, wishlist]);
const removeFromWishlist = useCallback(itemId => {
setWishlist(prev => prev.filter(item => item.id !== itemId));
}, []);
const moveToCart = useCallback(wishlistItemId => {
const wishlistItem = wishlist.find(item => item.id === wishlistItemId);
if (!wishlistItem) return;
addToCart(wishlistItem.productId, 1);
removeFromWishlist(wishlistItemId);
}, [wishlist, addToCart, removeFromWishlist]);
const shareWishlist = useCallback(() => {
const wishlistData = JSON.stringify(wishlist.map(item => item.productId));
return `${window.location.origin}/wishlist?items=${encodeURIComponent(wishlistData)}`;
}, [wishlist]);
const getRecommendations = useCallback((productId, type) => {
return recommendations[productId] || [];
}, [recommendations]);
const generateRecommendations = useCallback(async productId => {
const recs = await mockRecommendationEngine.generateRecommendations(productId, products);
setRecommendations(prev => ({
...prev,
[productId]: recs
}));
return recs;
}, [products]);
const createComparison = useCallback((productIds, title) => {
const comparisonProducts = productIds.map(id => getProduct(id)).filter(Boolean);
if (comparisonProducts.length < 2) throw new Error('At least 2 products required for comparison');
const comparisonMatrix = compareProducts(productIds);
const comparison = {
id: `comparison_${Date.now()}`,
products: comparisonProducts,
comparisonMatrix,
createdAt: new Date(),
title: title || `Comparison of ${comparisonProducts.length} products`
};
setComparisons(prev => [...prev, comparison]);
return comparison;
}, [getProduct]);
const updateComparison = useCallback((id, updates) => {
setComparisons(prev => prev.map(comp => comp.id === id ? {
...comp,
...updates
} : comp));
}, []);
const removeComparison = useCallback(id => {
setComparisons(prev => prev.filter(comp => comp.id !== id));
}, []);
const compareProducts = useCallback(productIds => {
const comparisonProducts = productIds.map(id => getProduct(id)).filter(Boolean);
const features = [];
// Price comparison
features.push({
name: 'Price',
category: 'General',
values: comparisonProducts.map(p => `$${p.price.toFixed(2)}`),
importance: 'high',
winner: comparisonProducts.indexOf(comparisonProducts.reduce((min, p) => p.price < min.price ? p : min))
});
// Rating comparison
features.push({
name: 'Rating',
category: 'General',
values: comparisonProducts.map(p => p.rating),
importance: 'high',
winner: comparisonProducts.indexOf(comparisonProducts.reduce((max, p) => p.rating > max.rating ? p : max))
});
// Stock comparison
features.push({
name: 'Stock',
category: 'Availability',
values: comparisonProducts.map(p => p.stock),
importance: 'medium'
});
return features;
}, [getProduct]);
const addReview = useCallback((productId, review) => {
const newReview = {
...review,
id: `review_${Date.now()}_${Math.random()}`,
productId,
createdAt: new Date()
};
setReviews(prev => ({
...prev,
[productId]: [...(prev[productId] || []), newReview]
}));
}, []);
const updateReview = useCallback((reviewId, updates) => {
setReviews(prev => {
const newReviews = {
...prev
};
Object.keys(newReviews).forEach(productId => {
newReviews[productId] = newReviews[productId].map(review => review.id === reviewId ? {
...review,
...updates
} : review);
});
return newReviews;
});
}, []);
const removeReview = useCallback(reviewId => {
setReviews(prev => {
const newReviews = {
...prev
};
Object.keys(newReviews).forEach(productId => {
newReviews[productId] = newReviews[productId].filter(review => review.id !== reviewId);
});
return newReviews;
});
}, []);
const getProductReviews = useCallback(productId => {
return reviews[productId] || [];
}, [reviews]);
const getAverageRating = useCallback(productId => {
const productReviews = getProductReviews(productId);
if (productReviews.length === 0) return 0;
const sum = productReviews.reduce((total, review) => total + review.rating, 0);
return sum / productReviews.length;
}, [getProductReviews]);
const trackPrice = useCallback(productId => {
const product = getProduct(productId);
if (!product) return;
const historyEntry = {
date: new Date(),
price: product.price,
source: 'tracking'
};
setPriceHistory(prev => ({
...prev,
[productId]: [...(prev[productId] || []), historyEntry]
}));
}, [getProduct]);
const untrackPrice = useCallback(productId => {
setPriceHistory(prev => {
const newHistory = {
...prev
};
delete newHistory[productId];
return newHistory;
});
}, []);
const getPriceHistory = useCallback(productId => {
return priceHistory[productId] || [];
}, [priceHistory]);
const getPriceAlerts = useCallback(() => {
// Mock price alerts
return [];
}, []);
const viewProduct = useCallback(productId => {
// Track product view for analytics
trackEvent('product_view', {
productId
});
}, []);
const trackEvent = useCallback((event, data) => {
// Mock analytics tracking
console.log('Analytics event:', event, data);
}, []);
const getAnalytics = useCallback(() => {
// Mock analytics data
return {
totalViews: 1250,
totalPurchases: 89,
conversionRate: 7.1,
averageOrderValue: 156.78,
popularProducts: products.slice(0, 5).map(p => ({
productId: p.id,
views: Math.floor(Math.random() * 500) + 100,
purchases: Math.floor(Math.random() * 50) + 10
})),
categoryPerformance: products.reduce((acc, p) => {
if (!acc[p.category]) {
acc[p.category] = {
views: 0,
purchases: 0
};
}
acc[p.category].views += Math.floor(Math.random() * 100) + 50;
acc[p.category].purchases += Math.floor(Math.random() * 20) + 5;
return acc;
}, {}),
searchQueries: [{
query: 'wireless headphones',
count: 45,
results: 12
}, {
query: 'laptop stand',
count: 38,
results: 8
}, {
query: 'smartphone case',
count: 32,
results: 15
}]
};
}, [products]);
const setShippingOption = useCallback(option => {
setSelectedShipping(option);
}, []);
const setPaymentMethod = useCallback(method => {
setSelectedPayment(method);
}, []);
const value = {
products,
addProduct,
updateProduct,
removeProduct,
getProduct,
getProductsByCategory,
searchProducts,
cart,
addToCart,
updateCartItem,
removeFromCart,
clearCart,
getCartTotal,
getCartItemCount,
cartSubtotal,
cartTax,
cartShipping,
cartTotal,
wishlist,
addToWishlist,
removeFromWishlist,
moveToCart,
shareWishlist,
recommendations,
getRecommendations,
generateRecommendations,
comparisons,
createComparison,
updateComparison,
removeComparison,
compareProducts,
reviews,
addReview,
updateReview,
removeReview,
getProductReviews,
getAverageRating,
priceHistory,
trackPrice,
untrackPrice,
getPriceHistory,
getPriceAlerts,
searchQuery,
setSearchQuery,
filters,
setFilters,
sortBy,
setSortBy,
viewProduct,
trackEvent,
getAnalytics,
shippingOptions,
paymentMethods,
selectedShipping,
selectedPayment,
setShippingOption,
setPaymentMethod
};
return jsx(EcommerceContext.Provider, {
"data-glass-component": true,
value: value,
children: children
});
};
const useEcommerce = () => {
const context = useContext(EcommerceContext);
if (!context) {
throw new Error('useEcommerce must be used within an EcommerceProvider');
}
return context;
};
export { EcommerceProvider, EcommerceProvider as GlassEcommerceProvider, useEcommerce };
//# sourceMappingURL=GlassEcommerceProvider.js.map