feat: implement full admin panel with dashboard, user management, and platform settings

Adds complete super_admin panel with 9 pages and account owner categories page.
Backend includes 5 new DB tables, ~25 API endpoints, settings manager with
in-memory cache, and 29 integration tests. Frontend includes reusable admin
components (DataTable, Pagination, ActionMenu, etc.) with code-split lazy loading.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-02-08 06:05:59 -05:00
parent 4f57c84d43
commit b570f8415f
50 changed files with 4589 additions and 5 deletions

View File

@@ -0,0 +1,71 @@
import { useState, useRef, useEffect, type ReactNode } from 'react'
import { MoreHorizontal } from 'lucide-react'
import { cn } from '@/lib/utils'
export interface ActionMenuItem {
label: string
icon?: ReactNode
onClick: () => void
destructive?: boolean
disabled?: boolean
}
interface ActionMenuProps {
items: ActionMenuItem[]
}
export function ActionMenu({ items }: ActionMenuProps) {
const [open, setOpen] = useState(false)
const ref = useRef<HTMLDivElement>(null)
useEffect(() => {
if (!open) return
const handler = (e: MouseEvent) => {
if (ref.current && !ref.current.contains(e.target as Node)) {
setOpen(false)
}
}
document.addEventListener('mousedown', handler)
return () => document.removeEventListener('mousedown', handler)
}, [open])
return (
<div className="relative" ref={ref}>
<button
onClick={() => setOpen(!open)}
className={cn(
'rounded-md p-1.5 text-muted-foreground transition-colors',
'hover:bg-accent hover:text-accent-foreground'
)}
>
<MoreHorizontal className="h-4 w-4" />
</button>
{open && (
<div className={cn(
'absolute right-0 top-full z-50 mt-1 min-w-[160px] rounded-md border border-border',
'bg-card py-1 shadow-lg animate-scale-in'
)}>
{items.map((item) => (
<button
key={item.label}
onClick={() => { item.onClick(); setOpen(false) }}
disabled={item.disabled}
className={cn(
'flex w-full items-center gap-2 px-3 py-2 text-sm transition-colors',
'disabled:opacity-50 disabled:pointer-events-none',
item.destructive
? 'text-destructive hover:bg-destructive/10'
: 'text-foreground hover:bg-accent'
)}
>
{item.icon}
{item.label}
</button>
))}
</div>
)}
</div>
)
}
export default ActionMenu