From fbbd36192988ab0682c8176d9b1e400343e54202 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Fri, 15 May 2026 17:10:27 +0700 Subject: [PATCH] =?UTF-8?q?[CLAUDE]=20FE-User:=20Plan=20AA=20redesign=20v2?= =?UTF-8?q?=20-=20Table=20layout=20rowSpan=20t=E1=BA=ADn=20d=E1=BB=A5ng=20?= =?UTF-8?q?full=20width=20+=207=20label=20ti=E1=BA=BFng=20Vi=E1=BB=87t=20+?= =?UTF-8?q?=20color=20coding=202=20layer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UAT feedback 2026-05-15 sau Run #212 deploy: bro request layout DẠNG TABLE tận dụng hết width thay vì stack vertical panel-per-NV (visual rộng theo chiều ngang). Refactor WorkflowCard structure → 4-col HTML table với rowSpan: Table cols: | Bước (Phòng) | Cấp | NV duyệt | Quyền duyệt | | rowSpan=N | rowSpan=M | per-NV | grid 2-col 7 checkbox | - Bước column: rowSpan = total NV trong Step. Header tone đậm Step palette. - Cấp column: rowSpan = N NV cùng Order (OR-of-N). Badge ring Cấp palette. Nếu N > 1: hint "N NV OR (chỉ cần 1 NV duyệt)". - NV duyệt column: 1 row per NV slot. Tên + email gray. - Quyền duyệt column: grid grid-cols-1 md:grid-cols-2 với 7 checkbox label: - 4 return mode (col-span-1): "Trả về 1 Cấp trước" / "Trả về 1 Bước trước" / "Trả về Người chỉ định" / "Trả về Drafter (mặc định)" - 3 long label (col-span-2): "Cho phép chỉnh sửa Section 2 (Hạng mục/NCC/Báo giá) lúc đang duyệt" / "Cho phép chỉnh sửa Section ngân sách lúc đang duyệt" / "Cho phép duyệt thẳng Cấp cuối khi đang duyệt" Color coding 2 layer preserved: - Step (Bước) bg + headerBg: blue/purple/emerald/amber/pink cycle (5 màu) - Cấp badge: violet/sky/teal/orange/rose cycle (5 màu) - NV + Quyền duyệt cell: bg-white/80 (lighten Step tone, vẫn show through) Helper extracted `buildStepRows(step)` build flat Row[] với rowSpan metadata (isFirstInStep + isFirstInCap + rowSpanStep + rowSpanCap). Drop StepBlock + NvPermissionPanel components (chuyển inline table cells). colgroup width hint: Bước=160px / Cấp=100px / NV=240px / Quyền duyệt=1fr (rest). Tại 1280-1366px viewport (laptop nhỏ Plan AA sidebar widen) Quyền duyệt cell ~400-500px → grid 2-col fit 7 label OK. Verify: - npm run build fe-user PASS clean 0 TS err, 522ms, 1907 modules - Bundle 1284.22 KB (+1.31 KB from baseline) Em main solo CSS/UX redesign (criteria #2 + #4 Implementer REFUSE — UX layout decision rowSpan grouping + cell distribution decision). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../src/pages/pe/WorkflowMatrixViewPage.tsx | 251 +++++++++++------- 1 file changed, 155 insertions(+), 96 deletions(-) diff --git a/fe-user/src/pages/pe/WorkflowMatrixViewPage.tsx b/fe-user/src/pages/pe/WorkflowMatrixViewPage.tsx index a04c45b..4eb0338 100644 --- a/fe-user/src/pages/pe/WorkflowMatrixViewPage.tsx +++ b/fe-user/src/pages/pe/WorkflowMatrixViewPage.tsx @@ -2,14 +2,17 @@ // V2 đã admin Designer ghim (`IsUserSelectable=true`, Mig 25). Hiển thị tất cả // version ghim cho ApplicableType (1=DuyetNcc, 2=DuyetNccPhuongAn). // -// [Plan AA redesign S24 t1] Bro UAT request: drop table 11 cột compact symbol → -// switch sang panel-per-NV layout mirror admin Designer read-only. 7 label rõ -// tiếng Việt + color coding 2 layer (Step/Phòng + Cấp). Group levels theo -// `level.order` (OR-of-N approvers cùng Cấp render N panel song song). +// [Plan AA redesign v2 S24 t1] Bro UAT request: dạng TABLE tận dụng full width +// thay vì stack vertical panel-per-NV. Cấu trúc 4 cột: +// Bước (Phòng) | Cấp | NV duyệt | Quyền duyệt (grid 2-col 7 label tiếng Việt) +// rowSpan cho Bước (Step) + Cấp (Level order). Color coding 2 layer: +// - Step bg + headerBg cycle 5 màu (blue/purple/emerald/amber/pink) +// - Cấp badge ring cycle 5 màu (violet/sky/teal/orange/rose) +// Mỗi cell Quyền duyệt = 7 checkbox read-only label nguyên văn admin Designer. // // URL: /purchase-evaluations/workflow-matrix?type=1|2 // Mirror layout admin `fe-admin/src/pages/system/ApprovalWorkflowsV2Page.tsx` -// line 853-949 (read-only — drop input onChange). +// line 853-949 cho 7 checkbox label (read-only — drop input onChange). import { useQuery } from '@tanstack/react-query' import { useSearchParams } from 'react-router-dom' import { Network, CheckCircle2, Pin } from 'lucide-react' @@ -102,11 +105,51 @@ export function WorkflowMatrixViewPage() { ) } +// Build flat row list per Step với rowSpan metadata cho table layout. +// Mỗi Level row = 1 NV slot (Mig 29 OR-of-N split). Group theo level.order. +type Row = { + level: AwLevelDto + order: number + isFirstInStep: boolean + isFirstInCap: boolean + rowSpanStep: number + rowSpanCap: number +} + +function buildStepRows(step: AwDefinitionDto['steps'][number]): Row[] { + const byOrder = new Map() + for (const lvl of step.levels) { + const arr = byOrder.get(lvl.order) ?? [] + arr.push(lvl) + byOrder.set(lvl.order, arr) + } + const sortedOrders = [...byOrder.keys()].sort((a, b) => a - b) + const totalInStep = step.levels.length + + const rows: Row[] = [] + let stepCounter = 0 + for (const order of sortedOrders) { + const levelsOfOrder = byOrder.get(order)! + levelsOfOrder.forEach((lvl, idx) => { + rows.push({ + level: lvl, + order, + isFirstInStep: stepCounter === 0, + isFirstInCap: idx === 0, + rowSpanStep: totalInStep, + rowSpanCap: levelsOfOrder.length, + }) + stepCounter++ + }) + } + return rows +} + function WorkflowCard({ wf }: { wf: AwDefinitionDto }) { const totalLevels = wf.steps.reduce((sum, s) => sum + s.levels.length, 0) return ( -
+
@@ -135,17 +178,115 @@ function WorkflowCard({ wf }: { wf: AwDefinitionDto }) {
-
- {totalLevels === 0 ? ( + {totalLevels === 0 ? ( +
Quy trình chưa cấu hình bước duyệt nào.
- ) : ( - wf.steps.map((step, sIdx) => ( - - )) - )} -
+
+ ) : ( +
+ + + + + + + + + + + + + + + + + {wf.steps.map((step, sIdx) => { + const stepColor = STEP_PALETTE[sIdx % STEP_PALETTE.length] + const rows = buildStepRows(step) + + if (rows.length === 0) { + return ( + + + + + ) + } + + return rows.map(r => { + const levelColor = LEVEL_PALETTE[(r.order - 1) % LEVEL_PALETTE.length] + return ( + + {r.isFirstInStep && ( + + )} + {r.isFirstInCap && ( + + )} + + + + ) + }) + })} + +
Bước (Phòng)CấpNV duyệtQuyền duyệt
+
+ Bước {sIdx + 1} +
+
+ {step.departmentName ?? '(Không gắn phòng)'} +
+
+ Chưa có cấp duyệt +
+
+ Bước {sIdx + 1} +
+
+ {step.departmentName ?? '(Không gắn phòng)'} +
+
+ + Cấp {r.order} + + {r.rowSpanCap > 1 && ( +
+ {r.rowSpanCap} NV OR +
+ (chỉ cần 1 NV duyệt) +
+ )} +
+
+ {r.level.approverUserName ?? r.level.approverUserId} +
+ {r.level.approverEmail && ( +
+ {r.level.approverEmail} +
+ )} +
+
+ + + + + + + +
+
+
+ )}