Files
solution-erp/.claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-implfe-k1.md
2026-07-31 14:52:48 +07:00

5.6 KiB
Raw Blame History

impl-fe K1

Tiến độ

  • Call-1: khung sub-file. OK.
  • Đọc xong nguồn:
    • sub-invest-fable-b2-cum1.md:53-57 §K1.d — kind mới contract-catalog vào KIND_CONFIG ×2 app, endpoint api/catalogs/contract-catalog, route :kind sẵn ⇒ 0 route mới.
    • BE THẬT: src/Backend/SolutionErp.Api/Controllers/ContractCatalogController.cs:21 [Route("api/catalogs/contract-catalog")], [Authorize] class + [Authorize(Roles="Admin")] 3 verb ghi (:39,:47,:56). List query groupCode/approvalGroup/isActive/q (:27-30).
    • DTO ContractCatalogFeatures.cs:27-38 = 11 field {Id, Code, TenVi, TenEn?, GroupCode, ApprovalGroup int, SignerRole, InitialsChain?, NduqNote?, IsActive, SortOrder}. Create/Update command = 10 field (không Id) :96-106 / :155-166. ApprovalGroup InclusiveBetween(1,8) :118. PUT check id != body.Id → 400 ⇒ FE phải gửi kèm id.
    • Khuôn FE: fe-user/src/pages/master/CatalogsPage.tsx 321 dòng — SHA IDENTICAL với fe-admin (6f482614…) ⇒ viết 1 lần rồi cp.
    • Menu: BE MenuKeys.cs:28 const ContractCatalog (VÀO All :173) + DbInitializer seed row (ContractCatalog, "Danh mục Hợp đồng", parent Catalogs, order 5, icon "FileSpreadsheet").
    • Layout.tsx + menuKeys.ts DIVERGE 2 app (SHA khác) ⇒ mirror TAY, không cp.
  • Sửa CatalogsPage.tsx fe-user (kind thứ 5) → cp fe-admin → menuKeys ×2 → Layout staticMap ×2 → build ×2. XONG.

File tạo/sửa (6 file, 0 file mới — 3 file/app, đối xứng)

File Δ Nội dung
fe-user/src/pages/master/CatalogsPage.tsx +201/68 (321→454 dòng) kind thứ 5
fe-admin/src/pages/master/CatalogsPage.tsx +201/68 cp y nguyên — SHA-pair
fe-user/src/lib/menuKeys.ts +4 ContractCatalog: 'ContractCatalog'
fe-admin/src/lib/menuKeys.ts +4 idem (2 file DIVERGE sẵn ⇒ edit tay, không cp)
fe-user/src/components/Layout.tsx +4 staticMap ContractCatalog: '/master/catalogs/contract-catalog'
fe-admin/src/components/Layout.tsx +4 idem

Chi tiết CatalogsPage.tsx (khuôn KIND_CONFIG, ADD-KIND playbook)

  1. type Kind += 'contract-catalog' · KINDS += (sub-tab thứ 5 tự hiện).
  2. FieldDef nới 3 thứ: type += 'number' | 'select', options?: {value:number;label:string}[], numeric?: boolean.
  3. KIND_CONFIG['contract-catalog'] — icon FileSpreadsheet (KHỚP icon BE seed), 10 field ĐÚNG 10 field của CreateContractCatalogEntryCommand: code · groupCode · tenVi · tenEn · approvalGroup(select N1N8, numeric) · sortOrder(number, numeric) · signerRole · initialsChain · nduqNote(textarea) · isActive(checkbox). 4 field * = 4 NotEmpty của validator BE (ContractCatalogFeatures.cs:114-120).
  4. columns (trước giờ là config CHẾT, không ai đọc) → thành nguồn <thead> cho nhánh contract-catalog: 8 cột {Mã · Tên VN · Tên EN · Nhóm · Nhóm duyệt · Vai ký chính · Ký nháy · Trạng thái}.
  5. <tbody> nhánh riêng (4 kind cũ giữ NGUYÊN byte cell cũ) · colSpan hardcode 6 → colCount tính theo kind.
  6. CatalogRow.name stringstring? (contract-catalog dùng tenVi) + helper rowLabel() cho confirm xóa (trước là row.name → sẽ in "undefined").
  7. ApprovalGroupBadge — Pattern 14: 8 chuỗi class ĐẦY ĐỦ trong APPROVAL_GROUP_BADGE, cycle (value-1) % 8, KHÔNG interpolate.
  8. buildBody — field numeric ép Number(), rỗng → 0 chứ không null (BE int non-nullable, null → int là System.Text.Json ném). Nhánh cũ ('' | undefined → null) giữ nguyên cho field còn lại.
  9. openCreate — select mặc định option đầu (N1) để không POST rỗng dính InclusiveBetween(1,8).
  10. PageHeader description đổi theo kind (giữ signature title/description, không thêm prop).

Pattern 16-bis — 4 chỗ

# Chỗ Trạng thái
1 Page/types CatalogsPage.tsx ×2 (0 file types mới — row là Record<string, unknown>)
2 App.tsx Route KHÔNG cần/master/catalogs/:kind có sẵn (fe-user/src/App.tsx:63, fe-admin/src/App.tsx:69), kind mới đi chung
3 lib/menuKeys.ts ×2
4 Layout.tsx staticMap ×2 — chỗ DỄ MISS (gotcha #50)

Kết quả build

  • fe-user: PASStsc -b && vite build, 1950 modules, dist/assets/index-C5SIaqt5.js 1,634.97 kB, ✓ built in 21.57s, 0 TS error.
  • fe-admin: PASSdist/assets/index-DLUxeB3d.js 1,718.77 kB, ✓ built in 9.52s, 0 TS error.
  • Warning: @import phải đứng trước rule + chunk >500 kB + INEFFECTIVE_DYNAMIC_IMPORT realtime.tspre-existing cả 3, không phải do K1.
  • SHA-pair CatalogsPage.tsx: d71a9e3bb17b835b85b4f3467905af2ab414f52e3ec0c58e79d55ef57673985a ×2 IDENTICAL (trước sửa: 6f482614… ×2).
  • Chứng Pattern 14 có răng (class KHÔNG bị purge) — grep CSS đã build: bg-sky-50 bg-violet-50 bg-teal-50 bg-orange-50 border-indigo-200 text-rose-700 có mặt ở CẢ fe-user/dist/assets/index-BjUevXzu.css LẪN fe-admin/dist/assets/index-B62-9mVN.css.
  • git diff --stat đối xứng: 201/201 · 4/4 · 4/4 → 350 insert / 68 delete / 6 file.

Ngoài phạm vi (KHÔNG đụng — đúng lệnh)

  • 0 file src/Backend/** (chỉ Read ContractCatalogController.cs + ContractCatalogFeatures.cs để lấy shape).
  • 0 file pipeline/khkk (K4/K5). 0 commit, 0 push.
  • KHÔNG sửa agent-memory/* (spawn-record trả về qua memoryDelta, em main harvest).

END impl-fe-k1 — 6 file · build ×2 PASS