[CLAUDE] Contract: UAT S174 tinh-gon UI KHKK + cot 2 tang KHKK o workspace PE (FE-only x2 app, 0-mig)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m51s

Anh chot qua 6 anh khoanh do + 4 cau tra loi. 7 chinh, mirror SHA256 identical 8/8 cap.

Man DANH SACH KHKK (KhkkListPage / KhkkListPanel)
- Giu DUY NHAT header trang "Ke hoach ky ket HD / Giai doan 2".
- Bo o loc "Tat ca nhom": may loc GIU NGUYEN (query + stage2Content), nhom nay den
  DUY NHAT tu URL ?group=n (8 leaf menu trai). Go luon prop onGroupChange (noUnusedLocals).
- Bo thanh "Cay toan trinh - N goi" qua prop MOI `hideHeader` opt-in tren PipelineTreePanel.
  6 host con lai (PE / GD3 / GD4 / Inbox) KHONG truyen => hinh cu nguyen ven.
  Nut "Hien/An cay" (mobile) song TRONG thanh vua an => hideHeader ep than cay `flex`,
  neu khong `<lg` mat trang cai cay.

Man CHI TIET KHKK (KhkkDetailPage / KhkkDetailContent)
- Go khoi "Quy trinh duyet" (so-do Buoc/Cap + HANH DONG + 2 lich su) — day la BAN SAO
  THU HAI, ban chinh o Panel-3 man danh sach. Anh: "bo het, no se hien thi o Menu duyet".
  KHAI HE QUA: `<lg` dieu huong thang vao trang nay => mobile hien khong con Gui duyet /
  Xoa phieu. Mo lai = boc `lg:hidden`.
- Section 5 "Y kien cap duyet" doi sang DUNG style Duyet NCC (PeDetailTabs.tsx:705-774):
  card `rounded-lg p-3` + h4 ten cap + chip trang thai + y kien text-sm + chan ngay
  border-t; thay o phang 1 dong text-[11px]. GIU o "Chua ky" (PE khong co) — vang o thi
  nguoi doc khong biet con thieu chu ky cua ai.

Man TAO KHKK (KhkkCreatePage)
- Doi sang khuon "Tao phieu Duyet NCC moi" (PeWorkspaceCreateView): 1 card + divide-y,
  thanh dau ke LUONG, thanh cuoi hint do liet ke DICH DANH truong con thieu thay vi chi
  lam xam nut. Nut "Luu nhap" -> "Tao ke hoach".
- Ve "tao xong sang chi tiet" VON DA DUNG tu S161 (onSuccess -> navigate /khkk/:id);
  dot nay KHONG dung luong do, chi doi hinh.

Man DUYET NCC — THAO TAC (PurchaseEvaluationWorkspacePage + PeKhkkSidePanel MOI)
- Them cot 3: 1 cot 2 TANG 50/50 — tren = PE da duyet CHUA lap KHKK gom theo DU AN,
  duoi = KHKK da tao. Ti le 50/50 bang `min-h-0 flex-1` ca hai tang.
- 0 ENDPOINT MOI: dung lai approved-pe-awaiting-plan + contract-signing-plans.
  "Chua co KHKK" = existingGroups RONG — tu K2/S164 BE KHONG con loc ho, loc o FE.
- GATE #85: ca 2 cua gac bang policy `KeHoachKyKet.Read` trong khi day la man PE =>
  gate bang DUNG key policy cua endpoint (KHONG OR key menu Khkk_*), thieu quyen thi
  NOI RA thay vi de cot trang (cot trang doc thanh "chua co gi").
- Cot chi moc tu `xl`; o `lg` bo cuc giu DUNG 2 panel nhu cu.

Con lai (chua lam, da khai voi anh): bam PE o tang tren moi mo /khkk/create chu chua
chon san dung phieu do — can them ?peId= vao man tao.

Verify: build 2 app PASS; mirror SHA256 8/8 cap KHOP; byte-level grep bundle xac nhan
chuoi moi co mat ca 2 app (khong tin dong "built" — bai gotcha #77).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-08-05 15:04:08 +07:00
parent 15367683de
commit 14a917f783
16 changed files with 1024 additions and 470 deletions

View File

@ -31,11 +31,9 @@ import { usePipelineStages } from '@/hooks/usePipelineStages'
import { api } from '@/lib/api'
import { cn } from '@/lib/cn'
import {
KHKK_APPROVAL_GROUPS,
KHKK_PHASE_BADGE,
KHKK_PHASE_LABELS,
KhkkPhase,
khkkGroupMenuLabel,
type KhkkListItemDto,
type KhkkPhaseValue,
type PagedResult,
@ -172,7 +170,6 @@ export function KhkkListPanel({
phase,
onPhaseChange,
group,
onGroupChange,
deletedView,
page,
onPageChange,
@ -184,8 +181,10 @@ export function KhkkListPanel({
onSearchChange: (v: string) => void
phase: KhkkPhaseValue | null
onPhaseChange: (v: KhkkPhaseValue | null) => void
// [S174 owner] CHỈ còn đọc — `Select` nhóm đã gỡ khỏi UI. Nhóm nay đến DUY NHẤT từ URL
// (`?group=n`, tức 8 leaf nhóm ở menu trái). Máy lọc giữ NGUYÊN (query + `stage2Content`);
// chỉ bỏ đường đổi nhóm bằng tay — vào từ leaf nhóm rồi thì ô đó là thừa.
group: number | null
onGroupChange: (v: number | null) => void
deletedView: boolean
page: number
onPageChange: (p: number) => void
@ -265,28 +264,16 @@ export function KhkkListPanel({
className="pl-8"
/>
</div>
<div className="grid grid-cols-2 gap-2">
<Select
value={phase ?? ''}
aria-label="Lọc trạng thái"
onChange={e => onPhaseChange(e.target.value === '' ? null : (Number(e.target.value) as KhkkPhaseValue))}
>
<option value="">Tất cả trạng thái</option>
{(Object.keys(KHKK_PHASE_LABELS) as unknown as number[]).map(p => (
<option key={p} value={p}>{KHKK_PHASE_LABELS[Number(p) as KhkkPhaseValue]}</option>
))}
</Select>
<Select
value={group ?? ''}
aria-label="Lọc nhóm duyệt"
onChange={e => onGroupChange(e.target.value === '' ? null : Number(e.target.value))}
>
<option value="">Tất cả nhóm</option>
{KHKK_APPROVAL_GROUPS.map(n => (
<option key={n} value={n}>{khkkGroupMenuLabel(n)}</option>
))}
</Select>
</div>
<Select
value={phase ?? ''}
aria-label="Lọc trạng thái"
onChange={e => onPhaseChange(e.target.value === '' ? null : (Number(e.target.value) as KhkkPhaseValue))}
>
<option value="">Tất cả trạng thái</option>
{(Object.keys(KHKK_PHASE_LABELS) as unknown as number[]).map(p => (
<option key={p} value={p}>{KHKK_PHASE_LABELS[Number(p) as KhkkPhaseValue]}</option>
))}
</Select>
{flatMode && !deletedView && canPe && (
<p className="text-[10px] italic text-slate-400">
Đang lọc danh sách lấy thẳng từ máy chủ (không giới hạn 200 phiếu của cây).
@ -305,6 +292,7 @@ export function KhkkListPanel({
<PipelineTreePanel
currentStage={2}
className="border-0 shadow-none"
hideHeader
bodyMaxHClass="max-h-[28rem] lg:max-h-none"
stage2Options={{ stage2Content, stage2Count, onOpenKhkk: onSelect }}
/>