feat: 統一全系統頁面標題樣式、優化側邊欄與實作角色成員查看功能
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import { useState } from "react";
|
||||
import { Plus, Trash2, Calendar, ArrowLeft, Save } from "lucide-react";
|
||||
import { Plus, Trash2, Calendar, ArrowLeft, Save, Boxes } from "lucide-react";
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import { Input } from "@/Components/ui/input";
|
||||
import { Label } from "@/Components/ui/label";
|
||||
@@ -183,8 +183,11 @@ export default function AddInventoryPage({ warehouse, products }: Props) {
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="mb-2">新增庫存(手動入庫)</h1>
|
||||
<p className="text-gray-600 font-medium">
|
||||
<h1 className="text-2xl font-bold text-grey-0 flex items-center gap-2">
|
||||
<Boxes className="h-6 w-6 text-[#01ab83]" />
|
||||
新增庫存(手動入庫)
|
||||
</h1>
|
||||
<p className="text-gray-500 mt-1">
|
||||
為 <span className="font-semibold text-gray-900">{warehouse.name}</span> 新增庫存記錄
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@ import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import { Input } from "@/Components/ui/input";
|
||||
import { Label } from "@/Components/ui/label";
|
||||
import { ArrowLeft, Save, Trash2 } from "lucide-react";
|
||||
import { ArrowLeft, Save, Trash2, Boxes } from "lucide-react";
|
||||
import { Warehouse, WarehouseInventory } from "@/types/warehouse";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
@@ -88,20 +88,13 @@ export default function EditInventory({ warehouse, inventory, transactions = []
|
||||
</Button>
|
||||
</Link >
|
||||
|
||||
<div className="flex items-center gap-2 text-sm text-gray-500 mb-2">
|
||||
<span>商品與庫存管理</span>
|
||||
<span>/</span>
|
||||
<span>倉庫管理</span>
|
||||
<span>/</span>
|
||||
<span>庫存管理</span>
|
||||
<span>/</span>
|
||||
<span className="text-gray-900">編輯庫存品項</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="mb-2">編輯庫存品項</h1>
|
||||
<p className="text-gray-600">
|
||||
<h1 className="text-2xl font-bold text-grey-0 flex items-center gap-2">
|
||||
<Boxes className="h-6 w-6 text-[#01ab83]" />
|
||||
編輯庫存品項
|
||||
</h1>
|
||||
<p className="text-gray-500 mt-1">
|
||||
倉庫:<span className="font-medium text-gray-900">{warehouse.name}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,7 @@ import { Warehouse } from "@/types/warehouse";
|
||||
import Pagination from "@/Components/shared/Pagination";
|
||||
import { toast } from "sonner";
|
||||
import { getBreadcrumbs } from "@/utils/breadcrumb";
|
||||
import { Can } from "@/Components/Permission/Can";
|
||||
|
||||
interface PageProps {
|
||||
warehouses: {
|
||||
@@ -133,20 +134,24 @@ export default function WarehouseIndex({ warehouses, filters }: PageProps) {
|
||||
|
||||
{/* 操作按鈕 */}
|
||||
<div className="flex gap-2 w-full md:w-auto">
|
||||
<Button
|
||||
onClick={handleAddTransferOrder}
|
||||
className="flex-1 md:flex-initial button-outlined-primary"
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
新增撥補單
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleAddWarehouse}
|
||||
className="flex-1 md:flex-initial button-filled-primary"
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
新增倉庫
|
||||
</Button>
|
||||
<Can permission="inventory.transfer">
|
||||
<Button
|
||||
onClick={handleAddTransferOrder}
|
||||
className="flex-1 md:flex-initial button-outlined-primary"
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
新增撥補單
|
||||
</Button>
|
||||
</Can>
|
||||
<Can permission="warehouses.create">
|
||||
<Button
|
||||
onClick={handleAddWarehouse}
|
||||
className="flex-1 md:flex-initial button-filled-primary"
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
新增倉庫
|
||||
</Button>
|
||||
</Can>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useMemo } from "react";
|
||||
import { ArrowLeft, PackagePlus, AlertTriangle, Shield } from "lucide-react";
|
||||
import { ArrowLeft, PackagePlus, AlertTriangle, Shield, Boxes } from "lucide-react";
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
|
||||
import { Head, Link, router } from "@inertiajs/react";
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "@/Components/ui/alert-dialog";
|
||||
import { Can } from "@/Components/Permission/Can";
|
||||
|
||||
// 庫存頁面 Props
|
||||
interface Props {
|
||||
@@ -107,8 +108,11 @@ export default function WarehouseInventoryPage({
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="mb-2">庫存管理 - {warehouse.name}</h1>
|
||||
<p className="text-gray-600 font-medium">查看並管理此倉庫內的商品庫存數量與批號資訊</p>
|
||||
<h1 className="text-2xl font-bold text-grey-0 flex items-center gap-2">
|
||||
<Boxes className="h-6 w-6 text-[#01ab83]" />
|
||||
庫存管理 - {warehouse.name}
|
||||
</h1>
|
||||
<p className="text-gray-500 mt-1">查看並管理此倉庫內的商品庫存數量與批號資訊</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -116,15 +120,17 @@ export default function WarehouseInventoryPage({
|
||||
{/* 操作按鈕 (位於標題下方) */}
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
{/* 安全庫存設定按鈕 */}
|
||||
<Link href={route('warehouses.safety-stock.index', warehouse.id)}>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="button-outlined-primary"
|
||||
>
|
||||
<Shield className="mr-2 h-4 w-4" />
|
||||
安全庫存設定
|
||||
</Button>
|
||||
</Link>
|
||||
<Can permission="inventory.safety_stock">
|
||||
<Link href={route('warehouses.safety-stock.index', warehouse.id)}>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="button-outlined-primary"
|
||||
>
|
||||
<Shield className="mr-2 h-4 w-4" />
|
||||
安全庫存設定
|
||||
</Button>
|
||||
</Link>
|
||||
</Can>
|
||||
|
||||
{/* 庫存警告顯示 */}
|
||||
<Button
|
||||
@@ -139,14 +145,16 @@ export default function WarehouseInventoryPage({
|
||||
</Button>
|
||||
|
||||
{/* 新增庫存按鈕 */}
|
||||
<Link href={route('warehouses.inventory.create', warehouse.id)}>
|
||||
<Button
|
||||
className="button-filled-primary"
|
||||
>
|
||||
<PackagePlus className="mr-2 h-4 w-4" />
|
||||
新增庫存
|
||||
</Button>
|
||||
</Link>
|
||||
<Can permission="inventory.adjust">
|
||||
<Link href={route('warehouses.inventory.create', warehouse.id)}>
|
||||
<Button
|
||||
className="button-filled-primary"
|
||||
>
|
||||
<PackagePlus className="mr-2 h-4 w-4" />
|
||||
新增庫存
|
||||
</Button>
|
||||
</Link>
|
||||
</Can>
|
||||
</div>
|
||||
|
||||
{/* 篩選工具列 */}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Head, Link } from "@inertiajs/react";
|
||||
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import { ArrowLeft, History } from "lucide-react";
|
||||
import { Warehouse } from "@/types/warehouse";
|
||||
import TransactionTable, { Transaction } from "@/Components/Warehouse/Inventory/TransactionTable";
|
||||
import { getInventoryBreadcrumbs } from "@/utils/breadcrumb";
|
||||
@@ -21,7 +21,7 @@ export default function InventoryHistory({ warehouse, inventory, transactions }:
|
||||
return (
|
||||
<AuthenticatedLayout breadcrumbs={getInventoryBreadcrumbs(warehouse.id, warehouse.name, "庫存變動紀錄")}>
|
||||
<Head title={`庫存異動紀錄 - ${inventory.productName}`} />
|
||||
<div className="container mx-auto p-6 max-w-4xl">
|
||||
<div className="container mx-auto p-6 max-w-7xl">
|
||||
{/* Header */}
|
||||
<div className="mb-6">
|
||||
<Link href={`/warehouses/${warehouse.id}/inventory`}>
|
||||
@@ -34,18 +34,13 @@ export default function InventoryHistory({ warehouse, inventory, transactions }:
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center gap-2 text-sm text-gray-500 mb-2">
|
||||
<span>倉庫管理</span>
|
||||
<span>/</span>
|
||||
<span>庫存管理</span>
|
||||
<span>/</span>
|
||||
<span className="text-gray-900">庫存異動紀錄</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="mb-2">庫存異動紀錄</h1>
|
||||
<p className="text-gray-600">
|
||||
<h1 className="text-2xl font-bold text-grey-0 flex items-center gap-2">
|
||||
<History className="h-6 w-6 text-[#01ab83]" />
|
||||
庫存異動紀錄
|
||||
</h1>
|
||||
<p className="text-gray-500 mt-1">
|
||||
商品:<span className="font-medium text-gray-900">{inventory.productName}</span>
|
||||
{inventory.productCode && <span className="text-gray-500 ml-2">({inventory.productCode})</span>}
|
||||
</p>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { ArrowLeft, Plus } from "lucide-react";
|
||||
import { ArrowLeft, Plus, Shield } from "lucide-react";
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
|
||||
import { Head, Link, router } from "@inertiajs/react";
|
||||
@@ -14,6 +14,17 @@ import AddSafetyStockDialog from "@/Components/Warehouse/SafetyStock/AddSafetySt
|
||||
import EditSafetyStockDialog from "@/Components/Warehouse/SafetyStock/EditSafetyStockDialog";
|
||||
import { toast } from "sonner";
|
||||
import { getInventoryBreadcrumbs } from "@/utils/breadcrumb";
|
||||
import { Can } from "@/Components/Permission/Can";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "@/Components/ui/alert-dialog";
|
||||
|
||||
interface Props {
|
||||
warehouse: Warehouse;
|
||||
@@ -31,6 +42,7 @@ export default function SafetyStockPage({
|
||||
const [settings, setSettings] = useState<SafetyStockSetting[]>(initialSettings);
|
||||
const [showAddDialog, setShowAddDialog] = useState(false);
|
||||
const [editingSetting, setEditingSetting] = useState<SafetyStockSetting | null>(null);
|
||||
const [deleteId, setDeleteId] = useState<string | null>(null);
|
||||
|
||||
|
||||
// 當 Props 更新時同步本地 State
|
||||
@@ -71,10 +83,16 @@ export default function SafetyStockPage({
|
||||
});
|
||||
};
|
||||
|
||||
const handleDelete = (id: string) => {
|
||||
router.delete(route('warehouses.safety-stock.destroy', [warehouse.id, id]), {
|
||||
const handleDelete = () => {
|
||||
if (!deleteId) return;
|
||||
|
||||
router.delete(route('warehouses.safety-stock.destroy', [warehouse.id, deleteId]), {
|
||||
onSuccess: () => {
|
||||
setDeleteId(null);
|
||||
toast.success("已刪除安全庫存設定");
|
||||
},
|
||||
onError: () => {
|
||||
toast.error("刪除失敗");
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -101,18 +119,23 @@ export default function SafetyStockPage({
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="mb-2">安全庫存設定 - {warehouse.name}</h1>
|
||||
<p className="text-gray-600 font-medium">
|
||||
<h1 className="text-2xl font-bold text-grey-0 flex items-center gap-2">
|
||||
<Shield className="h-6 w-6 text-[#01ab83]" />
|
||||
安全庫存設定 - {warehouse.name}
|
||||
</h1>
|
||||
<p className="text-gray-500 mt-1">
|
||||
設定商品的安全庫存量,當庫存低於安全值時將發出警告
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => setShowAddDialog(true)}
|
||||
className="button-filled-primary"
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
新增安全庫存
|
||||
</Button>
|
||||
<Can permission="inventory.safety_stock">
|
||||
<Button
|
||||
onClick={() => setShowAddDialog(true)}
|
||||
className="button-filled-primary"
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
新增安全庫存
|
||||
</Button>
|
||||
</Can>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -121,7 +144,7 @@ export default function SafetyStockPage({
|
||||
settings={settings}
|
||||
inventories={inventories}
|
||||
onEdit={setEditingSetting}
|
||||
onDelete={handleDelete}
|
||||
onDelete={setDeleteId}
|
||||
/>
|
||||
|
||||
{/* 新增對話框 */}
|
||||
@@ -143,6 +166,27 @@ export default function SafetyStockPage({
|
||||
onSave={handleEdit}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 刪除確認對話框 */}
|
||||
<AlertDialog open={!!deleteId} onOpenChange={(open) => !open && setDeleteId(null)}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>確認刪除安全庫存設定</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
您確定要刪除此項商品的安全庫存設定嗎?刪除後系統將不再針對此商品發出庫存不足警告。此動作無法復原。
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel className="button-outlined-primary">取消</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={handleDelete}
|
||||
className="bg-red-600 hover:bg-red-700 text-white"
|
||||
>
|
||||
確認刪除
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
</AuthenticatedLayout>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user