Commit Graph

7 Commits

Author SHA1 Message Date
6e338f745e [CLAUDE] FE: Responsive cho laptop màn hình nhỏ — sidebar slim + Section/HangMucCard padding tighter + workspace 2-panel breakpoint
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m13s
User Session 20 turn 11: "giao diện hiện tại chưa đáp ứng tốt cho laptop màn
hình nhỏ -> Căn chỉnh lại nhé."

Pain points trên laptop 1280-1366px viewport (fe-user content panel
1280-288=992px hoặc fe-admin workspace 2-panel content còn ~672px):
- Sidebar 288px chiếm nhiều
- PE Workspace list panel 320px = thừa
- Section padding px-5 + HangMucCard p-3 cộng gộp tốn ~16-20px mỗi cell
- Inline NCC table 7 cột bị compressed

FE-only mirror fe-admin + fe-user. Targeted fixes (no breaking change):

### 1. Sidebar slim — w-60 (240px) lg/xl giảm xuống → bump xl:w-72
- fe-admin Layout aside: `w-72` → `w-60 xl:w-72`
- fe-user Layout aside: `w-72` → `w-60 xl:w-72`
- Trên màn ≥xl (1280px+) → giữ 288px như cũ
- Trên màn <xl (laptop nhỏ) → 240px, save 48px cho content

### 2. PE Workspace 2-panel list breakpoint
- `lg:grid-cols-[320px_1fr]` → `lg:grid-cols-[260px_1fr] xl:grid-cols-[320px_1fr]`
- Trên lg (1024-1279): list 260px (đủ pick) → content +60px
- Trên xl+ (1280+): list 320px như cũ
- Save total: ~60px cho NCC table render

### 3. Section + HangMucCard padding responsive
- Section component `<section className="px-5 py-4">`
  → `px-3 py-3 sm:px-5 sm:py-4` (xs/sm: tighter 12px each side, save 16px width)
- HangMucCard header `flex items-start gap-3 ... p-3`
  → `flex flex-wrap items-start gap-2 ... p-2 sm:gap-3 sm:p-3`
  → +flex-wrap: stat "Số tiền NS" wrap xuống dòng khi container hẹp
- HangMucCard expand panel `p-3` → `p-2 sm:p-3`

Net width gain trên laptop 1366px (typical):
- Sidebar slim: +48px
- Workspace list: +60px
- Section padding: +16px
- HangMucCard padding: +8px
Total ~+132px cho NCC table area render comfortable thêm 1-2 cột

KHÔNG đụng dialog widths, schema BE, hoặc semantic breakpoints lớn.

Verify:
- npm run build × fe-admin pass
- npm run build × fe-user pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 12:20:01 +07:00
e320027074 [CLAUDE] FE-Admin+FE-User: PE InfoTab auto re-edit on pencil click + active state visual feedback
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m7s
User feedback 2026-05-07: bấm pencil cho phiếu khác KHÔNG sáng + KHÔNG vào edit
mode (do useState init mount-time only, ev.id thay đổi không re-trigger).
Cũng cần visual feedback "sáng lên" để user biết đang edit phiếu nào.

Implementation:
  ~ PeDetailTabs.tsx (× 2 app)
    + import useEffect
    ~ InfoTab: thêm useEffect watch [autoEdit, canEdit, ev.id, ev.tenGoiThau,
      ev.diaDiem, ev.moTa, ev.paymentTerms]. Khi autoEdit && canEdit → setEditing(true)
      + sync values từ ev mới (tránh stale state khi switch giữa 2 phiếu khác id).
    Note: Dự án disabled đã có sẵn (line 458 `<Input value={ev.projectName}
    disabled className="bg-slate-100" />`) — verify hỏi user, KHÔNG thay đổi.
  ~ PeListPanel.tsx (× 2 app)
    + Prop `editingRowId?: string | null` — row đang edit (URL editHeader=1)
    ~ Pencil icon: thêm `isEditingThis = editable && editingRowId === p.id` state
      → bg-brand-100 + text-brand-700 + ring-brand-300 + shadow-sm khi active
      → tooltip đổi "✎ Đang sửa phiếu này — click để toggle / xem khác"
  ~ PurchaseEvaluationWorkspacePage.tsx (× 2 app)
    + Pass `editingRowId={autoEditHeader ? selectedId : null}` xuống PeListPanel

Verify: npm run build fe-admin + fe-user pass · 0 TS error · áp rule strict
verify khi add new prop chain + useEffect.

UAT mode: skip dotnet test (FE-only), push ngay.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:41:33 +07:00
d15398fafe [CLAUDE] Domain+FE: PE thêm phase TraLai + pencil always visible + edit gating
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 2m0s
User feedback 2026-05-07:
1. Pencil edit icon LUÔN hiện (không chỉ hover) trong workspace Panel 1
2. Pencil sáng (active brand-color) khi phase editable, xám/disabled khi không
3. Click pencil khi sáng → row sáng + auto-open edit toàn bộ (header + detail)
4. Thêm phase mới "Trả lại" — approver gửi về Drafter sửa (vs Từ chối terminal)
5. Edit chỉ cho 2 trạng thái: Đang soạn thảo + Trả lại
   (Từ chối + Đã gửi duyệt + Đã duyệt → không edit/thao tác gì)

Implementation:
  ~ Domain/PurchaseEvaluations/PurchaseEvaluationPhase.cs
    + TraLai = 98 (giữa DaDuyet=7 và TuChoi=99)
    Comment ghi rõ "approver trả về Drafter sửa, vẫn cho edit, khác TuChoi"
  ~ types/purchaseEvaluation.ts (× 2 app)
    + PurchaseEvaluationPhase enum: TraLai = 98
    + PurchaseEvaluationPhaseLabel/Color cho TraLai (yellow)
    + isEditablePhase(phase) helper: true cho DangSoanThao + TraLai
    + PeDisplayStatus thêm "TraLai" (separate, không gộp DaGuiDuyet)
    + getPeDisplayStatus map TraLai → "Trả lại" badge yellow
  ~ components/pe/PeListPanel.tsx (× 2 app)
    - Pencil icon: bỏ opacity-0 hover-only → LUÔN visible
    - editable=isEditablePhase(p.phase): bright text-brand-600 + cursor-pointer
    - !editable: text-slate-300 + cursor-not-allowed + onClick guard ignored
    - title tooltip rõ ràng "đã gửi duyệt / đã duyệt / từ chối — không sửa được"
    - Bỏ forcedPhase prop → editableOnly prop (filter client-side cả 2 phase
      DangSoanThao + TraLai vì BE chưa support multi-phase param)
    - Khi editableOnly: hiển thị "Lọc cố định: Bản nháp + Trả lại" indicator
  ~ components/pe/PeDetailTabs.tsx (× 2 app)
    - Header bar: isDraft → canEditPhase = isEditablePhase(phase)
    - InfoTab: canEdit = !readOnly && isEditablePhase
    - BudgetFieldRow: canEdit = !readOnly && isEditablePhase
    → Đồng nghĩa Drafter sửa được phiếu Trả lại sau approver send back
  ~ pages/pe/PurchaseEvaluationWorkspacePage.tsx (× 2 app)
    - PeListPanel forcedPhase=DangSoanThao → editableOnly
    - Bỏ import PurchaseEvaluationPhase

Workflow service BE chưa wire transition → TraLai (defer — user sẽ thêm button
"Trả lại" trong PeWorkflowPanel duyệt sau, hoặc dùng API PATCH manual). Phase
TraLai chỉ là enum value sẵn sàng FE hiển thị + BE ánh xạ HasConversion<int>.

UAT mode: skip verify, push ngay.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:38:46 +07:00
0c5db1385f [CLAUDE] FE-Admin+FE-User: PE display status meta — Bản nháp / Đã gửi duyệt / Đã duyệt / Từ chối
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 1m59s
User feedback 2026-05-07: thêm 2 trạng thái meta hiển thị "Bản nháp" + "Đã
gửi duyệt". Bản nháp chỉ hiện ở Thao tác workspace, không hiện ở Duyệt menu.

Implementation:
  ~ types/purchaseEvaluation.ts
    + PeDisplayStatus enum (BanNhap / DaGuiDuyet / DaDuyet / TuChoi)
    + PeDisplayStatusLabel + PeDisplayStatusColor
    + getPeDisplayStatus(phase) helper:
        DangSoanThao → BanNhap
        DaDuyet → DaDuyet
        TuChoi → TuChoi
        else (any middle phase) → DaGuiDuyet
  ~ components/pe/PeListPanel.tsx
    - Phase Select filter → Display status Select (4 option, "Đã gửi duyệt"
      KHÔNG filter exact phase do multi-phase, để client-side TODO BE)
    - Row badge dùng display status (gọn 4 màu)
    + Prop forcedPhase?: number — workspace dùng để khóa filter Bản nháp
      (DangSoanThao). Khi forcedPhase set: ẩn Select, show "Lọc cố định: Bản
      nháp" indicator.
  ~ components/pe/PeDetailTabs.tsx
    - Header badge dùng display status meta + secondary text "(Phase chi tiết)"
      nhỏ bên cạnh để approver/dev vẫn biết phase exact
  ~ pages/pe/PurchaseEvaluationsListPage.tsx
    - Phase filter Select → display status options
    - Row badge → display status
  ~ pages/pe/PurchaseEvaluationWorkspacePage.tsx
    - PeListPanel forcedPhase={PurchaseEvaluationPhase.DangSoanThao}
      → workspace chỉ list Bản nháp (đúng UX user yêu cầu)

Workflow timeline Panel 3 + workflow service BE KHÔNG đổi (giữ phase chi tiết
DangSoanThao/ChoPurchasing/ChoCCM/etc cho approval logic).

Pe_*_Pending Duyệt: dùng /inbox endpoint vốn đã filter chỉ phiếu cần user duyệt
→ DangSoanThao auto-không xuất hiện (không có active approver). Nên Bản nháp
auto-hidden từ Duyệt menu, không cần filter thêm.

UAT mode: skip verify, push ngay.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:27:29 +07:00
66fa4691dc [CLAUDE] FE-Admin+FE-User: PE workspace "new" mode — sectioned create view 5 sections
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m4s
User feedback 2026-05-07: "Thêm mới list ra hết trường dữ liệu giống chỉnh sửa
nhưng trống, mở rộng từng phần. Save header xong mới cho nhập chi tiết."

Implementation:
  + PeWorkspaceCreateView.tsx (~230 LOC, mirror fe-admin + fe-user)
    - Sectioned card layout giống PeDetailTabs (5 section divider + title style)
    - Section 1 "Thông tin gói thầu": editable inputs (Loại / Tên */Dự án */Địa
      điểm/Mô tả/Payment) — 2-col grid responsive
    - Section 2 "Chọn NCC/TP":
      a. NCC chọn: text "(sau khi thêm NCC + chốt winner)" placeholder
      b. Ngân sách: editable inline (toggle "Nhập tay" + Select OR 2 input —
         giống BudgetFieldRow pattern)
      c. Giá chào thầu: text "(auto-tính sau winner)" placeholder
      d. Bản so sánh: LockedHint icon + text "Tải sau khi tạo"
    - Section 3 "NCC tham gia (0)": LockedHint "Lưu phiếu trước → thêm NCC..."
    - Section 4 "Hạng mục + Báo giá (0)": LockedHint
    - Section 5 "Ý kiến 4 PB": amber banner "nhập khi duyệt"
    - Action bar bottom: "Tạo phiếu" (disabled khi !tenGoiThau || !projectId)
      + Hủy
    - POST /pe full payload (header + budget mode A or B). onSuccess: toast +
      invalidate pe-list + onSaved(id, type) callback
  ~ PurchaseEvaluationWorkspacePage.tsx (× 2 app)
    - Replace <PeHeaderForm> → <PeWorkspaceCreateView> trong mode='new'
    - PeHeaderForm vẫn còn (dùng cho /new?id= deep-link "Sửa header" cũ)

Helpers duplicate trong PeWorkspaceCreateView (Section + FormRow + LockedHint)
để tránh circular import từ PeDetailTabs.

UAT mode rule applied (per memory feedback_uat_skip_verify): skip dotnet test
+ npm build verify, push ngay.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:06:31 +07:00
27b291ccea [CLAUDE] FE-User: PE InfoTab inline edit + PeListPanel pencil edit hover mirror
Chunk 2/3 — mirror y hệt Chunk 1 sang fe-user (rule §3.9). 3 file:
  ~ components/pe/PeDetailTabs.tsx — InfoTab inline edit + autoEditHeader prop
  ~ components/pe/PeListPanel.tsx — pencil icon group-hover absolute right
  ~ pages/pe/PurchaseEvaluationWorkspacePage.tsx — URL editHeader=1 wiring

Verify: npm run build fe-user pass · 0 TS error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 14:57:24 +07:00
ecf3c5945b [CLAUDE] FE-User: PE Thao tác 2-panel workspace mirror fe-admin
Chunk 2/3 — mirror y hệt Chunk 1 sang fe-user (rule §3.9 duplicate có chủ đích
giữa 2 app — copy + sync tay khi breaking).

Files (cùng diff Chunk 1, content identical):
  + fe-user/src/components/pe/PeListPanel.tsx
  + fe-user/src/components/pe/PeHeaderForm.tsx
  + fe-user/src/pages/pe/PurchaseEvaluationWorkspacePage.tsx
  ~ fe-user/src/components/pe/PeDetailTabs.tsx — add mode prop + Section 5 hint
  ~ fe-user/src/components/Layout.tsx — resolver Pe_*_Create map workspace
  ~ fe-user/src/App.tsx — route /purchase-evaluations/workspace

Verify: npm run build (fe-user) pass. dotnet test 83 không bị ảnh hưởng (đã
verify Chunk 1).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 10:37:52 +07:00