Files
solution-erp/.claude/workflows/runs/2026-07-29-S159-tong-quan-pipeline-menu/sub-reviewer-diff-tongquan.md
2026-07-29 11:36:35 +07:00

5.3 KiB
Raw Blame History

sub-reviewer-diff-tongquan — soi đối kháng diff fe-user/src/pages/UserDashboardPage.tsx (S159 L8)

Run: 2026-07-29-S159-tong-quan-pipeline-menu · vai: reviewer (adversarial, READ-only) Vật soi: git diff -- fe-user/src/pages/UserDashboardPage.tsx — 728 dòng (585+/143), 1 file. 🔴 Ghi đĩa TRONG LÚC LÀM (chống #53). Mỗi FLAG ghi ngay khi tìm ra, không đợi cuối. 🔴 Giới hạn đã khai: KHÔNG live-verify (route /dashboard cần login, FE chưa deploy) ⇒ toàn bộ kết luận là soi TĨNH trên diff + đọc file nguồn BE/FE + đọc route/type. Mọi phát biểu về hành vi runtime là suy luận từ mã, đã đánh dấu rõ chỗ nào chưa chứng được.


0 — Xác nhận phạm vi (đã chạm đĩa, không tin lời khai)

  • git diff --statđúng 1 file fe-user/src/pages/UserDashboardPage.tsx, 585+/143. khớp lệnh.
  • git status --porcelain → các file M khác (WAL.md, docs/STATUS.md, docs/HANDOFF.md, scripts/*, .claude/commands/*) không thuộc vật soi, đúng như FD khai là của lead. 0 file fe-admin/** bị chạm. ràng buộc "fe-user ONLY" THOẢ.
  • Named export UserDashboardPage giữ nguyên (dòng context không đổi trong hunk @@ -113,20 +351,180 @@ phía trên).
  • 0 dependency mới (chỉ thêm icon lucide-react đã có sẵn).

A — Những claim của FD tôi đã ĐỘC LẬP kiểm và XÁC NHẬN ĐÚNG (không phải tin lời)

Claim Kiểm bằng Kết quả
Paged<T>total, khôngtotalCount fe-user/src/types/master.ts:1-9 ĐÚNG — lead brief ghi totalCountSAI, FD đính chính đúng
phase là query-param BE thật PurchaseEvaluationsController.cs:23 [FromQuery] PurchaseEvaluationPhase? phase
PurchaseEvaluationPhase.DaDuyet === 7 fe-user/src/types/purchaseEvaluation.ts:28
pendingMe KHÔNG phải query-param BE; /inbox trả mảng phẳng PurchaseEvaluationsController.cs:30-35 trả List<...> (không PagedResult) — dùng .length là đúng
/reports/my-dashboard chỉ đếm bảng Contracts ⇒ gán GĐ3 đúng nghĩa GetMyDashboardQuery.cs — mọi query đi từ db.Contracts
.icon-chip có size nội tại 2.25rem ⇒ bỏ h-9 w-9 là no-op index.css:128-137
h1..h4 + .stat-value là rule unlayered ⇒ phải dùng ! để đè màu index.css:79-83 + :140-146 — cả 2 set color, KHÔNG set font-size và FD áp ! ĐÚNG CHỖ: text-brand-800! / text-brand-700! / text-accent-600! / text-slate-600!. text-base / text-[15px] không cần ! vì 2 rule đó không set font-size — tôi đã đọc để bác giả thuyết "chữ phình to".
Mọi stop màu dùng đều CÓ THẬT trong @theme index.css:7-51 — brand 50-900 · teal 50/100/500/600/700 · violet · amberx · accent 500/600 0 stop ma (không có -800 của teal/violet/amberx nào bị dùng)
.label-eyebrow = brand-600 chỉ 4.42:1 tự tính lại luminance từ #1f7dc1 4.41 — số FD khai đo được và đúng, né sang text-brand-700 là hợp lý
slate-500 = 4.76:1 (FD ghi 4.8) tự tính từ #64748b
Buttonsize="sm" + gap-1.5 sẵn ⇒ bỏ mr-1 là đúng fe-user/src/components/ui/button.tsx
1 file, 0 file fe-admin/**, 0 dep mới, named export giữ git diff --stat + đọc file

Giả thuyết tôi TỰ ĐẶT RA rồi TỰ BÁC (ghi lại để khỏi ai đào lại):

  • "Số GĐ1 là toàn hệ thống còn GĐ3 là của riêng tôi ⇒ lệch phạm vi, user đọc sai tỷ lệ rơi rụng"BÁC: cả 2 endpoint đều IDOR-scoped per-user (PurchaseEvaluationFeatures.cs:596-614 + ContractFeatures.cs:297-303). Cùng phạm vi ⇒ so sánh được.
  • "Chờ tôi duyệt GĐ1 = inbox.length sẽ LỚN HƠN số ở màn đích vì màn đích lọc thêm client-side DaGuiDuyet" (PurchaseEvaluationsListPage.tsx:211-212) → BÁC: BE inbox chỉ trả phase ∈ {ChoPurchasing, ChoDuAn, ChoCCM, ChoCEODuyetPA, ChoCEODuyetNCC, ChoDuyet} (PurchaseEvaluationFeatures.cs:731-742,762), tất cả đều map về DaGuiDuyet (purchaseEvaluation.ts:105-110) ⇒ bộ lọc client là no-op, 2 số khớp nhau.
  • "?phase=7 / ?pendingMe=1 là URL bịa, màn đích không đọc"BÁC: PurchaseEvaluationsListPage.tsx:37,45,95 đọc cả 2. Route /purchase-evaluations, /my-contracts, /inbox đều có thật trong App.tsx:50,58,59.
  • "queryKey mới đè cache trang list"BÁC: trang list dùng ['pe-list', {...}] / ['pe-detail', id]; key mới là ['pipeline-pe-approved'] / ['pipeline-pe-inbox'] — không giao.
  • "bắn request bão"BÁC: main.tsx:7-14 refetchOnWindowFocus:false, retry:1; +2 request đúng trần ≤3.
  • "chia 0 / NaN khi rỗng"BÁC: diff không có phép chia nào; value ?? 0 chặn undefined.
  • "skeleton che cả pipeline"BÁC: loading là per-row (StageStatRow), khung 4 GĐ luôn render.

B — FLAG