# sub-implementer-frontend-1 — W1 §②-10 Designer type-10 KHKK (fe-admin only)

**Verdict: DONE — 1 file sửa, `npm run build` fe-admin PASS 0 TS error.**
Scope thi công: CHỈ `fe-admin/src/pages/system/ApprovalWorkflowsV2Page.tsx`. KHÔNG đụng `fe-user` (không tồn tại bản sao — `fe-user/src/pages/system/` không có thư mục), KHÔNG đụng `src/Backend/**`, KHÔNG commit.

---

## 1. Khảo sát trước khi sửa (grep cùng-lớp mọi chỗ liệt kê ApplicableType)

**Trong file Designer — đúng 2 chỗ liệt kê tay, không có chỗ thứ 3:**

| Chỗ | Trước | Vai trò |
|---|---|---|
| `TYPE_CODE_TO_INT` (site THỰC `:144-148` bản cũ, không phải comment `:143`) | `DuyetNcc:1, DuyetNccPhuongAn:2, Contract:3` | map `:typeCode` URL → int, dùng ở `:257` `selectedTypeInt` |
| `DEFAULT_CODE_BY_TYPE` (`:149-153` bản cũ) | `1/2/3` → `QT-DN-V2-001` / `QT-DN-PA-V2-001` / `QT-HD-V2-001` | prefill ô "Mã quy trình", fallback `'QT-V2-001'` (`:614` bản cũ) |

**Không có "option list" / bảng nhãn trong FE** — trái với giả định của đề bài. Danh sách loại quy trình + nhãn tiếng Việt đến TỪ BACKEND qua `GET /approval-workflows-v2` → `TypeSummaryDto.applicableTypeLabel` (khai type ở `:92-97`, render card `:294-296`, tiêu đề trang `:278`, tiêu đề dialog `:833`). ⇒ FE **không** phải chép chuỗi 'Kế hoạch ký kết HĐ'; nhãn hiển thị đúng hay không là do BE map (`ApprovalWorkflowV2AdminFeatures.cs` — lane implementer-backend).

**Khuôn "entry type=9 TravelRequest" mà đề bài bảo mirror: KHÔNG TỒN TẠI trong file này.** `TYPE_CODE_TO_INT` dừng ở 3 — các loại Office 4..9 (ProposalGeneral…TravelRequest) chưa bao giờ có deep-link riêng ở Designer; chúng vào Designer qua trang tổng (không `:typeCode`) hoặc module page (`WorkflowAppDetailPage.tsx:216` truyền `config?.applicableType`). ⇒ Khuôn thật để mirror là **entry `Contract: 3`** (loại có deep-link nhưng không có menu leaf). Đã mirror theo đó.

**Repo-wide (fe-admin) không có bảng nhãn ApplicableType nào khác** — grep `Record<number,string>` toàn `src/`: toàn label map của enum KHÁC (ContractPhase, PeType, WorkflowAppStatus, Employee…). `Layout.tsx:18 TYPE_CODE_TO_INT` là enum **ContractType** (Ct_*/Wf_*), không phải ApplicableType.

## 2. Thay đổi đã land (file:line SAU khi sửa)

1. **`:147` `const TYPE_INT_CONTRACT_SIGNING_PLAN = 10`** — đặt tên cho số 10 vì nó dùng ở 3 nơi (map, default-code, rào checkbox); số trần rải nhiều chỗ là kiểu sửa-1-quên-1.
2. **`:151-152` `KHKK_EARLY_FINALIZE_NOTE`** — 1 chuỗi dùng chung cho tooltip 2 ô + dòng ghi chú (không chép 3 lần rồi lệch chữ).
3. **`:162` `ContractSigningPlan: TYPE_INT_CONTRACT_SIGNING_PLAN`** trong `TYPE_CODE_TO_INT` → mở deep-link `/system/approval-workflows-v2/ContractSigningPlan` (route đã có sẵn `App.tsx:76`, không cần route mới).
4. **`:170` `[TYPE_INT_CONTRACT_SIGNING_PLAN]: 'QT-KHKK-V2-001'`** trong `DEFAULT_CODE_BY_TYPE` — 🔴 **suy diễn của tôi theo khuôn 3 dòng trên, spec KHÔNG chốt chuỗi này**. Chỉ là giá trị GỢI Ý điền sẵn ô "Mã quy trình *" (admin sửa được trước khi Lưu); bỏ dòng này thì rơi về `'QT-V2-001'`. Lead/reviewer muốn chuỗi khác thì sửa đúng 1 dòng.
5. **`:247` `levelFlagsPayload(e, lockEarlyFinalize: boolean)`** — 2 cờ `allowApproverSkipToFinal` / `allowApproverFinalize` ép `false` khi khoá (`:254-255`). 2 call-site cùng truyền cờ: PUT `:783`, POST `:815`.
6. **`:638` `const earlyFinalizeLocked = applicableType === TYPE_INT_CONTRACT_SIGNING_PLAN`** trong `Designer` (prop `applicableType` có sẵn `:589/:596`, `TypePanel` truyền `:417`).
7. **`:1284-1288`** dòng ghi chú xám `col-span-2` (chỉ hiện khi khoá) + **`:1291-1310`** ô "Cho phép duyệt thẳng Cấp cuối khi đang duyệt" và **`:1313-1330`** ô "Duyệt là KẾT THÚC quy trình (không trình tiếp CEO)": `disabled={earlyFinalizeLocked}` (`:1306` / `:1325`), `checked={earlyFinalizeLocked ? false : entry.…}`, `title={… ? KHKK_EARLY_FINALIZE_NOTE : undefined}`, className ternary **chuỗi class ĐẦY ĐỦ** 2 nhánh (Pattern 14 Tailwind JIT — không nội suy mảnh class).

**Anchor Edit (bài S133):** className `col-span-2 flex items-center gap-1 text-[11px] text-slate-700` xuất hiện **6 lần** trong khối 9 ô tick ⇒ old_string bao trọn từ comment `{/* Mig 31 (S23 t1) … */}` tới hết `<span>Duyệt là KẾT THÚC…</span>` (2 câu chữ hiển thị là phần độc nhất). Không dùng className làm neo.

## 3. Vì sao khoá ở HAI lớp (render + payload), không chỉ ẩn ô tick

Chỉ `disabled` ô tick = containment giả: giá trị `true` vẫn có thể lọt vào state qua `copyFromDefinition()` (`:165-193`) rồi đi thẳng lên BE trong payload. Ép `false` ngay trong `levelFlagsPayload` là điểm duy nhất mọi đường ghi đi qua (comment `:232-240` của chính file khẳng định POST+PUT dùng chung đúng 1 hàm).

**Rủi ro 409 đã cân:** PUT sửa-tại-chỗ ECHO 2 cờ này và BE so BẰNG (`ApprovalWorkflowV2AdminFeatures.cs:580-585`) ⇒ ép `false` sẽ nổ 409 NẾU DB đang giữ `true`. Với type 10 điều đó không xảy ra: mọi bản type-10 đều do chính màn này tạo (POST đã ép false), và `cloneFrom` luôn cùng-type (`TypePanel` truyền `type.applicableType` `:417`) ⇒ display và payload luôn khớp, không có màn-hình-nói-một-đằng. Ghi rõ trong comment `:242-246`.

## 4. Cờ đỏ / việc KHÔNG thuộc lane này

- 🔴 **Chưa có đường vào bằng sidebar cho type 10.** Trang tổng (`:291-311`) render card mỗi loại nhưng card là `<div>` **không** link. Điều hướng per-type đi qua menu leaf `AwV2_<Code>` → `Layout.tsx:162-168` allowlist `resolvePath` (chỗ thứ 4 của Pattern 16-bis, gotcha #50). Hiện `MenuKeys.cs:74-75` chỉ có `AwV2_DuyetNcc` + `AwV2_DuyetNccPhuongAn` — **không có cả `AwV2_Contract`**, tức type 3 xưa nay cũng chỉ vào được bằng gõ URL. W1 chốt "menu KHÔNG đổi (142 giữ)" ⇒ **đúng spec**, admin vào bằng URL trực tiếp `/system/approval-workflows-v2/ContractSigningPlan`. Nếu về sau BE seed leaf `AwV2_ContractSigningPlan` thì **BẮT BUỘC** nới `Layout.tsx:165` cùng lượt, không thì MenuLeaf trả null → rơi khỏi sidebar im lặng. Tôi KHÔNG sửa `Layout.tsx` (ngoài scope task).
- Acceptance §B "Admin tạo được quy trình type=10 3 Bước" chỉ chạy được sau khi BE: (a) `ApprovalWorkflowApplicableType.ContractSigningPlan = 10`, (b) overview trả type 10 kèm nhãn 'Kế hoạch ký kết HĐ', (c) 3 site liệt-kê-tay trong `ApprovalWorkflowV2AdminFeatures.cs` (`:911/:929`, `:971/:992`, `:1044/:1056`). Lane implementer-backend.
- KHÔNG viết test (đợt-2 test-specialist). KHÔNG commit/push.

## 5. Bằng chứng build

```
cd fe-admin && npm run build   →   tsc -b && vite build
✓ 1952 modules transformed. ✓ built in 17.39s
dist/assets/index-iNZq9job.js  1,645.50 kB │ gzip: 411.12 kB
dist/assets/index-B5heFn8x.css    84.18 kB │ gzip:  14.04 kB
```
0 TS error. 3 warning đều PRE-EXISTING: `@import` Google Fonts phải đứng trước rule khác · chunk >500 kB · `realtime.ts` vừa dynamic vừa static import.

`git status --porcelain` phần của tôi: **đúng 1 dòng** `M fe-admin/src/pages/system/ApprovalWorkflowsV2Page.tsx` (`git diff --numstat` = **67 thêm / 9 xoá**). 2 mục còn lại trong cây KHÔNG phải của tôi: `.claude/governance/.session-counter.json` (harness) và `?? src/Backend/SolutionErp.Domain/ContractSigningPlans/` (lane implementer-backend chạy song song).
