Bỏ qua

Page Design: Dữ liệu Định vị (Anchored Data — Tree Table)

Follows MASTER.md — uses Domain-Specific Pattern "Tree Table". Applies to: SCR-ANCHOR-10 Route: /[locale]/anchored-data Users: Manager (full CRUD), Approver (read-only via SCR-ANCHOR-20)


Layout

+-----------------------------------------------------------+
| "Thiết lập dữ liệu định vị (Anchored Data)"              |
| "Khai báo cấu trúc dữ liệu tiêu chuẩn theo Phụ lục A"  |
|                                          [+ Thêm Domain]  |
+-----------------------------------------------------------+
| Search bar                    [Filter: status ▼]           |
+-----------------------------------------------------------+
| Tree Table                                                 |
| ┌─────────────────────────────┬──────────┬────────┐       |
| │ Cấu trúc Dữ liệu          │ Mã ID    │ Thao tác│      |
| ├─────────────────────────────┼──────────┼────────┤       |
| │ ▼ Con người                 │ [DM1]    │ Sửa    │      |
| │   ├ Định danh (italic)      │ [DM1.1]  │        │      |
| │   │  • Số CCCD              │ DE001... │        │      |
| │   │  • Họ và tên            │ DE002... │        │      |
| │   └ Y tế & Sức khỏe        │ [DM1.2]  │        │      |
| │ ▶ Tổ chức                   │ [DM2]    │        │      |
| │ ▶ Đất đai                   │ [DM3]    │        │      |
| └─────────────────────────────┴──────────┴────────┘       |
+-----------------------------------------------------------+
| Showing X domains, Y sub-domains, Z data elements          |
+-----------------------------------------------------------+
  • max-w-6xl mx-auto, space-y-6
  • Tree table is a single flat <table> with visual indentation (not nested tables)
  • All domains collapsed by default → expand on click

Components

flex justify-between items-end
  div
    h1.text-2xl.font-bold.text-foreground  /* title */
    p.text-sm.text-muted-foreground.font-medium  /* subtitle */
  /* Add Domain button — Primary */
  bg-primary text-primary-foreground px-6 py-2.5 rounded-2xl
  font-bold shadow-lg hover:bg-blue-700 transition-all
  flex items-center gap-2
    Plus.h-[18px].w-[18px].stroke-[2.5]

Search & Filter Bar

flex items-center gap-4
  /* Search input */
  flex-1 relative
    Search.absolute.left-4.top-1/2.-translate-y-1/2.h-4.w-4.text-muted-foreground
    input.w-full.pl-10.pr-4.py-2.5.rounded-2xl.border.border-input
    .text-sm.font-medium.placeholder:text-muted-foreground
    .focus:ring-2.focus:ring-ring
    placeholder="Tìm kiếm Domain, Sub Domain, Data Element..."

  /* Status filter — shadcn Select */
  w-48

Tree Table

/* Container */
bg-card rounded-3xl border border-border overflow-hidden shadow-sm

/* Table */
w-full text-sm text-left

/* Header row */
bg-muted border-b border-border
  th.px-8.py-5.font-bold.text-muted-foreground.uppercase.tracking-widest.text-[11px]
  /* Columns: Cấu trúc Dữ liệu | Mã ID | Thao tác (right-aligned) */

/* Body */
divide-y divide-border/50

Domain Row (Level 1)

bg-muted/50 cursor-pointer hover:bg-muted transition-colors
  td.px-8.py-4.font-black.text-foreground.flex.items-center.gap-2
    /* Expand icon */
    ChevronDown.h-4.w-4.text-primary  /* expanded */
    ChevronRight.h-4.w-4.text-muted-foreground  /* collapsed */
    /* Domain name */
    span
  td.px-8.py-4.font-mono.text-xs.text-muted-foreground.font-bold
    /* Code: [DM1] */
  td.px-8.py-4.text-right
    button.text-primary.font-bold.text-xs.hover:underline  "Sửa"

Interaction: Click row → toggle expand/collapse children. Click "Sửa" → open SCR-ANCHOR-11 popup.

Sub Domain Row (Level 2)

bg-card
  td.pl-14.py-3.font-bold.text-muted-foreground.italic
    /* Sub Domain name */
  td.px-8.py-3.font-mono.text-xs.text-muted-foreground.font-bold
    /* Code: [DM1.1] */
  td.px-8.py-3.text-right
    button.text-primary.font-bold.text-xs.hover:underline  "Sửa"

Interaction: Click "Sửa" → open SCR-ANCHOR-12 popup.

Data Element Row (Level 3)

hover:bg-accent/50 transition-colors
  td.pl-20.py-2.text-muted-foreground.font-medium
    /* "• " + DE name */
    span.mr-2  "•"
    span  "Số CCCD"
  td.px-8.py-2.font-mono.text-[10px].text-muted-foreground/60
    /* Code: [DE001-DM1.1] */
  td.px-8.py-2.text-right
    /* No action button at this level — click row to see detail */

Interaction: Click row → navigate to SCR-ANCHOR-20 (detail page).

Context Menu (Right-click or "..." button on Domain/Sub Domain)

/* shadcn DropdownMenu */
/* Items: Thêm Sub Domain, Thêm Data Element, Sửa, Xóa */
/* Xóa only visible if no children */
px-8 py-4 bg-muted/30 border-t border-border
text-sm text-muted-foreground font-medium
  "Hiển thị X domains, Y sub-domains, Z data elements"

Empty State

/* When no domains exist yet (fresh system) */
flex flex-col items-center justify-center py-16 text-center
  Database.h-12.w-12.text-muted-foreground/30
  p.text-lg.font-bold.text-muted-foreground.mt-4  "Chưa có dữ liệu định vị"
  p.text-sm.text-muted-foreground.mt-2  "Bắt đầu bằng cách import Master Data hoặc thêm Domain đầu tiên."
  div.flex.gap-3.mt-4
    Button(variant="outline")  "Import Master Data"
    Button(variant="default")  "Thêm Domain"

Loading State

/* Table skeleton */
bg-card rounded-3xl border border-border overflow-hidden shadow-sm
  /* Header skeleton */
  bg-muted px-8 py-5 flex gap-8
    Skeleton.h-3.w-40  Skeleton.h-3.w-16  Skeleton.h-3.w-12
  /* 5 row skeletons */
  divide-y divide-border/50
    px-8 py-4 flex gap-8
      Skeleton.h-4.w-48  Skeleton.h-3.w-12  Skeleton.h-3.w-8

Data & Business Rules

Rule Detail
Default state All domains collapsed
Sort Domains by code ASC (DM1, DM2...). Sub Domains by code ASC within domain. DEs by code ASC within sub domain
Search Filter across all levels — if a DE matches, show its parent Domain + Sub Domain expanded
Codes Auto-generated, read-only: DM{N}, DM{N}.{M}, DE{NNN}-DM{N}.{M}
Delete guard Cannot delete Domain with Sub Domains. Cannot delete Sub Domain with Data Elements. Show AlertDialog
Status filter Filter by Data Element status (DRAFT, IN_REVIEW, APPROVED, PUBLISHED)

Behaviors

State Trigger Display
Loading Page init Skeleton table
Empty No domains Empty state with dual CTA
Default Data loaded All domains collapsed, row counts in footer
Expanded Click domain row Show Sub Domains + DEs underneath, icon → ChevronDown
Collapsed Click expanded domain Hide children, icon → ChevronRight
Search active Type in search Live filter, matching rows highlighted, parents auto-expanded
Add Domain Click "+ Thêm Domain" Open SCR-ANCHOR-11 popup
Edit Domain Click "Sửa" on domain row Open SCR-ANCHOR-11 popup (edit mode)
Edit Sub Domain Click "Sửa" on sub domain row Open SCR-ANCHOR-12 popup
View DE detail Click DE row Navigate to SCR-ANCHOR-20
Delete Context menu → Xóa AlertDialog confirmation (destructive)

Responsive

Breakpoint Changes
Mobile (< 768px) Hide "Mã ID" column. "Thao tác" becomes icon-only (Pencil). Reduce indentation (pl-8, pl-12, pl-16). p-4
Tablet (768-1023px) Keep all columns. Reduce padding. p-6
Desktop (>= 1024px) Full layout as wireframe. p-10, max-w-6xl

Accessibility

  • Expand/collapse: aria-expanded="true/false" on domain rows
  • Tree semantics: role="treegrid", rows with role="row", aria-level="1/2/3"
  • Keyboard: Enter/Space to toggle expand. Arrow keys to navigate rows
  • "Sửa" links: aria-label="Sửa Domain Con người" (include name)
  • "+ Thêm Domain" button: aria-label="Thêm Domain mới"
  • Search: aria-label="Tìm kiếm trong dữ liệu định vị"
  • Status changes announced via aria-live="polite" region

MASTER.md Overrides

No overrides — uses MASTER.md Tree Table domain-specific pattern.