feat: improve line items layout, number inputs and supplier click-to-call
This commit is contained in:
@@ -194,7 +194,6 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
};
|
||||
}, [quoteId]);
|
||||
|
||||
// لیست اقلام برای ارسال به TermsheetCard (دقیقاً مشابه ویزارد)
|
||||
const itemOptions = useMemo(() => {
|
||||
return itemRows
|
||||
.filter((r) => !r.rejected || r.restore)
|
||||
@@ -204,7 +203,6 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
}));
|
||||
}, [itemRows]);
|
||||
|
||||
// محاسبه اقلام تحت پوشش هر کارت شرایط پرداخت
|
||||
const getCoveredIds = (card: EditTsCard) => {
|
||||
const cardId = card.domId || card.key;
|
||||
const explicit = itemRows
|
||||
@@ -217,7 +215,6 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
return explicit;
|
||||
};
|
||||
|
||||
// تغییر اقلام تحت پوشش یک کارت شرایط پرداخت
|
||||
const handleCoverageChange = (cardKey: string, newCoveredKeys: string[]) => {
|
||||
const card = tsCards.find((c) => c.key === cardKey);
|
||||
const cardId = card?.domId || cardKey;
|
||||
@@ -586,7 +583,7 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* لیست اقلام — بدون چکباکسهای شلوغ شرایط پرداخت */}
|
||||
{/* لیست اقلام — چیدمان ۵ سطری هماهنگ با ویزارد */}
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-xs font-bold text-gray-800">اقلام سفارش ({faNum(itemRows.length)})</span>
|
||||
@@ -623,23 +620,24 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2.5">
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-[11px] font-semibold text-gray-600">متریال</label>
|
||||
{/* ردیف ۱: متریال و برند */}
|
||||
<div className="grid grid-cols-2 gap-2.5">
|
||||
<div className="flex flex-col gap-1 min-w-0">
|
||||
<label className="text-[11px] font-semibold text-gray-600 text-right">متریال</label>
|
||||
<input
|
||||
disabled={hasReceipts}
|
||||
className="h-9 w-full rounded-md border border-gray-200 bg-white px-2.5 text-xs text-gray-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/30 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:opacity-60"
|
||||
className="h-9 w-full rounded-md border border-gray-200 bg-white px-2.5 text-xs text-gray-800 text-right focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/30 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:opacity-60"
|
||||
placeholder="نام متریال"
|
||||
value={row.cat}
|
||||
onChange={(e) => patchItem(row.key, { cat: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-[11px] font-semibold text-gray-600">برند</label>
|
||||
<div className="flex flex-col gap-1 min-w-0">
|
||||
<label className="text-[11px] font-semibold text-gray-600 text-right">برند</label>
|
||||
<input
|
||||
disabled={hasReceipts}
|
||||
className="h-9 w-full rounded-md border border-gray-200 bg-white px-2.5 text-xs text-gray-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/30 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:opacity-60"
|
||||
className="h-9 w-full rounded-md border border-gray-200 bg-white px-2.5 text-xs text-gray-800 text-right focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/30 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:opacity-60"
|
||||
placeholder="برند"
|
||||
value={row.brand}
|
||||
onChange={(e) => patchItem(row.key, { brand: e.target.value })}
|
||||
@@ -647,64 +645,75 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-2.5">
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-[11px] font-semibold text-gray-600">مشخصه</label>
|
||||
<MultiSelectCombobox
|
||||
disabled={hasReceipts}
|
||||
values={row.specs}
|
||||
onChange={(specs) => patchItem(row.key, { specs })}
|
||||
options={specOptions}
|
||||
placeholder="مشخصه"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-[11px] font-semibold text-gray-600">واحد</label>
|
||||
<input
|
||||
disabled={hasReceipts}
|
||||
className="h-9 w-full rounded-md border border-gray-200 bg-white px-2.5 text-xs text-gray-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/30 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:opacity-60"
|
||||
placeholder="واحد سنجش"
|
||||
value={row.unit}
|
||||
onChange={(e) => patchItem(row.key, { unit: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
{/* ردیف ۲: مشخصه فنی (تمامعرض با فضای کافی برای تگها) */}
|
||||
<div className="flex flex-col gap-1 min-w-0">
|
||||
<label className="text-[11px] font-semibold text-gray-600 text-right">مشخصه فنی / ابعاد</label>
|
||||
<MultiSelectCombobox
|
||||
disabled={hasReceipts}
|
||||
values={row.specs}
|
||||
onChange={(specs) => patchItem(row.key, { specs })}
|
||||
options={specOptions}
|
||||
placeholder="انتخاب مشخصات..."
|
||||
className="min-w-0"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-3 gap-2 rounded-lg bg-gray-50 p-2.5 border border-gray-200">
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-[10.5px] font-semibold text-gray-600">تعداد</label>
|
||||
<NumberInput
|
||||
disabled={hasReceipts}
|
||||
value={row.qty}
|
||||
onChange={(qty) => {
|
||||
patchItem(row.key, {
|
||||
qty,
|
||||
total: qty != null && row.price != null ? Math.round(qty * row.price * 100) / 100 : row.total,
|
||||
});
|
||||
}}
|
||||
placeholder="تعداد"
|
||||
/>
|
||||
{/* بخش مقادیر و محاسبات مالی */}
|
||||
<div className="rounded-lg bg-gray-50/70 p-2.5 border border-gray-200 space-y-3">
|
||||
{/* ردیف ۳: تعداد + واحد سنجش */}
|
||||
<div className="grid grid-cols-[100px_1fr] sm:grid-cols-[120px_1fr] gap-2.5">
|
||||
<div className="flex flex-col gap-1 min-w-0">
|
||||
<label className="text-[10.5px] font-semibold text-gray-600 text-right">تعداد</label>
|
||||
<NumberInput
|
||||
disabled={hasReceipts}
|
||||
value={row.qty}
|
||||
onChange={(qty) => {
|
||||
patchItem(row.key, {
|
||||
qty,
|
||||
total: qty != null && row.price != null ? Math.round(qty * row.price) : row.total,
|
||||
});
|
||||
}}
|
||||
placeholder="مقدار"
|
||||
className="!text-right text-right"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1 min-w-0">
|
||||
<label className="text-[10.5px] font-semibold text-gray-600 text-right">واحد سنجش</label>
|
||||
<input
|
||||
disabled={hasReceipts}
|
||||
className="h-9 w-full rounded-md border border-gray-200 bg-white px-2.5 text-xs text-gray-800 text-right focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/30 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:opacity-60"
|
||||
placeholder="واحد (شاخه، متر، کیلو...)"
|
||||
value={row.unit}
|
||||
onChange={(e) => patchItem(row.key, { unit: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-[10.5px] font-semibold text-gray-600">قیمت واحد</label>
|
||||
{/* ردیف ۴: قیمت هر واحد (تمامعرض با نمایش حروف) */}
|
||||
<div className="flex flex-col gap-1 min-w-0 border-t border-gray-200/80 pt-2.5">
|
||||
<label className="text-[10.5px] font-semibold text-gray-600 text-right">
|
||||
{row.unit ? `قیمت هر ${row.unit} (تومان)` : "قیمت هر واحد (تومان)"}
|
||||
</label>
|
||||
<NumberInput
|
||||
disabled={hasReceipts}
|
||||
value={row.price}
|
||||
onChange={(price) => {
|
||||
patchItem(row.key, {
|
||||
price,
|
||||
total: row.qty != null && price != null ? Math.round(row.qty * price * 100) / 100 : row.total,
|
||||
total: row.qty != null && price != null ? Math.round(row.qty * price) : row.total,
|
||||
});
|
||||
}}
|
||||
placeholder="واحد"
|
||||
placeholder="قیمت هر واحد"
|
||||
showWords
|
||||
maxDecimals={2}
|
||||
className="!text-right text-right"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-[10.5px] font-semibold text-gray-600">قیمت کل</label>
|
||||
{/* ردیف ۵: قیمت کل این قلم (تمامعرض با نمایش حروف) */}
|
||||
<div className="flex flex-col gap-1 min-w-0 border-t border-gray-200/80 pt-2.5">
|
||||
<label className="text-[10.5px] font-semibold text-gray-600 text-right">قیمت کل این قلم (تومان)</label>
|
||||
<NumberInput
|
||||
disabled={hasReceipts}
|
||||
value={row.total}
|
||||
@@ -715,7 +724,9 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
t != null && row.qty != null && row.qty > 0 ? Math.round((t / row.qty) * 100) / 100 : row.price,
|
||||
});
|
||||
}}
|
||||
placeholder="جمع"
|
||||
placeholder="قیمت کل قلم"
|
||||
showWords
|
||||
className="!text-right text-right"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user