diff --git a/app/Http/Controllers/Admin/Manage/PurchaseController.php b/app/Http/Controllers/Admin/Manage/PurchaseController.php index 66de86e..48a1a79 100644 --- a/app/Http/Controllers/Admin/Manage/PurchaseController.php +++ b/app/Http/Controllers/Admin/Manage/PurchaseController.php @@ -7,6 +7,7 @@ use App\Http\Requests\PaginatedRequest; use App\Models\Purchase; use App\Services\Admin\Manage\PurchaseService; +use App\Services\Admin\Master\SupplierService; use Illuminate\Http\RedirectResponse; use Inertia\Inertia; use Inertia\Response; @@ -14,7 +15,8 @@ class PurchaseController extends Controller { public function __construct( - private PurchaseService $service, + private readonly PurchaseService $service, + private readonly SupplierService $supplierService, ) {} public function index(PaginatedRequest $request): Response @@ -22,7 +24,10 @@ public function index(PaginatedRequest $request): Response return Inertia::render('admin/manage/purchase/index', [ 'purchases' => $this->service->paginated( ...$request->validatedWithDefaults(), + filters: $request->only(['supplier_id']), ), + 'suppliers' => $this->supplierService->getAll(), + 'filters' => $request->only(['supplier_id']), ]); } diff --git a/app/Services/Admin/Manage/PurchaseService.php b/app/Services/Admin/Manage/PurchaseService.php index 3a03eb2..3f2c9ea 100644 --- a/app/Services/Admin/Manage/PurchaseService.php +++ b/app/Services/Admin/Manage/PurchaseService.php @@ -21,7 +21,7 @@ public function __construct( private S3PresignedService $s3Service, ) {} - public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator + public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator { $paginator = Purchase::query() ->select(['id', 'supplier_id', 'created_by_id', 'subtotal', 'discount', 'shipping_cost', 'total', 'notes', 'created_at']) @@ -39,6 +39,7 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = $q->whereHas('supplier', fn ($sq) => $sq->where('name', 'like', "%{$search}%")) ->orWhere('notes', 'like', "%{$search}%"); }) + ->when($filters['supplier_id'] ?? null, fn ($q, $supplierId) => $q->where('supplier_id', $supplierId)) ->orderBy($sort, $direction) ->paginate($perPage); diff --git a/resources/js/pages/admin/manage/purchase/index.tsx b/resources/js/pages/admin/manage/purchase/index.tsx index fded9bd..e927101 100644 --- a/resources/js/pages/admin/manage/purchase/index.tsx +++ b/resources/js/pages/admin/manage/purchase/index.tsx @@ -1,19 +1,28 @@ -import { Head, Link, router } from '@inertiajs/react'; -import { Plus } from 'lucide-react'; -import { useState } from 'react'; import { CardTable } from '@/components/card-table'; import { DeleteConfirmDialog } from '@/components/delete-confirm-dialog'; +import { FilterPopover } from '@/components/filter-popover'; import { useCardTableExpand } from '@/components/hooks/use-card-table-expand'; import { PageHeader } from '@/components/page-header'; import { Button } from '@/components/ui/button'; +import { + Combobox, + ComboboxContent, + ComboboxEmpty, + ComboboxInput, + ComboboxItem, + ComboboxList, +} from '@/components/ui/combobox'; import { useCan } from '@/hooks/use-can'; import { useServerTable } from '@/hooks/use-server-table'; import { destroy, create as purchaseCreate, - index as purchaseIndex, edit as purchaseEdit, + index as purchaseIndex, } from '@/routes/admin/manage/purchases'; +import { Head, Link, router } from '@inertiajs/react'; +import { Plus } from 'lucide-react'; +import { useMemo, useState } from 'react'; import type { Purchase } from './columns'; import { PurchaseCardRow } from './purchase-card'; import { PurchaseItemSubRow } from './purchase-sub-row'; @@ -26,9 +35,20 @@ type Props = { per_page: number; total: number; }; + suppliers: { + id: number; + name: string; + }[]; + filters: { + supplier_id?: string; + }; }; -export default function PurchaseIndex({ purchases }: Props) { +export default function PurchaseIndex({ + purchases, + filters, + suppliers, +}: Props) { const { can } = useCan(); const [deleting, setDeleting] = useState(null); const expand = useCardTableExpand(true); @@ -42,14 +62,29 @@ export default function PurchaseIndex({ purchases }: Props) { const { search, + filterOpen, + setFilterOpen, handlePageChange, handlePerPageChange, handleSearchChange, + applyFilter, + clearFilters, } = useServerTable({ route: () => purchaseIndex.url(), pagination, + filters, + filterWithParams: false, + reloadOnly: ['purchases', 'filters'], }); + const selectedSupplier = useMemo( + () => + suppliers.find( + (s) => String(s.id) === filters.supplier_id, + ) ?? null, + [suppliers, filters.supplier_id], + ); + function handleDelete() { if (!deleting) { return; @@ -60,6 +95,50 @@ export default function PurchaseIndex({ purchases }: Props) { }); } + const filterToolbar = ( + +
+ + supplier.name} + value={selectedSupplier} + onValueChange={(value) => + applyFilter( + 'supplier_id', + value ? String(value.id) : '', + ) + } + > + + + + Tidak ada supplier ditemukan. + + + {(supplier) => ( + + {supplier.name} + + )} + + + +
+
+ ); + return ( <> @@ -87,6 +166,7 @@ export default function PurchaseIndex({ purchases }: Props) { searchValue={search} onSearchChange={handleSearchChange} searchPlaceholder="Cari berdasarkan supplier..." + toolbar={filterToolbar} pagination={pagination} onPageChange={handlePageChange} onPerPageChange={handlePerPageChange} @@ -100,7 +180,7 @@ export default function PurchaseIndex({ purchases }: Props) { purchase={item} index={ (pagination.current_page - 1) * - pagination.per_page + + pagination.per_page + index + 1 }