[CLAUDE] Move nested-type menu → fe-user; Admin workflow config page
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m41s

User clarified: menu loại HĐ 3-level (Danh sách/Thao tác/Duyệt) thuộc
fe-user. Admin có page riêng để config quy trình per loại HĐ.

fe-admin Layout:
- filterForAdmin() drops Ct_* entries (hide nested type menu).
- Admin sidebar giờ về lại đơn giản: Dashboard / Master / Hợp đồng
  (leaf) / Forms / Reports / System.

fe-user Layout:
- Dynamic menu tree từ /menus/me (thay fixed USER_MENU hardcoded).
- Recursive MenuNodeRenderer (top-level expanded, nested collapsed).
- resolvePath user-specific: Ct_*_List → /my-contracts?type=X,
  Ct_*_Create → /contracts/new?type=X, Ct_*_Pending → /inbox?type=X.
- filterForUser drops admin-only entries (Master/System/Forms/Reports).
- Static USER_FIXED_TOP prepends "Hộp thư" leaf → /inbox.
- MyContractsPage + InboxPage đọc ?type=X param, filter client-side.

Workflow config (Admin side):
- Domain: WorkflowTypeAssignment entity (ContractType → PolicyName
  override). Registry.ForContractWithOverrides() prefer DB override
  else default.
- Infrastructure: EF config + migration AddWorkflowTypeAssignments,
  unique index trên ContractType. ContractWorkflowService load
  overrides dict mỗi transition. ContractFeatures load overrides khi
  build WorkflowSummaryDto.
- Application: GetWorkflowAdminOverviewQuery returns 7 types × current
  policy + available policies. SetWorkflowAssignmentCommand validate
  policy name tồn tại; nếu = default thì delete override (no stale row).
- Api: GET /api/workflows + PUT /api/workflows/{contractType}
  với policy "Workflows.Read" + "Workflows.Update".
- Menu: new key `Workflows` dưới System, label "Quy trình HĐ".
- FE /system/workflows: 7 card per type, dropdown Standard/SkipCcm +
  'Đã override' badge khi khác default, phase sequence timeline,
  explanation banner ở top. Iteration 2 note: admin-authored custom
  policies.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-04-21 22:41:05 +07:00
parent 48e91fe7ca
commit 5e0f3801a1
20 changed files with 1737 additions and 48 deletions

View File

@ -39,6 +39,7 @@ function resolvePath(key: string): string | null {
Users: '/system/users',
Roles: '/system/roles',
Permissions: '/system/permissions',
Workflows: '/system/workflows',
}
if (staticMap[key]) return staticMap[key]
@ -54,6 +55,18 @@ function resolvePath(key: string): string | null {
return null
}
// Admin side: hide the per-ContractType submenu (Ct_*) — that's a user-app
// concern. Admin manages workflow config via /system/workflows instead.
function isAdminHidden(key: string): boolean {
return key.startsWith('Ct_')
}
function filterForAdmin(nodes: MenuNode[]): MenuNode[] {
return nodes
.filter(n => !isAdminHidden(n.key))
.map(n => ({ ...n, children: filterForAdmin(n.children) }))
}
function MenuNodeRenderer({ node, depth = 0 }: { node: MenuNode; depth?: number }) {
const hasChildren = node.children.length > 0
if (hasChildren) return <MenuGroup node={node} depth={depth} />
@ -138,7 +151,7 @@ export function Layout() {
</Link>
</div>
<nav className="flex-1 space-y-1 overflow-y-auto p-3">
{menu.map(n => (
{filterForAdmin(menu).map(n => (
<MenuNodeRenderer key={n.key} node={n} depth={0} />
))}
</nav>