[CLAUDE] FE-User: cây tổ chức gốc "SOLUTION COMPANY" -> toả xuống phòng ban
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m17s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m17s
Anh: hiển thị cha-con với gốc SOLUTION COMPANY trên cùng, phòng ban fan-out xuống (giống NamGroup "Nam Group" là gốc). Gộp nút "Tất cả phòng ban" + list phẳng thành 1 node gốc công ty trong EmployeesListPage org-tree panel: chevron mở/gập (companyOpen, mở mặc định) + bấm tên = pickDept(null) tất cả NV + CountBadge tổng; các phòng ban render TreeNode depth=1 toả xuống dưới. Build PASS fe-user (tsc -b). fe-user only (mirror fe-admin defer cùng Phase B). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -78,6 +78,7 @@ export function EmployeesListPage() {
|
||||
|
||||
const [localSearch, setLocalSearch] = useState(search)
|
||||
const [treeOpenMobile, setTreeOpenMobile] = useState(false)
|
||||
const [companyOpen, setCompanyOpen] = useState(true) // gốc công ty mở mặc định
|
||||
|
||||
// Org tree (consume /departments/tree). Class-level [Authorize] only → any
|
||||
// authenticated user. Counts come pre-rolled-up from BE (TotalEmployeeCount).
|
||||
@ -175,30 +176,54 @@ export function EmployeesListPage() {
|
||||
</div>
|
||||
</header>
|
||||
<div className="min-h-0 flex-1 overflow-auto p-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => pickDept(null)}
|
||||
className={cn(
|
||||
'mb-1 flex w-full items-center justify-between gap-2 rounded-lg px-2.5 py-1.5 text-left text-sm transition',
|
||||
!deptFilter ? 'bg-brand-50 font-semibold text-brand-700' : 'text-slate-700 hover:bg-slate-50',
|
||||
)}
|
||||
>
|
||||
<span className="flex items-center gap-2">
|
||||
<Users className="h-4 w-4 shrink-0 text-slate-400" />
|
||||
Tất cả phòng ban
|
||||
</span>
|
||||
<CountBadge value={list.data?.total ?? 0} active={!deptFilter} />
|
||||
</button>
|
||||
|
||||
{tree.isLoading ? (
|
||||
<div className="px-2 py-6 text-center text-xs text-slate-400">Đang tải cây tổ chức…</div>
|
||||
) : !tree.data || tree.data.length === 0 ? (
|
||||
<div className="px-2 py-6 text-center text-xs text-slate-400">Chưa có phòng ban.</div>
|
||||
) : (
|
||||
<ul className="space-y-0.5">
|
||||
{tree.data.map(n => (
|
||||
<TreeNode key={n.id} node={n} depth={0} selectedId={deptFilter} onPick={pickDept} />
|
||||
))}
|
||||
{/* Gốc công ty — bấm = tất cả NV; các phòng ban toả xuống dưới (cha→con) */}
|
||||
<li>
|
||||
<div
|
||||
className={cn(
|
||||
'group flex items-center gap-1 rounded-lg pr-1.5 transition',
|
||||
!deptFilter ? 'bg-brand-50' : 'hover:bg-slate-50',
|
||||
)}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setCompanyOpen(v => !v)}
|
||||
className="grid h-5 w-5 shrink-0 place-items-center rounded text-slate-400 hover:text-slate-700"
|
||||
aria-label={companyOpen ? 'Thu gọn' : 'Mở rộng'}
|
||||
aria-expanded={companyOpen}
|
||||
>
|
||||
<ChevronRight className={cn('h-3.5 w-3.5 transition-transform', companyOpen && 'rotate-90')} />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => pickDept(null)}
|
||||
className={cn(
|
||||
'flex min-w-0 flex-1 items-center justify-between gap-2 py-1.5 text-left text-sm transition',
|
||||
!deptFilter ? 'font-semibold text-brand-700' : 'text-slate-700',
|
||||
)}
|
||||
title="SOLUTION COMPANY"
|
||||
>
|
||||
<span className="flex min-w-0 items-center gap-2">
|
||||
<Building2 className="h-4 w-4 shrink-0 text-brand-500" />
|
||||
<span className="truncate font-semibold tracking-tight">SOLUTION COMPANY</span>
|
||||
</span>
|
||||
<CountBadge value={list.data?.total ?? 0} active={!deptFilter} />
|
||||
</button>
|
||||
</div>
|
||||
{companyOpen &&
|
||||
(!tree.data || tree.data.length === 0 ? (
|
||||
<div className="py-3 pl-9 text-xs text-slate-400">Chưa có phòng ban.</div>
|
||||
) : (
|
||||
<ul className="space-y-0.5">
|
||||
{tree.data.map(n => (
|
||||
<TreeNode key={n.id} node={n} depth={1} selectedId={deptFilter} onPick={pickDept} />
|
||||
))}
|
||||
</ul>
|
||||
))}
|
||||
</li>
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user