Files
breakpilot-lehrer/admin-lehrer/app/(admin)/ai/rag/_components/SearchTab.tsx
Benjamin Admin 9ba420fa91
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 42s
CI / test-go-edu-search (push) Successful in 34s
CI / test-python-klausur (push) Failing after 2m51s
CI / test-python-agent-core (push) Successful in 21s
CI / test-nodejs-website (push) Successful in 29s
Fix: Remove broken getKlausurApiUrl and clean up empty lines
sed replacement left orphaned hostname references in story page
and empty lines in getApiBase functions.

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

98 lines
3.5 KiB
TypeScript

'use client'
import React from 'react'
import type { UseRAGPageReturn } from '../_hooks/useRAGPage'
interface SearchTabProps {
hook: UseRAGPageReturn
}
export function SearchTab({ hook }: SearchTabProps) {
const {
searchQuery,
setSearchQuery,
searchResults,
searching,
selectedRegulations,
setSelectedRegulations,
handleSearch,
} = hook
return (
<div className="space-y-6">
{/* Search Box */}
<div className="bg-white rounded-xl border border-slate-200 p-6">
<h3 className="font-semibold text-slate-900 mb-4">Semantische Suche</h3>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-slate-700 mb-2">Suchanfrage</label>
<textarea
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder="z.B. 'Welche Anforderungen gibt es fuer KI-Systeme mit hohem Risiko?'"
rows={3}
className="w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-teal-500 focus:border-teal-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-slate-700 mb-2">Filter (optional)</label>
<div className="flex flex-wrap gap-2">
{['GDPR', 'AIACT', 'CRA', 'NIS2', 'BSI-TR-03161-1'].map((code) => (
<button
key={code}
onClick={() => {
setSelectedRegulations((prev: string[]) =>
prev.includes(code) ? prev.filter((c: string) => c !== code) : [...prev, code]
)
}}
className={`px-3 py-1 text-sm rounded-full border transition-colors ${
selectedRegulations.includes(code)
? 'bg-teal-100 border-teal-300 text-teal-700'
: 'bg-white border-slate-200 text-slate-600 hover:border-slate-300'
}`}
>
{code}
</button>
))}
</div>
</div>
<button
onClick={handleSearch}
disabled={searching || !searchQuery.trim()}
className="px-6 py-2 bg-teal-600 text-white rounded-lg hover:bg-teal-700 disabled:opacity-50"
>
{searching ? 'Suche...' : 'Suchen'}
</button>
</div>
</div>
{/* Search Results */}
{searchResults.length > 0 && (
<div className="bg-white rounded-xl border border-slate-200 overflow-hidden">
<div className="px-4 py-3 border-b bg-slate-50">
<h3 className="font-semibold text-slate-900">{searchResults.length} Ergebnisse</h3>
</div>
<div className="divide-y">
{searchResults.map((result, i) => (
<div key={i} className="p-4">
<div className="flex items-center gap-2 mb-2">
<span className="px-2 py-0.5 text-xs rounded bg-teal-100 text-teal-700">
{result.regulation_code}
</span>
{result.article && (
<span className="text-sm text-slate-500">Art. {result.article}</span>
)}
<span className="ml-auto text-sm text-slate-400">
Score: {(result.score * 100).toFixed(1)}%
</span>
</div>
<p className="text-slate-700 text-sm">{result.text}</p>
</div>
))}
</div>
</div>
)}
</div>
)
}