diff --git a/app/Modules/Inventory/Controllers/InventoryReportController.php b/app/Modules/Inventory/Controllers/InventoryReportController.php
index 4359257..0e065a5 100644
--- a/app/Modules/Inventory/Controllers/InventoryReportController.php
+++ b/app/Modules/Inventory/Controllers/InventoryReportController.php
@@ -24,9 +24,17 @@ class InventoryReportController extends Controller
public function index(Request $request)
{
$filters = $request->only([
- 'date_from', 'date_to', 'warehouse_id', 'category_id', 'search', 'per_page'
+ 'date_from', 'date_to', 'warehouse_id', 'category_id', 'search', 'per_page',
+ 'sort_by', 'sort_order'
]);
+ if (!isset($filters['date_from'])) {
+ $filters['date_from'] = date('Y-m-d');
+ }
+ if (!isset($filters['date_to'])) {
+ $filters['date_to'] = date('Y-m-d');
+ }
+
$reportData = $this->reportService->getReportData($filters, $request->input('per_page', 10));
$summary = $this->reportService->getSummary($filters);
diff --git a/app/Modules/Inventory/Exports/InventoryReportExport.php b/app/Modules/Inventory/Exports/InventoryReportExport.php
index 2154fe6..a3c177b 100644
--- a/app/Modules/Inventory/Exports/InventoryReportExport.php
+++ b/app/Modules/Inventory/Exports/InventoryReportExport.php
@@ -34,6 +34,8 @@ class InventoryReportExport implements FromCollection, WithHeadings, WithMapping
'分類',
'進貨量',
'出貨量',
+ '調撥入',
+ '調撥出',
'調整量',
'淨變動',
];
@@ -47,6 +49,8 @@ class InventoryReportExport implements FromCollection, WithHeadings, WithMapping
$row->category_name ?? '-',
$row->inbound_qty,
$row->outbound_qty,
+ $row->transfer_in_qty,
+ $row->transfer_out_qty,
$row->adjust_qty,
$row->net_change,
];
diff --git a/app/Modules/Inventory/Services/InventoryReportService.php b/app/Modules/Inventory/Services/InventoryReportService.php
index 5b682b6..152d605 100644
--- a/app/Modules/Inventory/Services/InventoryReportService.php
+++ b/app/Modules/Inventory/Services/InventoryReportService.php
@@ -30,6 +30,8 @@ class InventoryReportService
$warehouseId = $filters['warehouse_id'] ?? null;
$categoryId = $filters['category_id'] ?? null;
$search = $filters['search'] ?? null;
+ $sortBy = $filters['sort_by'] ?? 'product_code';
+ $sortOrder = $filters['sort_order'] ?? 'asc';
// 若無任何篩選條件,直接回傳空資料
if (!$dateFrom && !$dateTo && !$warehouseId && !$categoryId && !$search) {
@@ -54,9 +56,12 @@ class InventoryReportService
DB::raw("SUM(CASE WHEN inventory_transactions.type IN ('入庫', '手動入庫') AND inventory_transactions.quantity > 0 THEN inventory_transactions.quantity ELSE 0 END) as inbound_qty"),
// 出貨量:type 為 出庫 (排除 調撥出庫) (取絕對值)
DB::raw("ABS(SUM(CASE WHEN inventory_transactions.type IN ('出庫') AND inventory_transactions.quantity < 0 THEN inventory_transactions.quantity ELSE 0 END)) as outbound_qty"),
+ // 調撥入:type 為 調撥入庫
+ DB::raw("SUM(CASE WHEN inventory_transactions.type = '調撥入庫' AND inventory_transactions.quantity > 0 THEN inventory_transactions.quantity ELSE 0 END) as transfer_in_qty"),
+ // 調撥出:type 為 調撥出庫 (取絕對值)
+ DB::raw("ABS(SUM(CASE WHEN inventory_transactions.type = '調撥出庫' AND inventory_transactions.quantity < 0 THEN inventory_transactions.quantity ELSE 0 END)) as transfer_out_qty"),
// 調整量:type 為 庫存調整, 手動編輯
DB::raw("SUM(CASE WHEN inventory_transactions.type IN ('庫存調整', '手動編輯') THEN inventory_transactions.quantity ELSE 0 END) as adjust_qty"),
- // 調撥淨額 (隱藏欄位,但包含在 net_change)
// 淨變動:總和 (包含所有類型:進貨、出貨、調整、調撥)
DB::raw("SUM(inventory_transactions.quantity) as net_change"),
])
@@ -92,7 +97,7 @@ class InventoryReportService
});
}
- // 分組與排序
+ // 分組
$query->groupBy([
'products.id',
'products.code',
@@ -100,7 +105,20 @@ class InventoryReportService
'categories.name'
]);
- $query->orderBy('products.code', 'asc');
+ // 動態排序
+ $allowedSortFields = [
+ 'product_code' => 'products.code',
+ 'product_name' => 'products.name',
+ 'inbound_qty' => 'inbound_qty',
+ 'outbound_qty' => 'outbound_qty',
+ 'transfer_in_qty' => 'transfer_in_qty',
+ 'transfer_out_qty' => 'transfer_out_qty',
+ 'adjust_qty' => 'adjust_qty',
+ 'net_change' => 'net_change',
+ ];
+
+ $sortColumn = $allowedSortFields[$sortBy] ?? 'products.code';
+ $query->orderBy($sortColumn, $sortOrder === 'desc' ? 'desc' : 'asc');
if ($perPage) {
@@ -169,6 +187,8 @@ class InventoryReportService
return $query->select([
DB::raw("SUM(CASE WHEN inventory_transactions.type IN ('入庫', '手動入庫') AND inventory_transactions.quantity > 0 THEN inventory_transactions.quantity ELSE 0 END) as total_inbound"),
DB::raw("ABS(SUM(CASE WHEN inventory_transactions.type IN ('出庫') AND inventory_transactions.quantity < 0 THEN inventory_transactions.quantity ELSE 0 END)) as total_outbound"),
+ DB::raw("SUM(CASE WHEN inventory_transactions.type = '調撥入庫' AND inventory_transactions.quantity > 0 THEN inventory_transactions.quantity ELSE 0 END) as total_transfer_in"),
+ DB::raw("ABS(SUM(CASE WHEN inventory_transactions.type = '調撥出庫' AND inventory_transactions.quantity < 0 THEN inventory_transactions.quantity ELSE 0 END)) as total_transfer_out"),
DB::raw("SUM(CASE WHEN inventory_transactions.type IN ('庫存調整', '手動編輯') THEN inventory_transactions.quantity ELSE 0 END) as total_adjust"),
DB::raw("SUM(inventory_transactions.quantity) as total_net_change"),
])->first();
diff --git a/app/Modules/Sales/Controllers/SalesImportController.php b/app/Modules/Sales/Controllers/SalesImportController.php
index 2718256..8e40743 100644
--- a/app/Modules/Sales/Controllers/SalesImportController.php
+++ b/app/Modules/Sales/Controllers/SalesImportController.php
@@ -16,8 +16,17 @@ class SalesImportController extends Controller
public function index(Request $request)
{
$perPage = $request->input('per_page', 10);
+ $search = $request->input('search');
$batches = SalesImportBatch::with('importer')
+ ->when($search, function ($query, $search) {
+ $query->where(function ($q) use ($search) {
+ $q->where('id', 'like', "%{$search}%")
+ ->orWhereHas('importer', function ($u) use ($search) {
+ $u->where('name', 'like', "%{$search}%");
+ });
+ });
+ })
->orderByDesc('created_at')
->paginate($perPage)
->withQueryString();
@@ -25,7 +34,8 @@ class SalesImportController extends Controller
return Inertia::render('Sales/Import/Index', [
'batches' => $batches,
'filters' => [
- 'per_page' => $perPage,
+ 'per_page' => (string) $perPage,
+ 'search' => $search,
],
]);
}
diff --git a/resources/js/Layouts/AuthenticatedLayout.tsx b/resources/js/Layouts/AuthenticatedLayout.tsx
index 7f63942..693bd70 100644
--- a/resources/js/Layouts/AuthenticatedLayout.tsx
+++ b/resources/js/Layouts/AuthenticatedLayout.tsx
@@ -425,6 +425,7 @@ export default function AuthenticatedLayout({
setIsMobileOpen(false)}
+ preserveScroll={true}
className={cn(
"w-full flex items-center transition-all rounded-lg group",
level === 0 ? "px-3 py-2.5" : "px-3 py-2",
@@ -483,7 +484,7 @@ export default function AuthenticatedLayout({
>
{isMobileOpen ? :
}
-
+
{branding?.short_name || 'Star'} ERP
@@ -510,6 +511,7 @@ export default function AuthenticatedLayout({
@@ -551,7 +553,7 @@ export default function AuthenticatedLayout({
)}
-
+
@@ -596,7 +598,7 @@ export default function AuthenticatedLayout({
-
+
diff --git a/resources/js/Pages/Accounting/Report.tsx b/resources/js/Pages/Accounting/Report.tsx
index d933fbe..764bd8e 100644
--- a/resources/js/Pages/Accounting/Report.tsx
+++ b/resources/js/Pages/Accounting/Report.tsx
@@ -174,8 +174,9 @@ export default function AccountingReport({ records, summary, filters }: PageProp
{/* Filters with Quick Date Range */}
-
-
+ {/* Top Config: Date Range & Quick Buttons */}
+
+
{[
@@ -201,8 +202,9 @@ export default function AccountingReport({ records, summary, filters }: PageProp
-
-
+ {/* Date Inputs */}
+
+
@@ -237,22 +239,25 @@ export default function AccountingReport({ records, summary, filters }: PageProp
- {/* Action Buttons */}
-
-
-
+ {/* Row 2: Actions */}
+
+
+
+
+
+
diff --git a/resources/js/Pages/Inventory/GoodsReceipt/Index.tsx b/resources/js/Pages/Inventory/GoodsReceipt/Index.tsx
index 87148fb..1bfa3f8 100644
--- a/resources/js/Pages/Inventory/GoodsReceipt/Index.tsx
+++ b/resources/js/Pages/Inventory/GoodsReceipt/Index.tsx
@@ -1,7 +1,7 @@
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
import { Head, Link, router } from '@inertiajs/react';
import { Button } from '@/Components/ui/button';
-import { Plus, Search, FileText, RotateCcw, Calendar, ChevronDown, ChevronUp } from 'lucide-react';
+import { Plus, Search, FileText, RotateCcw, Calendar } from 'lucide-react';
import { Input } from '@/Components/ui/input';
import { Label } from '@/Components/ui/label';
import { SearchableSelect } from '@/Components/ui/searchable-select';
@@ -49,9 +49,7 @@ export default function GoodsReceiptIndex({ receipts, filters, warehouses }: Pro
const [dateRangeType, setDateRangeType] = useState('custom');
// Advanced Filter Toggle
- const [showAdvanced, setShowAdvanced] = useState(
- !!(filters.date_start || filters.date_end)
- );
+
// Sync filters from props
useEffect(() => {
@@ -149,55 +147,12 @@ export default function GoodsReceiptIndex({ receipts, filters, warehouses }: Pro
{/* Filter Bar */}
-
- {/* Row 1: Search, Status, Warehouse */}
-
-
-
-
-
- setSearch(e.target.value)}
- className="pl-10 h-9 block"
- onKeyDown={(e) => e.key === 'Enter' && handleFilter()}
- />
-
-
-
-
-
-
-
-
-
-
- 10}
- />
-
-
-
- {/* Row 2: Date Filters (Collapsible) */}
- {showAdvanced && (
-
-
-
+
+
+ {/* Row 1: Date Range & Quick Buttons */}
+
+
+
{[
{ label: "今日", value: "today" },
@@ -222,8 +177,9 @@ export default function GoodsReceiptIndex({ receipts, filters, warehouses }: Pro
-
-
+ {/* Date Inputs */}
+
+
@@ -257,45 +213,71 @@ export default function GoodsReceiptIndex({ receipts, filters, warehouses }: Pro
- )}
-
-
-
-
+ {/* Row 2: Filters & Actions */}
+
+ {/* Search */}
+
+
+
+
+ setSearch(e.target.value)}
+ className="pl-10 h-9 block"
+ onKeyDown={(e) => e.key === 'Enter' && handleFilter()}
+ />
+
+
+
+ {/* Status */}
+
+
+
+
+
+ {/* Warehouse */}
+
+
+ 10}
+ />
+
+
+ {/* Actions */}
+
+
+
+
+
diff --git a/resources/js/Pages/Inventory/Report/Index.tsx b/resources/js/Pages/Inventory/Report/Index.tsx
index fe3eb57..077b58b 100644
--- a/resources/js/Pages/Inventory/Report/Index.tsx
+++ b/resources/js/Pages/Inventory/Report/Index.tsx
@@ -12,7 +12,10 @@ import {
ArrowUpFromLine,
ArrowDownToLine,
ArrowRightLeft,
- TrendingUp
+ TrendingUp,
+ ArrowUpDown,
+ ArrowUp,
+ ArrowDown
} from 'lucide-react';
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
import { Head, Link, router } from "@inertiajs/react";
@@ -29,6 +32,12 @@ import Pagination from "@/Components/shared/Pagination";
import { SearchableSelect } from "@/Components/ui/searchable-select";
import { Can } from "@/Components/Permission/Can";
import { PageProps } from "@/types/global";
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from "@/Components/ui/tooltip";
interface ReportData {
product_code: string;
@@ -37,6 +46,8 @@ interface ReportData {
product_id: number;
inbound_qty: number;
outbound_qty: number;
+ transfer_in_qty: number;
+ transfer_out_qty: number;
adjust_qty: number;
net_change: number;
}
@@ -44,6 +55,8 @@ interface ReportData {
interface SummaryData {
total_inbound: number;
total_outbound: number;
+ total_transfer_in: number;
+ total_transfer_out: number;
total_adjust: number;
total_net_change: number;
}
@@ -67,6 +80,8 @@ interface InventoryReportProps extends PageProps {
category_id: string;
search: string;
per_page?: number;
+ sort_by?: string;
+ sort_order?: 'asc' | 'desc';
};
}
@@ -120,7 +135,7 @@ export default function InventoryReportIndex({ reportData, summary, warehouses,
search: search,
per_page: perPage,
},
- { preserveState: true }
+ { preserveState: true, preserveScroll: true }
);
}, [dateStart, dateEnd, warehouseId, categoryId, search, perPage]);
@@ -136,7 +151,7 @@ export default function InventoryReportIndex({ reportData, summary, warehouses,
search: search,
per_page: value,
},
- { preserveState: true }
+ { preserveState: true, preserveScroll: true }
);
};
@@ -161,10 +176,51 @@ export default function InventoryReportIndex({ reportData, summary, warehouses,
warehouse_id: warehouseId === "all" ? "" : warehouseId,
category_id: categoryId === "all" ? "" : categoryId,
search: search,
+ sort_by: filters.sort_by,
+ sort_order: filters.sort_order,
};
window.location.href = route("inventory.report.export", query);
};
+ const handleSort = (field: string) => {
+ let newSortBy: string | undefined = field;
+ let newSortOrder: 'asc' | 'desc' | undefined = 'asc';
+
+ if (filters.sort_by === field) {
+ if (filters.sort_order === 'asc') {
+ newSortOrder = 'desc';
+ } else {
+ newSortBy = undefined;
+ newSortOrder = undefined;
+ }
+ }
+
+ router.get(
+ route("inventory.report.index"),
+ {
+ date_from: dateStart,
+ date_to: dateEnd,
+ warehouse_id: warehouseId === "all" ? "" : warehouseId,
+ category_id: categoryId === "all" ? "" : categoryId,
+ search: search,
+ per_page: perPage,
+ sort_by: newSortBy,
+ sort_order: newSortOrder,
+ },
+ { preserveState: true, preserveScroll: true }
+ );
+ };
+
+ const SortIcon = ({ field }: { field: string }) => {
+ if (filters.sort_by !== field) {
+ return
;
+ }
+ if (filters.sort_order === "asc") {
+ return
;
+ }
+ return
;
+ };
+
return (
@@ -271,7 +327,7 @@ export default function InventoryReportIndex({ reportData, summary, warehouses,
{/* Detailed Filters row */}
{/* Warehouse & Category */}
-
+
-
+
{/* Search */}
-
+
e.key === 'Enter' && handleFilter()}
/>
-
- {/* Action Buttons */}
-
-
-
+ {/* Action Buttons Integrated */}
+
+
+
+
{/* Summary Cards */}
-
-
-
-
-
總進貨量
-
{Number(summary?.total_inbound || 0).toLocaleString()}
+
+
+
+
+
+
進貨量
+
+
+ {Number(summary?.total_inbound || 0).toLocaleString()}
+
+
+ {Number(summary?.total_inbound || 0).toLocaleString()}
+
+
+
-
-
-
-
-
總出貨量
-
{Number(summary?.total_outbound || 0).toLocaleString()}
+
+
+
+
出貨量
+
+
+ {Number(summary?.total_outbound || 0).toLocaleString()}
+
+
+ {Number(summary?.total_outbound || 0).toLocaleString()}
+
+
+
-
-
-
-
-
調整量
-
{Number(summary?.total_adjust || 0).toLocaleString()}
+
+
+
+
調撥入
+
+
+ {Number(summary?.total_transfer_in || 0).toLocaleString()}
+
+
+ {Number(summary?.total_transfer_in || 0).toLocaleString()}
+
+
+
-
-
-
-
-
淨變動
-
= 0 ? "text-emerald-600" : "text-red-600"}`}>
- {summary?.total_net_change > 0 ? "+" : ""}{Number(summary?.total_net_change || 0).toLocaleString()}
-
+
+
+
+
調撥出
+
+
+ {Number(summary?.total_transfer_out || 0).toLocaleString()}
+
+
+ {Number(summary?.total_transfer_out || 0).toLocaleString()}
+
+
+
+
+
+
+
+
+
調整量
+
+
+ {Number(summary?.total_adjust || 0).toLocaleString()}
+
+
+ {Number(summary?.total_adjust || 0).toLocaleString()}
+
+
+
+
+
+
+
+
+
淨變動
+
+
+ = 0 ? "text-emerald-600" : "text-red-600"}`}>
+ {summary?.total_net_change > 0 ? "+" : ""}{Number(summary?.total_net_change || 0).toLocaleString()}
+
+
+
+ {summary?.total_net_change > 0 ? "+" : ""}{Number(summary?.total_net_change || 0).toLocaleString()}
+
+
+
-
+
{/* Results Table */}
@@ -368,18 +484,32 @@ export default function InventoryReportIndex({ reportData, summary, warehouses,
商品代碼
- 商品名稱
+ 商品名稱
分類
- 進貨量
- 出貨量
- 調整量
- 淨變動
+ handleSort('inbound_qty')}>
+ 進貨量
+
+ handleSort('outbound_qty')}>
+ 出貨量
+
+ handleSort('transfer_in_qty')}>
+ 調撥入
+
+ handleSort('transfer_out_qty')}>
+ 調撥出
+
+ handleSort('adjust_qty')}>
+ 調整量
+
+ handleSort('net_change')}>
+ 淨變動
+
{reportData.data.length === 0 ? (
-
+
無符合條件的報表資料
@@ -431,6 +561,12 @@ export default function InventoryReportIndex({ reportData, summary, warehouses,
{row.outbound_qty > 0 ? `-${row.outbound_qty}` : "-"}
+
+ {row.transfer_in_qty > 0 ? `+${row.transfer_in_qty}` : "-"}
+
+
+ {row.transfer_out_qty > 0 ? `-${row.transfer_out_qty}` : "-"}
+
{row.adjust_qty !== 0 ? (row.adjust_qty > 0 ? `+${row.adjust_qty}` : row.adjust_qty) : "-"}
diff --git a/resources/js/Pages/PurchaseOrder/Index.tsx b/resources/js/Pages/PurchaseOrder/Index.tsx
index 1059dca..91abb91 100644
--- a/resources/js/Pages/PurchaseOrder/Index.tsx
+++ b/resources/js/Pages/PurchaseOrder/Index.tsx
@@ -3,7 +3,7 @@
*/
import { useState, useEffect } from "react";
-import { Plus, ShoppingCart, Search, RotateCcw, Calendar, ChevronDown, ChevronUp } from 'lucide-react';
+import { Plus, ShoppingCart, Search, RotateCcw, Calendar } from 'lucide-react';
import { Button } from "@/Components/ui/button";
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
import { Head, router } from "@inertiajs/react";
@@ -57,9 +57,7 @@ export default function PurchaseOrderIndex({ orders, filters, warehouses }: Prop
const [dateRangeType, setDateRangeType] = useState('custom');
// Advanced Filter Toggle
- const [showAdvancedFilter, setShowAdvancedFilter] = useState(
- !!(filters.date_start || filters.date_end)
- );
+
// 同步 URL 參數到 State (雖有初始值,但若由外部連結進入可確保同步)
useEffect(() => {
@@ -152,60 +150,13 @@ export default function PurchaseOrderIndex({ orders, filters, warehouses }: Prop
{/* 篩選區塊 */}
-
- {/* Row 1: Search, Status, Warehouse */}
-
-
-
-
-
- setSearch(e.target.value)}
- className="pl-10 h-9 block"
- onKeyDown={(e) => e.key === 'Enter' && handleFilter()}
- />
-
-
-
-
-
-
-
-
-
-
- ({ label: w.name, value: String(w.id) }))
- ]}
- placeholder="選擇倉庫"
- className="w-full h-9"
- />
-
-
-
- {/* Row 2: Date Filters (Collapsible) */}
- {showAdvancedFilter && (
-
-
-
+ {/* 篩選區塊 */}
+
+
+ {/* Row 1: Date Range & Quick Buttons */}
+
+
+
{[
{ label: "今日", value: "today" },
@@ -230,8 +181,9 @@ export default function PurchaseOrderIndex({ orders, filters, warehouses }: Prop
-
-
+ {/* Date Inputs */}
+
+
@@ -265,45 +217,76 @@ export default function PurchaseOrderIndex({ orders, filters, warehouses }: Prop
- )}
-
-
-
-
+ {/* Row 2: Filters & Actions */}
+
+ {/* Search */}
+
+
+
+
+ setSearch(e.target.value)}
+ className="pl-10 h-9 block"
+ onKeyDown={(e) => e.key === 'Enter' && handleFilter()}
+ />
+
+
+
+ {/* Status */}
+
+
+
+
+
+ {/* Warehouse */}
+
+
+ ({ label: w.name, value: String(w.id) }))
+ ]}
+ placeholder="選擇倉庫"
+ className="w-full h-9"
+ />
+
+
+ {/* Actions */}
+
+
+
+
+
diff --git a/resources/js/Pages/Sales/Import/Index.tsx b/resources/js/Pages/Sales/Import/Index.tsx
index 2b3861e..41e383c 100644
--- a/resources/js/Pages/Sales/Import/Index.tsx
+++ b/resources/js/Pages/Sales/Import/Index.tsx
@@ -21,11 +21,12 @@ import {
AlertDialogTrigger,
} from "@/Components/ui/alert-dialog";
import { Badge } from "@/Components/ui/badge";
-import { Plus, FileUp, Eye, Trash2 } from 'lucide-react';
+import { Plus, FileUp, Eye, Trash2, Search, X } from 'lucide-react';
import { useState, useEffect } from "react";
import { format } from 'date-fns';
import Pagination from "@/Components/shared/Pagination";
import { SearchableSelect } from "@/Components/ui/searchable-select";
+import { Input } from "@/Components/ui/input";
import { router } from "@inertiajs/react";
import { usePermission } from "@/hooks/usePermission";
import SalesImportDialog from "@/Components/Sales/SalesImportDialog";
@@ -47,27 +48,41 @@ interface Props {
data: ImportBatch[];
links: any[]; // Pagination links
};
- filters?: { // Add filters prop if not present, though we main need per_page state
+ filters?: {
per_page?: string;
+ search?: string;
}
}
export default function SalesImportIndex({ batches, filters = {} }: Props) {
const { can } = usePermission();
const [perPage, setPerPage] = useState(filters?.per_page?.toString() || "10");
+ const [search, setSearch] = useState(filters?.search || "");
const [isImportDialogOpen, setIsImportDialogOpen] = useState(false);
useEffect(() => {
if (filters?.per_page) {
setPerPage(filters.per_page.toString());
}
- }, [filters?.per_page]);
+ setSearch(filters?.search || "");
+ }, [filters]);
+
+ const handleFilter = () => {
+ router.get(
+ route("sales-imports.index"),
+ {
+ per_page: perPage,
+ search: search
+ },
+ { preserveState: true, replace: true }
+ );
+ };
const handlePerPageChange = (value: string) => {
setPerPage(value);
router.get(
route("sales-imports.index"),
- { per_page: value },
+ { ...filters, per_page: value },
{ preserveState: true, preserveScroll: true, replace: true }
);
};
@@ -92,15 +107,56 @@ export default function SalesImportIndex({ batches, filters = {} }: Props) {
匯入並管理銷售出貨紀錄
- {can('sales_imports.create') && (
-
- )}
+
+
+ {/* Toolbar (Aligned with Recipe Management) */}
+
+
+ {/* Search */}
+
+
+ setSearch(e.target.value)}
+ className="pl-10 pr-10 h-9"
+ onKeyDown={(e) => e.key === 'Enter' && handleFilter()}
+ />
+ {search && (
+
+ )}
+
+
+ {/* Action Buttons */}
+
+
+
+ {can('sales_imports.create') && (
+
+ )}
+
+
- ID
+ #
匯入日期
匯入人員
總數量
@@ -129,9 +185,11 @@ export default function SalesImportIndex({ batches, filters = {} }: Props) {
) : (
- batches.data.map((batch) => (
+ batches.data.map((batch, index) => (
- #{batch.id}
+
+ {(batches as any).from + index}
+
{format(new Date(batch.created_at), 'yyyy/MM/dd HH:mm')}
diff --git a/resources/js/Pages/UtilityFee/Index.tsx b/resources/js/Pages/UtilityFee/Index.tsx
index eb9155e..59955e6 100644
--- a/resources/js/Pages/UtilityFee/Index.tsx
+++ b/resources/js/Pages/UtilityFee/Index.tsx
@@ -13,9 +13,7 @@ import {
RotateCcw,
ArrowUpDown,
ArrowUp,
- ArrowDown,
- ChevronDown,
- ChevronUp
+ ArrowDown
} from 'lucide-react';
import { Label } from "@/Components/ui/label";
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
@@ -81,10 +79,7 @@ export default function UtilityFeeIndex({ fees, availableCategories, filters }:
const [editingFee, setEditingFee] = useState(null);
const [deletingFeeId, setDeletingFeeId] = useState(null);
- // Advanced Filter Toggle
- const [showAdvancedFilter, setShowAdvancedFilter] = useState(
- !!(filters.date_start || filters.date_end)
- );
+
// Sorting
const [sortField, setSortField] = useState(filters.sort_field || null);
@@ -236,11 +231,76 @@ export default function UtilityFeeIndex({ fees, availableCategories, filters }:
-
- {/* Row 1: Search and Category */}
-
-
-
+
+ {/* Row 1: Date Range & Quick Buttons (Aligned with Inventory Report) */}
+
+
+
+
+ {[
+ { label: "今日", value: "today" },
+ { label: "昨日", value: "yesterday" },
+ { label: "本週", value: "this_week" },
+ { label: "本月", value: "this_month" },
+ { label: "上月", value: "last_month" },
+ ].map((opt) => (
+
+ ))}
+
+
+
+ {/* Date Inputs */}
+
+
+
+
+
+
+ {
+ setDateStart(e.target.value);
+ setDateRangeType('custom');
+ }}
+ className="pl-9 block w-full h-9 bg-white"
+ />
+
+
+
+
+
+
+ {
+ setDateEnd(e.target.value);
+ setDateRangeType('custom');
+ }}
+ className="pl-9 block w-full h-9 bg-white"
+ />
+
+
+
+
+
+
+ {/* Row 2: Search, Category & Actions */}
+
+
+
setSearchTerm(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && handleSearch()}
- className="pl-10 h-9 block"
+ className="pl-10 h-9 block bg-white"
/>
{searchTerm && (
-
+
({ label: c, value: c }))
]}
placeholder="篩選類別"
- className="h-9"
+ className="h-9 w-full"
/>
-
- {/* Row 2: Date Filters (Collapsible) */}
- {showAdvancedFilter && (
-
-
-
-
- {[
- { label: "今日", value: "today" },
- { label: "昨日", value: "yesterday" },
- { label: "本週", value: "this_week" },
- { label: "本月", value: "this_month" },
- { label: "上月", value: "last_month" },
- ].map((opt) => (
-
- ))}
-
-
-
-
-
-
-
-
-
- {
- setDateStart(e.target.value);
- setDateRangeType('custom');
- }}
- className="pl-9 block w-full h-9 bg-white"
- />
-
-
-
-
-
-
- {
- setDateEnd(e.target.value);
- setDateRangeType('custom');
- }}
- className="pl-9 block w-full h-9 bg-white"
- />
-
-
-
-
+ {/* Actions Buttons Group */}
+
+
+
- )}
-
- {/* Action Buttons */}
-
-
-
-