Bỏ qua

Page Design: Anchored Data CRUD Popups

Follows MASTER.md — Dialog component pattern. Applies to: SCR-ANCHOR-11 (Domain), SCR-ANCHOR-12 (Sub Domain), SCR-ANCHOR-13 (Data Element) Triggered from: SCR-ANCHOR-10 (Tree Table) Users: Manager (create/edit)


Common Popup Pattern

All three popups share the same Dialog structure. Differences are in fields only.

Dialog Shell

/* shadcn <Dialog> */
bg-card rounded-3xl border border-border shadow-xl
max-w-lg /* all three are small forms */

/* Header */
px-8 py-6 border-b border-border
  h2.text-xl.font-bold  /* "Thêm Domain" / "Sửa Domain" / etc. */
  p.text-sm.text-muted-foreground  /* context hint */

/* Body */
px-8 py-6 space-y-4

/* Footer */
px-8 py-4 border-t border-border flex justify-end gap-3
  Button(variant="outline")  "Hủy"
  Button(variant="default")  "Lưu" / "Tạo mới"

SCR-ANCHOR-11: Popup Thêm/Sửa Domain

Fields:

Field Type Required Validation Component
Tên Domain Text Yes Min 2, Max 200 chars <Input />
Mã ID Text Auto-generated DM{N}, read-only in edit <Input disabled /> with font-mono text-muted-foreground
Mô tả Textarea No Max 1000 chars <Textarea />

Behaviors: - Create mode: Title = "Thêm Domain mới". Mã ID field hidden (auto-generated on save). Button = "Tạo mới" - Edit mode: Title = "Sửa Domain: [name]". Mã ID shown as read-only. Button = "Lưu" - Save: Close dialog + toast success "Domain đã được tạo/cập nhật" + refresh tree table - Validation: Inline error under field, button disabled until valid


SCR-ANCHOR-12: Popup Thêm/Sửa Sub Domain

Context: Always opened within a Domain (parent context shown)

Fields:

Field Type Required Validation Component
Domain cha Text Read-only, auto-filled from context Badge showing domain name + code
Tên Sub Domain Text Yes Min 2, Max 200 chars <Input />
Mã ID Text Auto-generated DM{N}.{M}, read-only in edit <Input disabled />
Mô tả Textarea No Max 1000 chars <Textarea />

Parent Context Display:

/* At top of form body, before fields */
bg-muted/50 rounded-2xl p-3 flex items-center gap-2
  span.text-xs.font-bold.text-muted-foreground.uppercase  "Domain:"
  Badge(variant="outline")  "[DM1] Con người"


SCR-ANCHOR-13: Popup Thêm/Sửa Data Element

Context: Always opened within a Sub Domain

Fields:

Field Type Required Validation Component
Sub Domain cha Text Read-only context Badge showing sub domain name + code
Tên Data Element Text Yes Min 2, Max 200 chars <Input />
Mã ID Text Auto-generated DE{NNN}-DM{N}.{M} <Input disabled />
Mô tả Textarea Yes Min 10, Max 2000 chars <Textarea />
Kiểu dữ liệu Enum Yes Text/Number/Date/Boolean/Enum/Other <Select />
Mức độ nhạy cảm Enum Yes PUBLIC/INTERNAL/CONFIDENTIAL/SECRET <Select /> default: INTERNAL

Layout: Single column, all fields stacked. Dialog may be max-w-xl due to more fields.

Parent Context Display:

bg-muted/50 rounded-2xl p-3 flex items-center gap-2
  span.text-xs.font-bold.text-muted-foreground.uppercase  "Sub Domain:"
  Badge(variant="outline")  "[DM1.1] Định danh"


Common States

Loading (saving)

/* Save button → loading state */
Button(disabled, isLoading)
  Loader2.h-4.w-4.animate-spin  "Đang lưu..."

Validation Error

/* Under invalid field */
p.text-xs.text-destructive.font-medium.mt-1
  "Tên Domain phải có ít nhất 2 ký tự"

/* Field border turns red */
input.border-destructive.focus:ring-destructive/20

Delete Confirmation (from context menu, not popup)

/* AlertDialog — only when deleting */
AlertDialog
  title: "Xóa [Domain/Sub Domain]?"
  description: "Hành động này không thể hoàn tác. [Name] sẽ bị xóa vĩnh viễn."
  cancel: "Hủy"
  action: Button(variant="destructive")  "Xóa"

Accessibility

  • Dialog: role="dialog", aria-labelledby pointing to title
  • Required fields: aria-required="true", asterisk on label
  • Auto-focus first input on open
  • Escape key closes dialog
  • Tab trapping within dialog
  • Read-only Mã ID: aria-readonly="true", aria-label="Mã ID tự động sinh"

MASTER.md Overrides

What MASTER.md This Page Reason
Dialog max-width max-w-lg max-w-xl (SCR-ANCHOR-13 only) More fields in Data Element form need extra width