Page Design: Bản đồ Hiện trạng (Matrix View)¶
Follows MASTER.md — uses Domain-Specific Pattern "Bản đồ hiện trạng (Matrix View)". Applies to:
SCR-MAP-10Route:/[locale]/current-state-mapUsers: Manager (edit mapping), Data Owner (review + confirm/dispute), Approver (view + approve)
Layout¶
+-------------------------------------------------------------------+
| "Bản đồ hiện trạng (Phụ lục C)" |
| "Phân tích sự lưu trữ chồng chéo..." [AI Matched badge] [▼] |
+-------------------------------------------------------------------+
| [Filter: Domain ▼] [Filter: Status ▼] [Search DE...] |
+-------------------------------------------------------------------+
| Matrix Table (horizontally scrollable) |
| ┌──────────┬────────┬────────┬────────┬────────┬─────────────┐ |
| │ Trường DL│ Công an│ Sở TC │Cục Thuế│ BHXH │ Ghi chú │ |
| ├──────────┼────────┼────────┼────────┼────────┼─────────────┤ |
| │ Số CCCD │ ● │ ○ │ │ ● │ chồng chéo │ |
| │ Họ và tên│ ● │ ● │ ● │ ● │ định danh │ |
| │ Số BHYT │ │ │ │ ● │ BHXH+Y tế │ |
| └──────────┴────────┴────────┴────────┴────────┴─────────────┘ |
+-------------------------------------------------------------------+
| [Data Owner role: Confirmation Alert Bar] |
+-------------------------------------------------------------------+
- Critical: Horizontal scroll with sticky first column
overflow-x-autoon table container- First column
sticky left-0 z-10 - Content area: no
max-w-6xl— matrix needs full width
Components¶
Page Header¶
flex justify-between items-end mb-6
div
h1.text-2xl.font-bold.text-foreground
p.text-sm.text-muted-foreground.font-medium.italic
div.flex.gap-2
/* AI Matched badge */
Badge.bg-blue-100.text-blue-700.border-blue-200
.text-[10px].font-black.uppercase "AI Matched"
/* Export button (optional) */
Button(variant="outline", size="sm") Download icon
Filter Bar¶
flex items-center gap-4 mb-6
/* Domain filter — shadcn Select */
Select.w-48 placeholder="Tất cả Domain"
/* Status filter */
Select.w-48 placeholder="Tất cả trạng thái"
/* Search */
div.relative.flex-1
Search.absolute.left-3.top-1/2.-translate-y-1/2.h-4.w-4.text-muted-foreground
Input.pl-9.rounded-2xl placeholder="Tìm Data Element..."
Matrix Table¶
/* Outer container — rounded, scrollable */
bg-card rounded-3xl border border-border overflow-hidden shadow-sm overflow-x-auto
/* Table */
w-full text-xs text-left border-collapse
/* Header row */
bg-muted border-b border-border
/* First column header — sticky */
th.px-6.py-5.sticky.left-0.bg-muted.z-10.w-48
.border-r.border-border.font-black.text-muted-foreground.uppercase
"Trường dữ liệu"
/* Unit column headers */
th.px-2.py-5.text-center.border-r.border-border.min-w-[80px]
.font-bold.text-muted-foreground
/* Unit name — truncated */
/* Last column: Ghi chú */
th.px-6.py-5.font-bold.text-muted-foreground.italic.min-w-[200px]
"Ghi chú hiện trạng"
Matrix Cell — Dot Indicators¶
/* Cell container */
p-2 border-r border-border text-center
/* Dot states — per MASTER.md Domain-Specific Pattern */
/* DATABASE */
div.w-4.h-4.bg-primary.rounded-[4px].mx-auto.shadow-inner
/* DATABASE_OVERLAP */
div.w-4.h-4.bg-primary/30.rounded-[4px].mx-auto
/* FRAGMENTED */
div.w-4.h-4.bg-warning.rounded-[4px].mx-auto
/* READY */
div.w-4.h-4.bg-success.rounded-[4px].mx-auto
/* EMPTY */
/* no dot, empty cell */
/* DISPUTED */
div.w-4.h-4.bg-destructive.rounded-[4px].mx-auto
/* Cell background: bg-red-50 dark:bg-red-950 */
/* CONFIRMED */
div.w-4.h-4.bg-success.rounded-[4px].mx-auto
/* Cell background: bg-green-50 dark:bg-green-950 */
/* REJECTED */
/* no dot, cell bg-muted, strikethrough on row text */
Matrix Cell — Interaction¶
/* Clickable cell (Manager) */
cursor-pointer hover:bg-accent/50 transition-colors
/* Click → open SCR-MAP-11 popup (edit mapping) */
/* Data Owner cell (own unit column only) */
cursor-pointer hover:bg-accent/50
/* Click → show context menu: "Xác nhận" / "Đánh dấu tranh chấp" */
/* Approver cell */
cursor-default /* view only */
First Column (Data Element name)¶
px-6 py-4 sticky left-0 bg-card z-10 border-r border-border
font-bold text-foreground
/* On hover: bg-accent/50 */
/* Transition between card bg and hover */
Notes Column (last)¶
Legend Bar (below table)¶
flex items-center gap-6 px-6 py-3 bg-muted/30 border-t border-border text-xs
/* Each legend item */
flex items-center gap-2
div.w-3.h-3.rounded-sm /* colored dot */
span.text-muted-foreground.font-medium /* label */
/* Items: ● Lưu trữ | ○ Chồng chéo | ● Phân mảnh | ● Sẵn sàng | ● Tranh chấp | ● Xác nhận */
Data Owner: Dedicated Review Mode (UXI-05 — CREATIVE REDESIGN)¶
Problem with old mockup: Data Owner forced to navigate a full matrix (all DEs × all units) just to confirm their own unit's 15 fields. Too complex, too many clicks.
New approach: When role = Data Owner, SCR-MAP-10 switches to a card-based review list showing ONLY their unit's mapped fields, with inline confirm/reject per item.
+-----------------------------------------------------------+
| "Xác nhận Hiện trạng — Sở Y tế" |
| Deadline: 05/04/2026 (còn 7 ngày) |
| ████████████████░░░░░░░░ 53% (8/15 đã xác nhận) |
+-----------------------------------------------------------+
| [Tab: Chờ xác nhận (7)] [Tab: Đã xác nhận (8)] [Tất cả] |
+-----------------------------------------------------------+
| |
| ┌─ Field Card ────────────────────────────────────────┐ |
| │ ho_ten → Họ và tên (DE002-DM1.1) Score: 0.95 │ |
| │ Nguồn: AI+Rule | Bảng: nhan_vien | Kiểu: VARCHAR │ |
| │ │ |
| │ [✅ Xác nhận đồng ý] [🚩 Tranh chấp] │ |
| └─────────────────────────────────────────────────────┘ |
| |
| ┌─ Field Card ────────────────────────────────────────┐ |
| │ ma_bhyt → Số BHYT (DE005-DM1.2) Score: 0.72 │ |
| │ Nguồn: AI | Bảng: benh_nhan | Kiểu: VARCHAR │ |
| │ ⚠️ "Đơn vị chỉ lưu bản sao, không phải nguồn gốc" │ |
| │ │ |
| │ [✅ Xác nhận đồng ý] [🚩 Tranh chấp] │ |
| └─────────────────────────────────────────────────────┘ |
| |
+-----------------------------------------------------------+
| Sticky bottom bar: |
| [✅ Xác nhận tất cả còn lại (7)] [Xem dạng ma trận] |
+-----------------------------------------------------------+
/* Progress header */
bg-card rounded-2xl border border-border p-5 mb-6
div.flex.items-center.justify-between.mb-3
h2.text-xl.font-bold "Xác nhận Hiện trạng — [Unit name]"
Badge /* deadline with urgency color */
/* Progress bar */
div.space-y-1
div.flex.justify-between.text-sm.font-semibold
span "8/15 đã xác nhận"
span.text-primary "53%"
div.h-3.bg-muted.rounded-full.overflow-hidden
div.h-full.bg-primary.rounded-full
/* Field review card */
bg-card border border-border rounded-xl p-4 space-y-3
hover:border-primary/20 transition-all
/* Row 1: mapping info */
flex items-center justify-between
div.flex.items-center.gap-2
span.font-mono.font-bold.text-sm /* source field */
ArrowRight.h-4.w-4.text-muted-foreground
span.font-semibold /* DE name */
Badge.font-mono.text-[10px] /* DE code */
/* Score */
div.flex.items-center.gap-2
div.h-2.w-10.bg-muted.rounded-full
div.h-full.rounded-full /* colored by score */
span.font-mono.text-xs.font-bold
/* Row 2: metadata */
div.flex.gap-4.text-xs.text-muted-foreground
span "Nguồn: AI+Rule"
span "Bảng: nhan_vien"
span "Kiểu: VARCHAR"
/* Row 3: optional warning/note */
/* If Data Owner previously commented */
/* Row 4: actions */
div.flex.items-center.gap-3.pt-2.border-t.border-border
Button(variant="outline", size="sm").text-success.border-success.hover:bg-success.hover:text-white
Check.h-4.w-4.mr-1 "Xác nhận đồng ý"
Button(variant="outline", size="sm").text-destructive.border-destructive.hover:bg-destructive.hover:text-white
Flag.h-4.w-4.mr-1 "Tranh chấp"
/* Click → open SCR-MAP-40 popup */
/* Batch action bar (sticky bottom) */
sticky bottom-0 bg-card/95 backdrop-blur-sm border-t border-border p-4
flex items-center justify-between
Button(variant="default")
CheckCheck.h-4.w-4.mr-2 "Xác nhận tất cả còn lại (7)"
Button(variant="ghost")
Grid3x3.h-4.w-4.mr-2 "Xem dạng ma trận"
/* Switches to matrix view if Data Owner prefers */
Why better than mockup matrix approach:
- Focused: Data Owner sees ONLY their fields, not the entire city's matrix
- Deadline visible: Progress bar + countdown creates urgency without stress
- 1-click confirm: Inline button per field, no popup
- Batch confirm: "Xác nhận tất cả" for efficiency
- Still accessible: "Xem dạng ma trận" toggle for those who want the old view
Data Owner: Confirmation Popup (GAP-07)¶
/* AlertDialog — triggered by "Xác nhận tất cả" batch action */
AlertDialog
title: "Xác nhận hiện trạng đơn vị?"
description: "Bạn xác nhận đồng ý với 7 kết quả matching còn lại.
Sau khi xác nhận, không thể thay đổi trực tiếp
(cần đánh dấu tranh chấp nếu phát hiện sai sót)."
cancel: "Quay lại"
action: Button(variant="default") "Xác nhận đồng ý"
Data Owner: Rejection Comment Popup (GAP-07)¶
/* Dialog — triggered by "Từ chối" action on individual field */
Dialog.max-w-lg
/* Header */
h2 "Góp ý chỉnh sửa"
p "[field name] → [DE name]"
/* Body */
Label "Nội dung góp ý *"
Textarea.min-h-[100px] placeholder="Mô tả lý do không đồng ý..."
p.text-xs.text-muted-foreground "Góp ý sẽ được gửi về Manager để điều chỉnh"
/* Footer */
Button(variant="outline") "Hủy"
Button(variant="default") "Gửi góp ý"
/* Note: This is different from DISPUTED (which goes to Approver).
Regular rejection goes back to Manager for adjustment. */
Approver: Readiness Panel (GAP-10)¶
/* Shown at top of SCR-MAP-10 when role = Approver */
/* Replaces simple DISPUTED badge with a full readiness dashboard */
bg-card rounded-2xl border border-border p-5 mb-6
h3.font-bold.text-lg.mb-4 "Trạng thái phê duyệt Bảng C"
div.grid.grid-cols-3.gap-4
/* Confirmed units */
div.text-center.p-3.bg-success/10.rounded-xl
p.text-2xl.font-black.text-success "18/24"
p.text-xs.font-semibold.text-success "Sở đã xác nhận (75%)"
/* DISPUTED */
div.text-center.p-3.bg-destructive/10.rounded-xl.cursor-pointer
.hover:ring-2.hover:ring-destructive
p.text-2xl.font-black.text-destructive "3"
p.text-xs.font-semibold.text-destructive "Ô DISPUTED"
/* Click → SCR-MAP-41 */
/* Readiness */
div.text-center.p-3.rounded-xl
/* If both guards pass: bg-success/10 */
/* If not: bg-warning/10 */
p.text-2xl.font-black "⏳"
p.text-xs.font-semibold "Chưa đủ điều kiện"
/* or ✅ "Sẵn sàng phê duyệt" */
/* CTA */
div.mt-4.flex.justify-end
Button(variant="default", disabled={!ready})
Shield.h-4.w-4.mr-2 "Phê duyệt Bảng C"
/* Opens SCR-MAP-43 */
Data & Business Rules¶
| Rule | Detail |
|---|---|
| Default sort | Data Elements by Domain code ASC, then DE code ASC |
| Default filter | None (show all) |
| Pagination | No pagination — virtual scroll for large datasets |
| Cell click (Manager) | Opens SCR-MAP-11 popup to edit mapping |
| Cell click (Data Owner) | Context menu: Confirm / Dispute (own unit only) |
| Color coding | 8 states per MASTER.md domain-specific pattern |
| AI badge | Shown on cells where match_method = AUTO_AI |
| Sticky column | First column always visible during horizontal scroll |
Behaviors¶
| State | Trigger | Display |
|---|---|---|
| Loading | Page init | Skeleton matrix (header + 5 rows) |
| Empty | No mapping data | Empty state: "Chưa có dữ liệu matching. Hãy chạy Discovery trước." |
| Default | Data loaded | Matrix with dots + colors |
| Filter active | Select domain/status | Matrix filters, URL params updated |
| Cell hover | Mouse over cell | Tooltip: "DE name + Unit name + status" |
| Cell click (Manager) | Click cell | Open SCR-MAP-11 popup |
| Confirm (Data Owner) | Click "Xác nhận Đồng ý" | Toast success, cells turn green |
| Dispute (Data Owner) | Click "Đánh dấu tranh chấp" | Open SCR-MAP-40 popup |
| Approve (Approver) | Click DISPUTED badge | Navigate to SCR-MAP-41 |
Responsive¶
| Breakpoint | Changes |
|---|---|
| Mobile (< 768px) | Matrix collapses to card list view (each DE as card showing unit statuses). Filter stacked. p-4 |
| Tablet (768-1023px) | Matrix with horizontal scroll. Fewer visible columns. p-6 |
| Desktop (>= 1024px) | Full matrix, all columns visible (horizontal scroll if many units). Sticky first column. p-10 |
Accessibility¶
- Matrix:
role="grid", header cellsrole="columnheader", data cellsrole="gridcell" - Cell dots: NOT color alone — tooltip shows status text.
aria-label="Số CCCD tại Công an: Lưu trữ" - Sticky column: proper
z-indexso focus ring not cut off - Keyboard: Arrow keys to navigate cells, Enter to activate cell action
- DISPUTED cells: Red color + "DISPUTED" text in tooltip (not color alone)
- Screen reader:
aria-live="polite"for filter changes announcing result count - Confirmation alert:
role="alert"witharia-label
MASTER.md Overrides¶
| What | MASTER.md | This Page | Reason |
|---|---|---|---|
| Content max-width | max-w-6xl |
max-w-full (no constraint) |
Matrix needs full available width for many unit columns |
| Content padding | p-10 |
p-6 xl:p-10 |
More room for wide matrix on medium screens |