Files
solution-erp/fe-admin
pqhuy1987 4c0625c0d2
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m9s
[CLAUDE] FE-Admin+FE-User: PE detail Section 2 + 3 tweak + bottom action bar Lưu/Gửi Duyệt
User feedback 2026-05-07 (annotation screenshot):
1. "a. NCC/TP được chọn" → dropdown picker chọn từ Section 3 list (canEdit only)
2. "c. Giá chào thầu" → tách 2 message rõ:
   - Chưa chọn NCC → "(chọn NCC/TP ở (a) trước)"
   - Đã chọn nhưng chưa có quotes → "(chưa nhập báo giá ở Section 4)"
   - Có quotes → số tiền
3. Section 3 NCC tham gia row → khi NCC là winner (selected): KHÔNG cho sửa/xóa
   (chỉ giữ icon ✓ active state, ẩn ✏ + 🗑 buttons)
4. Workspace mode bottom action bar: 2 nút "Lưu (đóng)" + "Lưu & Gửi Duyệt →"
   - Lưu: invokes onBack (đóng workspace, các thay đổi đã auto-save inline)
   - Lưu & Gửi Duyệt: confirm dialog → POST /transitions với targetPhase = first
     nextPhase (skip TuChoi/TraLai) → toast + invalidate + onBack
     → workflow chuyển từ Bản nháp/Trả lại → Đã gửi duyệt (ChoPurchasing thường)

Implementation:
  ~ PeDetailTabs.tsx (× 2 app, mirror y hệt)
    + NccSelectorRow component (~50 LOC) — Select dropdown tích hợp /select-winner
      endpoint hiện có. Read-only mode: hiển thị FormRow như cũ. Disable khi
      ev.suppliers empty + hint "Thêm NCC ở Section 3 trước".
    ~ ChonNccSection: thay <FormRow "a. NCC"> → <NccSelectorRow>. Cải tiến text
      "c. Giá chào thầu" empty state.
    ~ SuppliersTab row actions: wrap conditional isWinner = ev.selectedSupplierId
      === s.supplierId. !isWinner → render Pencil + Trash. isWinner → chỉ Check
      icon active state.
    ~ PeDetailTabs root: + qc useQueryClient + submitForApproval mutation +
      canSubmitForApproval flag. Bottom action bar hiển thị khi mode='workspace'
      + canEditPhase + !readOnly.

Verify: npm run build fe-admin + fe-user pass · 0 TS error · áp rule strict
verify (lesson hotfix CI 0ae3fe2 — luôn build trước commit khi có new code).

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

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

React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

React Compiler

The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see this documentation.

Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...

      // Remove tseslint.configs.recommended and replace with this
      tseslint.configs.recommendedTypeChecked,
      // Alternatively, use this for stricter rules
      tseslint.configs.strictTypeChecked,
      // Optionally, add this for stylistic rules
      tseslint.configs.stylisticTypeChecked,

      // Other configs...
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
])

You can also install eslint-plugin-react-x and eslint-plugin-react-dom for React-specific lint rules:

// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...
      // Enable lint rules for React
      reactX.configs['recommended-typescript'],
      // Enable lint rules for React DOM
      reactDom.configs.recommended,
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
])