[CLAUDE] PurchaseEvaluation: ràng trường bắt buộc — form tạo hiện thiếu gì + checklist xanh/đỏ gửi duyệt (anh Kiệt FDC UAT R3)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m50s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m50s
Anh chốt "không chọn quy trình thì không cho tạo phiếu, ràng mấy cái rủi ro lại hết": - Form TẠO: nút "Tạo phiếu" disabled khi thiếu (Quy trình duyệt / Hạng mục / Dự án) + hint ĐỎ liệt kê rõ còn thiếu gì (✓ xanh khi đủ). Defense-in-depth với BE validator NotEmpty (S83). - Detail (D4): checklist xanh ✓ "đã khai" / đỏ ✗ "chưa khai" cho 4 trường bắt buộc gửi duyệt (NCC winner · giá>0 · ngân sách · bảng so sánh) hiện phía trên nút "Lưu & Gửi Duyệt" (mirror missingForApproval predicate, khớp annotation anh Kiệt "xanh=đã khai, đỏ=chưa khai"). FE-only 2 component × 2 app SHA-identical. Both build PASS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -139,7 +139,15 @@ export function PeWorkspaceCreateView({
|
||||
onError: e => toast.error(getErrorMessage(e)),
|
||||
})
|
||||
|
||||
const canSubmit = !!form.tenGoiThau && !!form.projectId && !!form.workItemId && !!form.approvalWorkflowId && !create.isPending
|
||||
// [D4/R3 anh Kiệt — "ràng mấy cái rủi ro lại hết"] Trường BẮT BUỘC để tạo phiếu — thiếu cái
|
||||
// nào thì liệt kê cho user thấy (nút "Tạo phiếu" disabled + hint đỏ). KHÔNG chọn Quy trình
|
||||
// duyệt → KHÔNG tạo được phiếu (anh chốt; defense-in-depth với BE validator NotEmpty S83).
|
||||
const missingCreate = [
|
||||
!form.approvalWorkflowId && 'Quy trình duyệt',
|
||||
!form.workItemId && 'Hạng mục công việc (tên gói thầu)',
|
||||
!form.projectId && 'Dự án',
|
||||
].filter(Boolean) as string[]
|
||||
const canSubmit = missingCreate.length === 0 && !!form.tenGoiThau && !create.isPending
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border border-slate-200 bg-white shadow-sm">
|
||||
@ -298,17 +306,26 @@ export function PeWorkspaceCreateView({
|
||||
ở Detail tabs sau khi tạo phiếu. */}
|
||||
</div>
|
||||
|
||||
{/* Action bar */}
|
||||
<div className="flex items-center justify-end gap-2 border-t border-slate-200 bg-slate-50 px-5 py-3">
|
||||
{onCancel && (
|
||||
<Button variant="ghost" onClick={onCancel} className="text-xs">Hủy</Button>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => create.mutate()}
|
||||
disabled={!canSubmit}
|
||||
>
|
||||
{create.isPending ? 'Đang tạo…' : 'Tạo phiếu'}
|
||||
</Button>
|
||||
{/* Action bar — [D4/R3 anh Kiệt] hint trái hiện RÕ còn thiếu gì (ràng rủi ro), nút phải. */}
|
||||
<div className="flex items-center justify-between gap-3 border-t border-slate-200 bg-slate-50 px-5 py-3">
|
||||
<div className="min-w-0 text-[11px]">
|
||||
{missingCreate.length > 0 ? (
|
||||
<span className="text-red-600">⚠ Chưa đủ để tạo phiếu — còn thiếu: <strong>{missingCreate.join(' · ')}</strong></span>
|
||||
) : (
|
||||
<span className="font-medium text-emerald-600">✓ Đủ thông tin bắt buộc — có thể tạo phiếu</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-2">
|
||||
{onCancel && (
|
||||
<Button variant="ghost" onClick={onCancel} className="text-xs">Hủy</Button>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => create.mutate()}
|
||||
disabled={!canSubmit}
|
||||
>
|
||||
{create.isPending ? 'Đang tạo…' : 'Tạo phiếu'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user