Add more tests

This commit is contained in:
Yaojia Wang
2026-02-01 22:40:41 +01:00
parent a564ac9d70
commit 400b12a967
55 changed files with 9306 additions and 267 deletions

View File

@@ -1,47 +1,58 @@
import React from 'react'
import { FileText, CheckCircle, Clock, TrendingUp, Activity } from 'lucide-react'
import { Button } from './Button'
import { useDocuments } from '../hooks/useDocuments'
import { useTraining } from '../hooks/useTraining'
import { FileText, CheckCircle, AlertCircle, Clock, RefreshCw } from 'lucide-react'
import {
StatsCard,
DataQualityPanel,
ActiveModelPanel,
RecentActivityPanel,
SystemStatusBar,
} from './dashboard/index'
import { useDashboard } from '../hooks/useDashboard'
interface DashboardOverviewProps {
onNavigate: (view: string) => void
}
export const DashboardOverview: React.FC<DashboardOverviewProps> = ({ onNavigate }) => {
const { total: totalDocs, isLoading: docsLoading } = useDocuments({ limit: 1 })
const { models, isLoadingModels } = useTraining()
const {
stats,
model,
runningTraining,
activities,
isLoading,
error,
} = useDashboard()
const stats = [
{
label: 'Total Documents',
value: docsLoading ? '...' : totalDocs.toString(),
icon: FileText,
color: 'text-warm-text-primary',
bgColor: 'bg-warm-bg',
},
{
label: 'Labeled',
value: '0',
icon: CheckCircle,
color: 'text-warm-state-success',
bgColor: 'bg-green-50',
},
{
label: 'Pending',
value: '0',
icon: Clock,
color: 'text-warm-state-warning',
bgColor: 'bg-yellow-50',
},
{
label: 'Training Models',
value: isLoadingModels ? '...' : models.length.toString(),
icon: TrendingUp,
color: 'text-warm-state-info',
bgColor: 'bg-blue-50',
},
]
const handleStatsClick = (filter?: string) => {
if (filter) {
onNavigate(`documents?status=${filter}`)
} else {
onNavigate('documents')
}
}
if (error) {
return (
<div className="p-8 max-w-7xl mx-auto">
<div className="bg-red-50 border border-red-200 rounded-lg p-6 text-center">
<AlertCircle className="w-12 h-12 text-red-500 mx-auto mb-4" />
<h2 className="text-lg font-semibold text-red-800 mb-2">
Failed to load dashboard
</h2>
<p className="text-sm text-red-600 mb-4">
{error instanceof Error ? error.message : 'An unexpected error occurred'}
</p>
<button
onClick={() => window.location.reload()}
className="inline-flex items-center gap-2 px-4 py-2 bg-red-100 hover:bg-red-200 text-red-800 rounded-md text-sm font-medium transition-colors"
>
<RefreshCw className="w-4 h-4" />
Retry
</button>
</div>
</div>
)
}
return (
<div className="p-8 max-w-7xl mx-auto animate-fade-in">
@@ -55,94 +66,74 @@ export const DashboardOverview: React.FC<DashboardOverviewProps> = ({ onNavigate
</p>
</div>
{/* Stats Grid */}
{/* Stats Cards Row */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
{stats.map((stat) => (
<div
key={stat.label}
className="bg-warm-card border border-warm-border rounded-lg p-6 shadow-sm hover:shadow-md transition-shadow"
>
<div className="flex items-center justify-between mb-4">
<div className={`p-3 rounded-lg ${stat.bgColor}`}>
<stat.icon className={stat.color} size={24} />
</div>
</div>
<p className="text-2xl font-bold text-warm-text-primary mb-1">
{stat.value}
</p>
<p className="text-sm text-warm-text-muted">{stat.label}</p>
</div>
))}
<StatsCard
label="Total Documents"
value={stats?.total_documents ?? 0}
icon={FileText}
iconColor="text-warm-text-primary"
iconBgColor="bg-warm-bg"
isLoading={isLoading}
onClick={() => handleStatsClick()}
/>
<StatsCard
label="Complete"
value={stats?.annotation_complete ?? 0}
icon={CheckCircle}
iconColor="text-warm-state-success"
iconBgColor="bg-green-50"
isLoading={isLoading}
onClick={() => handleStatsClick('labeled')}
/>
<StatsCard
label="Incomplete"
value={stats?.annotation_incomplete ?? 0}
icon={AlertCircle}
iconColor="text-orange-600"
iconBgColor="bg-orange-50"
isLoading={isLoading}
onClick={() => handleStatsClick('labeled')}
/>
<StatsCard
label="Pending"
value={stats?.pending ?? 0}
icon={Clock}
iconColor="text-blue-600"
iconBgColor="bg-blue-50"
isLoading={isLoading}
onClick={() => handleStatsClick('pending')}
/>
</div>
{/* Quick Actions */}
<div className="bg-warm-card border border-warm-border rounded-lg p-6 shadow-sm mb-8">
<h2 className="text-lg font-semibold text-warm-text-primary mb-4">
Quick Actions
</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Button onClick={() => onNavigate('documents')} className="justify-start">
<FileText size={18} className="mr-2" />
Manage Documents
</Button>
<Button onClick={() => onNavigate('training')} variant="secondary" className="justify-start">
<Activity size={18} className="mr-2" />
Start Training
</Button>
<Button onClick={() => onNavigate('models')} variant="secondary" className="justify-start">
<TrendingUp size={18} className="mr-2" />
View Models
</Button>
</div>
{/* Two-column layout: Data Quality + Active Model */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
<DataQualityPanel
completenessRate={stats?.completeness_rate ?? 0}
completeCount={stats?.annotation_complete ?? 0}
incompleteCount={stats?.annotation_incomplete ?? 0}
pendingCount={stats?.pending ?? 0}
isLoading={isLoading}
onViewIncomplete={() => handleStatsClick('labeled')}
/>
<ActiveModelPanel
model={model}
runningTraining={runningTraining}
isLoading={isLoading}
onGoToTraining={() => onNavigate('training')}
/>
</div>
{/* Recent Activity */}
<div className="bg-warm-card border border-warm-border rounded-lg shadow-sm overflow-hidden">
<div className="p-6 border-b border-warm-border">
<h2 className="text-lg font-semibold text-warm-text-primary">
Recent Activity
</h2>
</div>
<div className="p-6">
<div className="text-center py-8 text-warm-text-muted">
<Activity size={48} className="mx-auto mb-3 opacity-20" />
<p className="text-sm">No recent activity</p>
<p className="text-xs mt-1">
Start by uploading documents or creating training jobs
</p>
</div>
</div>
<div className="mb-8">
<RecentActivityPanel
activities={activities}
isLoading={isLoading}
/>
</div>
{/* System Status */}
<div className="mt-8 bg-warm-card border border-warm-border rounded-lg p-6 shadow-sm">
<h2 className="text-lg font-semibold text-warm-text-primary mb-4">
System Status
</h2>
<div className="space-y-3">
<div className="flex items-center justify-between">
<span className="text-sm text-warm-text-secondary">Backend API</span>
<span className="flex items-center text-sm text-warm-state-success">
<span className="w-2 h-2 bg-green-500 rounded-full mr-2"></span>
Online
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-warm-text-secondary">Database</span>
<span className="flex items-center text-sm text-warm-state-success">
<span className="w-2 h-2 bg-green-500 rounded-full mr-2"></span>
Connected
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-warm-text-secondary">GPU</span>
<span className="flex items-center text-sm text-warm-state-success">
<span className="w-2 h-2 bg-green-500 rounded-full mr-2"></span>
Available
</span>
</div>
</div>
</div>
<SystemStatusBar />
</div>
)
}