2.4 KiB
2.4 KiB
Lazy Loading Card Table
Date
2026-08-14
Goal
Optimize page load performance for raw materials, products, and purchases list pages by implementing lazy loading for child/variant data in card-based layouts.
Problem
Pages with 100+ records loaded all child data eagerly (variants, items), causing slow initial page loads.
Solution Pattern
- Backend: Remove eager-loaded relationships from paginated query
- Backend: Add SQL subqueries for summary data (
variants_count,total_qty,material_name,unit) - Backend: Add new controller method returning JSON for lazy load
- Frontend: Use
useCardTableExpand(false)for default collapsed state - Frontend: Fetch child data via
fetch()on expand, store inRecord<number, T[]>state - Frontend: Pass
items+isLoadingprops to sub-row components
Files Modified
Purchases (this session)
app/Services/Admin/Manage/PurchaseService.php-paginated()no longer eager loadspurchaseItems; addedgetItems()methodapp/Http/Controllers/Admin/Manage/PurchaseController.php- addeditems()methodroutes/web.php- addedGET purchases/{purchase}/itemsrouteresources/js/pages/admin/manage/purchase/columns.tsx-Purchasetype:variants_count,total_qty,material_name,unitresources/js/pages/admin/manage/purchase/purchase-card.tsx- uses summary data from propsresources/js/pages/admin/manage/purchase/purchase-sub-row.tsx- acceptsitems&isLoadingpropsresources/js/pages/admin/manage/purchase/index.tsx- lazy loading withfetchItems()
Raw Materials & Products (previous sessions)
- Same pattern applied to
RawMaterialService,RawMaterialController,ProductService,ProductController - Frontend pages updated with lazy loading state
Route Added
Route::get('purchases/{purchase}/items', [PurchaseController::class, 'items'])->name('purchases.items')->middleware('permission:purchases.view');
Key Implementation Details
- SQL subqueries avoid N+1 queries while keeping summary data in the paginated response
getItems()method handles media URL resolution for item photos- Frontend caches loaded items to avoid re-fetching on repeated expand/collapse
- Loading state shown while items are being fetched
Verification
- PHP syntax check: OK
- TypeScript: Only pre-existing errors in
use-purchase-draft.ts(unrelated) - Route cache cleared