Skip to content

Đặc tả UI — Tab Chu kỳ khách ghé không mua

Version: 2.8
Date: 11/05/2026
Canonical Inputs: SOURCE_OF_TRUTH.md, EVIDENCE_PACK.md, prd.md.

v2.8 — 11/05/2026

Thay đổiSectionẢnh hưởng
Thêm UI-009 info strip vào inventoryB0.1) InventoryFE
Thêm 9 row delta NEW (sub-text + column rename T6)B0.2) Field deltaFE
Wireframe B2 redrawn — info strip + sub-text overview/matrix + column rename T6B2) SCR-01FE, UI/UX
Wireframe B3 popup updated — ℹ️ icon cạnh 6 column headerB3) SCR-02FE, UI/UX
Thêm 9 i18n keys mới vào dictionaryB6) Từ điểnFE
B9 tooltip rewrite gộp 19 required (bỏ phân tách Phase 1 + Backlog)B9) TooltipFE, QA
Thêm 4 row B-PITFALLS phòng tránh confusion v2.8B-PITFALLSAll
Thêm B0.6 style guideline (info strip + sub-text + tooltip icon) cho designer + FEB0.6) Style guideline v2.8Designer, FE

File này mô tả màn hình và delta UI. SOURCE_OF_TRUTH.md thắng khi có conflict về scope; PRD thắng khi có conflict về FR/công thức.

B-PRE) Discovery checklist

Hạng mụcKết quả
Route/component hiện có/r/reports/customer_cycle_report_group, CustomerCycleReport.tsx
Tab hiện cóTổng quan, Chu kỳ mua hàng, Chu kỳ khách hàng
Filter hiện cóLoại chu kỳ, Bước chu kỳ, thời gian, Chi nhánh, Đặt lại
Matrix hiện cóHeader 2 tầng, row hardcode, click mở popup
Popup hiện cóSearch + filter dịch vụ + filter nhóm dịch vụ + export + table purchase
PermissionTheo report group hiện tại; action role user; branch scope từ account branches
ExportDeferred phase 1
Mobile/responsiveMatrix có scroll; popup cần width responsive
Copy reviewBắt buộc Vietnamese-first, không dùng wording purchase

B0) As-Is UI Inventory và Delta Contract

B0.1) Inventory đầy đủ

UI IDMànThành phần hiện tạiEvidenceDelta StatusTarget
UI-001SCR-01Tab bar 3 tabCustomerCycleReport.tsxUPDATEThêm tab Chu kỳ khách ghé không mua
UI-002SCR-01localStorage.currentTab whitelist 3 keyCustomerCycleReport.tsxUPDATEThêm key mới, rà key CUSTOMER_CYCLE_CUSTOMER
UI-003SCR-01Filter bar purchaseCustomerCyclePurchaseFilterReport.tsxKEEPReuse visible controls
UI-004SCR-01Overview purchase copyCustomerCyclePurchaseViewChart.tsxUPDATECopy visit-based
UI-005SCR-01Matrix purchase copyCustomerCyclePurchaseTable.tsxUPDATEHeader/row visit-based
UI-006SCR-02Popup toolbar có service/group/exportCustomerCycleDetailPopup.tsxUPDATEChỉ search, bỏ export/filter nâng cao
UI-007SCR-02Popup columns purchaseCustomerCycleDetailPopup.tsxUPDATEColumns chăm sóc visit
UI-008SCR-02Click row mở hồ sơ kháchCustomerCycleDetailPopup.tsxKEEPGiữ behavior
UI-009SCR-01(none — new component)-NEWInfo strip permanent above filter bar (DEC-028)

B0.2) Field delta

Field / CopySurfaceStatusTarget behavior
Chu kỳ khách ghé không muaTab label (≥768px)NEWTab thứ 4 trong report group, viewport desktop/tablet lớn
Khách ghé không muaTab label (<768px)NEW (DEC-022)Short form cho mobile, tab key + URL không đổi
Số lượng khách có lượt ghé không muaCard labelNEWThay Số lượng khách bắt đầu mua
Cơ cấu khách: đã/chưa quay lại ghéDonut titleNEWThay wording tần suất mua; nêu thẳng 2 nhóm
Tỉ lệ KH theo thời gian chưa ghé lạiDonut titleNEWThay wording chưa mua lại
KH chưa quay lại ghéMatrix rowNEWThay row Số khách có khả năng rời bỏ
Lượt ghé gần nhấtPopup columnNEWDate từ latest qualified visit
Loại ghéPopup columnNEWMap source: consultantTư vấn, do_serviceLàm dịch vụ. Multi-source: Tư vấn + Làm dịch vụ (DEC-017)
Số lượt ghé không mua trong kỳPopup columnNEW (rename T4)Đếm qualified visits của khách trong kỳ filter
Đơn mua gần nhấtPopup columnNEW (rename T1)Order hợp lệ gần nhất tới to_date
Chưa từng muaPopup empty valueNEW (rename T2)Hiển thị khi closest_order_date null
Cùng ngàyMatrix row labelNEW (rename T3)Thay row 0 ngày; khách có nhiều lượt qualified cùng 1 ngày
Tab hiển thị khách đã ghé tư vấn / làm dịch vụ nhưng chưa phát sinh doanh số. Đã loại khách đã mua sau lượt ghé.Info strip copyNEW (DEC-028)Permanent strip trên đầu tab, không dismiss
Đã loại khách chuyển đổi sau ghéCard 1 sub-textNEW (DEC-029)Sub-text dưới label card 1
Trên tổng {total} KHDonut 1 sub-textNEW (DEC-029)Sub-text dưới donut 1, runtime interpolate
Trên tổng {total} KHDonut 2 sub-textNEW (DEC-029)Sub-text dưới donut 2
Khoảng cách trung bình giữa các lượt ghéMatrix header dọc sub-textNEW (DEC-029)Sub-text dưới header Chu kỳ khách ghé
Tính tới ngày kết thúc kỳMatrix header ngang sub-textNEW (DEC-029)Sub-text dưới header Số ngày/tháng chưa ghé lại
Nhiều lượt ghé qualified trong 1 ngàyMatrix row Cùng ngày sub-textNEW (DEC-029)Sub-text dưới row label
Chỉ có 1 lượt ghé qualified trong kỳMatrix row KH chưa quay lại ghé sub-textNEW (DEC-029)Sub-text dưới row label
% trên tổngMatrix cột cuối — column headerRENAME T6 (DEC-029)Đổi tên cột từ Tỷ lệ% trên tổng; logic data binding không đổi

B0.4) Field x Surface matrix

TrườngTab/cardMatrixPopupSearchFilterXuất dữ liệuQuyềnMobileTooltipKiểm tra
total_customerTổng rowKhôngKhôngTheo filterKhôngReport scopeFit0 -> empty
visit_cycleKhôngKhôngKhôngTheo durationKhôngReport scopeScroll1 visit -> no cycle
days_since_last_visitDonut 2Column bucketKhôngTheo to_dateKhôngReport scopeFitClamp to now
branch_nameKhôngKhôngKhôngTheo branchKhôngBranch scopeFitKhôngMulti-branch -> Nhiều chi nhánh
closest_order_dateKhôngKhôngKhôngTheo to_dateKhôngReport scopeFitNo order -> Chưa từng mua (rename T2)

B0.5) State x Screen matrix

StateSCR-01SCR-02
DefaultFilter default + loading vùng dataKhông mở
Đang tảiSpinner/skeleton giống tab purchase, copy Đang tải dữ liệu...Table loading
RỗngChưa có khách ghé không mua trong điều kiện lọc này. Vui lòng đổi thời gian hoặc chi nhánh.Chưa có khách hàng trong nhóm này.
Lỗi hệ thốngKhông thể tải báo cáo. Vui lòng thử lại. + nút Thử lại nếu cóKhông thể tải danh sách khách. Vui lòng thử lại.
Không có quyềnẨn tabKhông mở
Một phầnChart có data nhưng bucket rỗng vẫn render matrixPopup rỗng với title đúng bucket
Info stripVisible always (không phụ thuộc state khác — DEC-028)Không hiển thị

B0.6) Style guideline v2.8 (DEC-028, DEC-029)

Style spec dưới đây dành cho designer + FE cùng đọc — không phải đợi dev-spec.md C6. Giúp designer build mockup / FE build component không lệch nhau.

ElementStyle spec
Info strip container (DEC-028)Background bg-amber-50 (Quasar palette); border-radius nhẹ; padding 12-16px; font-size body; không bold; full container width
Info strip iconq-icon name="info", color amber-9, size 18-20px, đặt left
Info strip textColor amber-9 (đậm hơn background); 1-2 dòng max; mobile <768px auto-wrap
Sub-text dưới label (DEC-029)Font-size 12px (text-caption Quasar); color text-grey-7 hoặc text-secondary; margin-top 4px; line-height tight; không italic (italic gây rối với dấu tiếng Việt)
Sub-text wrapMobile <768px: auto-wrap 2 dòng max, không cắt chữ; donut sub-text có thể trim còn Trên tổng nếu Chart.js label clutter
Popup column tooltip icon (DEC-029, DEC-030)q-icon name="info"; size 14px; color grey-6; class q-ml-xs cursor-help; inline cạnh column header text
Tooltip popoverQuasar q-tooltip default style; mobile tap toggle; max-width responsive, không cắt chữ
KHÔNG cóAnimation, dismiss button, localStorage cho info strip; italic cho sub-text; chip/badge cho tooltip icon

Reference component cho FE:

  • VisitNoPurchaseInfoStrip.tsx (info strip, static)
  • LabelWithSubText.tsx (sub-text wrapper, props: label, subtext, tooltip, level: 'card' | 'header' | 'row')

Chi tiết implementation FE: xem dev-spec.md C6.

B1) Bản đồ màn hình

SCRTênRouteMục tiêu
SCR-01Tab Chu kỳ khách ghé không mua/r/reports/customer_cycle_report_groupXem phân bố khách đã ghé nhưng chưa mua
SCR-02Popup chi tiết bucketDialog từ SCR-01Xem danh sách khách để chăm sóc tiếp

B2) SCR-01 — Tab Chu kỳ khách ghé không mua

Mục tiêu màn hình

User vào màn để xác định nhóm khách đã có tín hiệu quay lại chi nhánh nhưng chưa tạo doanh số. Primary action là click bucket trong matrix để mở danh sách khách; secondary action là đổi filter hoặc đặt lại.

Demo gắn vào UI hiện tại

text
Route: /r/reports/customer_cycle_report_group

[Tổng quan] [Chu kỳ mua hàng] [Chu kỳ khách hàng] [Chu kỳ khách ghé không mua]
--------------------------------------------------------------------------------
ℹ️  Tab hiển thị khách đã ghé tư vấn / làm dịch vụ nhưng chưa phát sinh
    doanh số. Đã loại khách đã mua sau lượt ghé.                  (DEC-028)
--------------------------------------------------------------------------------
[Chu kỳ theo ngày v] [30 ngày  i] [01/02/2026 - 30/04/2026] [Chi nhánh v] [Đặt lại]

Tổng quan
+-----------------------------+ +-----------------------------+ +-----------------------------+
| Số lượng khách có lượt      | | Cơ cấu khách: đã/chưa        | | Tỉ lệ KH theo thời gian     |
| ghé không mua  ℹ️           | | quay lại ghé  ℹ️             | | chưa ghé lại  ℹ️            |
| Đã loại khách chuyển đổi    | | Trên tổng 1.250 KH           | | Trên tổng 1.250 KH          |
| sau ghé           (DEC-029) | |                    (DEC-029) | |                   (DEC-029) |
|                              | |                              | |                             |
| 1.250                       | | KH đã quay / Chưa quay      | | 1-30 / 31-60 / 61-90        |
+-----------------------------+ +-----------------------------+ +-----------------------------+

Chu kỳ khách ghé
+--------------------------------+---------+---------+---------+-------+----------+
| Chu kỳ khách ghé ℹ️            | 1-30 ℹ️ | 31-60   | 61-90   | Tổng  | % trên   |
| Khoảng cách trung bình         | Số ngày chưa ghé lại                   | tổng     |
| giữa các lượt ghé    (DEC-029) | Tính tới ngày kết thúc kỳ    (DEC-029) | (T6)     |
+--------------------------------+---------+---------+---------+-------+----------+
| Tổng ℹ️                        | 450     | 620     | 180     | 1250  | 100%     |
| Tỷ lệ KH theo thời gian        | 36.00%  | 49.60%  | 14.40%  | 100%  |          |
| chưa ghé lại ℹ️                |         |         |         |       |          |
| KH chưa quay lại ghé ℹ️        | 300     | 380     | 120     | 800   | 64.00%   |
| Chỉ có 1 lượt ghé qualified    |         |         |         |       |          |
| trong kỳ             (DEC-029) |         |         |         |       |          |
| Cùng ngày ℹ️                   | 5       | 3       | 0       | 8     | 0.64%    |
| Nhiều lượt ghé qualified       |         |         |         |       |          |
| trong 1 ngày         (DEC-029) |         |         |         |       |          |
| 1 - 30 ngày                    | 145     | 237     | 60      | 442   | 35.36%   |
+--------------------------------+---------+---------+---------+-------+----------+

Filter behavior

ControlDefaultBehavior
Loại chu kỳChu kỳ theo ngàyĐổi sang tháng thì period reset 3
Bước chu kỳ30 ngày hoặc 3 thángDebounce giống filter hiện có. Validation (DEC-024): by_day ∈ [1, 180], by_month ∈ [1, 12]. Out-of-range → inline error Bước chu kỳ phải từ 1 đến {max} {đơn vị}, không gọi BE, giữ giá trị cũ trong query state.
Thời gian báo cáoĐầu tháng cách đây 2 tháng -> cuối tháng hiện tạiQuery lại khi đổi. Max range (DEC-023): 365 ngày. Nếu user chọn to_date - from_date > 365, FE clamp from_date = to_date - 365 ngày + toast warning Phạm vi báo cáo tối đa 1 năm. Đã điều chỉnh ngày bắt đầu thành DD/MM/YYYY.
Chi nhánhAll branch user có quyềnMulti-select
Đặt lại-Reset toàn bộ filter về default

Hidden rules:

  • Source visit = consultant, do_service.
  • is_zero_order = true.
  • Loại khách đã chuyển đổi: nếu khách có order hợp lệ với created_at > last_qualified_visit_date (trong kỳ, đến to_date), không hiển thị (DEC-014).

Interaction

ActionFeedbackCopy
Đổi filterData area loadingĐang tải dữ liệu...
Đặt lạiReset filter + query lạiKhông cần toast
Click bucket có data (value > 0)Mở SCR-02Title theo row + column; cursor pointer
Click bucket rỗng (value 0/empty)KHÔNG mở popup (DEC-019)Cursor default, không có hover effect
Query lỗiInline errorKhông thể tải báo cáo. Vui lòng thử lại.

B3) SCR-02 — Popup chi tiết khách ghé không mua

Mục tiêu màn hình

Popup giúp CSKH xem khách cụ thể trong bucket và mở hồ sơ khách để gọi/chăm sóc lại. Popup không phải màn export và không hiển thị field tài chính phase 1.

Title format (DEC-021)

Format cố định: {Row label} • {Column label} (separator — bullet với 2 space mỗi bên). Ví dụ:

  • KH chưa quay lại ghé • 31 - 60 ngày
  • 1 - 30 ngày • 4 - 6 tháng (chu kỳ row × bucket column)
  • Cùng ngày • ≤ 3 tháng
  • Tổng • 31 - 60 ngày (popup từ row Tổng)

KHÔNG dùng pattern (Chu kỳ: ...) của tab purchase.

text
Popup: KH chưa quay lại ghé • 31 - 60 ngày
--------------------------------------------------------------------------------
[Tìm tên hoặc số điện thoại_______________________________________________]

+-----+----------------+------------+--------------------+----------------------+---------------------+------------------------------------+----------------------+--------------------------+
| STT | Khách hàng     | SĐT        | Chi nhánh ℹ️       | Lượt ghé gần nhất ℹ️ | Loại ghé ℹ️         | Số lượt ghé không mua trong kỳ ℹ️ | Đơn mua gần nhất ℹ️ | Số ngày chưa ghé lại ℹ️ |
+-----+----------------+------------+--------------------+----------------------+---------------------+------------------------------------+----------------------+--------------------------+
| 1   | Nguyễn Thị Lan | 0909xxxxxx | CN Quận 1       | 10/04/2026        | Tư vấn            | 1                              | 15/03/2026         | 20                   |
| 2   | Trần Minh Anh  | 0912xxxxxx | Nhiều chi nhánh | 08/04/2026        | Tư vấn + Làm dịch vụ | 2                          | Chưa từng mua      | 22                   |
+-----+----------------+------------+-----------------+-------------------+-------------------+--------------------------------+--------------------+----------------------+
CộtDataBehavior
STTindexTheo page
Khách hàngdisplay_name + avatar nếu cóClick mở hồ sơ khách
SĐTphone_numberMask/format theo component phone hiện có
Chi nhánhbranch_nameNhiều chi nhánh nếu same-day latest multi-branch
Lượt ghé gần nhấtlast_visit_dateDD/MM/YYYY
Loại ghévisit_sourceMap consultant -> Tư vấn, do_service -> Làm dịch vụ. Visit có cả 2 source: hiển thị Tư vấn + Làm dịch vụ (thứ tự cố định, separator +, không xuống dòng, không chip — DEC-017)
Số lượt ghé không mua trong kỳcount_visit_no_orderĐếm qualified visits của khách trong kỳ filter
Đơn mua gần nhấtclosest_order_dateChưa từng mua nếu null (không giới hạn trong kỳ filter)
Số ngày chưa ghé lạidays_since_last_visitInteger ngày

V2.8 update (DEC-029, DEC-030): Mỗi column header trong bảng popup trên (Chi nhánh, Lượt ghé gần nhất, Loại ghé, Số lượt ghé không mua trong kỳ, Đơn mua gần nhất, Số ngày chưa ghé lại) phải render icon ℹ️ inline cạnh tên column. Hover/tap ℹ️ hiển thị tooltip copy lift từ B9 required.

Responsive/accessibility

AreaRule
Matrix desktopSticky header, horizontal scroll nếu nhiều bucket
Matrix tablet/mobileGiữ scroll ngang; không co chữ đến mức mất nghĩa
Popup desktopWidth tối đa như dialog hiện có, bảng scroll ngang
Popup mobile/tabletFull-width dialog, focus vào search khi mở
KeyboardEsc đóng popup, Tab đi từ search -> table -> pagination
Screen readerIcon info có aria-label theo tooltip

B4) Notification và action feedback

Không có thông báo hệ thống. Feedback nằm tại màn:

SituationCopy
LoadingĐang tải dữ liệu...
Empty reportChưa có khách ghé không mua (chưa chuyển đổi) trong điều kiện lọc này. Vui lòng đổi thời gian hoặc chi nhánh.
Empty popupChưa có khách hàng trong nhóm này.
Đơn mua gần nhất = nullChưa từng mua (rename T2: rõ all-time, không nhầm "trong kỳ")
Lỗi báo cáoKhông thể tải báo cáo. Vui lòng thử lại.
Lỗi popupKhông thể tải danh sách khách. Vui lòng thử lại.
Date range vượt 365 ngày (DEC-023)Toast: Phạm vi báo cáo tối đa 1 năm. Đã điều chỉnh ngày bắt đầu thành DD/MM/YYYY. (info, auto-dismiss 5s)
Bước chu kỳ ngoài range (DEC-024)Inline error dưới input: Bước chu kỳ phải từ 1 đến 180 ngày / Bước chu kỳ phải từ 1 đến 12 tháng

B5) Xuất dữ liệu

Không áp dụng phase 1. Không hiển thị nút Tải xuống trong popup tab mới. Nếu phase sau bật export, phải có quyết định mới, action permission và QA export cases.

B6) Từ điển nội dung hiển thị

Key gợi ýText VIGhi chú
customer_cycle.visit_no_purchase_tabChu kỳ khách ghé không muaTab label
customer_cycle.visit_no_purchase_totalSố lượng khách có lượt ghé không muaCard 1
customer_cycle.visit_frequencyCơ cấu khách: đã/chưa quay lại ghéDonut
customer_cycle.return_visit_customerKH đã quay lại ghéSegment
customer_cycle.non_return_visit_customerKH chưa quay lại ghéSegment/row
customer_cycle.days_since_visitTỉ lệ KH theo thời gian chưa ghé lạiDonut
customer_cycle.visit_cycle_matrixChu kỳ khách ghéMatrix title
customer_cycle.empty_reportChưa có khách ghé không mua (chưa chuyển đổi) trong điều kiện lọc này. Vui lòng đổi thời gian hoặc chi nhánh.Empty
customer_cycle.empty_popupChưa có khách hàng trong nhóm này.Empty popup
customer_cycle.visit_source.consultantTư vấnMap source
customer_cycle.visit_source.do_serviceLàm dịch vụMap source
customer_cycle.visit_source.separator+Separator multi-source (DEC-017)
customer_cycle.matrix.same_day_rowCùng ngàyMatrix row label (rename T3 từ 0 ngày)
customer_cycle.popup.col_count_visitSố lượt ghé không mua trong kỳPopup column (rename T4)
customer_cycle.popup.col_closest_orderĐơn mua gần nhấtPopup column (rename T1)
customer_cycle.popup.no_orderChưa từng muaPopup empty value (rename T2)
customer_cycle.tab.fullChu kỳ khách ghé không muaTab label viewport ≥768px (DEC-022)
customer_cycle.tab.shortKhách ghé không muaTab label viewport <768px (DEC-022)
customer_cycle.popup.title_separatorSeparator title popup (DEC-021)
customer_cycle.filter.date_range_max_warningPhạm vi báo cáo tối đa 1 năm. Đã điều chỉnh ngày bắt đầu thành {date}.Toast warning (DEC-023)
customer_cycle.filter.duration_invalid_dayBước chu kỳ phải từ 1 đến 180 ngàyInline error by_day (DEC-024)
customer_cycle.filter.duration_invalid_monthBước chu kỳ phải từ 1 đến 12 thángInline error by_month (DEC-024)
customer_cycle.info_stripTab hiển thị khách đã ghé tư vấn / làm dịch vụ nhưng chưa phát sinh doanh số. Đã loại khách đã mua sau lượt ghé.Info strip permanent (DEC-028)
customer_cycle.card1.subtextĐã loại khách chuyển đổi sau ghéCard 1 sub-text (DEC-029)
customer_cycle.donut1.subtextTrên tổng {total} KHDonut 1 sub-text (DEC-029, runtime interpolate {total})
customer_cycle.donut2.subtextTrên tổng {total} KHDonut 2 sub-text (DEC-029)
customer_cycle.matrix.header_doc.subtextKhoảng cách trung bình giữa các lượt ghéMatrix header dọc sub-text (DEC-029)
customer_cycle.matrix.header_ngang.subtextTính tới ngày kết thúc kỳMatrix header ngang sub-text (DEC-029)
customer_cycle.matrix.row_cung_ngay.subtextNhiều lượt ghé qualified trong 1 ngàyRow Cùng ngày sub-text (DEC-029)
customer_cycle.matrix.row_chua_quay_lai.subtextChỉ có 1 lượt ghé qualified trong kỳRow KH chưa quay lại ghé sub-text (DEC-029)
customer_cycle.matrix.col_percent% trên tổngMatrix column header rename T6 (DEC-029, cũ Tỷ lệ)

B7) Đo lường sử dụng

Phase 1 không thêm event tracking. Report module hiện chưa có pattern telemetry/event logging thống nhất, nên các event dưới đây chỉ là future reference, không phải implementation contract và không có QA phase 1.

Event candidateTriggerPayload gợi ý
report_visit_no_purchase_viewedUser mở tabbranch_ids, type_cycle, duration
report_visit_no_purchase_bucket_openedUser click bucketrow_label, column_label, customer_count

Nếu sau này cần đo usage, mở decision riêng để chốt naming convention, payload chuẩn, nơi gửi event, và QA analytics cases.

B8) Quy tắc responsive và accessibility

CheckĐiều kiện đạt
Text không overlapTab label dài vẫn có outside arrows/scroll như XTabs hiện tại
Matrix nhiều bucketHorizontal scroll hoạt động, sticky header không che row
Popup focusFocus trap trong dialog, search là focus đầu tiên
Icon tooltipIcon thông tin có tooltip tiếng Việt
Empty/error copyCó hướng xử lý, không dùng copy trạng thái tiếng Anh

B9) Tooltip dictionary

Mục tiêu: user PO/BA/Marketing/CSKH hiểu cách tính và nghiệp vụ ngay khi hover, không cần mở docs.

Format mỗi tooltip ưu tiên: định nghĩa ngắn, công thức rút gọn nếu có, ví dụ ngắn nếu giúp, edge case nếu liên quan DEC.

V2.8 update (DEC-030): Tất cả 19 tooltip dưới đây là required cho Phase 1 GA — gộp 7 v2.7 required + 11 lift từ backlog + 1 new (popup Chi nhánh). Không còn phân tách "core" vs "backlog".

Required tooltip (19 items)

Field/IconTooltip TextĐiều kiện hiện
Chi nhánhLọc theo chi nhánh user có quyền. Để trống = tất cả chi nhánh được phép. Hệ thống tự loại chi nhánh ngoài quyền của user.Hover icon info trong filter
Row KH chưa quay lại ghéKhách chỉ có 1 lượt ghé qualified trong kỳ → chưa đủ dữ liệu tính chu kỳ. Khác với Cùng ngày.Hover icon info ở row label
Row Cùng ngàyKhách có nhiều lượt ghé qualified trong cùng 1 ngày; chu kỳ tính ra = 0 ngày. Không có nghĩa là 0 ngày chưa ghé lại.Hover icon info ở row label
Loại ghéLoại tương tác của khách trong lượt ghé qualified gần nhất. Có thể là Tư vấn, Làm dịch vụ, hoặc Tư vấn + Làm dịch vụ.Hover icon info trong popup
Số lượt ghé không mua trong kỳĐếm số lượt ghé qualified của khách trong kỳ filter; không tính source khác như order, payment.Hover icon info trong popup
Đơn mua gần nhấtĐơn hàng hợp lệ gần nhất của khách tính tới ngày kết thúc kỳ. Có thể là đơn cũ trước lượt ghé. Hiển thị Chưa từng mua nếu khách chưa từng có đơn hợp lệ.Hover icon info trong popup
Số ngày chưa ghé lạiNgày kết thúc kỳ trừ lượt ghé qualified gần nhất. VD kỳ kết thúc 30/04, ghé gần nhất 10/04 → 20 ngày.Hover icon info trong popup
Loại chu kỳ (filter)Cách chia bucket thời gian trong matrix. "Chu kỳ theo tháng" = duration × 30 ngày, không phải tháng dương lịch. VD chọn tháng + bước 3 → bucket 90 ngày.Hover icon info
Bước chu kỳ (filter)Số đơn vị thời gian (ngày hoặc tháng) dùng để chia bucket cột "Số ngày chưa ghé lại". VD bước 30 → bucket 1-30, 31-60, 61-90 ngày...
Range cho phép: 1-180 ngày hoặc 1-12 tháng.
Hover icon info
Thời gian báo cáo (filter)Khoảng thời gian xét lượt ghé qualified. Khách phải có ≥1 lượt ghé consultant hoặc do_service (chưa phát sinh doanh số) trong kỳ này mới được đưa vào báo cáo.
Tối đa 1 năm để bảo đảm matrix dễ đọc và performance ổn định.
Hover icon info
Số lượng khách có lượt ghé không mua (overview)Số khách duy nhất có lượt Tư vấn hoặc Làm dịch vụ chưa phát sinh doanh số, và chưa có đơn mua hợp lệ sau lượt ghé gần nhất trong kỳ lọc.
Công thức: qualified − converted
VD: Lan ghé 10/04, mua 12/04 → đã chuyển đổi → loại. Anh ghé 10/04 + 20/04, mua 15/04 (giữa 2 lượt) → giữ.
Hover icon info
Cơ cấu khách: đã/chưa quay lại ghé (overview)Tỉ lệ khách đã hình thành chu kỳ ghé so với khách chỉ ghé 1 lần.
Đã quay lại: ≥2 lượt ghé qualified trong kỳ.
Chưa quay lại: đúng 1 lượt.
Tổng = 100%.
Hover icon info
Tỉ lệ KH theo thời gian chưa ghé lại (overview)Phân bố khách theo bucket "Số ngày chưa ghé lại" = ngày kết thúc kỳ − lượt ghé gần nhất.
VD: 36% khách thuộc bucket 1-30 ngày nghĩa là 36% khách có lượt ghé gần nhất cách ngày kết thúc 1-30 ngày.
Hover icon info
Header trục dọc Chu kỳ khách ghé (matrix)Số ngày trung bình giữa các lượt ghé qualified liên tiếp của cùng khách trong kỳ.
VD: ghé 1/3, 21/3, 10/4 → gaps 20 + 20 → chu kỳ = 20 ngày → khách thuộc bucket 1-30 ngày.
Hover icon info
Header trục ngang Số ngày/tháng chưa ghé lại (matrix)Tính từ lượt ghé qualified gần nhất đến ngày kết thúc kỳ.
"Chu kỳ theo tháng" → bucket tính theo duration × 30 ngày. Bucket đầu = ≤ N tháng (0 < days ≤ N×30); kế tiếp N+1 - 2N tháng; cuối > M tháng.
Hover icon info
Row Tổng (matrix)Tổng khách trong từng bucket cột. Đã loại khách đã chuyển đổi sau ghé (DEC-014).Hover icon info
Row Tỷ lệ KH theo thời gian chưa ghé lại (matrix)% khách trong bucket cột so với tổng khách. Cùng dữ liệu với donut "Tỉ lệ KH theo thời gian chưa ghé lại".Hover icon info
Lượt ghé gần nhất (popup)Ngày của lượt ghé qualified gần nhất trong kỳ filter (Tư vấn hoặc Làm dịch vụ, chưa phát sinh doanh số).Hover icon info trong popup
Chi nhánh (popup)Chi nhánh của lượt ghé qualified gần nhất. Nếu khách có nhiều lượt ghé cùng ngày ở các chi nhánh khác nhau, hiển thị Nhiều chi nhánh.Hover icon info trong popup (NEW v2.8)

B-POST) Verification

CheckStatus
Mọi UI hiện hữu có Delta StatusĐạt
Target wireframe hiển thị vùng KEEP quanh deltaĐạt
Copy user-facing tiếng Việt tự nhiênĐạt
Không dùng copy CTA/trạng thái tiếng AnhĐạt
Export phase 1 bị ẩnĐạt
Permission/no-permission state có mô tảĐạt
Responsive/accessibility có contractĐạt
UI/PRD/Dev cùng thuật ngữ KH chưa quay lại ghéĐạt

B-PITFALLS) Anti-pattern review

PitfallĐã phòng tránh ở
Chỉ đổi label nhưng giữ purchase dataPRD FR-002, Dev C3/C5
Bỏ sót persistence tabPRD FR-001, Dev C6
Popup vẫn có exportUI B3/B5, QA TC-005
Dùng rời bỏ như churnUI B6/B9, PRD A9
Gộp Cùng ngày với KH chưa quay lại ghéPRD A10, UI B9, QA TC-004
Liệt khách đã chuyển đổi vào popup CSKHPRD FR-002 AC + DEC-014, Dev C3 SQL exclude, QA TC-010
Tab Chu kỳ khách hàng rớt persistence sau refresh do bug toPRD FR-001 AC + DEC-015, Dev C1/C6, QA TC-001
Manager bypass branch scope qua DevToolsPRD FR-002/FR-006 AC + DEC-016, Dev C8, QA TC-012
Loại ghé hiển thị thứ tự ngẫu nhiên giữa các rowUI B3/B6 + DEC-017, Dev C5/C6 normalize, QA TC-013
User nhầm 0 ngày là "0 ngày chưa ghé lại" thay vì chu kỳ 0 ngàyRename T3 thành Cùng ngày + tooltip B9 mô tả rõ
User nhầm Chưa có đơn hàng là "chưa mua trong kỳ"Rename T2 thành Chưa từng mua + tooltip popup Đơn mua gần nhất rõ scope all-time
User nhầm Số lần ghé không mua đếm cả ngoài kỳ hoặc source khácRename T4 thành Số lượt ghé không mua trong kỳ + tooltip rõ scope
User nhầm bucket by_month 3 tháng là điểm mốc thay vì rangeDEC-018 đổi label ≤ 3 tháng cho tab mới
Click cell value=0 mở popup empty vô nghĩaDEC-019 disable click; cursor default; QA TC-015
Action timeout @ 500k rowsDEC-020 benchmark gate + SQL fallback plan; QA TC-016
Tab label overflow trên mobile gây cắt chữDEC-022 responsive label; QA TC-017
User chọn date range nhiều năm → matrix không đọc nổiDEC-023 max 365 ngày + clamp + toast
User nhập bước chu kỳ extreme (9999, -1)DEC-024 FE/BE validate; QA TC-018
Popup title inconsistent giữa tab cũ/mớiDEC-021 lock format cho tab mới; tab cũ giữ
User mở tab không hiểu context, không biết "khách ghé không mua" là gìInfo strip permanent (DEC-028); QA TC-020
User hover mới biết denominator donut → mờ hồInline sub-text Trên tổng {total} KH dưới donut (DEC-029); QA TC-021
Cột bảng cuối Tỷ lệ không nói mẫu sốRename T6 → % trên tổng (DEC-029); QA TC-022
User mới không biết hover ℹ️ để xem tooltip → bỏ lỡ contextSub-text inline + tooltip ℹ️ kết hợp 3-layer (DEC-027/029/030)