diff --git a/client/src/components/AppShell.tsx b/client/src/components/AppShell.tsx index 0ebf3d8..a73dded 100644 --- a/client/src/components/AppShell.tsx +++ b/client/src/components/AppShell.tsx @@ -1,4 +1,4 @@ -import type { ReactNode } from 'react' +import { useEffect, useState, type ReactNode } from 'react' import { Link, useLocation } from 'react-router' import { BookMarked, @@ -21,12 +21,39 @@ import { } from 'lucide-react' import { Button } from '@/components/ui/button' import { Separator } from '@/components/ui/separator' +import { api } from '@/lib/api' import { cn } from '@/lib/utils' import { useAuth } from '@/store/auth' +/** Polls the count of held actions awaiting review, so the nav can flag work is waiting. */ +function usePendingReviewCount(organizationId: string | null): number { + const [count, setCount] = useState(0) + useEffect(() => { + if (!organizationId) return + let cancelled = false + const tick = async () => { + try { + const items = await api.get(`/api/governance/reviews?organizationId=${organizationId}&status=Pending`) + if (!cancelled) setCount(items.length) + } catch { + // leave the last known count on a transient failure + } + } + void tick() + const id = setInterval(tick, 12000) + return () => { + cancelled = true + clearInterval(id) + } + }, [organizationId]) + return count +} + export function AppShell({ children }: { children: ReactNode }) { const email = useAuth((s) => s.email) const logout = useAuth((s) => s.logout) + const organizationId = useAuth((s) => s.organizationId) + const reviewCount = usePendingReviewCount(organizationId) return (
@@ -59,7 +86,7 @@ export function AppShell({ children }: { children: ReactNode }) { - + @@ -115,12 +142,14 @@ function NavItem({ to, muted, color, + badge, }: { icon: LucideIcon label: string to?: string muted?: boolean color?: string + badge?: number }) { const location = useLocation() const active = to ? location.pathname === to : false @@ -142,6 +171,11 @@ function NavItem({ {label} + {!!badge && badge > 0 && ( + + {badge} + + )} {muted && soon} )