From 1f9aba6ba5e3be882673f5d12e300f5a82f0d88e Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Wed, 29 Jul 2026 08:59:56 +0700 Subject: [PATCH] feat: enhance order management with additional filters and pagination support - Added channel, status, and payment type filters to the order index functionality. - Updated OrderService to handle new filter parameters in pagination queries. - Introduced filter definitions and values in the OrderGroupedTable component for improved data filtering. - Enhanced the frontend to support dynamic filtering options for orders based on the new criteria. --- .../Admin/Manage/Order/OrderController.php | 10 +++- app/Services/Manage/OrderService.php | 5 +- resources/js/constants/order-channel.ts | 1 + .../js/pages/admin/manage/orders/Index.vue | 54 ++++++++++++++++++- .../manage/orders/table/OrderGroupedTable.vue | 7 ++- 5 files changed, 73 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/Admin/Manage/Order/OrderController.php b/app/Http/Controllers/Admin/Manage/Order/OrderController.php index b133c6f..b04b297 100644 --- a/app/Http/Controllers/Admin/Manage/Order/OrderController.php +++ b/app/Http/Controllers/Admin/Manage/Order/OrderController.php @@ -30,9 +30,17 @@ public function index(Request $request): Response { $tableQuery = $this->parseDataTableQuery($request); + $tableQuery['channel'] = $request->string('channel')->toString(); + $tableQuery['status'] = $request->string('status')->toString(); + $tableQuery['payment_type'] = $request->string('payment_type')->toString(); + return Inertia::render('admin/manage/orders/Index', [ 'orders' => $this->orderService->paginateForIndex($tableQuery, $request->user()), - 'filters' => $this->dataTableFilters($tableQuery), + 'filters' => $this->dataTableFilters($tableQuery, [ + 'channel' => $tableQuery['channel'], + 'status' => $tableQuery['status'], + 'payment_type' => $tableQuery['payment_type'], + ]), ]); } diff --git a/app/Services/Manage/OrderService.php b/app/Services/Manage/OrderService.php index 4a0d544..238fc8a 100644 --- a/app/Services/Manage/OrderService.php +++ b/app/Services/Manage/OrderService.php @@ -84,7 +84,10 @@ public function paginateForIndex(array $tableQuery, User $user): LengthAwarePagi ->orWhereHas('product', fn (Builder $query) => $query->where('name', 'like', "%{$search}%")); }); }); - }); + }) + ->when(($tableQuery['channel'] ?? '') !== '', fn (Builder $query) => $query->where('channel', $tableQuery['channel'])) + ->when(($tableQuery['status'] ?? '') !== '', fn (Builder $query) => $query->where('status', $tableQuery['status'])) + ->when(($tableQuery['payment_type'] ?? '') !== '', fn (Builder $query) => $query->where('payment_type', $tableQuery['payment_type'])); $this->applySorting($query, $tableQuery['sort'], $tableQuery['direction']); diff --git a/resources/js/constants/order-channel.ts b/resources/js/constants/order-channel.ts index 71fa459..bfbfeec 100644 --- a/resources/js/constants/order-channel.ts +++ b/resources/js/constants/order-channel.ts @@ -1,4 +1,5 @@ export const OrderChannel = { + STORE: 'store', TIKTOK: 'tiktok', SHOPEE: 'shopee', } as const; diff --git a/resources/js/pages/admin/manage/orders/Index.vue b/resources/js/pages/admin/manage/orders/Index.vue index eeaa3b6..255891b 100644 --- a/resources/js/pages/admin/manage/orders/Index.vue +++ b/resources/js/pages/admin/manage/orders/Index.vue @@ -14,9 +14,13 @@ import { getPaperSizeLabel, useThermalPrinter, } from '@/composables/useThermalPrinter'; +import { OrderChannel } from '@/constants/order-channel'; +import { OrderPaymentType } from '@/constants/order-payment-type'; +import { OrderStatus } from '@/constants/order-status'; import AdminLayout from '@/layouts/AdminLayout.vue'; import type { PaperSize } from '@/lib/thermal-printer/types'; import { index, create } from '@/routes/admin/manage/orders'; +import type { DataTableFilterDef } from '@/types/data-table'; import type { PaginatedOrders } from '@/types/order'; import OrderGroupedTable from './table/OrderGroupedTable.vue'; @@ -26,6 +30,9 @@ const props = defineProps<{ search: string; sort?: string; direction?: 'asc' | 'desc'; + channel?: string; + status?: string; + payment_type?: string; }; }>(); @@ -34,13 +41,55 @@ const page = usePage(); const { isConnected, printOrderReceipt, tryReconnect } = useThermalPrinter(); const search = ref(props.filters.search ?? ''); -const { setSearch, resetFilters, syncFromServer } = useDataTableQuery({ +const { query, setSearch, setFilter, resetFilters, syncFromServer } = useDataTableQuery({ url: index.url(), initial: { ...props.filters }, + filterKeys: ['channel', 'status', 'payment_type'], }); useDataTableQuerySync(() => props.filters, syncFromServer); +const filterDefs = computed(() => [ + { + key: 'channel', + label: 'Channel', + type: 'select', + options: [ + { value: OrderChannel.STORE, label: 'Toko' }, + { value: OrderChannel.SHOPEE, label: 'Shopee' }, + { value: OrderChannel.TIKTOK, label: 'TikTok' }, + ], + }, + { + key: 'status', + label: 'Status', + type: 'select', + options: [ + { value: OrderStatus.PENDING, label: 'Menunggu' }, + { value: OrderStatus.PROCESSING, label: 'Diproses' }, + { value: OrderStatus.COMPLETED, label: 'Selesai' }, + { value: OrderStatus.CANCELLED, label: 'Dibatalkan' }, + ], + }, + { + key: 'payment_type', + label: 'Tipe Pembayaran', + type: 'select', + options: [ + { value: OrderPaymentType.CASH, label: 'Cash' }, + { value: OrderPaymentType.TRANSFER, label: 'Transfer' }, + { value: OrderPaymentType.QRIS, label: 'QRIS' }, + { value: OrderPaymentType.MARKETPLACE, label: 'Marketplace' }, + ], + }, +]); + +const filterValues = computed(() => ({ + channel: query.value.channel ?? '', + status: query.value.status ?? '', + payment_type: query.value.payment_type ?? '', +})); + const tablePagination = computed(() => ({ currentPage: props.orders.current_page, perPage: props.orders.per_page, @@ -138,6 +187,9 @@ onMounted(async () => { :first-item="firstItem" :pagination="tablePagination" :pagination-links="orders.links" + :filter-defs="filterDefs" + :filter-values="filterValues" + @filter-change="setFilter" @filters-reset="resetFilters" /> diff --git a/resources/js/pages/admin/manage/orders/table/OrderGroupedTable.vue b/resources/js/pages/admin/manage/orders/table/OrderGroupedTable.vue index c4ffc10..e1bbba6 100644 --- a/resources/js/pages/admin/manage/orders/table/OrderGroupedTable.vue +++ b/resources/js/pages/admin/manage/orders/table/OrderGroupedTable.vue @@ -21,6 +21,7 @@ import { usePaginationSummary } from '@/composables/usePaginationSummary'; import { orderStatusBadgeVariant } from '@/constants/order-status'; import { groupedTableRowNumber } from '@/lib/grouped-table'; import type { + DataTableFilterDef, DataTablePagination, DataTablePaginationLink, } from '@/types/data-table'; @@ -32,11 +33,14 @@ const props = defineProps<{ firstItem?: number; pagination?: DataTablePagination; paginationLinks?: DataTablePaginationLink[]; + filterDefs?: DataTableFilterDef[]; + filterValues?: Record; }>(); const search = defineModel('search', { default: '' }); const emit = defineEmits<{ + 'filter-change': [key: string, value: string]; 'filters-reset': []; }>(); @@ -50,7 +54,8 @@ function rowNumber(index: number): number {