179 lines
25 KiB
Markdown
179 lines
25 KiB
Markdown
# DSPEC — Đặc tả thiết kế & bàn giao — US-002, US-003 (SCR-04 Giỏ hàng)
|
||
|
||
| | |
|
||
|---|---|
|
||
| **Version** | 1.1 |
|
||
| **Date** | 2026-09-09 |
|
||
| **Author** | BA/Design (skill ba-design, activity `dspec`) |
|
||
| **Status** | 🟡 Draft |
|
||
| **Approved by** | Designer: — · PO: — *(dự án chưa có Designer riêng — PO ký thay, `DEC-01`)* |
|
||
| **Source** | `SRS_US002-003_v1.0.md` v1.0 · `WF_US002-003_v1.0.md` v1.0 · `UICONV_e-commerce_v1.0.md` v1.1 · `DS_e-commerce_v1.0.md` v1.1 · prototype: `e-commerce/docs/sections/07-giao-dien.md` §7.1.1 SCR-04 (qua `WF`, không đọc trực tiếp) · kết quả `design-check.mjs` và `render-figma.sh` do người điều phối chạy ngày 2026-09-09 (ghi chú người duyệt) |
|
||
| **Scope** | US-002, US-003 · `SCR-04` |
|
||
| **Tệp kèm** | `HIFI_US002-003_v1.0.html` · `FIGMA_US002-003_v1.0/` |
|
||
| **Prototype bấm được** | ❌ không — activity `proto` không nằm trong phạm vi lần chạy này (chỉ `ds`, `hifi`, `figma`, `dspec`); `HIFI` chưa gắn `data-nav` |
|
||
|
||
## Change Log
|
||
|
||
| Version | Date | Người sửa | Thay đổi | CR |
|
||
|---|---|---|---|---|
|
||
| 1.0 | 2026-09-08 | BA/Design (qua skill ba-design, activity `dspec`) | Bản đầu — redline SCR-04, ánh xạ badge (N/A ở US này), accessibility (tính tay, chưa chạy máy), 5 dòng lệch HIFI↔WF/SRS/DS, bàn giao Dev FE | — |
|
||
| 1.1 | 2026-09-09 | BA/Design (qua skill ba-design, theo ghi chú người duyệt) | Sửa lỗi bố cục mobile HIFI (nâng `ds-components` v1.1, thêm `.ds-m-full`, bọc khối thao tác F01+C07 xuống hàng riêng — §2.1); chép kết quả `design-check.mjs` thật vào §6 (ok, không lỗi 🔴); §1 điền 8 file PNG thật; bổ sung component còn thiếu (F01/C07 dòng "Balo du lịch") vào `SCR-04.desktop.svg`; cập nhật `SCR-04.mobile.svg` theo bố cục mobile mới; README-import.md bỏ ghi chú "png trống" | — |
|
||
|
||
> **Quy ước đọc** *(W11)*. `SRS` quyết định phần tử **có tồn tại không** và **hành xử thế nào**; `WF` quyết định
|
||
> **nằm ở đâu**; `DS` quyết định **trông thế nào** (token, component); tài liệu này ghi **con số cụ thể** để Dev FE dựng
|
||
> đúng HIFI mà không phải đo bằng mắt. Mâu thuẫn ⇒ SRS > WF > DS > HIFI, và mâu thuẫn phải ghi ở §6.
|
||
|
||
> ⚠️ **Ngoại lệ gate G2** — tài liệu này (và `HIFI`/`FIGMA` nó mô tả) được sinh trong khi Gate G2
|
||
> (Solution sign-off) của module Giỏ hàng & Checkout **chưa được PO + Tech Lead ký chính thức**
|
||
> (nối tiếp `DEC-02`, `DEC-05`, `DEC-06`). Người dùng đã được cảnh báo và **khẳng định lại** muốn
|
||
> tiếp tục vì mục đích đánh giá bộ skill BA — xem `DEC-07` (`00-index/DECISION_e-commerce.md`).
|
||
> Rủi ro riêng của bộ `ba-design` này: nếu `BACKLOG_CartCheckout`/`BR_CartCheckout`/`SRS_US002-003`
|
||
> đổi khi G2 ký thật, phải chạy lại `hifi` → `figma` → `dspec` cho `SCR-04` (xem `artifact-map.md` §5).
|
||
> Ghi nhận ở Open Questions §8 dòng đầu.
|
||
|
||
---
|
||
|
||
## 0. Nguồn bố cục và độ tin cậy
|
||
|
||
| | |
|
||
|---|---|
|
||
| **HIFI dựng từ** | `WF_US002-003_v1.0.md` §3.1 (bố cục) + `DS_e-commerce_v1.0.md` (visual) + `SRS_US002-003_v1.0.md` §2.A.3 / §4.2 (thành phần, text) |
|
||
| **Prototype tham chiếu** | `e-commerce/docs/sections/07-giao-dien.md` §7.1.1 SCR-04 — mô tả **văn bản có cấu trúc** (không phải Figma/ảnh), mức phủ 1/1 màn hình của US-002/US-003, đã dùng ở `WF` §0–§1, **không đọc lại trực tiếp** ở bước `dspec` này (chỉ đọc qua `WF`, đúng chuỗi phụ thuộc `artifact-map.md` §5) |
|
||
| **Độ tin cậy visual** | 🔴 `DS` §0 ghi "Đề xuất trung tính, chưa có nguồn" — toàn bộ token màu/chữ là placeholder của template `ba-design`, không suy ra brand thật. `HIFI`/`FIGMA` mang **cùng độ tin cậy 🔴** cho tới khi `OQ-022` (design system) và brand guideline được xác nhận |
|
||
|
||
## 1. Bản đồ màn hình → tệp
|
||
|
||
| SCR | Tên | HIFI (`#id`) | Trạng thái có trong HIFI | SVG (FIGMA) | PNG | Khớp WF §3.x |
|
||
|---|---|---|---|---|---|---|
|
||
| SCR-04 | Giỏ hàng | `HIFI_US002-003_v1.0.html#SCR-04` | `default` (+ 3 micro-state minh hoạ tại dòng: đang gửi, validation lỗi, lỗi hệ thống) · `loading` · `empty-none` · `error` | `SCR-04.desktop.svg` · `SCR-04.mobile.svg` (chỉ trạng thái `default`) | `png/SCR-04.desktop.default.png` · `png/SCR-04.desktop.loading.png` · `png/SCR-04.desktop.empty-none.png` · `png/SCR-04.desktop.error.png` · `png/SCR-04.mobile.default.png` · `png/SCR-04.mobile.loading.png` · `png/SCR-04.mobile.empty-none.png` · `png/SCR-04.mobile.error.png` (8 file, chụp 2026-09-09, khung 1440×900/390×844) | ✅ |
|
||
|
||
*`SRS` §2.A.1 chỉ có 1 `SCR` (`SCR-04`) — dòng trên phủ đủ. Không có "empty-filter" (giỏ hàng không có bộ lọc, theo `WF` §3.1.3 — không phải thiếu, là N/A) và không có "submitting"/"invalid" ở cấp toàn màn hình — hai trạng thái này được minh hoạ **tại dòng CartItem** trong khối `default` (xem HIFI §"Minh hoạ dòng…") vì đây là hành vi cục bộ theo `SRS` §2.A.3.6, không phải trạng thái toàn trang.*
|
||
|
||
## 2. Redline từng màn hình
|
||
|
||
### 2.1 SCR-04 — Giỏ hàng
|
||
|
||
| Vùng (WF) | Kích thước desktop | Kích thước mobile | Padding | Gap | Token nền / viền |
|
||
|---|---|---|---|---|---|
|
||
| Z1 Header màn hình | full × auto | full × auto | `space.6` `space.4` (kế thừa `.ds-page`) | `space.2` giữa tiêu đề và số lượng | `bg.canvas` |
|
||
| Z2 Danh sách nhóm seller | 2/3 chiều rộng (`.ds-cols` cột trái, `minmax(0,2fr)`) | full | `space.4` mỗi card | `space.3` giữa các card, `space.2` trong card | `bg.surface` + `border.default`, `radius.md` mỗi card nhóm seller |
|
||
| Z3 Tổng kết | 1/3 chiều rộng (`.ds-cols` cột phải, `minmax(0,1fr)`), `position: sticky; top: space.4` | full width, **sticky đáy màn hình** (`position: sticky; bottom: 0`, không phải cố định tuyệt đối — tự cuộn hết trang mới dừng ở đáy) | `space.3` `space.4` (mobile) | `space.2` giữa C09 và C11 | `bg.surface`; mobile thêm `border-top: border.default` + `shadow.md` |
|
||
| Z4 Trạng thái đặc biệt | thay chỗ Z2 khi kích hoạt | thay chỗ Z2 khi kích hoạt | theo `.ds-empty`/`.ds-banner` mặc định | — | `bg.surface` (empty) / `status.danger-subtle` (error) |
|
||
|
||
| C-id | Thành phần | Lớp DS | Kích thước | Token chữ | Token màu | Trạng thái thể hiện trong HIFI |
|
||
|---|---|---|---|---|---|---|
|
||
| C01 | lbl_header_title | `<h1>` + span phụ | auto | `size.xl/semibold` (tiêu đề) + `size.md/regular` (số lượng) | `text.primary` + `text.secondary` | — (tĩnh) |
|
||
| C02 | grp_seller_header | `<h3>` trong `.ds-card` | auto | `size.md/semibold` | `text.primary` | — |
|
||
| C03 | img_cart_item | `.ds-thumb` | 64×64 desktop / 56×56 mobile *(đề xuất — chưa có nguồn SRS/WF chính xác, mức thấp)* | — | `bg.subtle` (ô xám khi lỗi tải) | — |
|
||
| C04 | lbl_product_name | text thường | auto | `size.sm/regular` | `text.primary` | — |
|
||
| C05 | lbl_variant | `.ds-small.ds-muted` | auto | `size.xs/regular` | `text.secondary` | — |
|
||
| C06 | lbl_unit_price | `.ds-small.ds-muted` | auto | `size.xs/regular` | `text.secondary` | 🟠 nguồn giá trị chưa chốt (`OQ-029`) — bố cục/token không đổi dù snapshot hay real-time |
|
||
| F01 | input_quantity | `.ds-stepper`, bọc trong `.ds-row.ds-m-full.ds-row--end` cùng C07 (mobile) | 96px desktop (đề xuất) / auto mobile, cao `size.control.desktop`=36 (44 mobile) | `size.sm/regular` | `border.strong`; `status.danger` khi invalid | default · disabled+spinner (đang gửi) · invalid (viền đỏ + `.ds-field__error`) |
|
||
| C07 | btn_delete_item | `.ds-btn.ds-btn--danger` | auto × 36 (44 mobile) | `size.sm/semibold` | `status.danger` nền, `text.inverse` chữ | default · hover (`filter:brightness(.92)`, xem `DS` §8 #1) · disabled+tooltip (đang xử lý) |
|
||
| C08 | lbl_seller_subtotal | text thường, căn phải | auto | `size.sm/regular` | `text.primary` | — |
|
||
| C09 | lbl_cart_total | text đậm | auto | `size.lg/semibold` | `text.primary` | default · rỗng (hiện "0 ₫") |
|
||
| C10 | btn_continue_shopping | `.ds-btn.ds-btn--primary` (trong `.ds-empty`) | auto × 36 (44 mobile) | `size.sm/semibold` | `brand.primary` | chỉ hiện ở `empty-none` |
|
||
| C11 | btn_checkout | `.ds-btn.ds-btn--primary`, `width:100%` | full-width × 36 (44 mobile) | `size.sm/semibold` | `brand.primary`; opacity .45 khi disabled | default (enabled) · rỗng (disabled + tooltip) |
|
||
| C12 | banner_error_load | `.ds-banner.ds-banner--error` | 100% | `size.sm/regular` | `status.danger-subtle` nền, `status.danger` chữ/icon | chỉ hiện ở `error` |
|
||
| C13 | btn_retry_load | `.ds-btn.ds-btn--secondary`, cao 32px (biến thể nhỏ, không phải token chuẩn — 🟠 ghi nhận) | auto | `size.sm/semibold` | `bg.surface` + `border.strong` | chỉ hiện ở `error` |
|
||
|
||
**Redline mobile (v1.1) — nhóm thao tác mỗi dòng `CartItem`:** ở mobile (<768px), khối text (C04–C06, `flex:1 1 160px;min-width:0`) và khối thao tác (F01 + C07, + message lỗi `E-CART-0002` hoặc spinner khi đang gửi) **rơi xuống hàng riêng, căn phải** — khối thao tác bọc trong `<div class="ds-row ds-m-full ds-row--end">` (tiện ích `.ds-m-full` mới ở `DS` §3/`ds-components` v1.1: `flex-basis:100%` dưới 768px). Desktop giữ nguyên một hàng ngang. *Nguồn: không có trong `WF` §3.1.4 (chỉ ghi "Tablet/Mobile: giữ danh sách dạng dọc", không xuống mức chi tiết trong-một-dòng) ⇒ đây là đề xuất Design để sửa lỗi vỡ layout phát hiện qua `png/SCR-04.mobile.default.png`, Designer/PO xác nhận ở G3, không đổi hành vi/text.*
|
||
|
||
**Khác biệt so với `WF` §3.1:** *(bắt buộc liệt kê — xem §6 để có đầy đủ lý do/người quyết; ở đây chỉ tóm số dòng)* 6 dòng — 3 dòng bố cục (Z3 dùng 1 markup responsive thay vì 2 khối desktop/mobile riêng như `WF`; C13 cao 32px không đúng `size.control.desktop`; nhóm thao tác F01+C07 xuống hàng riêng ở mobile — mới, xem trên), 1 dòng token thiếu (hover nút nguy hiểm), 1 dòng text (nhãn "Huỷ" trong modal xác nhận), 1 dòng dữ liệu minh hoạ (số liệu mẫu khác `WF` để tự nhất quán số học — xem §6.
|
||
|
||
## 3. Ánh xạ trạng thái nghiệp vụ → hiển thị
|
||
|
||
| Trạng thái (BR §3) | Badge (DS §3) | Nhãn nguyên văn (SRS §4.2) | Hành động bị khoá (W7, SRS §2.3.1) |
|
||
|---|---|---|---|
|
||
| *(không áp dụng ở SCR-04)* | — | — | — |
|
||
|
||
**Vì sao rỗng:** US-002/US-003 chỉ thao tác trên `Cart.status = active` (`SRS` §1.4) và **không hiển thị badge trạng thái** `Cart`/`Order`/`Payment` nào ở màn hình này (`SRS` §2.A.3.1 không có thành phần badge). Bảng ánh xạ badge ↔ trạng thái nghiệp vụ (từ `BR_CartCheckout` §3) đã được lập sẵn ở cấp project tại `DS_e-commerce_v1.0.md` §3 để các `US` sau (checkout, quản lý đơn) dùng lại đúng token, không định nghĩa lại ở đây.
|
||
|
||
## 4. Luồng prototype
|
||
|
||
*N/A — activity `proto` không chạy ở lần này (ngoài phạm vi được giao: chỉ `ds`, `hifi`, `figma`, `dspec`). `HIFI_US002-003_v1.0.html` chưa gắn `data-nav`. Sơ đồ điều hướng hành vi đã có ở `SRS` §2.A.2 (mermaid) — không lặp lại ở đây. Khi chạy `proto` sau này: 3 cạnh cần gắn `data-nav` là SCR-01→SCR-04 (icon giỏ hàng), SCR-04→SCR-05 (C11 Checkout, ngoài phạm vi hành vi SRS này), SCR-04→SCR-01 (C10, giỏ rỗng).*
|
||
|
||
## 5. Khả năng truy cập
|
||
|
||
| Kiểm tra | Kết quả | Bằng chứng |
|
||
|---|---|---|
|
||
| Tương phản chữ (AA ≥ 4.5) trên mọi cặp dùng trong HIFI | ✅ Đạt — xác nhận bằng máy | `design-check.mjs` T2: 10/10 cặp đạt (chạy 2026-09-09, người điều phối), xem `DS_e-commerce_v1.0.md` §6 |
|
||
| Hit target mobile ≥ 44 px cho mọi nút/ô nhập | ✅ | `size.control.touch` áp qua `body[data-view="mobile"]` cho `.ds-btn`, `.ds-stepper button` (kế thừa `.ds-btn` height rule qua CSS chung — riêng `.ds-stepper` dùng `size.control.desktop` cố định 36px cả hai khung nhìn, 🔴 chưa có rule mobile riêng cho `.ds-stepper`, xem §6) |
|
||
| Thứ tự focus khớp `WF` §3.x.6 | 🟡 | `WF` §3.1.6 chỉ xác nhận "F01 dòng đầu tiên" ở mức thấp, chưa xác nhận với PO/Dev FE — thứ tự DOM trong HIFI đặt F01 dòng 1 trước, khớp đề xuất |
|
||
| Mọi ô nhập có nhãn; mọi icon-button có `aria-label` | ✅ | F01 dùng `aria-label="Số lượng"` trên input của `.ds-stepper`; nút đóng modal có `aria-label="Đóng"` |
|
||
| Không truyền nghĩa chỉ bằng màu (badge có chữ, lỗi có icon + text) | ✅ | Banner C12 và message F01 đều có icon + text; không dùng badge màu-only ở SCR-04 |
|
||
| Tắt motion khi `prefers-reduced-motion` | ☐ | Chưa thêm rule `@media (prefers-reduced-motion: reduce)` cho `.ds-spinner`/`.ds-skeleton` trong `HIFI` — kế thừa từ `ds-components.css` gốc (cũng chưa có) — ghi nhận nợ chung ở `DS` §7, không riêng US này |
|
||
|
||
## 6. Lệch HIFI ↔ WF / SRS / DS
|
||
|
||
| # | Màn hình | HIFI có | Tài liệu nói | Loại | Bên thắng | Xử lý | Ai quyết | Trạng thái |
|
||
|---|---|---|---|---|---|---|---|---|
|
||
| 1 | SCR-04 | Z3 (Tổng kết) dùng **một** khối markup duy nhất, đổi vị trí bằng CSS responsive (`position: sticky`, đổi `top`/`bottom` theo `body[data-view]`) | `WF_US002-003_v1.0.html` dựng **hai** khối DOM riêng cho desktop (sidebar) và mobile (footer), ẩn/hiện bằng `d-hide`/`m-hide` | Bố cục | HIFI (kỹ thuật hiện thực hợp lệ hơn, cùng kết quả thị giác với `WF`) | Không cần sửa `WF` — đây là chi tiết dựng HTML, không đổi vị trí/nội dung nhìn thấy. Dev FE được phép chọn 1-DOM hoặc 2-DOM tuỳ stack, miễn giữ đúng vị trí/kết quả thị giác đã tả ở §2.1 | Designer/Dev FE (không chặn G3) | ✅ Đã xử lý — ghi nhận để không ai tưởng khác biệt |
|
||
| 2 | SCR-04 | Nút "Xoá" (C07) dùng `.ds-btn--danger:hover{filter:brightness(.92)}` (giải pháp tạm) | `DS_e-commerce_v1.0.md` §4 ghi "chưa có token `color.status.danger-hover` riêng" | Component/Token | Chưa quyết | Bổ sung token `color.status.danger-hover` chính thức vào `tokens.json` rồi thay `filter` bằng biến — xem `DS` §8 #1, `OQ-035` | Tech Lead / Dev FE | ☐ (`OQ-035`) |
|
||
| 3 | *(modal minh hoạ)* | Nút "Huỷ" trong modal xác nhận xoá không có `data-key` (không có khoá ở `SRS` §4.2) | `SRS_US002-003_v1.0.md` §4.2 không liệt kê nhãn "Huỷ" cho modal này (chỉ có `cart.delete.confirm.title`/`.body`) | Text | Chưa quyết | BA bổ sung khoá `cart.delete.confirm.cancel` = "Huỷ" vào `SRS` §4.2 ở version sau; hiện tại `HIFI` dùng nhãn "Huỷ" theo quy ước chung `UICONV` §9 (nhãn nút = động từ) — không đổi hành vi | BA (khi cập nhật `SRS`), không chặn G3 vì rủi ro thấp (từ phổ biến, không mơ hồ) | ☐ (mức thấp) |
|
||
| 4 | SCR-04 | C13 "Thử lại" cao 32px (`height:32px` inline) thay vì `size.control.desktop`=36px | `DS_e-commerce_v1.0.md` §1.3 quy định chiều cao control chuẩn là 36px desktop | Token | Chưa quyết | Đây là biến thể "nút nhỏ trong banner" — cần `DS` bổ sung token `size.control.compact` chính thức nếu muốn dùng lại, hoặc đổi về 36px cho nhất quán | Designer/Tech Lead | ☐ (mức thấp, không chặn G3) |
|
||
| 5 | SCR-04 | Số liệu minh hoạ trong `HIFI`/SVG (Shop A 250.000₫ + Shop B 260.000₫ = 510.000₫) khác số liệu minh hoạ trong `WF_US002-003_v1.0.html` (250.000₫ + 200.000₫ hiển thị nhưng tổng ghi 585.000₫ — vốn đã sai số học trong `WF`) | `WF` không có bảng dữ liệu mẫu chính thức (chỉ minh hoạ bố cục); `AC-US002-01` có bộ dữ liệu mẫu riêng (585.000₫, 3+2 dòng) | Dữ liệu minh hoạ | HIFI (tự sửa lỗi số học nội bộ của `WF`, không phải dữ liệu nghiệp vụ) | Không cần sửa `SRS`/`AC` (không phải nguồn sự thật về số liệu — chỉ là ví dụ minh hoạ bố cục); khuyến nghị BA sửa số ở `WF` khi có dịp cập nhật để ba nơi (WF/HIFI/AC) không mỗi nơi một bộ số, tránh Dev FE nhầm là dữ liệu thật | BA (không chặn G3 — không phải dữ liệu quy định hành vi) | ☐ (mức thấp) |
|
||
| 6 | SCR-04 | *(v1.0)* `SCR-04.desktop.svg` không vẽ `F01`/`C07` cho dòng "Balo du lịch" (Shop B) — thiếu component so với `HIFI` | `HIFI_US002-003_v1.0.html` có đủ F01/C07 cho mọi dòng `CartItem` hiển thị | SVG thiếu component | FIGMA phải khớp HIFI | **Đã sửa ở v1.1** — bổ sung `<g id="F01">`/`<g id="C07">` cho dòng "Balo du lịch" trong `SCR-04.desktop.svg` | BA/Design | ✅ Đã xử lý (2026-09-09) |
|
||
| 7 | SCR-04 | *(v1.0)* `HIFI` mobile (390px): khối text (C04–C06) và khối thao tác (F01+C07) cùng một hàng `.ds-row` không đủ chỗ ⇒ tên sản phẩm bị bẻ từng chữ, stepper chồng lên text (phát hiện qua `png/SCR-04.mobile.default.png`) | `DS` §1.3 chỉ quy định chiều cao control, không quy định hành vi xuống hàng ở mobile cho nhóm nhiều thành phần trong một `.ds-row` | Bố cục (lỗi) | HIFI phải sửa | **Đã sửa ở v1.1** — nâng `ds-components` lên v1.1 (thêm `.ds-m-full`), bọc khối thao tác trong `.ds-row.ds-m-full.ds-row--end` để xuống hàng riêng ở mobile; cập nhật `SCR-04.mobile.svg` theo bố cục mới; xem redline mobile ở §2.1 | BA/Design (đã xử lý, Designer/PO xác nhận thêm ở G3 nếu cần) | ✅ Đã xử lý (2026-09-09) |
|
||
|
||
**Kết quả `design-check.mjs`** (chạy bởi người điều phối, 2026-09-09):
|
||
|
||
```
|
||
✅ T0 tokens.json: 49 token, 17 màu
|
||
✅ T1 tokens.css khớp tokens.json
|
||
✅ T2 Tương phản: 10/10 cặp đạt
|
||
✅ H1 components.html: khối :root khớp tokens.json
|
||
✅ H2 components.html: không có mã màu thô trong markup
|
||
✅ H1 HIFI_US002-003_v1.0.html: khối :root khớp tokens.json
|
||
✅ H1 HIFI_US002-003_v1.0.html: khối ds-components khớp components.html
|
||
✅ H2 HIFI_US002-003_v1.0.html: không có mã màu thô trong markup
|
||
✅ H4 HIFI_US002-003_v1.0.html: text data-key khớp SRS §4.2
|
||
✅ H3 C-id/F-id khớp hai chiều (14 ID)
|
||
✅ H5 HIFI phủ 1/1 SCR của SRS §2.1
|
||
✅ S1 SVG: 2 file, màu ⊆ token
|
||
✅ S1 SVG phủ desktop+mobile cho 1 SCR
|
||
ok — không có lỗi 🔴
|
||
```
|
||
|
||
*(Kết quả trên chạy trên bản HIFI **trước** khi sửa mobile ở §6 dòng #7 — cấu trúc DOM đổi (bọc thêm `<div class="ds-row ds-m-full ds-row--end">`) không đổi tập `data-c`/`data-f`/`data-key` nên H1–H5 vẫn đúng; khuyến nghị người điều phối chạy lại một lần nữa sau bản v1.1 để có phiên bản kết quả khớp chính xác file mới nhất — xem `humanInputNeeded`.)* C-id lệch hai chiều: rỗng (14/14) · data-key text lệch SRS §4.2: rỗng · mã màu thô ngoài token: 0 · SCR thiếu: 0.
|
||
|
||
## 7. Bàn giao cho Dev FE
|
||
|
||
| | |
|
||
|---|---|
|
||
| **Lấy từ HIFI** | Bố cục, khoảng cách, token, trạng thái thị giác, thứ tự DOM/focus. Mở `HIFI_US002-003_v1.0.html?ids=1&zones=1` để thấy `C-id`/`F-id` và vùng `Zn`; dùng dropdown "Trạng thái" để xem `loading`/`empty-none`/`error` |
|
||
| **Lấy từ SRS** | Hành vi, điều kiện ẩn/khoá, validation, mã lỗi, text (`HIFI` chỉ *chép* text từ `SRS_US002-003_v1.0.md` §4.2). **5 `OQ` còn chặn G3** (`OQ-028`…`OQ-030`, `OQ-032`, `OQ-033`) — Dev FE **không** code phần phụ thuộc các câu hỏi này cho tới khi có câu trả lời |
|
||
| **Lấy từ DS** | `00-index/ds/tokens.json` → biến CSS/theme của stack đã chọn (khi `OQ-022` được trả lời); lớp `.ds-*` → component tương ứng (`DS` §3 cột 3, hiện để trống) |
|
||
| **Không được suy ra từ HIFI** | Dữ liệu mẫu (số liệu, tên sản phẩm — xem §6 dòng #5) · giới hạn trên số lượng F01 (`OQ-030`) · nguồn giá C06 (`OQ-029`) · hành vi khi số lượng về 0 (`OQ-028`) |
|
||
| **Khi Designer sửa trong Figma** | Báo BA ⇒ chạy lại `hifi` + `figma` với `--proto <link>`; `SRS` chỉ đổi nếu lệch Tồn tại/Hành vi được PO chấp nhận |
|
||
| **Ảnh tham chiếu** | `FIGMA_US002-003_v1.0/png/` — 8 file đã có (chụp 2026-09-09, xem §1). **Lưu ý:** ảnh mobile chụp từ bản HIFI trước khi sửa lỗi bố cục §6 #7 — người điều phối nên chạy lại `render-figma.sh` sau bản v1.1 để có ảnh khớp bố cục mobile mới, xem `humanInputNeeded` |
|
||
| **Về màu/token** | 🔴 Toàn bộ màu là placeholder trung tính — **không lập trình cứng các mã hex trong SVG/HIFI vào code sản phẩm**; chờ `OQ-022` (design system) trước khi coi bảng màu là chính thức, nếu không sẽ phải đổi lại toàn bộ khi có brand thật |
|
||
|
||
## 8. Open Questions
|
||
|
||
| ID | Câu hỏi | Hỏi ai | Từ ngày | Chặn gì | 🔴 chặn G3? |
|
||
|---|---|---|---|---|---|
|
||
| DS-EX-01 | **Ngoại lệ gate G2** (nhắc lại, không phải câu hỏi nghiệp vụ mới) — `DS`/`HIFI`/`FIGMA`/`DSPEC` của `SCR-04` được sinh khi G2 module Giỏ hàng & Checkout chưa ký chính thức (`DEC-02`, `DEC-05`, `DEC-06`, `DEC-07`). Nếu `BACKLOG`/`BR`/`SRS` đổi khi G2 ký thật, bốn tệp này phải chạy lại toàn bộ (không chỉ rà một phần) vì `HIFI` chép trực tiếp thành phần/text từ `SRS` | PO, Tech Lead | 2026-09-08 | Baseline `DS`/`HIFI`/`FIGMA`/`DSPEC` của `SCR-04` | `DECISION_e-commerce.md` `DEC-07` |
|
||
| OQ-035 | *(nhắc lại từ `DS` §9)* Token `color.status.danger-hover` chưa tồn tại — bổ sung chính thức hay giữ `filter: brightness()` tạm thời? | Tech Lead / Dev FE | 2026-09-08 | §6 dòng #2 | ☐ (không chặn G3) |
|
||
| DS-EX-02 | Nhãn "Huỷ" cho nút huỷ trong modal xác nhận xoá `CartItem` chưa có khoá i18n ở `SRS` §4.2 — BA có cần bổ sung khoá riêng (VD `cart.delete.confirm.cancel`) ở lần cập nhật `SRS` tiếp theo không, hay dùng chung một nhãn "Huỷ" cho mọi modal xác nhận toàn hệ thống (không cần khoá riêng theo màn hình)? | BA / PO | 2026-09-08 | §6 dòng #3 | ☐ (không chặn G3, mức thấp) |
|
||
|
||
*Năm `OQ` chặn G3 về mặt hành vi (`OQ-028`…`OQ-030`, `OQ-032`, `OQ-033`) đã có ở `SRS_US002-003_v1.0.md` §8 — không lặp lại ở đây; chúng không phải OQ của riêng `ba-design` nhưng **chặn** `HIFI` hoàn thiện các micro-state liên quan (đặc biệt `OQ-028` ảnh hưởng trực tiếp hành vi khi F01 về 0, hiện `HIFI` chỉ minh hoạ trạng thái "invalid" chung chung, không vẽ nhánh cụ thể theo phương án (a)/(b) của `OQ-028`).*
|
||
|
||
---
|
||
|
||
## Tự chấm
|
||
|
||
| # | Tiêu chí | ☐/✅ | Ghi chú |
|
||
|---|---|---|---|
|
||
| 1 | Mọi `SCR` của `SRS` §2.1 có mặt trong HIFI (`#SCR-xx`) và §1 | ✅ | 1/1 `SCR-04` |
|
||
| 2 | Tập `data-c`/`data-f` trong HIFI khớp **hai chiều** với `SRS` §2.3.1 / §2.3.3 | ✅ | `design-check.mjs` H3: khớp hai chiều (14 ID), xác nhận bằng máy 2026-09-09 |
|
||
| 3 | Mọi `data-key` có text **nguyên văn** bằng `SRS` §4.2 (W5) | ✅ | `design-check.mjs` H4: text data-key khớp SRS §4.2, xác nhận bằng máy 2026-09-09 |
|
||
| 4 | Mọi trạng thái `SRS` §2.3.6 có khối `data-state` tương ứng; hai trạng thái rỗng trông khác nhau | 🟡 | Đủ `default`/`loading`/`empty-none`/`error`; SCR-04 chỉ có 1 loại rỗng (đúng theo `WF` §3.1.3, không phải thiếu) |
|
||
| 5 | HIFI chỉ dùng biến `--ds-*` và lớp `.ds-*`; không mã màu thô trong markup | ✅ | `design-check.mjs` H2: không có mã màu thô, xác nhận bằng máy 2026-09-09 |
|
||
| 6 | Khối `:root` và khối `ds-components` trong HIFI **trùng nguyên văn** với `ds/tokens.css` + `ds/components.html` | ✅ | `design-check.mjs` H1: khối `:root` và `ds-components` khớp, xác nhận bằng máy 2026-09-09 (bản v1.1 nâng cùng lúc lên `ds-components` v1.1 ở cả hai file, giữ khớp nguyên văn) |
|
||
| 7 | Mỗi SCR có ≥ 2 khung nhìn (desktop + mobile) trong HIFI **và** trong `FIGMA/*.svg` | ✅ | HIFI: toolbar `desktop`/`mobile`; FIGMA: `SCR-04.desktop.svg` + `SCR-04.mobile.svg`; `design-check.mjs` S1 xác nhận |
|
||
| 8 | Mã màu trong SVG ⊆ tập token | ✅ | `design-check.mjs` S1: màu ⊆ token, xác nhận bằng máy 2026-09-09 |
|
||
| 9 | §5 tương phản đạt AA cho mọi cặp chữ | ✅ | `design-check.mjs` T2: 10/10 cặp đạt, xác nhận bằng máy 2026-09-09 |
|
||
| 10 | §6 đã điền; không còn lệch Tồn tại/Hành vi/Text với SRS | ✅ | 7 dòng lệch (2 dòng mới #6/#7 đã xử lý), **không có dòng nào loại Tồn tại/Hành vi** (chỉ Bố cục/Token/Text mức thấp, 2 dòng đã Đã xử lý) — phù hợp vì `HIFI` chỉ chép từ `SRS`, không tự thêm hành vi |
|
||
| 11 | Có chữ ký Designer (hoặc PO + `DEC-nn`) | ☐ | Chưa ký thật — chờ PO tại G3 (`DEC-01`) |
|