# 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 1. **Backend**: Remove eager-loaded relationships from paginated query 2. **Backend**: Add SQL subqueries for summary data (`variants_count`, `total_qty`, `material_name`, `unit`) 3. **Backend**: Add new controller method returning JSON for lazy load 4. **Frontend**: Use `useCardTableExpand(false)` for default collapsed state 5. **Frontend**: Fetch child data via `fetch()` on expand, store in `Record` state 6. **Frontend**: Pass `items` + `isLoading` props to sub-row components ## Files Modified ### Purchases (this session) - `app/Services/Admin/Manage/PurchaseService.php` - `paginated()` no longer eager loads `purchaseItems`; added `getItems()` method - `app/Http/Controllers/Admin/Manage/PurchaseController.php` - added `items()` method - `routes/web.php` - added `GET purchases/{purchase}/items` route - `resources/js/pages/admin/manage/purchase/columns.tsx` - `Purchase` type: `variants_count`, `total_qty`, `material_name`, `unit` - `resources/js/pages/admin/manage/purchase/purchase-card.tsx` - uses summary data from props - `resources/js/pages/admin/manage/purchase/purchase-sub-row.tsx` - accepts `items` & `isLoading` props - `resources/js/pages/admin/manage/purchase/index.tsx` - lazy loading with `fetchItems()` ### Raw Materials & Products (previous sessions) - Same pattern applied to `RawMaterialService`, `RawMaterialController`, `ProductService`, `ProductController` - Frontend pages updated with lazy loading state ## Route Added ```php 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