Appearance
UI Spec: Cải thiện UX cài đặt Mã Công Việc / Tiền Tour
Feature slug: settings-ux-subtask-tagVersion: 1.0 Ngày: 2026-03-26
B1) Screen Map
Cấu Hình Nội Bộ > Quản Lý Công Việc
├── SCR-01: TourFeeConfig — Trang Cấu Hình Tiền Tour (NEW, gộp Group + Tag)
│ ├── TourFeeGroupAccordion (per nhóm)
│ │ ├── TourFeeTagTable (bảng tags trong nhóm)
│ │ └── TourFeeUsageExpand ("Đang dùng bởi N mã CV")
│ └── TaskTagForm (side dialog, reuse)
├── SCR-02: SubTaskTable (sửa) — Bảng Mã Công Việc + cột tag + filter
├── SCR-03: SubTaskForm (sửa) — Form Chỉnh sửa Mã Công Việc + enriched chip
│
Blast radius (ngoài settings):
├── SCR-04: TaskForm (projects, sửa) — Dropdown "Loại tiền tour" enriched
├── SCR-05: OrderTaskLimitForm (ecommerce, sửa) — Tag display enriched
└── SCR-06: ServiceSubtaskItem (ecommerce, sửa) — Tag display enrichedB2) Component Inventory
| SCR | Component | File | Loại | FR |
|---|---|---|---|---|
| SCR-01 | TourFeeConfig | settings/pages/TourFeeConfig.tsx | New | FR-001, FR-002, FR-003 |
| SCR-01 | TourFeeGroupAccordion | settings/components/tour-fee/TourFeeGroupAccordion.tsx | New | FR-001 |
| SCR-01 | TourFeeTagTable | settings/components/tour-fee/TourFeeTagTable.tsx | New | FR-002 |
| SCR-01 | TourFeeUsageExpand | settings/components/tour-fee/TourFeeUsageExpand.tsx | New | FR-003 |
| SCR-02 | SubTaskTable | settings/components/subtask/SubTaskTable.tsx | Sửa | FR-007 |
| SCR-03 | SubTaskForm | settings/components/subtask/SubTaskForm.tsx | Sửa | FR-004, FR-005, FR-006 |
| SCR-03 | TaskTagSelect | settings/components/task-tag/TaskTagSelect.tsx | Sửa | FR-004, FR-006 |
| SCR-04 | TaskForm (section tag) | projects/components/TaskForm/index.tsx | Sửa (indirect) | FR-004, FR-006 |
| SCR-05 | OrderTaskLimitForm | ecommerce/components/order/OrderForm/OrderTaskLimitForm.tsx | Sửa | FR-004 |
| SCR-06 | ServiceSubtaskItem | ecommerce/components/service/ServiceForm/ServiceSubtaskItem.tsx | Sửa | FR-004 |
B3) User Flows
Flow 1: IT Staff cấu hình tiền tour (tạo tag mới)
[Sidebar] Click "Cấu Hình Tiền Tour"
→ [SCR-01] TourFeeConfig hiện tất cả nhóm
→ Click ▼ nhóm "Tiền tour 2024" → expand
→ Click [+ Thêm tag tiền tour]
→ Side dialog: TaskTagForm mở, nhóm pre-fill "Tiền tour 2024"
→ Nhập mã, tên, bảng tiền tour 5 cấp
→ Click [Lưu]
→ Tag xuất hiện trong bảng nhóm
→ Refresh "Đang dùng bởi" countFlow 2: IT Staff gán tag vào subtask
[Sidebar] Click "Mã Công Việc"
→ [SCR-02] SubTaskTable hiện 275+ items, có cột "Tag tiền tour"
→ Filter theo [Nhóm tiền tour: Tiền tour 2024 ▼]
→ Click edit SUB280 "Tạo hình tai vểnh"
→ [SCR-03] SubTaskForm mở
→ Field "Tag tiền tour": chip [T08 — 80,000đ ×]
→ Hover chip → tooltip hiện 5 cấp bậc
→ Search thêm tag → dropdown hiện [Mã] [Tên] [Range] [Nhóm]
→ Click [Cập nhật]Flow 3: KTV chọn tag khi tạo subtask (blast radius)
[Chi tiết khách hàng] Tab Công Việc
→ Click "Thêm công việc" (tạo subtask)
→ [SCR-04] TaskForm mở
→ Field "Loại tiền tour *"
→ Dropdown hiện: T26 100k 100,000đ (Tiền tour 2024)
→ Chọn T26
→ Tiền tour auto-fill theo cấp bậc KTVB4) Notification Spec
Không có notification trong feature này.
B5) Permission Matrix
| Màn hình | Action | IT Staff | IT Leader | Admin | Manager | Staff (KTV) |
|---|---|---|---|---|---|---|
| SCR-01 TourFeeConfig | Xem nhóm + tags | ✅ | ✅ | ✅ | Ẩn | Ẩn |
| SCR-01 TourFeeConfig | CRUD nhóm + tags | ✅ | ✅ | ✅ | Ẩn | Ẩn |
| SCR-02 SubTaskTable | Xem list | ✅ | ✅ | ✅ | Ẩn | Ẩn |
| SCR-02 SubTaskTable | CRUD subtask | ✅ | ✅ | ✅ | Ẩn | Ẩn |
| SCR-03 SubTaskForm | Xem + sửa | ✅ | ✅ | ✅ | Ẩn | Ẩn |
| SCR-04 TaskForm (tag select) | Chọn tag khi tạo subtask | ✅ | ✅ | ✅ | ✅ | ✅ (subtask mình assign) |
| SCR-05 OrderTaskLimitForm | Xem tag display | ✅ | ✅ | ✅ | ✅ (branch) | ✅ (order mình) |
| SCR-06 ServiceSubtaskItem | Xem tag display | ✅ | ✅ | ✅ | Ẩn | Ẩn |
SCR-01, SCR-02, SCR-03: Giữ nguyên permission
UserRole.ITLeader, UserRole.ITStafftừ module.ts. SCR-04, SCR-05, SCR-06: Giữ nguyên permission hiện tại — chỉ sửa display format.
B6) State Matrix
| Màn hình | Loading | Empty | Error | No Permission |
|---|---|---|---|---|
| SCR-01 TourFeeConfig | Skeleton accordion (3 nhóm placeholder) | "Chưa có nhóm tiền tour. Bấm [+ Nhóm] để tạo." | Toast "Không thể tải dữ liệu" | Ẩn menu hoàn toàn |
| SCR-01 TourFeeUsageExpand | Spinner inline | "Chưa có mã công việc nào sử dụng" | Toast error | — |
| SCR-02 SubTaskTable (cột tag) | "..." placeholder | "—" (dash) | Toast error | Ẩn menu |
| SCR-03 SubTaskForm (tag chip) | Skeleton chips | Text "Chưa chọn tag tiền tour" | Toast error | Ẩn form |
| SCR-03 Tooltip | Spinner nhỏ | "Chưa có tiền tour" | "Không thể tải" | — |
| SCR-04 TaskForm (tag dropdown) | Loading spinner trong dropdown | Dropdown trống | Toast error | Ẩn field |
| SCR-05/06 Tag display | "..." | "—" | "—" | Ẩn section |
B7) Copy Text Dictionary
| Key (i18n) | Text (VI) | Màn hình | Ghi chú |
|---|---|---|---|
settings.label.tour_fee_config | Cấu Hình Tiền Tour | SCR-01 | Page title + sidebar |
settings.label.tour_fee_group_summary | {count} tags · {active} đang hoạt động | SCR-01 | Collapsed group summary |
settings.label.tour_fee_range_flat | {amount}đ | SCR-01 | Flat-rate display |
settings.label.tour_fee_range_multi | {min}~ | SCR-01 | Multi-rate display |
settings.label.tour_fee_detail_flat | CĐ1-{n}: đều | SCR-01 | Flat detail |
settings.label.tour_fee_no_config | Chưa có tiền tour | SCR-01 | Empty tour fee |
settings.label.tour_fee_usage | Đang dùng bởi: {count} mã công việc | SCR-01 | Usage footer |
settings.label.tour_fee_usage_empty | Chưa có mã công việc nào sử dụng | SCR-01 | Empty usage |
settings.label.tour_fee_add_tag | Thêm tag tiền tour | SCR-01 | Add button |
settings.label.tour_fee_add_group | Thêm nhóm | SCR-01 | Add group button |
settings.label.subtask_menu | Mã Công Việc | Sidebar | Rename from "Công Việc" |
settings.label.subtask_edit_title | CHỈNH SỬA MÃ CÔNG VIỆC | SCR-03 | Rename form title |
settings.label.subtask_create_title | TẠO MÃ CÔNG VIỆC | SCR-03 | Rename form title |
settings.label.tag_tour_fee | Tag tiền tour | SCR-02, SCR-03 | Column + field label |
settings.label.tag_tour_fee_search | Tìm tag tiền tour... | SCR-03 | Search placeholder |
settings.label.tooltip_view_detail | Xem chi tiết | SCR-03 | Tooltip link |
settings.label.tour_fee_group_filter | Nhóm tiền tour | SCR-02 | Filter label |
B8) Analytics Events
| Event | Trigger | Data | Mục đích |
|---|---|---|---|
tour_fee_config_viewed | IT Staff mở trang Cấu Hình Tiền Tour | { user_role } | Track adoption trang mới |
tour_fee_group_expanded | Expand nhóm | { group_id, tag_count } | Track nhóm nào hay dùng |
tour_fee_usage_viewed | Click "Xem ↗" usage | { group_id, subtask_count } | Track nhu cầu traceability |
subtask_tag_filter_used | Dùng filter tag/nhóm trên SubTaskTable | { filter_type } | Track adoption filter mới |
B9) Tooltip Dictionary
| Màn hình | Field/Icon | Tooltip Text | Điều kiện hiện |
|---|---|---|---|
| SCR-01 | Range column | Khoảng tiền tour từ cấp thấp nhất đến cao nhất | Hover header "Range" |
| SCR-01 | Chi tiết column | Tiền tour chi tiết theo từng cấp bậc | Hover header "Chi tiết" |
| SCR-01 | "Đang dùng bởi" | Số mã công việc (subtask) đang gán tag thuộc nhóm này | Hover text |
| SCR-03 | Tag chip | Bảng tiền tour theo cấp bậc + link xem chi tiết | Hover chip tag |
| SCR-03 | "Tag tiền tour" label | Chọn tag tiền tour để gán cho mã công việc này | Hover label |
B-Desktop: Wireframes
SCR-01: TourFeeConfig — Trang gộp
┌─── CẤU HÌNH TIỀN TOUR ────────────────────────────────────────────┐
│ │
│ [🔍 Tìm theo mã, tên, số tiền...] [Nhóm: Tất cả ▼] [+ Nhóm] │
│ │
│ ┌─── Tiền tour 2024 ──────────────────────── [Sửa nhóm] [▼] ──┐ │
│ │ │ │
│ │ ┌────┬───────┬─────────┬───────────────────┬───────┬─────┐ │ │
│ │ │ Mã │ Tên │ Range │ Chi tiết │T.thái │ │ │ │
│ │ ├────┼───────┼─────────┼───────────────────┼───────┼─────┤ │ │
│ │ │T26 │ 100k │100,000đ │ CĐ1-5: đều 100k │ ✅ │[Sửa]│ │ │
│ │ │T15 │LaserX │50k-120k │ CĐ1:50k CĐ5:120k │ ✅ │[Sửa]│ │ │
│ │ │T08 │ Ok │ 80,000đ │ CĐ1-5: đều 80k │ ❌ │[Sửa]│ │ │
│ │ └────┴───────┴─────────┴───────────────────┴───────┴─────┘ │ │
│ │ │ │
│ │ [+ Thêm tag tiền tour] │ │
│ │ Đang dùng bởi: 45 mã công việc [Xem ↗] │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Tiền tour 2023 ──────────────────────── [Sửa nhóm] [▶] ──┐ │
│ │ 12 tags · 8 đang hoạt động │ │
│ └────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘SCR-02: SubTaskTable — Bảng Mã Công Việc (sau)
┌─── MÃ CÔNG VIỆC ─────────────────────────────────────────────────────┐
│ │
│ [🔍 Tìm kiếm...] [Loại ▼] [Nhóm TT ▼] [Tag TT ▼] [Trạng thái ▼] │
│ │
│ ┌────┬────────┬──────────┬───────────────────┬──────────────────┬───┐ │
│ │ # │ Mã │ Loại │ Tên công việc │ Tag tiền tour │TT │ │
│ ├────┼────────┼──────────┼───────────────────┼──────────────────┼───┤ │
│ │ 1 │ SUB280 │ Dịch vụ │ Tạo hình tai vểnh│ T08: 80,000đ │ ✅│ │
│ │ 2 │ SUB279 │ Dịch vụ │ BS- Meso da chất │ T26: 100k │ ✅│ │
│ │ 3 │ SUB278 │ Dịch vụ │ BS- Meso HA căng │ T26: 100k, T15 │ ✅│ │
│ │ 4 │ SUB089 │ Thủ công │ Chăm sóc cơ bản │ — │ ✅│ │
│ └────┴────────┴──────────┴───────────────────┴──────────────────┴───┘ │
└───────────────────────────────────────────────────────────────────────┘SCR-03: SubTaskForm — Tag chip enriched + tooltip
┌─── CHỈNH SỬA MÃ CÔNG VIỆC ──────────────────────────────────────┐
│ │
│ Mã công việc * Mô tả │
│ [SUB280] (readonly) [Tạo hình tai vểnh ] │
│ │
│ Loại công việc * Tag tiền tour * │
│ [Làm dịch vụ ▼] ┌──────────────────────────────────────┐ │
│ │ 🔍 Tìm tag tiền tour... │ │
│ Tên công việc * │ │ │
│ [Tạo hình tai vểnh] │ [T08 — 80,000đ ×] │ │
│ │ │ │
│ Trạng thái │ ┌─── Tooltip ──────────────────┐ │ │
│ 🟢 Đang hoạt động │ │ T08 — Ok │ │ │
│ │ │ Nhóm: Tiền tour 2024 │ │ │
│ │ │ │ │ │
│ │ │ Cấp độ 1 80,000đ │ │ │
│ │ │ Cấp độ 2 80,000đ │ │ │
│ │ │ Cấp độ 3 80,000đ │ │ │
│ │ │ Cấp độ 4 80,000đ │ │ │
│ │ │ Cấp độ 5 80,000đ │ │ │
│ │ │ │ │ │
│ │ │ [Xem chi tiết ↗] │ │ │
│ │ └───────────────────────────────┘ │ │
│ └──────────────────────────────────────┘ │
│ │
│ [Hủy] [Cập nhật] │
└─────────────────────────────────────────────────────────────────────┘SCR-04: TaskForm (projects) — Dropdown enriched
┌─── TẠO CÔNG VIỆC CON ──────────────────────────────────────────────┐
│ │
│ Loại tiền tour * │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ T08 — Ok — 80,000đ (Tiền tour 2024) ▼ │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
│ Khi dropdown mở: │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ T26 100k 100,000đ (Tiền tour 2024) │ │
│ │ T15 Laser CO2 50k~120k (Tiền tour 2024) │ │
│ │ T08 Ok 80,000đ (Tiền tour 2024) │ │
│ │ T03 Massage 30k~60k (CHĂM SÓC DA) │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ ↑ mã ↑ tên ↑ range ↑ nhóm │
└──────────────────────────────────────────────────────────────────────┘SCR-05/06: OrderTaskLimitForm + ServiceSubtaskItem — Display enriched
TRƯỚC:
Tag: Ok, 100k (text xanh link cho IT, đen cho role khác)
SAU:
Tag: T08 (80,000đ), T26 (100,000đ) (giữ nguyên màu + link behavior)B-Edge Cases
| # | Tình huống | Behavior | SCR |
|---|---|---|---|
| EC-01 | Nhóm tiền tour rỗng (0 tags) | Nhóm vẫn hiện, expand hiện "Chưa có tag. Bấm [+ Thêm tag tiền tour]" | SCR-01 |
| EC-02 | Tag chưa cấu hình tiền tour (0 tour_moneys) | Range = "—", Chi tiết = "Chưa có tiền tour", Chip = "[T08 — —]" | SCR-01, SCR-03 |
| EC-03 | Subtask type = "Thủ công" → tag không bắt buộc | Field "Tag tiền tour" readonly, cột bảng hiện "—" | SCR-02, SCR-03 |
| EC-04 | Subtask có 4+ tags → chips overflow | Max-width container, chips wrap to next line. SubTaskTable cột tag hiện 2 tags + "+2 more" | SCR-03, SCR-02 |
| EC-05 | Search tag không tìm thấy | Dropdown trống + "Không tìm thấy" | SCR-03, SCR-04 |
| EC-06 | Xóa nhóm có tags đang dùng | Block xóa + toast "Nhóm đang có {N} tag. Xóa hoặc chuyển tag trước." | SCR-01 |
| EC-07 | Route cũ /task-tag/abc123 | Redirect → /tour-fee-config?tag=abc123, auto-expand nhóm chứa tag, highlight tag | SCR-01 |
| EC-08 | Tag disabled → hiện trong chip subtask | Chip hiện bình thường (đã gán rồi), dropdown search filter ra disabled | SCR-03 |
| EC-09 | Tất cả cấp bậc tiền tour = 0 | Range = "0đ", Chi tiết = "CĐ1-5: đều 0" | SCR-01 |
| EC-10 | Group có 50+ tags | Bảng tags trong accordion có pagination (20 per page) | SCR-01 |