# Refactored Code Usage Guide Quick reference for developers working with the refactored codebase. ## Backend Helper Functions ### 1. CRUD Helpers #### `_get_or_404(db, model, record_id, error_message)` Fetch a record by ID or raise 404 error. **Usage:** ```python # Before result = await db.execute(select(Product).where(Product.id == product_id)) product = result.scalar_one_or_none() if not product: raise HTTPException(status_code=404, detail="Product not found") # After product = await _get_or_404(db, Product, product_id, "Product not found") ``` #### `_soft_delete(db, record, commit=True)` Soft delete a record (set `is_active=False`). **Usage:** ```python # Before product.is_active = False await db.commit() return {"message": "Product deleted"} # After return await _soft_delete(db, product) ``` #### `_build_response(message, **kwargs)` Build standardized API responses. **Usage:** ```python # Before return {"message": "Success", "id": product.id, "status": "active"} # After return _build_response("Success", id=product.id, status="active") ``` ### 2. Serialization Helpers #### `_safe_isoformat(dt)` Safely convert datetime to ISO format string. **Usage:** ```python # Before "created_at": product.created_at.isoformat() if product.created_at else None # After "created_at": _safe_isoformat(product.created_at) ``` #### `_safe_enum_value(enum_val, default="pending")` Safely extract enum value. **Usage:** ```python # Before "status": order.status.value if order.status else "pending" # After "status": _safe_enum_value(order.status) ``` #### `_calculate_reviews_stats(reviews)` Calculate review statistics. **Usage:** ```python # Before if reviews: total = len(reviews) avg = sum(r.rating for r in reviews) / total stats = {"average_rating": round(avg, 2), "total_reviews": total} else: stats = {"average_rating": 0, "total_reviews": 0} # After stats = _calculate_reviews_stats(reviews) ``` ### 3. Query Optimization Patterns #### Batched Queries **Before:** ```python total_users = await db.execute(select(func.count(User.id))) total_users = total_users.scalar() total_products = await db.execute(select(func.count(Product.id))) total_products = total_products.scalar() # ... 8 more queries ``` **After:** ```python counts_result = await db.execute( select( func.count(distinct(User.id)).label('users'), func.count(distinct(Product.id)).label('products'), func.count(distinct(Service.id)).label('services'), func.count(distinct(Order.id)).label('orders') ) ) counts = counts_result.one() stats = { "total_users": int(counts.users), "total_products": int(counts.products), "total_services": int(counts.services), "total_orders": int(counts.orders) } ``` #### Streamlined Filtering **Before:** ```python query = select(Order).where(Order.status != OrderStatus.CANCELLED) query = query.where(Order.status != OrderStatus.REFUNDED) ``` **After:** ```python valid_statuses = [s for s in OrderStatus if s not in (OrderStatus.CANCELLED, OrderStatus.REFUNDED)] query = select(Order).where(Order.status.in_(valid_statuses)) ``` ## Frontend Custom Hooks ### 1. useAdminAPI Hook Centralized API call management with error handling. **Import:** ```javascript import { useAdminAPI } from '../hooks/useAdminAPI'; ``` **Usage:** ```javascript function AdminDashboard() { const { token } = useAuth(); const { loading, apiGet, apiPost, apiPut, apiDelete } = useAdminAPI(token); // GET request const fetchData = async () => { try { const data = await apiGet('/admin/dashboard', 'Failed to load dashboard'); setDashboardData(data); } catch (error) { // Error already handled by hook (toast shown, navigation handled) } }; // POST request const createProduct = async (productData) => { try { const result = await apiPost('/admin/products', productData, 'Failed to create product'); toast.success('Product created!'); return result; } catch (error) { // Error handled } }; // PUT request const updateProduct = async (id, data) => { await apiPut(`/admin/products/${id}`, data, 'Failed to update'); }; // DELETE request const deleteProduct = async (id) => { await apiDelete(`/admin/products/${id}`, 'Failed to delete'); }; } ``` **Features:** - ✅ Automatic 10-second timeout - ✅ Consistent error handling - ✅ Auto-navigation on 401/403 - ✅ Toast notifications - ✅ Loading state management ### 2. useDialog Hook Simplified dialog/modal state management. **Import:** ```javascript import { useDialog } from '../hooks/useDialogState'; ``` **Usage:** ```javascript function ProductsTab() { const { isOpen, item, open, close } = useDialog(); return ( <> > ); } ``` ### 3. useFormState Hook Manage form state efficiently. **Import:** ```javascript import { useFormState } from '../hooks/useDialogState'; ``` **Usage:** ```javascript function ProductForm({ initialData }) { const { form, updateField, updateForm, resetForm } = useFormState( initialData || { name: '', price: 0, stock: 0 } ); return (
); } ``` ## Common Patterns ### Complete CRUD Endpoint (Refactored) ```python # List with optional filtering @api_router.get("/admin/products") async def admin_get_products( include_inactive: bool = False, user: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db) ): query = select(Product) if not include_inactive: query = query.where(Product.is_active == True) result = await db.execute(query) products = result.scalars().all() return [product_to_dict(p) for p in products] # Create @api_router.post("/admin/products") async def admin_create_product( product_data: ProductCreate, user: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db) ): product = Product(**product_data.model_dump()) db.add(product) await db.commit() await db.refresh(product) return product_to_dict(product) # Update @api_router.put("/admin/products/{product_id}") async def admin_update_product( product_id: str, product_data: ProductUpdate, user: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db) ): product = await _get_or_404(db, Product, product_id, "Product not found") update_data = product_data.model_dump(exclude_unset=True) for key, value in update_data.items(): setattr(product, key, value) await db.commit() await db.refresh(product) return product_to_dict(product) # Delete (soft) @api_router.delete("/admin/products/{product_id}") async def admin_delete_product( product_id: str, user: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db) ): product = await _get_or_404(db, Product, product_id, "Product not found") return await _soft_delete(db, product) ``` ### Complete React Component (Refactored) ```javascript import { useState, useEffect } from 'react'; import { useAdminAPI } from '../hooks/useAdminAPI'; import { useDialog, useFormState } from '../hooks/useDialogState'; import { useAuth } from '../context/AuthContext'; function ProductsTab() { const { token } = useAuth(); const { loading, apiGet, apiPost, apiPut, apiDelete } = useAdminAPI(token); const { isOpen, item, open, close } = useDialog(); const { form, updateField, resetForm } = useFormState({ name: '', price: 0, stock: 0, category: 'electronics' }); const [products, setProducts] = useState([]); useEffect(() => { fetchProducts(); }, []); const fetchProducts = async () => { try { const data = await apiGet('/admin/products', 'Failed to load products'); setProducts(data); } catch (error) { // Error handled by hook } }; const handleSubmit = async () => { try { if (item) { await apiPut(`/admin/products/${item.id}`, form, 'Failed to update'); } else { await apiPost('/admin/products', form, 'Failed to create'); } await fetchProducts(); close(); resetForm(); } catch (error) { // Error handled } }; const handleDelete = async (id) => { try { await apiDelete(`/admin/products/${id}`, 'Failed to delete'); await fetchProducts(); } catch (error) { // Error handled } }; return (