更新:優化配方詳情彈窗 UI 與一般修正
All checks were successful
Koori-ERP-Deploy-System / deploy-demo (push) Has been skipped
Koori-ERP-Deploy-System / deploy-production (push) Successful in 49s

This commit is contained in:
2026-01-29 16:13:56 +08:00
parent 7619dc24f7
commit 746eeb6f01
23 changed files with 1925 additions and 79 deletions

View File

@@ -1,4 +1,5 @@
import { useEffect } from "react";
import { Wand2 } from "lucide-react";
import {
Dialog,
DialogContent,
@@ -36,6 +37,7 @@ export default function ProductDialog({
}: ProductDialogProps) {
const { data, setData, post, put, processing, errors, reset, clearErrors } = useForm({
code: "",
barcode: "",
name: "",
category_id: "",
brand: "",
@@ -52,6 +54,7 @@ export default function ProductDialog({
if (product) {
setData({
code: product.code,
barcode: product.barcode || "",
name: product.name,
category_id: product.categoryId.toString(),
brand: product.brand || "",
@@ -99,6 +102,11 @@ export default function ProductDialog({
}
};
const generateRandomBarcode = () => {
const randomDigits = Math.floor(Math.random() * 9000000000) + 1000000000;
setData("barcode", randomDigits.toString());
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-3xl max-h-[90vh] overflow-y-auto">
@@ -159,6 +167,32 @@ export default function ProductDialog({
{errors.code && <p className="text-sm text-red-500">{errors.code}</p>}
</div>
<div className="space-y-2">
<Label htmlFor="barcode">
<span className="text-red-500">*</span>
</Label>
<div className="flex gap-2">
<Input
id="barcode"
value={data.barcode}
onChange={(e) => setData("barcode", e.target.value)}
placeholder="輸入條碼或自動生成"
className={`flex-1 ${errors.barcode ? "border-red-500" : ""}`}
/>
<Button
type="button"
variant="outline"
size="icon"
onClick={generateRandomBarcode}
title="隨機生成條碼"
className="shrink-0 button-outlined-primary"
>
<Wand2 className="h-4 w-4" />
</Button>
</div>
{errors.barcode && <p className="text-sm text-red-500">{errors.barcode}</p>}
</div>
<div className="space-y-2">
<Label htmlFor="brand"></Label>
<Input

View File

@@ -74,11 +74,7 @@ export default function ProductTable({
<TableHeader className="bg-gray-50">
<TableRow>
<TableHead className="w-[50px] text-center">#</TableHead>
<TableHead>
<button onClick={() => onSort("code")} className="flex items-center hover:text-gray-900">
<SortIcon field="code" />
</button>
</TableHead>
<TableHead className="w-[150px]"></TableHead>
<TableHead>
<button onClick={() => onSort("name")} className="flex items-center hover:text-gray-900">
<SortIcon field="name" />
@@ -112,12 +108,15 @@ export default function ProductTable({
{startIndex + index}
</TableCell>
<TableCell className="font-mono text-sm text-gray-700">
{product.code}
{product.barcode || "-"}
</TableCell>
<TableCell>
<div className="flex flex-col">
<span className="font-medium">{product.name}</span>
{product.brand && <span className="text-xs text-gray-400">{product.brand}</span>}
<div className="flex items-center gap-2">
<span className="font-medium text-grey-0">{product.name}</span>
{product.brand && <Badge variant="secondary" className="text-[10px] h-4 px-1 bg-gray-100 text-gray-500 border-none">{product.brand}</Badge>}
</div>
<span className="text-xs text-gray-400 font-mono">: {product.code}</span>
</div>
</TableCell>
<TableCell>