'use client' import { useState } from 'react' import type { Collection } from '../types' const API_BASE = process.env.NEXT_PUBLIC_KLAUSUR_SERVICE_URL || 'http://localhost:8086' 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', } const useCaseLabels: Record = { klausur: 'Klausurkorrektur', zeugnis: 'Zeugniserstellung', material: 'Unterrichtsmaterial', curriculum: 'Lehrplan', other: 'Sonstiges', unknown: 'Unbekannt', } export function CollectionCard({ collection }: { collection: Collection }) { const [ingesting, setIngesting] = useState(false) const [reindexing, setReindexing] = useState(false) const [ingestMessage, setIngestMessage] = useState(null) const [showReindexConfirm, setShowReindexConfirm] = useState(false) const [chunkingStrategy, setChunkingStrategy] = useState<'semantic' | 'recursive'>('semantic') const handleIngest = async () => { setIngesting(true) setIngestMessage(null) try { const res = await fetch(`${API_BASE}/api/v1/admin/rag/collections/${collection.name}/ingest?incremental=true`, { method: 'POST', }) if (res.ok) { const data = await res.json() setIngestMessage(data.message || 'Indexierung gestartet') } else { const error = await res.json() setIngestMessage(error.detail || 'Fehler beim Starten') } } catch (err) { setIngestMessage('Netzwerkfehler') } finally { setIngesting(false) } } const handleReindex = async () => { setShowReindexConfirm(false) setReindexing(true) setIngestMessage('Starte Re-Indexierung...') try { const res = await fetch( `${API_BASE}/api/v1/admin/rag/collections/${collection.name}/reindex?chunking_strategy=${chunkingStrategy}`, { method: 'POST' } ) if (!res.ok) { const error = await res.json() setIngestMessage(error.detail || 'Fehler beim Starten') setReindexing(false) return } const pollProgress = async () => { try { const progressRes = await fetch(`${API_BASE}/api/v1/admin/rag/reindex/progress`) if (progressRes.ok) { const progress = await progressRes.json() if (progress.phase === 'deleting') { setIngestMessage('Loesche alte Chunks...') } else if (progress.phase === 'indexing') { const pct = progress.total_docs > 0 ? Math.round((progress.current_doc / progress.total_docs) * 100) : 0 setIngestMessage( `Indexiere: ${progress.current_doc}/${progress.total_docs} (${pct}%) - ${progress.current_filename}` ) } else if (progress.phase === 'complete') { setIngestMessage( `Fertig: ${progress.documents_processed} Dokumente, ` + `${progress.chunks_created} neue Chunks (${progress.old_chunks_deleted} alte geloescht)` ) setReindexing(false) return } else if (progress.phase === 'failed') { setIngestMessage(`Fehler: ${progress.error || 'Unbekannter Fehler'}`) setReindexing(false) return } if (progress.running) { setTimeout(pollProgress, 1000) } else { setReindexing(false) } } } catch (err) { setTimeout(pollProgress, 2000) } } setTimeout(pollProgress, 500) } catch (err) { setIngestMessage('Netzwerkfehler bei Re-Indexierung') setReindexing(false) } } return (

{collection.displayName}

{collection.name}

{collection.description && (

{collection.description}

)}
{statusLabels[collection.status]} {useCaseLabels[collection.useCase] || collection.useCase}

Chunks

{collection.chunkCount.toLocaleString()}

Jahre

{collection.years?.length > 0 ? `${Math.min(...collection.years)}-${Math.max(...collection.years)}` : '-'}

Faecher

{collection.subjects?.length > 0 ? collection.subjects.length : '-'}

Bundesland

{collection.bundesland}

{collection.subjects.length > 0 && (
{collection.subjects.slice(0, 8).map((subject) => ( {subject} ))} {collection.subjects.length > 8 && ( +{collection.subjects.length - 8} weitere )}
)} {/* Ingestion Buttons */}
{ingestMessage &&

{ingestMessage}

}
{/* Re-Index Confirmation Modal */} {showReindexConfirm && (

Collection neu indexieren?

Dies loescht alle {collection.chunkCount.toLocaleString()} bestehenden Chunks und erstellt sie mit dem gewaehlten Chunking-Algorithmus neu.

Semantisches Chunking respektiert Satzgrenzen und verbessert die Suchqualitaet.

)}
) }