14 KiB
K2-FE: DONE — build ×2 PASS · SHA-pair 5/5
sub-implfe-k2 — K2 FRONTEND (S164, wave 2/8, SP-002 phiếu mang hạng-mục + nhóm)
Luật đan-xen (bài K1 + #53): làm mục nào GHI NGAY mục đó. Dòng-1 = verdict, cập nhật CUỐI. Nguồn:
sub-implbe-k2.md(BE đã land) + spec-cum1 vá-4 + spec-tổng-quát QĐ-1/OG-1/OG-7 + nềnsub-invest-fable-b2-cum1.md§K2.f.
§0 Tiền đề — ĐO TRƯỚC MỌI WRITE (không tin sổ)
git status --porcelain@start:sub-implfe-k2.mdKHÔNG tồn tại trong run-folder (có k1/implbe-k2/test/reviewer/cicd) ⇒ Write mới AN TOÀN, không đè lane khác.- 0 file
fe-*/srcnào đang M trong git status @start ⇒ mọi thay đổi FE dưới đây là của lane này, git-diff sẽ quy trách nhiệm đúng. - BE lane đã land (đọc
sub-implbe-k2.md): Mig 71 applied 2-DB · rào (PeId,Group) · submit-guard · list?group=· Σ-Approved · build 0W/0E · suite 598/0. - 🔴 CẤM theo task: đụng BE/.cs · chạy dotnet (lane test song song) · route/menu mới (K4a) · sửa spec.
§0.a SHA baseline 5 cặp KHKK FE (TRƯỚC khi sửa) — cả 5 IDENTICAL
File (fe-*/src/…) |
admin (12 ký tự đầu SHA256) | user | Trạng thái |
|---|---|---|---|
types/khkk.ts |
8b757f5b1422 |
8b757f5b1422 |
IDENTICAL |
pages/khkk/KhkkCreatePage.tsx |
ea51e7626eb1 |
ea51e7626eb1 |
IDENTICAL |
pages/khkk/KhkkDetailPage.tsx |
c8ab2eadd3fd |
c8ab2eadd3fd |
IDENTICAL |
pages/khkk/KhkkListPage.tsx |
40a650bf6964 |
40a650bf6964 |
IDENTICAL |
pages/khkk/KhkkWorkflowPanel.tsx |
2b64144ef6e8 |
2b64144ef6e8 |
IDENTICAL |
⇒ Chiến lược: sửa fe-admin → cp sang fe-user → đo lại SHA (khuôn cookie-cutter, 9× proven). Không có UX riêng 2 app trong 5 file này (đối chứng: baseline identical).
§0.b Hình dạng DTO BE ĐỌC TỪ MÃ THẬT (không đoán — task ép)
ContractSigningPlanListItemDtoContractSigningPlanFeatures.cs:58-64: append-CUỐIint ApprovalGroup+decimal TotalApprovedAmount(vá-8 — Σ thứ 3).ContractSigningPlanLineDto:66-79: append-CUỐIGuid? CatalogEntryId+string? TenHangMuc(denorm).ContractSigningPlanDetailDto:130-166: append-CUỐI (SAU cả các List)int ApprovalGroup+bool BudgetFrozen(display-gate, KHÔNG phải cột DB).ApprovedPeAwaitingPlanDto:169-191: append-CUỐIList<int> ExistingGroups(nhóm của các planPhase != TuChoi; rỗng = PE chưa có phiếu). Picker KHÔNG còn loại PE-đã-có-phiếu (:1291-1295gỡ vế!Any(...)).CreateContractSigningPlanCommand:333-337:PeId, ApprovalWorkflowId, GhiChu?, **int? ApprovalGroup = null**— null ⇒ nhóm 1 (:393); validatorInclusiveBetween(1,8)CHỈ khi có giá trị (:349-353).ListContractSigningPlansQuery:700-705+int? ApprovalGroup; controller expose?group=(BE lane §f).- 409 message create (
:400-402): "Phiếu Duyệt NCC này đã có kế hoạch ký kết cho nhóm duyệt N{g}. Chọn nhóm duyệt khác, hoặc xoá/để bị từ chối kế hoạch cũ của nhóm này trước khi lập lại."
🔴 [lead @S165] p1 CHẾT ngay sau §0.b — 4 dòng markup tool-call rò vào đuôi file (sub-class #53 MỚI: content-Write lẫn cú pháp invoke), lead đã cắt. Disk-truth p1: fe-admin 4 file M (types +69 · CreatePage +177 mid-wire [unused: select-nhóm + nút-phụ + badge chưa vào JSX] · Detail +33 · List +1); fe-user CHƯA cp. p2 tiếp từ đây — append §1 trở xuống.
p2 (relaunch @S165) — tiếp từ §0.b
§1 Wire CreatePage — ĐO ĐĨA TRƯỚC, KHÔNG TIN SỔ
🔴 Tiền đề của lead SAI MỘT PHẦN (đã đo lại bằng git diff, không đọc lại sổ):
lead khai CreatePage "GIỮA CHỪNG WIRE, các khai báo chưa vào JSX". Đo thật trên đĩa
(git diff -- fe-admin/src/pages/khkk/KhkkCreatePage.tsx, 177 dòng +) thì 8/8 khai báo
lead liệt là unused đều ĐÃ có call-site trong JSX:
(số dòng dưới = đo bằng grep -n trên file SAU khi p2 xong, không phải trí nhớ)
| Khai báo lead nói "chưa vào JSX" | Call-site THẬT trên đĩa (fe-admin) |
|---|---|
KHKK_APPROVAL_GROUPS |
firstFreeGroup() :55 + .map dựng 8 <option> :281 |
KHKK_APPROVAL_GROUP_DEFAULT |
useState<number>(...) :62 |
KHKK_APPROVAL_GROUP_LABELS |
title= badge nhóm-đã-dùng :232 + text <option> :285 |
approvalGroup / setApprovalGroup |
body POST :99 · value= select :277 · onChange :278 |
firstFreeGroup |
selectPe() :131 + const free mỗi dòng PE :180 |
groupTaken |
cảnh báo đỏ :291-293 · disabled nút Lưu :360 |
selectPe |
onClick dòng PE :185 + onClick nút "Tạo thêm cho nhóm khác" :240 |
icon Layers / Plus |
<Layers> label nhóm :272 · <Plus> nút phụ :241 |
⇒ Suy đoán về nguyên nhân lệch: p1 chết ở lượt Write CUỐI (rò markup tool-call), nên lead nhìn thấy transcript dở-dang và kết luận theo Ý ĐỊNH đang thực thi, không theo đĩa. Đây đúng khuôn "WRITE-lane garble ≠ mất code" (MEMORY S114) — code đã LAND, chỉ báo cáo chết. p2 KHÔNG viết lại CreatePage (viết lại = phá thứ đang đúng).
Nội dung K2 mà CreatePage đã có (đọc để xác nhận đúng spec, không phải đọc để chép):
- vá-4:
<select id="approvalGroup">N1–N8, default 1 (KHKK_APPROVAL_GROUP_DEFAULT), option nhóm đã dùng bịdisabled+ hậu tố "(đã có kế hoạch)"; header section đổi "Quy trình duyệt" → "Nhóm duyệt & quy trình", lưới 1→2 cộtmd:grid-cols-2. - body POST
approvalGroupgửi TƯỜNG MINH (không dựa default ngầmCreateCommand:337). - OG-7 UI-hướng-1: dòng PE không còn bị ẩn khi đã có kế hoạch → hiện hàng chip
N{g}(nhóm đã dùng) + nút phụ "Tạo thêm cho nhóm khác"; hết 8 nhóm → chữ "Đã dùng hết 8 nhóm duyệt" (không mời bấm vào thứ chắc chắn 409). <button>PE bọc trong<div key>phụ vì nút phụ không được lồng trong<button>(HTML không hợp lệ) — p1 đã xử đúng.- Rào cứng vẫn ở BE (
Features.cs:395-402409); FE chỉdisablednút Lưu khigroupTaken.
⇒ §1 = 0 dòng sửa mới. Việc thật của p2 dồn vào §2 (ListPage) + §3 (cp) + §4 (build/SHA).
§2 Detail / List
KhkkDetailPage — cũng ĐÃ LAND ĐỦ (0 dòng sửa mới, +33 của p1):
- badge
N{approvalGroup}ởPageHeader actions, ĐỨNG TRƯỚC badge phase,title= nhãn nghiệp vụ (:298-304), guard!= nullcho payload cache cũ. - cột "Hạng mục" trong bảng Lines (
<th>:460,<td>:472—tenHangMucrỗng ⇒—xám) + 1 câu chú thích "ô gán thuộc bước Lines-editor" (K4b) ở cuối bảng:485. - badge
🔒 Giá đã chốt tại thời điểm duyệtkhibudgetFrozen:443— gắn qua propactionscủaSectionCard. ✅ đã kiểm:actions?: ReactNodelà prop CÓ SẴN:63(không phải p1 tự bịa), render{actions && <span className="ml-auto">…}:82.
KhkkListPage — ĐÂY LÀ CHỖ THẬT SỰ DỞ (p1 chỉ kịp thêm dòng import). p2 sửa:
:240-246badgeN{g}trong ô "Mã kế hoạch", không đẻ cột riêng — bảng này đã cuộn ngang ở 1366 khi có cây GĐ 19rem bên trái (ghi chú S162 ngay trong file); guard!= null+title=KHKK_APPROVAL_GROUP_LABELS[k.approvalGroup]:243⇒ import treo đã có người dùng (đây chính là dòng làm build đỏ TS6133 nếu bỏ mặc).:190+cột "Tổng duyệt" (ΣtotalApprovedAmount) và:271-273ô giá trị (emerald,tabular-nums). Phiếu chưa duyệt BE trả 0 ⇒ ép hiện—(k.totalApprovedAmount ? … : '—'), không in "0 đ" gây đọc nhầm "đã duyệt 0 đ".colSpan={7}→{8}hai chỗ (hàng "Đang tải...":198+ hàng rỗng:205) — quên chỗ này thì 2 hàng đó thụt 1 ô, lỗi câm không ai thấy tới lúc bảng rỗng. (Cột này KHÔNG có trong gạch đầu dòng của lead, nhưng là vá-8 spec-cum1 — "list thêm Σ Approved sau freeze để list/detail không lệch số" — và BE đã trả fieldListItemDto:64; khai lệch ở phần cuối.)
- ❌ KHÔNG thêm ô lọc
?group=ở list: K2 là CHỦ tham số nhưng chỗ lọc thuộc K4b/K5 (leaf nhóm + cây 8 folder) — đẻ chỗ lọc thứ hai bây giờ là giẫm chân wave sau.
§3 cp sang fe-user (khuôn cookie-cutter)
cp 4 file admin → user, KHÔNG gõ tay lần hai (gõ tay = đẻ lệch không ai thấy):
types/khkk.ts · pages/khkk/{KhkkCreatePage,KhkkDetailPage,KhkkListPage}.tsx.
KhkkWorkflowPanel.tsxKHÔNG cp vì K2 không sửa nó — và đó là đối chứng dương của phép đo §4: hash panel sau lượt này phải BẰNG ĐÚNG baseline §0.a2b64144ef6e8. Nếu nó cũng "identical" mà lệch baseline thì phép đo của tôi vô nghĩa.- Không import mới nào ngoài
lucide-react(Layers,Plus) + const trong chínhtypes/khkk.tsđã cp ⇒ không có rủi ro "fe-user thiếu component" (bẫy Card/Badge quen). git diff --statĐỐI XỨNG 2 app:269 insertions(+), 36 deletions(-), từng file khớp số dòng (177 / 33 / 26 / 69). Lệch số ở đây = cp sót, không cần đợi tới SHA.
§4 Build ×2 + SHA-pair — TRỌNG TÀI
npm run build = tsc -b && vite build (package.json:11 cả 2 app) và
tsconfig.app.json:19 noUnusedLocals: true ⇒ build LÀ phép thử TS6133: import treo
KHKK_APPROVAL_GROUP_LABELS ở ListPage chắc chắn làm đỏ, không phải "IDE dọa" (#68).
| App | Kết quả | Bundle | Thời gian |
|---|---|---|---|
| fe-admin | ✅ PASS 0 TS error | dist/assets/index-DORfkFnc.js 1,722.60 kB |
23.10s |
| fe-user | ✅ PASS 0 TS error | dist/assets/index-qYI2yszp.js 1,638.80 kB |
8.80s |
Warning cả 2 app = pre-existing, không phải do lượt này: @import phải đứng trước
rule khác (font Google trong CSS) · chunk > 500 kB · realtime.ts vừa dynamic vừa
static import từ NotificationBell.
SHA256 (Get-FileHash, 12 ký tự đầu) — 5/5 cặp IDENTICAL:
File (fe-*/src/…) |
admin | user | Cặp | So baseline §0.a |
|---|---|---|---|---|
types/khkk.ts |
72A71451B98F |
72A71451B98F |
✅ | ĐỔI (từ 8b757f5b1422) |
pages/khkk/KhkkCreatePage.tsx |
677F4AB803B0 |
677F4AB803B0 |
✅ | ĐỔI (từ ea51e7626eb1) |
pages/khkk/KhkkDetailPage.tsx |
1863153B4F99 |
1863153B4F99 |
✅ | ĐỔI (từ c8ab2eadd3fd) |
pages/khkk/KhkkListPage.tsx |
E892310434F2 |
E892310434F2 |
✅ | ĐỔI (từ 40a650bf6964) |
pages/khkk/KhkkWorkflowPanel.tsx |
2B64144EF6E8 |
2B64144EF6E8 |
✅ | BẰNG baseline (chứng: đo đúng thứ, không đụng file ngoài phạm vi) |
§5 Ranh giới đã giữ + khoảng hở khai thật
Giữ đúng 5 điều cấm của task: 0 lệnh dotnet · 0 file .cs bị ghi (13 .cs đang M/??
trong git status là lane BE — Mig 20260731085624_AddKhkkApprovalGroupCatalogAndFinalizeRuntime
ContractSigningPlanFeatures.cs+ 3 test file; tôi chỉ ĐỌC DTO, không Edit) · 0 route mới (App.tsxkhông nằm trong diff) · 0 menu key mới (lib/menuKeys.ts,components/Layout.tsxkhông nằm trong diff — K4a giữ chỗ đó) · 0 dòng spec bị sửa.
Khoảng hở / lệch — khai để lead phán, không tự nuốt:
- 🔴 Tiền đề task sai một phần (§1): CreatePage + DetailPage đã LAND ĐỦ trên đĩa từ
p1; chỉ ListPage dở. Việc thật của p2 ≈ 1/4 mô tả. Tôi không viết lại phần đã đúng.
(Bài học tái xác nhận: báo cáo chết ≠ code chết — đo
git difftrước khi gõ.) - ⚠️ Cột "Tổng duyệt" (Σ Approved) là việc TÔI THÊM ngoài gạch đầu dòng của lead.
Căn cứ: vá-8 spec-cum1 ("list thêm Σ Approved sau freeze để list/detail không lệch
số") + BE đã trả
ListItemDto:64+ p1 đã khai field trong types kèm đúng lý do đó. Không thêm thì field nằm chết. Nếu lead thấy quá tay: gỡ = xoá 1<th>+ 1<td>+ trảcolSpan8→7, không ảnh hưởng gì khác. - ⚠️
existingGroupschỉ đọcPhase != TuChoi(BE). Phiếu xóa mềm có rơi khỏi tập này không thì tôi KHÔNG kiểm được từ FE. Nếu BE không loại phiếu deleted thì user xoá phiếu nhóm 2 xong vẫn thấy N2 bị khoá trong ô chọn (rào 409 BE mới là lời cuối). Câu này thuộc lane BE — nêu để có người soi, không tự sửa. - ⚠️ Nhãn 8 nhóm còn treo [OG-6] (owner soát sau trên UI). Đang nằm 1 chỗ
KHKK_APPROVAL_GROUP_LABELS× 2 app ⇒ K4a đổi nhãn menu thì sửa đúng 1 const, đừng vá rải. - ℹ️ Không tự bấm được UI (acceptance vá-4 "tạo phiếu nhóm 2 TỪ UI ×2 app" cần người chạy app + login). Tôi dừng ở mức build-PASS + đọc mã; acceptance UI vẫn ĐANG MỞ, đừng đọc "build PASS" thành "đã UAT".
- ℹ️ Chỗ lọc
?group=cố ý chưa làm (thuộc K4b/K5) — nêu lại ở đây để wave sau không tưởng là sót.
END p2 — 4 file × 2 app · build ×2 PASS · SHA-pair 5/5.