[CLAUDE] FE-Admin: PE Thao tác 2-panel workspace + Panel 1 read-only picker + Section 5 disabled
Chunk 1/3 — restructure leaf "Thao tác" (Pe_*_Create) từ page tạo header riêng
sang workspace 2-panel mirror pattern HĐ Thầu phụ ContractCreatePage:
Panel 1 (320px): list pure picker (KHÔNG inline edit/delete per Q1 user) +
sticky "+ Thêm mới" bottom button.
Panel 2 (1fr): empty state | mode=new <PeHeaderForm> | <PeDetailTabs
mode="workspace"> (5 section, Section 5 Ý kiến 4PB DISABLED
per Q5 user — nhập ở leaf "Duyệt").
Workflow Panel + Approvals + History KHÔNG render trong workspace (Q1) — chỉ
hiện ở leaf "Danh sách" + "Duyệt" giữ nguyên 3-panel hiện tại (Q3).
URL: /purchase-evaluations/workspace?type={1|2}[&id=...][&mode=new][&q=][&phase=]
Menu resolver Pe_*_Create: /purchase-evaluations/new?type=N → /workspace?type=N.
Route mới /workspace; route /new giữ tồn tại cho deep-link "Sửa header" button.
Files:
+ fe-admin/src/components/pe/PeListPanel.tsx (~180 LOC) — pure picker reuseable
+ fe-admin/src/components/pe/PeHeaderForm.tsx (~210 LOC) — extract header form
+ fe-admin/src/pages/pe/PurchaseEvaluationWorkspacePage.tsx (~120 LOC)
~ fe-admin/src/components/pe/PeDetailTabs.tsx — add mode prop + Section 5 hint
~ fe-admin/src/components/Layout.tsx — resolver Pe_*_Create map workspace
~ fe-admin/src/App.tsx — route /purchase-evaluations/workspace
Verify: npm run build pass · dotnet test 83 vẫn pass (54 Domain + 29 Infra).
fe-user mirror = Chunk 2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -38,20 +38,32 @@ const fmtMoney = (v: number) => v.toLocaleString('vi-VN')
|
||||
|
||||
// Main detail content — flat render 3 section không tabs.
|
||||
// Tên giữ PeDetailTabs để không break callsite (rename gây churn).
|
||||
//
|
||||
// `mode` (2026-05-07):
|
||||
// - 'detail' (default): full UX — Section 5 Ý kiến 4PB editable theo readOnly.
|
||||
// Dùng ở leaf "Danh sách" + "Duyệt" (3-panel pages).
|
||||
// - 'workspace': dùng ở leaf "Thao tác" (2-panel workspace). Section 5 LUÔN
|
||||
// disabled (Q5 user — ý kiến nhập khi duyệt, không phải workspace nhập liệu).
|
||||
// Workflow Panel + Approvals + History KHÔNG render trong PeDetailTabs (luôn
|
||||
// ở caller PeWorkflowPanel — workspace caller skip render Panel 3 hoàn toàn).
|
||||
export function PeDetailTabs({
|
||||
evaluation,
|
||||
onBack,
|
||||
onDelete,
|
||||
readOnly = false,
|
||||
mode = 'detail',
|
||||
}: {
|
||||
evaluation: PeDetailBundle
|
||||
onBack: () => void
|
||||
onDelete: () => void
|
||||
/** Menu "Duyệt" (pendingMe=1) — ẩn mọi action thêm/sửa/xóa, chỉ xem + duyệt phase. */
|
||||
readOnly?: boolean
|
||||
/** 'workspace' = Section 5 LUÔN disabled (ý kiến nhập ở leaf Duyệt). */
|
||||
mode?: 'detail' | 'workspace'
|
||||
}) {
|
||||
const navigate = useNavigate()
|
||||
const isDraft = evaluation.phase === PurchaseEvaluationPhase.DangSoanThao
|
||||
const opinionsReadOnly = readOnly || mode === 'workspace'
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border border-slate-200 bg-white shadow-sm">
|
||||
@ -112,7 +124,12 @@ export function PeDetailTabs({
|
||||
<ItemsTab ev={evaluation} readOnly={readOnly} />
|
||||
</Section>
|
||||
<Section title="5. Ý kiến 4 phòng ban (sign-off)">
|
||||
<DepartmentOpinionsSection ev={evaluation} readOnly={readOnly} />
|
||||
{mode === 'workspace' && (
|
||||
<div className="mb-3 rounded border border-amber-200 bg-amber-50 px-3 py-2 text-[12px] text-amber-800">
|
||||
Ý kiến + chữ ký nhập khi duyệt phiếu — vào menu “Duyệt” để ký.
|
||||
</div>
|
||||
)}
|
||||
<DepartmentOpinionsSection ev={evaluation} readOnly={opinionsReadOnly} />
|
||||
</Section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user