[CLAUDE] Contract: UAT S174 dot-B — be style PE sang KHKK (FE-only, 0-mig)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m37s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m37s
Nguon: spec runs/2026-08-05-S174-khkk-style-audit/spec-khkk-style-dong-bo-05-08-2026.md (ensemble /fable-clone frontend-designer 5 lane). Owner S175: "KHKK theo khuon PE". Mirror 7 CAP file, sha256 khop 7/7. Build XANH ca 2 app, 0 error TS. === B1 panel Quy trinh duyet (KhkkWorkflowPanel) === X2 GO card-accent -> panel TRAN khuon PE (:345). 🔴 GO HAN CLASS, khong de border-0/shadow-none: .card-accent (index.css:112) nam NGOAI @layer nen thang utility Tailwind v4 (gotcha #66). - Tieu de h3 tran + bo icon-chip; so hieu WF padStart(2,'0') => v01 (PE :350). - Banner ket-thuc-som violet -> EMERALD (PE :360-377). PE danh violet RIENG cho "Duyet thay CEO"; dung violet ca 2 cho la tron 2 nghia vao mot mau. - Chip PHONG vien-xam-nen-trang -> emerald dac (PE :406-410). - Nut lucide -> glyph '✓ Duyet' / '← Tra lai' (PE :540); nut Xoa xam -> DO (PE :574). - File dinh kem: +border-t pt-4 +h3 +nut <Eye> xem truoc. Route BE DA CO ContractSigningPlansController.cs:231 (/view, cung hinh PE :317). Nhan "Tai xuong" chuyen vao title= chu KHONG bo — giu chuoi do trong bundle de phep verify prod con control-duong soi duoc. - Lich su duyet: bo pill dem -> (n) trong ngoac; the bg-slate-50/60 -> bg-white p-3 text-sm; moc-gio day phai bang justify-between. 🔴 Badge 2-nga -> 3-NGA: truoc day MOI thu khong phai Reject deu to emerald => "Tra lai" (amber o PE) bi ve xanh nhu da-duyet, doc NGUOC nghia. toPhase da co san (khkk.ts:307). - Lich su thay doi: BO GAP, render thang (PE PeDetailTabs.tsx:787-794). 🔴 BAT BUOC bo luon `enabled: showChangelog` cua useQuery: giu lai thi khoi luon hien nhung query KHONG BAO GIO chay, va no hong duoi dang "Chua co thay doi nao duoc ghi." — tuc trong y het phieu chua tung sua, KHONG phai trong nhu loi. Doi lay +1 request/phieu, dung gia PE dang tra. - Micro-copy: Huy / tuy chon; nhan O NHAP -> "Ghi chu" (PE :869). 🔴 CHI doi ten TRUONG — chuoi "Y kien cap duyet" o dong tro-giup la TEN THAT cua muc dich den trong phieu (Section 5, Mig 26), doi no la tro nguoi dung toi mot muc khong ton tai. - KHONG be chip "NS PRO"/"NS CCM" (2 co do mo quyen sua ngan sach per-goi-thau, khai niem KHKK khong co). GIU moc chu-ky KHKK (cho KHKK tot hon PE). === B2 noi dung phieu (KhkkDetailContent) — 6 P0 === - 2 bang: table-fixed + <colgroup> + min-w-[880px] trong overflow-x-auto. Bang co gian tu-do truoc day de cot tien nhay be rong theo do dai ten NCC => 3 cot so khong thang hang. - O RONG -> em-dash MO (text-slate-300) gom vao helper orDash/moneyOrDash: truoc day em-dash thua-huong dung mau chu that => luot bang thi "—" trong y nhu mot GIA-TRI. moneyOrDash rieng vi formatVnd tra CHUOI "—" nen khong to mo duoc. - empty-block -> text-sm italic text-slate-400 (3 cho). - emoji 🔒 -> icon lucide <Lock>: emoji render khac nhau theo font he dieu-hanh va KHONG an currentColor nen luon lech tong voi chu amber ben canh. - thong nhat text-xs ca hang bang; +hover:bg-slate-50/60 cho <tr>. === B3 panel danh sach (KhkkListPanel + KhkkWorkListPanel + PipelineTreePanel) === - DAU COT: che-do CAY truoc day di thang vao than, khong tieu-de/so dem => cot "cut dau", lech ca voi man Thao tac (Tier header) LAN voi chinh che-do phang (co dem o chan). Mirror khuon Tier. - Gop 2 o tim chong nhau: +prop hideSearch cho PipelineTreePanel (MAC DINH giu nguyen — 4/6 host kia khong truyen, 0 doi hanh vi). O trong cay KHONG bao gio dung toi vi o ngoai di server-side va go vao la chuyen han sang flatMode => cay bien mat. - Thang chu 4 nac (13/11/10/9) -> 3 nac chuan 13/11/10. - 🔴 WCAG: text-slate-400 = 2.56:1 tren nen trang, DUOI nguong AA 4.5:1 — nang len slate-500 (4.76:1) cho 7 dong MANG THONG TIN (6 note/empty-state + 1 so dem). GIU slate-400 cho 2 cho TRANG TRI (icon Search, dau cham phan cach) — WCAG khong doi tuong phan cho noi dung trang tri. - Nut phan trang ky-tu tran ←/→ -> icon ChevronLeft/Right + aria-label: mui ten dang chu doi hinh theo font he dieu-hanh va KHONG co ten cho trinh doc man hinh. - Chip nhom: inline + co chu khac dong chua => hop chip cao khac chu ben canh nen tut baseline; inline-flex items-center leading-none ghim thang hang. === B4 host (KhkkCreatePage) === - Grid 260/320 DA land tu dot A — chi con COMMENT stale ghi 300px, da va. - 🔴 Va comment SAI SU THAT (L3 H-5): comment khai Panel 1 co "nut hanh-dong dinh day" nhung grep -c Button KhkkWorkListPanel = 0 (control-duong PeListPanel = 8). Do la mo ta CUA PE be nguyen sang => tu khai mot thu chua dung. === 2 component DUNG CHUNG — mo rong kieu MAC-DINH-GIU-NGUYEN === AttachmentPreviewDialog +basePath? (mac dinh /purchase-evaluations) => 6 call-site PE KHONG phai sua dong nao (module da golive; bat sua het call-site cu = tu de rui-ro o cho dang chay tot). PipelineTreePanel +hideSearch? y het. Da verify: 0 call-site PE bi dong. === CON NO === 🔴 CHUA soi mat tren prod 375/1366/1440 — ca 5 lane deu NO-SCREENSHOT (dev-rig chan: chi :8080 LISTENING, API :5443 khong co, trang sau ProtectedRoute — gotcha #3). Moi ket luan la DOC MA, khong phai da nhin. Dot C3 (Field to brand cho MOI value) + dot D (O3/O4/O6/O7/O8) chua lam. O3 con cho owner xac nhan cach doc "sum tong" — do la tien. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@ -23,7 +23,7 @@
|
||||
// (bật chế-độ danh-sách phẳng), luôn có đường tới phiếu cũ; và dòng cảnh-báo
|
||||
// "Cây tải 200 phiếu mới nhất…" của cây KHÔNG bị nuốt.
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { FileCheck, Inbox, Search } from 'lucide-react'
|
||||
import { ChevronLeft, ChevronRight, FileCheck, Inbox, ListTree, Search } from 'lucide-react'
|
||||
import { Input } from '@/components/ui/Input'
|
||||
import { Select } from '@/components/ui/Select'
|
||||
import { PipelineTreePanel } from '@/components/pipeline/PipelineTreePanel'
|
||||
@ -144,8 +144,12 @@ export function KhkkPlanCard({
|
||||
</div>
|
||||
<div className="mt-0.5 flex items-center gap-1.5 text-[11px] text-slate-500">
|
||||
<span className="font-mono">{plan.maKeHoach ?? '(chưa cấp mã)'}</span>
|
||||
{/* [S175 · B3] Chip nhóm: `text-[9px]` là nấc thứ TƯ của thang chữ (13/11/10/9) —
|
||||
gom về 3 nấc chuẩn 13/11/10. Và `inline` + cỡ chữ khác dòng chứa ⇒ hộp chip cao
|
||||
khác chữ bên cạnh nên tụt baseline; `inline-flex items-center leading-none` ghim
|
||||
nó thẳng hàng thay vì dựa vào baseline của 2 cỡ chữ khác nhau. */}
|
||||
{plan.approvalGroup != null && (
|
||||
<span className="rounded border border-violet-200 bg-violet-50 px-1 text-[9px] font-semibold text-violet-700">
|
||||
<span className="inline-flex shrink-0 items-center rounded border border-violet-200 bg-violet-50 px-1 py-0.5 text-[10px] font-semibold leading-none text-violet-700">
|
||||
N{plan.approvalGroup}
|
||||
</span>
|
||||
)}
|
||||
@ -227,7 +231,7 @@ export function KhkkListPanel({
|
||||
const shown = group === null ? plans : plans.filter(k => k.approvalGroup === group)
|
||||
if (shown.length === 0) {
|
||||
return (
|
||||
<p className="px-3 py-2 text-[11px] italic text-slate-400">
|
||||
<p className="px-3 py-2 text-[11px] italic text-slate-500">
|
||||
{group === null ? 'Gói này chưa có kế hoạch ký kết.' : `Gói này chưa có phiếu nhóm N${group}.`}
|
||||
</p>
|
||||
)
|
||||
@ -275,23 +279,42 @@ export function KhkkListPanel({
|
||||
))}
|
||||
</Select>
|
||||
{flatMode && !deletedView && canPe && (
|
||||
<p className="text-[10px] italic text-slate-400">
|
||||
<p className="text-[10px] italic text-slate-500">
|
||||
Đ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).
|
||||
</p>
|
||||
)}
|
||||
{!canPe && (
|
||||
<p className="text-[10px] italic text-slate-400">
|
||||
<p className="text-[10px] italic text-slate-500">
|
||||
Bạn chưa có quyền xem phiếu Duyệt NCC nên cây toàn trình không dựng được — danh
|
||||
sách kế hoạch ký kết vẫn liệt kê đầy đủ ở dưới.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* [S175 · B3] ĐẦU CỘT — trước đây chế-độ CÂY đi thẳng vào thân, không tiêu-đề cũng
|
||||
không số đếm ⇒ cột "cụt đầu": lệch cả với màn Thao tác (`KhkkWorkListPanel` có
|
||||
`Tier` header) LẪN với chính chế-độ phẳng (có dòng đếm ở chân). Mirror đúng khuôn
|
||||
`Tier` để 2 màn KHKK cùng một hình. */}
|
||||
<div className="flex shrink-0 items-center gap-2 border-b border-slate-200 bg-slate-50/80 px-3 py-2">
|
||||
<span className="inline-flex h-5 w-5 shrink-0 items-center justify-center rounded bg-brand-100 text-brand-700" aria-hidden>
|
||||
{flatMode ? <FileCheck className="h-3 w-3" /> : <ListTree className="h-3 w-3" />}
|
||||
</span>
|
||||
<span className="min-w-0 flex-1 truncate text-[11px] font-bold uppercase tracking-wide text-slate-600">
|
||||
{deletedView ? 'Phiếu đã xóa' : flatMode ? 'Danh sách kế hoạch' : 'Cây toàn trình'}
|
||||
</span>
|
||||
{flatMode && !list.isLoading && !list.isError && (
|
||||
<span className="shrink-0 rounded-full bg-slate-100 px-2 py-0.5 text-[10px] font-medium tabular-nums text-slate-600">
|
||||
{total}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex-1 overflow-y-auto">
|
||||
{!flatMode && (
|
||||
<PipelineTreePanel
|
||||
currentStage={2}
|
||||
hideHeader
|
||||
hideSearch
|
||||
bodyMaxHClass="max-h-[28rem] lg:max-h-none"
|
||||
stage2Options={{ stage2Content, stage2Count, onOpenKhkk: onSelect }}
|
||||
/>
|
||||
@ -350,22 +373,28 @@ export function KhkkListPanel({
|
||||
<FileCheck className="mr-1 inline h-3 w-3" />
|
||||
{total} kế hoạch — Trang {page} / {totalPages}
|
||||
</span>
|
||||
{/* [S175 · B3] Ký-tự trần `←`/`→` → icon: mũi tên dạng chữ đổi hình theo font hệ
|
||||
điều-hành và KHÔNG có tên cho trình đọc màn hình. Icon + `aria-label` sửa cả hai. */}
|
||||
<div className="flex gap-1">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onPageChange(Math.max(1, page - 1))}
|
||||
disabled={page <= 1}
|
||||
className="rounded border border-slate-300 px-2 py-0.5 text-slate-600 hover:bg-slate-50 disabled:opacity-40"
|
||||
aria-label="Trang trước"
|
||||
title="Trang trước"
|
||||
className="rounded border border-slate-300 p-1 text-slate-600 hover:bg-slate-50 disabled:opacity-40"
|
||||
>
|
||||
←
|
||||
<ChevronLeft className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onPageChange(page + 1)}
|
||||
disabled={page >= totalPages}
|
||||
className="rounded border border-slate-300 px-2 py-0.5 text-slate-600 hover:bg-slate-50 disabled:opacity-40"
|
||||
aria-label="Trang sau"
|
||||
title="Trang sau"
|
||||
className="rounded border border-slate-300 p-1 text-slate-600 hover:bg-slate-50 disabled:opacity-40"
|
||||
>
|
||||
→
|
||||
<ChevronRight className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user