UNPKG

ruch

Version:

Revolutionary React TypeScript CLI with hexagonal architecture & AI-powered development assistance. Create maintainable, scalable applications with domain-driven design and integrated AI tooling.

376 lines (342 loc) 11.3 kB
/** * Product Domain Hooks * * React hooks for product-related operations following the hexagonal architecture pattern. * These hooks integrate with React Query for efficient data fetching and caching. */ import { useState, useEffect } from 'react'; import type { Product, ProductCategory, ProductFilter, ProductSort } from '../entities'; // Mock data pour les produits const mockProducts: Product[] = [ { id: '1', name: 'Premium Wireless Headphones', description: 'High-quality wireless headphones with noise cancellation and premium sound quality.', price: 299.99, currency: 'USD', brand: 'TechBrand', sku: 'WH-1000XM4', category: { id: 'electronics', name: 'Electronics', slug: 'electronics' }, images: [ { id: '1', url: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=600&h=400&fit=crop', alt: 'Premium Wireless Headphones', isPrimary: true, order: 1 } ], inventory: { isInStock: true, quantity: 50, lowStockThreshold: 10, reserved: 5, available: 45 }, specifications: [ { name: 'Battery Life', value: '30', unit: 'hours' }, { name: 'Weight', value: '254', unit: 'g' } ], isFeatured: true, isActive: true, createdAt: '2024-01-01T00:00:00Z', updatedAt: '2024-01-01T00:00:00Z' }, { id: '2', name: 'Smart Watch Pro', description: 'Advanced smartwatch with health monitoring, GPS, and long battery life.', price: 399.99, currency: 'USD', brand: 'TechBrand', sku: 'SW-PRO-2024', category: { id: 'wearables', name: 'Wearables', slug: 'wearables' }, images: [ { id: '2', url: 'https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=600&h=400&fit=crop', alt: 'Smart Watch Pro', isPrimary: true, order: 1 } ], inventory: { isInStock: true, quantity: 30, lowStockThreshold: 5, reserved: 2, available: 28 }, specifications: [ { name: 'Battery Life', value: '7', unit: 'days' }, { name: 'Display', value: '1.4', unit: 'inches' } ], isFeatured: true, isActive: true, createdAt: '2024-01-01T00:00:00Z', updatedAt: '2024-01-01T00:00:00Z' }, { id: '3', name: 'Wireless Gaming Mouse', description: 'High-precision wireless gaming mouse with customizable RGB lighting.', price: 89.99, currency: 'USD', brand: 'GameGear', sku: 'GM-WIRELESS-X1', category: { id: 'gaming', name: 'Gaming', slug: 'gaming' }, images: [ { id: '3', url: 'https://images.unsplash.com/photo-1527864550417-7fd91fc51a46?w=600&h=400&fit=crop', alt: 'Wireless Gaming Mouse', isPrimary: true, order: 1 } ], inventory: { isInStock: true, quantity: 75, lowStockThreshold: 15, reserved: 8, available: 67 }, specifications: [ { name: 'DPI', value: '16000', unit: '' }, { name: 'Battery Life', value: '80', unit: 'hours' } ], isFeatured: false, isActive: true, createdAt: '2024-01-01T00:00:00Z', updatedAt: '2024-01-01T00:00:00Z' }, { id: '4', name: 'Ultra-Wide Monitor', description: '34-inch ultra-wide monitor perfect for productivity and gaming.', price: 799.99, currency: 'USD', brand: 'DisplayTech', sku: 'UW-34-4K', category: { id: 'monitors', name: 'Monitors', slug: 'monitors' }, images: [ { id: '4', url: 'https://images.unsplash.com/photo-1593640408182-31c70c8268f5?w=600&h=400&fit=crop', alt: 'Ultra-Wide Monitor', isPrimary: true, order: 1 } ], inventory: { isInStock: false, quantity: 0, lowStockThreshold: 3, reserved: 0, available: 0 }, specifications: [ { name: 'Size', value: '34', unit: 'inches' }, { name: 'Resolution', value: '3440x1440', unit: '' } ], isFeatured: false, isActive: true, createdAt: '2024-01-01T00:00:00Z', updatedAt: '2024-01-01T00:00:00Z' } ]; const mockCategories: ProductCategory[] = [ { id: 'electronics', name: 'Electronics', slug: 'electronics' }, { id: 'wearables', name: 'Wearables', slug: 'wearables' }, { id: 'gaming', name: 'Gaming', slug: 'gaming' }, { id: 'monitors', name: 'Monitors', slug: 'monitors' } ]; /** * Hook pour récupérer tous les produits avec filtres et tri optionnels */ export function useProducts(filters?: ProductFilter, sort?: ProductSort) { const [data, setData] = useState<Product[]>([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState<Error | null>(null); useEffect(() => { setIsLoading(true); // Simuler un délai API setTimeout(() => { try { let filteredProducts = [...mockProducts]; // Appliquer les filtres if (filters) { if (filters.categoryId) { filteredProducts = filteredProducts.filter(p => p.category.id === filters.categoryId); } if (filters.minPrice !== undefined) { filteredProducts = filteredProducts.filter(p => p.price >= filters.minPrice!); } if (filters.maxPrice !== undefined) { filteredProducts = filteredProducts.filter(p => p.price <= filters.maxPrice!); } if (filters.inStock !== undefined) { filteredProducts = filteredProducts.filter(p => p.inventory.isInStock === filters.inStock); } if (filters.isFeatured !== undefined) { filteredProducts = filteredProducts.filter(p => p.isFeatured === filters.isFeatured); } if (filters.brand) { filteredProducts = filteredProducts.filter(p => p.brand === filters.brand); } if (filters.search) { const query = filters.search.toLowerCase(); filteredProducts = filteredProducts.filter(p => p.name.toLowerCase().includes(query) || p.description.toLowerCase().includes(query) ); } } // Appliquer le tri if (sort) { filteredProducts.sort((a, b) => { switch (sort.field) { case 'price': return sort.direction === 'asc' ? a.price - b.price : b.price - a.price; case 'name': return sort.direction === 'asc' ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name); case 'createdAt': return sort.direction === 'asc' ? new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime() : new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(); default: return 0; } }); } setData(filteredProducts); setError(null); } catch (err) { setError(err instanceof Error ? err : new Error('Unknown error')); } finally { setIsLoading(false); } }, 500); }, [filters, sort]); return { data, isLoading, error }; } /** * Hook pour récupérer un produit par ID */ export function useProduct(id: string) { const [data, setData] = useState<Product | null>(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState<Error | null>(null); useEffect(() => { setIsLoading(true); setTimeout(() => { try { const product = mockProducts.find(p => p.id === id); setData(product || null); setError(product ? null : new Error('Product not found')); } catch (err) { setError(err instanceof Error ? err : new Error('Unknown error')); } finally { setIsLoading(false); } }, 300); }, [id]); return { data, isLoading, error }; } /** * Hook pour récupérer les produits en vedette */ export function useFeaturedProducts() { const [data, setData] = useState<Product[]>([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState<Error | null>(null); useEffect(() => { setIsLoading(true); setTimeout(() => { try { const featuredProducts = mockProducts.filter(p => p.isFeatured); setData(featuredProducts); setError(null); } catch (err) { setError(err instanceof Error ? err : new Error('Unknown error')); } finally { setIsLoading(false); } }, 300); }, []); return { data, isLoading, error }; } /** * Hook pour récupérer les catégories de produits */ export function useProductCategories() { const [data, setData] = useState<ProductCategory[]>([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState<Error | null>(null); useEffect(() => { setIsLoading(true); setTimeout(() => { try { setData(mockCategories); setError(null); } catch (err) { setError(err instanceof Error ? err : new Error('Unknown error')); } finally { setIsLoading(false); } }, 200); }, []); return { data, isLoading, error }; } /** * Hook pour créer un produit */ export function useCreateProduct() { const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState<Error | null>(null); const mutate = async (productData: Partial<Product>) => { setIsLoading(true); setError(null); try { // Simuler création await new Promise(resolve => setTimeout(resolve, 1000)); console.log('Creating product:', productData); // En production, ceci ferait un appel API } catch (err) { setError(err instanceof Error ? err : new Error('Failed to create product')); throw err; } finally { setIsLoading(false); } }; return { mutate, isLoading, error }; } /** * Hook pour mettre à jour un produit */ export function useUpdateProduct() { const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState<Error | null>(null); const mutate = async ({ id, ...productData }: { id: string } & Partial<Product>) => { setIsLoading(true); setError(null); try { // Simuler mise à jour await new Promise(resolve => setTimeout(resolve, 1000)); console.log('Updating product:', id, productData); // En production, ceci ferait un appel API } catch (err) { setError(err instanceof Error ? err : new Error('Failed to update product')); throw err; } finally { setIsLoading(false); } }; return { mutate, isLoading, error }; } /** * Hook pour supprimer un produit */ export function useDeleteProduct() { const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState<Error | null>(null); const mutate = async (id: string) => { setIsLoading(true); setError(null); try { // Simuler suppression await new Promise(resolve => setTimeout(resolve, 1000)); console.log('Deleting product:', id); // En production, ceci ferait un appel API } catch (err) { setError(err instanceof Error ? err : new Error('Failed to delete product')); throw err; } finally { setIsLoading(false); } }; return { mutate, isLoading, error }; }