[CLAUDE] FE: TopBar + NotificationBell + UserMenu — ERP shell foundation
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled

Kiến trúc Layout giờ tách thành [sidebar] [topbar + content], foundation
để scale thêm module trong tương lai (HR, Accounting, Inventory...).

TopBar: title placeholder + NotificationBell + UserMenu (initials avatar
+ role badges + logout). UserMenu thay cho bottom-of-sidebar (cleaner).

NotificationBell:
- fe-admin: cảnh báo SLA (HĐ quá/sắp quá hạn, 24h window)
- fe-user: hộp thư chờ xử lý (items trong /contracts/inbox)
- refetchInterval: 60s
- Placeholder cho SignalR/email notifications thật sẽ thay bằng
  /api/notifications endpoint ở Tier 3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-04-21 15:16:15 +07:00
parent 2e43799046
commit 2b6f91c2b2
6 changed files with 416 additions and 49 deletions

View File

@ -1,8 +1,9 @@
import { Link, NavLink, Outlet } from 'react-router-dom'
import { LogOut, ChevronDown, Circle, type LucideIcon } from 'lucide-react'
import { ChevronDown, Circle, type LucideIcon } from 'lucide-react'
import * as Icons from 'lucide-react'
import { useState } from 'react'
import { useAuth } from '@/contexts/AuthContext'
import { TopBar } from '@/components/TopBar'
import type { MenuNode } from '@/types/menu'
import { cn } from '@/lib/cn'
@ -74,7 +75,7 @@ function MenuLeaf({ node }: { node: MenuNode }) {
}
export function Layout() {
const { user, menu, logout } = useAuth()
const { menu } = useAuth()
return (
<div className="flex h-screen">
@ -87,23 +88,13 @@ export function Layout() {
<nav className="flex-1 space-y-1 overflow-y-auto p-3">
{menu.map(n => (n.children.length > 0 ? <MenuGroup key={n.key} node={n} /> : <MenuLeaf key={n.key} node={n} />))}
</nav>
<div className="border-t border-slate-200 p-3">
<div className="mb-2 px-3 text-xs text-slate-500">
<div className="truncate font-medium text-slate-700">{user?.fullName}</div>
<div className="truncate">{user?.email}</div>
</div>
<button
onClick={logout}
className="flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm text-slate-600 transition hover:bg-slate-100"
>
<LogOut className="h-4 w-4" />
Đăng xuất
</button>
</div>
</aside>
<main className="flex-1 overflow-auto">
<Outlet />
</main>
<div className="flex flex-1 flex-col overflow-hidden">
<TopBar />
<main className="flex-1 overflow-auto">
<Outlet />
</main>
</div>
</div>
)
}