feat(inventory): 實作過期與瑕疵庫存總計顯示,並強化庫存明細過期提示
This commit is contained in:
@@ -135,6 +135,12 @@ export default function InventoryTable({
|
||||
<span className="text-sm text-gray-500">
|
||||
{hasInventory ? `${group.batches.length} 個批號` : '無庫存'}
|
||||
</span>
|
||||
{group.batches.some(b => b.expiryDate && new Date(b.expiryDate) < new Date()) && (
|
||||
<Badge className="bg-red-50 text-red-600 border-red-200">
|
||||
<AlertTriangle className="mr-1 h-3 w-3" />
|
||||
含過期項目
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="text-sm">
|
||||
@@ -217,7 +223,23 @@ export default function InventoryTable({
|
||||
<TableCell>${batch.total_value?.toLocaleString()}</TableCell>
|
||||
</Can>
|
||||
<TableCell>
|
||||
{batch.expiryDate ? formatDate(batch.expiryDate) : "-"}
|
||||
{batch.expiryDate ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<span className={new Date(batch.expiryDate) < new Date() ? "text-red-600 font-medium" : ""}>
|
||||
{formatDate(batch.expiryDate)}
|
||||
</span>
|
||||
{new Date(batch.expiryDate) < new Date() && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<AlertTriangle className="h-4 w-4 text-red-500 cursor-help" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>此批號已過期</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
) : "-"}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{batch.lastInboundDate ? formatDate(batch.lastInboundDate) : "-"}
|
||||
@@ -280,7 +302,7 @@ export default function InventoryTable({
|
||||
})}
|
||||
|
||||
|
||||
</div>
|
||||
</TooltipProvider>
|
||||
</div >
|
||||
</TooltipProvider >
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/Components/ui/dialog";
|
||||
import { Can } from "@/Components/Permission/Can";
|
||||
|
||||
interface WarehouseCardProps {
|
||||
warehouse: Warehouse;
|
||||
@@ -59,9 +60,12 @@ export default function WarehouseCard({
|
||||
>
|
||||
{/* 警告橫幅 */}
|
||||
{hasWarning && (
|
||||
<div className="absolute top-0 left-0 right-0 bg-orange-500 text-white px-4 py-1 flex items-center gap-2 text-sm">
|
||||
<AlertTriangle className="h-4 w-4" />
|
||||
<span>低庫存警告</span>
|
||||
<div className="absolute top-0 left-0 right-0 bg-orange-500 text-white px-4 py-1 flex items-center justify-between text-sm">
|
||||
<div className="flex items-center gap-2">
|
||||
<AlertTriangle className="h-4 w-4" />
|
||||
<span>低庫存警告</span>
|
||||
</div>
|
||||
<span className="font-bold">{stats.lowStockCount} 項</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -81,12 +85,16 @@ export default function WarehouseCard({
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex gap-2 mt-1">
|
||||
<Badge variant="outline" className="text-xs font-normal">
|
||||
<Badge
|
||||
variant={warehouse.type === 'quarantine' ? "secondary" : "outline"}
|
||||
className={`text-xs font-normal ${warehouse.type === 'quarantine' ? 'bg-red-100 text-red-700 border-red-200' : ''}`}
|
||||
>
|
||||
{WAREHOUSE_TYPE_LABELS[warehouse.type || 'standard'] || '標準倉'}
|
||||
{warehouse.type === 'quarantine' ? ' (不計入可用)' : ' (計入可用)'}
|
||||
</Badge>
|
||||
{warehouse.type === 'transit' && warehouse.license_plate && (
|
||||
<Badge variant="secondary" className="text-xs font-normal bg-yellow-100 text-yellow-800 border-yellow-200">
|
||||
{warehouse.license_plate}
|
||||
{warehouse.license_plate} {warehouse.driver_name && `(${warehouse.driver_name})`}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
@@ -100,46 +108,36 @@ export default function WarehouseCard({
|
||||
|
||||
{/* 統計區塊 - 狀態標籤 */}
|
||||
<div className="space-y-3">
|
||||
{/* 銷售狀態與可用性說明 */}
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-500">庫存可用性</span>
|
||||
{warehouse.type === 'quarantine' ? (
|
||||
<Badge variant="secondary" className="bg-red-100 text-red-700 border-red-200">
|
||||
不計入可用
|
||||
</Badge>
|
||||
) : (
|
||||
<Badge variant="default" className="bg-green-600">
|
||||
計入可用
|
||||
</Badge>
|
||||
|
||||
{/* 帳面庫存總計 (金額) */}
|
||||
<Can permission="inventory.view_cost">
|
||||
<div className="flex items-center justify-between p-3 rounded-lg bg-primary-50/50 border border-primary-100">
|
||||
<div className="flex items-center gap-2 text-primary-700">
|
||||
<Package className="h-4 w-4" />
|
||||
<span className="text-sm font-medium">帳面庫存總計</span>
|
||||
</div>
|
||||
<div className="text-sm font-bold text-primary-main">
|
||||
${Number(stats.totalValue || 0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
|
||||
</div>
|
||||
</div>
|
||||
</Can>
|
||||
|
||||
{/* 過期與瑕疵總計 (金額) */}
|
||||
<Can permission="inventory.view_cost">
|
||||
{Number(stats.abnormalValue || 0) > 0 && (
|
||||
<div className="flex items-center justify-between p-3 rounded-lg bg-red-50/50 border border-red-100 mt-3">
|
||||
<div className="flex items-center gap-2 text-red-700">
|
||||
<AlertTriangle className="h-4 w-4" />
|
||||
<span className="text-sm font-medium">過期與瑕疵總計</span>
|
||||
</div>
|
||||
<div className="text-sm font-bold text-red-600">
|
||||
${Number(stats.abnormalValue || 0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Can>
|
||||
|
||||
{/* 低庫存警告狀態 */}
|
||||
<div className="flex items-center justify-between p-3 rounded-lg bg-gray-50">
|
||||
<div className="flex items-center gap-2 text-gray-600">
|
||||
<AlertTriangle className="h-4 w-4" />
|
||||
<span className="text-sm">低庫存警告</span>
|
||||
</div>
|
||||
<div>
|
||||
{hasWarning ? (
|
||||
<Badge className="bg-orange-500 text-white hover:bg-orange-600 border-none px-2 py-0.5">
|
||||
{stats.lowStockCount} 項
|
||||
</Badge>
|
||||
) : (
|
||||
<Badge variant="secondary" className="bg-green-100 text-green-700 hover:bg-green-100 border-green-200">
|
||||
正常
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 移動倉司機資訊 */}
|
||||
{warehouse.type === 'transit' && warehouse.driver_name && (
|
||||
<div className="flex items-center justify-between pt-2 border-t border-gray-100">
|
||||
<span className="text-sm text-gray-500">司機</span>
|
||||
<span className="text-sm font-medium text-gray-900">{warehouse.driver_name}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user