mirror of
https://github.com/ruvnet/RuVector.git
synced 2026-05-24 13:54:31 +00:00
Major additions: - Complete Next.js studio application with 1600+ components - Docker support (Dockerfile.combined, docker-compose.yml) - GCP deployment documentation and benchmarks - SQL benchmark scripts for performance testing - Sentry integration for monitoring - Comprehensive test suite and mocks Studio features: - Dashboard and admin interfaces - Data visualization components - Authentication and user management - API integration with RuVector backend - Static data and public assets 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
import { ReactNode } from 'react'
|
|
import { cn, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from 'ui'
|
|
import { Loader2 } from 'lucide-react'
|
|
import NoDataPlaceholder from 'components/ui/Charts/NoDataPlaceholder'
|
|
|
|
export type OverviewTableColumn<T> = {
|
|
key: keyof T | string
|
|
header: string
|
|
render?: (row: T) => ReactNode
|
|
className?: string
|
|
}
|
|
|
|
export interface OverviewTable<T> {
|
|
columns: OverviewTableColumn<T>[]
|
|
data: T[]
|
|
isLoading?: boolean
|
|
emptyMessage?: string
|
|
}
|
|
|
|
export function OverviewTable<T>({ columns, data, isLoading, emptyMessage }: OverviewTable<T>) {
|
|
const hasData = !isLoading && data.length > 0
|
|
|
|
return (
|
|
<Table>
|
|
{hasData && (
|
|
<TableHeader>
|
|
<TableRow>
|
|
{columns.map((col) => (
|
|
<TableHead
|
|
key={String(col.key)}
|
|
className={cn(col.className, 'bg-surface-200 border-t h-8 px-6')}
|
|
>
|
|
{col.header}
|
|
</TableHead>
|
|
))}
|
|
</TableRow>
|
|
</TableHeader>
|
|
)}
|
|
<TableBody className="text-foreground">
|
|
{isLoading ? (
|
|
<TableRow className="[&>td]:hover:bg-transparent">
|
|
<TableCell colSpan={columns.length} className="text-center text-foreground-light">
|
|
<div className="flex items-center justify-center gap-2 py-4">
|
|
<Loader2 className="size-4 animate-spin" />
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
) : data.length === 0 ? (
|
|
<TableRow className="[&>td]:hover:bg-transparent">
|
|
<TableCell colSpan={columns.length} className="text-center text-foreground-light">
|
|
<div className="p-2 pt-0">
|
|
<NoDataPlaceholder
|
|
size="normal"
|
|
message={emptyMessage || 'No data available'}
|
|
isFullHeight
|
|
/>
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
) : (
|
|
(data as unknown as T[]).map((row, idx) => (
|
|
<TableRow key={idx}>
|
|
{columns.map((col) => (
|
|
<TableCell key={String(col.key)} className={cn('py-1.5 pl-6 pr-4', col.className)}>
|
|
{col.render ? col.render(row) : (row as any)[col.key as string]}
|
|
</TableCell>
|
|
))}
|
|
</TableRow>
|
|
))
|
|
)}
|
|
{data.length > 0 && <span className="h-2 flex w-full" />}
|
|
</TableBody>
|
|
</Table>
|
|
)
|
|
}
|