Files
solution-erp/fe-admin
pqhuy1987 d814429cee
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m14s
[CLAUDE] PE Workflow V2: disable nút Duyệt nếu actor không trong cấp hiện tại
User feedback: "Nếu không đúng bước duyệt thì nút duyệt cho Disable luôn cũng đc."

BE — DTO + Handler populate "Bước/Cấp đang chờ duyệt":
- Application/PurchaseEvaluations/Dtos/PurchaseEvaluationDtos.cs:
  +PurchaseEvaluationApprovalLevelApproverDto { UserId, FullName, Email }
  +PurchaseEvaluationCurrentApprovalDto { StepIndex, StepName,
    StepDepartmentId/Name, LevelOrder, LevelName, Approvers[] }
  PurchaseEvaluationDetailBundleDto +CurrentApproval? optional field
- Application/PurchaseEvaluations/PurchaseEvaluationFeatures.cs handler
  GetById: khi pin V2 + Phase=ChoDuyet → load AW.Steps.Levels Include
  3-level + group by Order = Cấp + resolve user names → populate
  CurrentApproval. Null khi V1 legacy hoặc không phải ChoDuyet.

FE — types + PeWorkflowPanel (cả 2 app mirror):
- types/purchaseEvaluation.ts: +PeCurrentApproval + PeCurrentApprovalLevelApprover
  + PeDetail.currentApproval optional
- PeWorkflowPanel:
  * Banner V2 hiển thị "Đang chờ Bước N (TênBước · Phòng X) — Cấp K"
    + list NV được duyệt + status emerald (đến lượt) / amber (không phải lượt)
  * useAuth() để check currentUser.id ∈ approvers + Admin bypass
  * Button "Duyệt forward" disabled khi V2 pin + actor không khớp.
    Title tooltip "Cấp K chỉ {NV X / NV Y} mới duyệt được."
  * Button "Trả lại" + "Từ chối" vẫn enabled (BE không gating 2 hành
    động này theo Cấp — Approver có thể reject bất cứ lúc nào).
  * Send-back logic update: target = DangSoanThao OR TraLai (V2 dùng TraLai)
- Admin role bypass mọi check.

Verify: 81 test pass · npm build × 2 OK · BE 0 error.

Test thử:
1. NV X (approver Cấp 1 V2) login → banner emerald "Đến lượt bạn duyệt"
   + nút "✓ Duyệt → ChoDuyet" enabled
2. NV Y (không phải approver) login → banner amber "Không phải lượt
   bạn — chỉ NV X mới duyệt được" + nút Duyệt grey disabled, hover tooltip
3. Admin login → bypass, button enabled
2026-05-08 15:03:29 +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...
    },
  },
])