Files
solution-erp/.claude/agent-memory/frontend-designer/MEMORY.md
pqhuy1987 fe28ca3993 [CLAUDE] Docs: S65 session-end closeout — HRM go-live + Hồ sơ NS master-detail + Department hierarchy + PE Link hồ sơ (6 deploy #289→#295)
Closeout S65 (~6 deploy prod-verified, anh + anh Kiệt FDC UAT realtime):
- STATUS/HANDOFF S65 (Mig 52 · 88 bảng · 263 test · 65 gotcha · menu 53 · bundle admin BDwV5d0X / user DbVv6rsf Run #295) + session log #289→#295.
- gotcha #65 (build csproj con ≠ dotnet build slnx gồm tests → CS7036 Run #291 FAIL-gated; fix +trailing-optional sweep).
- CLAUDE.md root Mig 50→52 + PE row +Mig 52.
- Harvest: H2 GATE 2-MISS closed — 2 on-behalf record (PE-Workflow FE + reviewer empty-return #53) → impl-frontend + reviewer agent-memory. H1 tooling CLEAN (roster/skill/plugin 11/6/18).
- Memory (user-global): +feedback_workflow_fanout_reliability.
Carry-P1: cicd-monitor L1 82KB curate-L2 · mirror Employee page→fe-admin · test-after (HoSoLink/ParentId/HRM-perm).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 11:56:03 +07:00

45 lines
14 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# frontend-designer — MEMORY (L1 HOT)
> 8th sub-agent (S47, 2026-06-02). Role: FE **design/UX/aesthetic** cho 2 app SOLUTION_ERP. Floor FD1FD10 (AI_INFRA canonical, KHÔNG hạ). Forked `frontend-designer.agent.template.md`.
## Role + boundary
- **MINE:** FE design/UX/redesign — `fe-admin/src/**` + `fe-user/src/**` styling/component/page/design-system/a11y/responsive/micro-interaction. Design-by-code (React/Tailwind/shadcn), KHÔNG Figma.
- **NOT MINE:** BE/DB/business-logic (implementer-backend) · cookie-cutter mechanical mirror theo spec (implementer-frontend — **KHÔNG double-touch cùng file UI**) · test (test-specialist).
- **store_memory GỠ** (broadcast 2026-06-02) → ghi finding/token/component vào FILE NÀY; em main + re-index đưa vào RAG.
## SE design-system (FD1 — DÙNG, KHÔNG reinvent) — VERIFIED S47
- Brand primary **`#1F7DC1`** · font **Be Vietnam Pro** (Vietnamese diacritics) · Tailwind tokens · ERP shell (TopBar + Bell + UserMenu).
- ⚠️ **Token source = Tailwind v4 CSS-first** (NO `tailwind.config.js` file — template path stale). Tokens live in `fe-user/src/index.css` `@theme{}` block (mirror `fe-admin/src/index.css`). Read TRƯỚC khi build.
- Brand scale `--color-brand-50..900`; **`--color-brand-600 = #1f7dc1`** (exact logo). Accent red `--color-accent-500/600` (from ® mark). Be Vietnam Pro + JetBrains Mono via Google Fonts `@import` in index.css. body 14px / lh 1.55 / letter-spacing -0.003em.
- UI primitives are **hand-rolled cva** (NOT vanilla shadcn copy): `fe-user/src/components/ui/{Button,Input,Label}.tsx`. Button variants primary/secondary/outline/ghost/danger × sm/md/lg; focus-visible ring brand-500 + disabled:opacity-50 already wired. Input has focus-visible border-brand-500 + ring. REUSE these, don't reinvent.
- Stack: React 19 + Vite 8 + TS 6 + TanStack Query + lucide-react + sonner. Node v22 local (engines `>=20`).
- UI 100% tiếng Việt · Named export (trừ App) · TS6 `const X = {...} as const` thay enum · PageHeader chỉ {title, description, actions} · Duplicate 2 app CÓ CHỦ ĐÍCH (§3.9).
## FD2 visual-verification rig (SE-specific) — ✅ VERIFIED RAN end-to-end S47
- Dev: `cd fe-admin && npm run dev` → :8082 (proxy /api→:5443) · `cd fe-user && npm run dev` → :8080.
- Auth: ERP behind login — token localStorage `solution-erp-admin-token` / `solution-erp-user-token`. Authed page screenshot cần API+SQL chạy + login fixture (seed JWT). Public `/login` chụp trực tiếp.
- **PROVEN rig** (`webapp-testing` skill = Python Playwright, NOT npm @playwright/test):
- Bash tool is **POSIX bash** despite env "PowerShell" note → use `cd "abs/path"` (NO `cd /d`). Forward-slash Windows paths work.
- Chromium for Testing already installed (`C:\Users\pqhuy\AppData\Local\ms-playwright\chromium-1223`). Python 3.11 + `playwright` binding present & drives headless OK. NO install needed.
- Run pattern: `python <skill>/scripts/with_server.py --server "npm run dev" --port 8080 --timeout 90 -- python my_shot.py` (helper starts/stops dev). Write my_shot.py in fe-user dir, **delete after** (throwaway, not app code).
- Screenshot: `browser.new_page(viewport={w,h}, device_scale_factor=2)``page.screenshot(full_page=True)`**Read PNG** to NHÌN.
- 🪲 **2 Vite-dev gotchas (cost me 2 failed runs):** (1) `wait_until="networkidle"` NEVER fires — Vite HMR websocket stays open → use `domcontentloaded` + `wait_for_selector("form")`. (2) FIRST goto after cold server triggers Vite dep-optimize compile (>15s) → add a **warm-up goto with 60s timeout** before the viewport loop, else first viewport times out.
- 🪲 (3) **Authed-page (Dashboard…) S55 BLOCKER:** `dotnet run` API binds **HTTPS :5443** + HTTP :5444 (Program.cs overrides `ASPNETCORE_URLS`), nhưng `vite.config.ts` proxy target = `http://localhost:5443` → protocol mismatch → /api login fail → kẹt /login. ĐỂ chụp authed: temp-set proxy `https://localhost:5443` (`secure:false` sẵn) + restart Vite + **REVERT sau**; HOẶC run API HTTP-only. + Dashboard = ProtectedRoute (cần JWT) → Playwright login THẬT (fill `admin@solutions.com.vn`/`Admin@123456` + submit + wait url≠/login). S55 rig này chặn cả designer + em main → **đáng tin nhất = deploy prod rồi login thật xem authed pages** (đừng vật lộn dev-rig cho authed screenshot).
- Fallback khi stack chưa chạy: static component preview / screenshot `/login`**KHÔNG bỏ soi** (FD2 cấm ship-unseen).
## Component inventory (built/verified — chống reinvent)
- `fe-user/src/pages/LoginPage.tsx` — login (public, no auth). Layout: gradient bg + 2 blur blobs + centered `max-w-md` card (bg-white/90 backdrop-blur) → logo / brand eyebrow / subtitle / Email+Mật khẩu / full-width Đăng nhập. Uses ui/{Button,Input,Label}. Solid baseline; nearly identical in fe-admin (mirror candidate).
- `fe-user/src/pages/hrm/EmployeesListPage.tsx`**2-panel master-detail HRM (S66 refine, was 3-panel S65)**: shell `lg:grid-cols-[22rem_1fr] xl:grid-cols-[24rem_1fr]`. **CỘT TRÁI** = `<div flex flex-col gap-4>` chứa Org-tree (TRÊN, `lg:max-h-[44%] lg:shrink-0`, cuộn riêng) + List+filter (DƯỚI, `flex-1`, cuộn riêng). **CỘT PHẢI** = Detail 5-tab (flex-1, rộng). <lg 1-col (treelistdetail) + mobile tree-toggle `treeOpenMobile` (tree `hidden``flex`). Org tree = recursive `TreeNode` consume `GET /api/departments/tree` (DepartmentTreeNode {id,code,name,parentId,directEmployeeCount,totalEmployeeCount,children}); gốc "SOLUTION COMPANY" (`companyOpen`) `pickDept(null)`=all; `CountBadge` (totalEmployeeCount, active=brand-600 fill) `deptId` URL param. Detail = avatar header (`.app-gradient-brand` + initials-in-rounded-2xl) + 5-tab nav (Tổng quan/Thân nhân/Trình độ/Kinh nghiệm/Hợp đồng) count pills + brand underline. **Accent system (S66 việc 2+3):** `type Accent='brand'|'teal'|'violet'|'amberx'|'greenx'` + `ACCENT` map (chipBg/chipFg/head/rail/labelText). `Card` nhận `accent` prop `.icon-chip` tinted (`--chip-bg`/`--chip-fg` inline) + heading `text-{x}-700` + left rail pseudo `before:content-[''] before:w-1 before:bg-{x}-500` (clip qua overflow-hidden). `Field` label = `text-{x}-700` uppercase semibold (was slate-400), value = `font-medium text-slate-900` (was slate-800). OverviewTab: 1 accent/card (Thông tin chung=brand, Sức khoẻ/Lương=greenx, Liên hệ/Ngân hàng=teal, Giấy tờ/Đoàn thể=violet, Công việc=amberx). Tab-body sections: family=violet, đào tạo=teal, kỹ năng=greenx, công tác=amberx, hợp đồng=brand. **accent palettes chỉ có stop 50/100/500/600/700 — KHÔNG -800** head dùng -700 (else Tailwind v4 silent no-class). Reusable: `Avatar`(hash 5 gradients + dim), `CountBadge`, `Card`(+accent), `Field`(+accent/mono/icon/full). **ALL 5 satellite CRUD + 15 satellite api endpoint (+ top-level del + 3 reads) + 3 query keys preserved verbatim** (grep+tsc verified, layout/style-only). fe-admin NOT mirrored (separate pass).
## Anti-slop catches + rubric verdicts
- **LoginPage (S47): rubric PASS.** Anti-generic (brand #1F7DC1 NOT default-blue, no emoji, lucide-ready, purposeful palette). Fix applied: subtitle "Đăng nhập để tiếp tục" `text-slate-500``text-slate-600` (borderline ~4.6:1 over translucent card solid ~7.5:1, FD5 contrast floor). 1-line, no layout shift, on-scale (FD1). Screenshots: `/tmp/fd2-login-shots/login-{before,after}-{mobile-375,desktop-1440}.png`.
- **fe-admin parity follow-up:** same subtitle likely `text-slate-500` in fe-admin LoginPage apply same bump next fe-admin touch (did NOT touch fe-admin this run; scope-disciplined).
- Minor noted (NOT fixed, out of bounded scope): 2 `blur-3xl` blobs barely visible at 1440 = render cost ~0 payoff; eyebrow `tracking-[0.2em]` heavy. Candidates if login redesign requested.
## Activity log
- **S66 (2026-06-16) HRM Hồ Nhân sự fe-user REFINE từ eoffice LIVE (3 việc) layout 3-cột2-cột + màu detail:** anh góp ý sau khi xem prod. **Việc 1 (layout):** 3-cột-ngang `[tree 244 | list 352 | detail 1fr]` **2-cột** `lg:grid-cols-[22rem_1fr] xl:[24rem_1fr]`: CỘT TRÁI = `<div flex flex-col gap-4>` ôm tree (TRÊN, `lg:max-h-[44%] lg:shrink-0`, overflow-auto) + list+filter (DƯỚI, `flex-1`, overflow-auto) mỗi panel cuộn độc lập; CỘT PHẢI = detail (flex-1, rộng hơn nhiều, đỡ chật). <lg vẫn 1-col treelistdetail + giữ nguyên `treeOpenMobile` toggle. **Việc 2+3 (màu detail):** thêm `ACCENT` map 5 tone (brand/teal/violet/amberx/greenx) `Card` prop `accent` icon-chip nền nhạt (`--chip-bg/--chip-fg`) + heading `text-{x}-700` + rail trái pseudo-element; `Field` label uppercase `text-{x}-700` semibold (was slate-400 đơn điệu) + value `font-medium text-slate-900`; mỗi card/section gán 1 accent màu nhưng tinh tế, brand #1F7DC1 + Be Vietnam Pro + avatar gradient brand GIỮ. **Strategy chống truncation #53 = ONE atomic `Write` cả file** (1556 LOC) emit change-list + build status SỚM. **2 self-caught bug TRƯỚC build:** (1) `text-{teal,violet,greenx}-800` accent palettes KHÔNG stop -800 (chỉ 50/100/500/600/700) Tailwind v4 silent no-class đổi head sang -700 (all AA on white); (2) rail pseudo thiếu `before:content-['']` ::before không render box thêm. `npm run build` (tsc -b strict + vite v8) **PASS 0 TS err, 495ms** (warning @import-order + chunk-size = pre-existing, không phải mình). **5 satellite CRUD + 15 satellite api endpoint + top-level del + 3 reads + 3 query keys (employees-list/employee-detail/departments-tree-hrm) + cây SOLUTION COMPANY + 5 tab + search/filter preserved VERBATIM** (grep: 15 satellite api.post/put/delete + 3 queryKey + 5 form fns; tsc type-checks mọi payload shape = wiring bất biến). FD2 authed-screenshot SKIPPED per task instruction + gotcha #3 (rig chặn authed ProtectedRoute; anh xem qua deploy) structural verify thay thế. fe-admin + BE NOT touched, no commit (em main commits). Tag [s66, hrm-2col-refine, eoffice-ref, accent-system, atomic-write-antitrunc, crud-preserved, build-pass, tailwind-v4-stop-gotcha].
- **S65 (2026-06-16) HRM Hồ Nhân sự fe-user 3-panel master-detail NamGroup-ref:** RESTRUCTURE `EmployeesListPage.tsx` (1201→~1140 LOC) 6 `<details>` [Org tree | List | Detail 5-tab]. **Strategy chống truncation #53 = ONE atomic `Write` (cả file)** thay piecemeal Edit (atomic Write either fully-lands or errors, KHÔNG half-break) emit change-list TRƯỚC build DID BOTH Part A (avatar header+5 tab+sectiontab redistribution) + Part B (org tree panel) trong 1 pass, không phải defer B. Org tree consume `/departments/tree` verified BE-side (DepartmentFeatures.cs DepartmentTreeNodeDto, controller `[HttpGet("tree")]`, class-Authorize only). Foundation màu mới DÙNG: `.app-gradient-brand` header / `.icon-chip` / accent palette teal/violet/amberx/greenx (avatar tones) brand #1F7DC1 + Be Vietnam Pro KEPT. **5 satellite CRUD + 16 api endpoint + query keys preserved VERBATIM** (grep-verified: 16 api.post/put/delete identical payload shape, 5 form fns intact). `npm run build` (tsc -b strict + vite) **PASS 0 TS err, 6.13s**. 1 self-caught bug: typo garbage token `网络Placeholder` trong lucide import (mojibake autocomplete) removed, all 21 icons valid (node-checked). FD2 authed-screenshot SKIPPED per explicit task instruction + gotcha #3 (rig blocks authed; anh xem qua deploy) did static structural verify instead (grep endpoint/key preservation). fe-admin NOT touched (mirror = separate pass), no commit. Tag [s65, hrm-3panel, namgroup-ref, atomic-write-antitrunc, crud-preserved, build-pass].
- **S58 (2026-06-11) fe-user redesign theo UI/UX guide AI_INFRA canonical KEEP brand [em main proxy truncated #53 giữa FD2 screenshot, 2nd consecutive]:** Mirror design-system fe-admin S55 14 file fe-user (index.css heading-ladder+.label-eyebrow / 6 ui primitives Button gần SHA-identical fe-admin chỉ khác comment / 6 shell DataTable+RowActions-additive·Layout-brand-left-rail·TopBar·PageHeader·PhaseBadge-ring·EmptyState / LoginPage polish). Rubric mới = guide 13 mục `D:\Dropbox\CONG_VIEC\AI_INFRA\docs\reference\ui-ux-design-guide.md` (density 14px/h32-34/radius-8/thead-sticky/action-luôn-hiện/no-font-bold). BRAND KEPT: #1F7DC1 + Be Vietnam Pro + slate (guide cho plug hue riêng). Chết NGAY TRƯỚC with_server.py screenshot /login em main recover: build ×2 PASS 0 TS + diff-review key-stability từng file + ship `e959f72`; authed visual qua deploy prod (rig-gotcha #3 standing). LESSON: 2 lần liên tiếp truncate CÙNG điểm (sau khi sửa xong, lúc bắt đầu FD2 rig) lần sau EMIT file-list verdict TRƯỚC khi vào screenshot loop. Tag [s58, fe-user-redesign, guide-aiinfra, keep-brand, truncated-53-proxy].
- **S55 (2026-06-09) Phase-1 fe-admin redesign density-first NAMGROUP-ref, KEEP brand [em main proxy designer truncated gotcha #53 trước build/MEMORY]:** Applied 14 file: index.css (density heading ladder semibold + `.label-eyebrow` 11px uppercase slate-500 + drop font-bold) + 6 ui primitives (Button `text-xs font-semibold rounded-lg` h-7/8/10 + brand focus-ring/70 variant/size keys STABLE 51 call-sites) + 6 shell (DataTable/Layout/TopBar/PageHeader/PhaseBadge/EmptyState) + DashboardPage (KPI card `rounded-lg border-slate-200` + `bg-brand-50` icon chip h-7w7 + uppercase tracking-wider label + brand accent bar). Brand #1F7DC1 + Be Vietnam Pro KEPT (NAMGROUP density = mượn cấu trúc, brand=ours). `npm run build` 0 TS err. **Visual loop BLOCKED** by authed-rig gotcha (3) above CHỈ chụp /login (polished, on-brand). em main recover: build + login-visual + diff-review (index.css/Button/DashboardPage high-quality, brand-consistent). User chọn commit+deploy login prod xem authed. Tag [s55, phase1-redesign, density-namgroup, keep-brand, authed-rig-blocked].
- **S47 (2026-06-02) FD2 RIG VERIFIED ✅** first real spawn. Ran full FD2 loop end-to-end on fe-user `/login`: read DS (Tailwind v4 CSS-first, corrected stale config-path assumption) started Vite via `with_server.py` Playwright screenshot 375+1440 Read PNGs FD4 critique 1-line contrast fix re-screenshot confirmed `npm run build` 0 TS error. Closes adap-report `2026-06-02-Agent-frontend-designer-floor` FD2 runtime proof. 2 Vite gotchas captured above. Loop is REAL, not theoretical.