'use client' import React, { useState, useEffect, useCallback } from 'react' import { useRouter } from 'next/navigation' import { useTheme } from '@/lib/ThemeContext' import { Sidebar } from '@/components/Sidebar' import { AudioButton } from '@/components/learn/AudioButton' interface VocabWord { id: string english: string german: string ipa_en: string ipa_de: string part_of_speech: string syllables_en: string[] syllables_de: string[] example_en: string example_de: string image_url: string difficulty: number tags: string[] } function getBackendUrl() { if (typeof window === 'undefined') return 'http://localhost:8001' const { hostname, protocol } = window.location if (hostname === 'localhost') return 'http://localhost:8001' return `${protocol}//${hostname}:8001` } export default function VocabularyPage() { const { isDark } = useTheme() const router = useRouter() const [query, setQuery] = useState('') const [results, setResults] = useState([]) const [isSearching, setIsSearching] = useState(false) const [filters, setFilters] = useState<{ tags: string[]; parts_of_speech: string[]; total_words: number }>({ tags: [], parts_of_speech: [], total_words: 0 }) const [posFilter, setPosFilter] = useState('') const [diffFilter, setDiffFilter] = useState(0) // Unit builder const [selectedWords, setSelectedWords] = useState([]) const [unitTitle, setUnitTitle] = useState('') const [isCreating, setIsCreating] = useState(false) const glassCard = isDark ? 'bg-white/10 backdrop-blur-xl border border-white/10' : 'bg-white/80 backdrop-blur-xl border border-black/5' const glassInput = isDark ? 'bg-white/10 border-white/20 text-white placeholder-white/40' : 'bg-white border-slate-200 text-slate-900 placeholder-slate-400' // Load filters on mount useEffect(() => { fetch(`${getBackendUrl()}/api/vocabulary/filters`) .then(r => r.ok ? r.json() : null) .then(d => { if (d) setFilters(d) }) .catch(() => {}) }, []) // Search with debounce useEffect(() => { if (!query.trim() && !posFilter && !diffFilter) { setResults([]) return } const timer = setTimeout(async () => { setIsSearching(true) try { let url: string if (query.trim()) { url = `${getBackendUrl()}/api/vocabulary/search?q=${encodeURIComponent(query)}&limit=30` } else { const params = new URLSearchParams({ limit: '30' }) if (posFilter) params.set('pos', posFilter) if (diffFilter) params.set('difficulty', String(diffFilter)) url = `${getBackendUrl()}/api/vocabulary/browse?${params}` } const resp = await fetch(url) if (resp.ok) { const data = await resp.json() setResults(data.words || []) } } catch (err) { console.error('Search failed:', err) } finally { setIsSearching(false) } }, 300) return () => clearTimeout(timer) }, [query, posFilter, diffFilter]) const toggleWord = useCallback((word: VocabWord) => { setSelectedWords(prev => { const exists = prev.find(w => w.id === word.id) if (exists) return prev.filter(w => w.id !== word.id) return [...prev, word] }) }, []) const createUnit = useCallback(async () => { if (!unitTitle.trim() || selectedWords.length === 0) return setIsCreating(true) try { const resp = await fetch(`${getBackendUrl()}/api/vocabulary/units`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: unitTitle, word_ids: selectedWords.map(w => w.id), }), }) if (resp.ok) { const data = await resp.json() router.push(`/learn/${data.unit_id}/flashcards`) } } catch (err) { console.error('Create unit failed:', err) } finally { setIsCreating(false) } }, [unitTitle, selectedWords, router]) const isSelected = (wordId: string) => selectedWords.some(w => w.id === wordId) return (
{/* Header */}

Woerterbuch

{filters.total_words > 0 ? `${filters.total_words.toLocaleString()} Woerter` : 'Woerter suchen und Lernunits erstellen'}

{/* Left: Search + Results */}
{/* Search Bar */}
setQuery(e.target.value)} placeholder="Wort suchen (EN oder DE)..." className={`flex-1 px-4 py-3 rounded-xl border outline-none text-lg ${glassInput}`} autoFocus />
{/* Results */} {isSearching && (
)} {!isSearching && results.length === 0 && query.trim() && (

Keine Ergebnisse fuer "{query}"

)}
{results.map(word => (
toggleWord(word)} > {/* Image or emoji placeholder */}
{word.image_url ? ( {word.english} ) : ( ๐Ÿ“ )}
{/* Word info */}
{word.english} {word.ipa_en && {word.ipa_en}}
{word.german}
{word.part_of_speech && ( {word.part_of_speech} )} {word.syllables_en.length > 0 && ( {word.syllables_en.join(' ยท ')} )}
{/* Select indicator */}
))}
{/* Right: Unit Builder */}

Lernunit erstellen

setUnitTitle(e.target.value)} placeholder="Titel (z.B. Unit 3 - Food)" className={`w-full px-4 py-2.5 rounded-xl border outline-none text-sm mb-4 ${glassInput}`} /> {selectedWords.length === 0 ? (

Klicke auf Woerter um sie hinzuzufuegen

) : (
{selectedWords.map((w, i) => (
{i+1} {w.english} {w.german}
))}
)}
{selectedWords.length} Woerter ausgewaehlt
) }