Files
breakpilot-lehrer/website/app/admin/rag/_components/CollectionsTab.tsx
Benjamin Admin 0b37c5e692 [split-required] Split website + studio-v2 monoliths (Phase 3 continued)
Website (14 monoliths split):
- compliance/page.tsx (1,519 → 9), docs/audit (1,262 → 20)
- quality (1,231 → 16), alerts (1,203 → 10), docs (1,202 → 11)
- i18n.ts (1,173 → 8 language files)
- unity-bridge (1,094 → 12), backlog (1,087 → 6)
- training (1,066 → 8), rag (1,063 → 8)
- Deleted index_original.ts (4,899 LOC dead backup)

Studio-v2 (5 monoliths split):
- meet/page.tsx (1,481 → 9), messages (1,166 → 9)
- AlertsB2BContext.tsx (1,165 → 5 modules)
- alerts-b2b/page.tsx (1,019 → 6), korrektur/archiv (1,001 → 6)

All existing imports preserved. Zero new TypeScript errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 17:52:36 +02:00

124 lines
5.3 KiB
TypeScript

'use client'
import type { Collection } from './types'
function CollectionCard({ collection }: { collection: Collection }) {
const statusColors = {
ready: 'bg-green-100 text-green-800',
indexing: 'bg-yellow-100 text-yellow-800',
empty: 'bg-slate-100 text-slate-800',
}
const statusLabels = {
ready: 'Bereit',
indexing: 'Indexierung...',
empty: 'Leer',
}
return (
<div className="bg-white rounded-lg border border-slate-200 p-6 hover:shadow-md transition-shadow">
<div className="flex items-start justify-between">
<div className="flex items-center gap-4">
<div className="w-12 h-12 bg-primary-100 rounded-lg flex items-center justify-center">
<svg className="w-6 h-6 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
</div>
<div>
<h3 className="text-lg font-semibold text-slate-900">{collection.displayName}</h3>
<p className="text-sm text-slate-500 font-mono">{collection.name}</p>
</div>
</div>
<span className={`px-3 py-1 rounded-full text-xs font-medium ${statusColors[collection.status]}`}>
{statusLabels[collection.status]}
</span>
</div>
<div className="mt-4 grid grid-cols-2 md:grid-cols-4 gap-4">
<div>
<p className="text-xs text-slate-500 uppercase tracking-wider">Chunks</p>
<p className="text-lg font-semibold text-slate-900">{collection.chunkCount.toLocaleString()}</p>
</div>
<div>
<p className="text-xs text-slate-500 uppercase tracking-wider">Jahre</p>
<p className="text-lg font-semibold text-slate-900">
{collection.years.length > 0 ? `${Math.min(...collection.years)}-${Math.max(...collection.years)}` : '-'}
</p>
</div>
<div>
<p className="text-xs text-slate-500 uppercase tracking-wider">Fächer</p>
<p className="text-lg font-semibold text-slate-900">{collection.subjects.length}</p>
</div>
<div>
<p className="text-xs text-slate-500 uppercase tracking-wider">Bundesland</p>
<p className="text-lg font-semibold text-slate-900">{collection.bundesland}</p>
</div>
</div>
{collection.subjects.length > 0 && (
<div className="mt-4 flex flex-wrap gap-2">
{collection.subjects.slice(0, 8).map((subject) => (
<span key={subject} className="px-2 py-1 bg-slate-100 text-slate-700 text-xs rounded-md">{subject}</span>
))}
{collection.subjects.length > 8 && (
<span className="px-2 py-1 bg-slate-100 text-slate-500 text-xs rounded-md">+{collection.subjects.length - 8} weitere</span>
)}
</div>
)}
</div>
)
}
export function CollectionsTab({
collections,
loading,
onRefresh,
}: {
collections: Collection[]
loading: boolean
onRefresh: () => void
}) {
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h2 className="text-lg font-semibold text-slate-900">RAG Sammlungen</h2>
<p className="text-sm text-slate-500">Verwaltung der indexierten Dokumentensammlungen</p>
</div>
<button onClick={onRefresh} className="px-4 py-2 text-sm font-medium text-slate-700 bg-white border border-slate-300 rounded-lg hover:bg-slate-50">
Aktualisieren
</button>
</div>
{loading && (
<div className="flex items-center justify-center py-12">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary-600"></div>
</div>
)}
{!loading && (
<div className="grid gap-4">
{collections.length === 0 ? (
<div className="bg-slate-50 rounded-lg p-8 text-center">
<svg className="w-12 h-12 text-slate-400 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" />
</svg>
<h3 className="text-lg font-medium text-slate-900 mb-2">Keine Sammlungen vorhanden</h3>
<p className="text-slate-500 mb-4">Starten Sie die Ingestion oder laden Sie Dokumente hoch.</p>
</div>
) : (
collections.map((col) => <CollectionCard key={col.name} collection={col} />)
)}
<div className="border-2 border-dashed border-slate-300 rounded-lg p-6 text-center hover:border-slate-400 transition-colors cursor-pointer">
<svg className="w-8 h-8 text-slate-400 mx-auto mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
<span className="text-sm font-medium text-slate-600">Neue Sammlung (demnächst)</span>
</div>
</div>
)}
</div>
)
}