diff --git a/frontend/src/pages/ExercisesListPage.jsx b/frontend/src/pages/ExercisesListPage.jsx index 49eb660..78fcba5 100644 --- a/frontend/src/pages/ExercisesListPage.jsx +++ b/frontend/src/pages/ExercisesListPage.jsx @@ -34,7 +34,7 @@ function ExercisesListPage() { skills: [], }) const [catalogsReady, setCatalogsReady] = useState(false) - const [loading, setLoading] = useState(true) + const [listFetching, setListFetching] = useState(false) const [loadingMore, setLoadingMore] = useState(false) const [offset, setOffset] = useState(0) const [hasMore, setHasMore] = useState(false) @@ -222,6 +222,12 @@ function ExercisesListPage() { statusOptions, ]) + /** Für Browser-/datalist-Vorschläge (aktuelle Treffer-Titel, begrenzt) */ + const searchTitleSuggestions = useMemo(() => { + const titles = exercises.map((e) => (e.title || '').trim()).filter(Boolean) + return [...new Set(titles)].slice(0, 80) + }, [exercises]) + const queryBase = useMemo(() => { const q = {} const n = (v) => (v === '' || v == null ? undefined : Number(v)) @@ -284,7 +290,7 @@ function ExercisesListPage() { if (!catalogsReady) return let cancelled = false const run = async () => { - setLoading(true) + setListFetching(true) setOffset(0) try { const batch = await api.listExercises({ ...queryBase, limit: PAGE_SIZE, offset: 0 }) @@ -298,7 +304,7 @@ function ExercisesListPage() { alert('Fehler beim Laden: ' + err.message) } } finally { - if (!cancelled) setLoading(false) + if (!cancelled) setListFetching(false) } } run() @@ -334,11 +340,11 @@ function ExercisesListPage() { const resetAllFilters = useCallback(() => setFilters({ ...INITIAL_FILTERS }), []) - if (!catalogsReady || loading) { + if (!catalogsReady) { return (
-

Laden...

+

Lade Kataloge…

) } @@ -363,13 +369,21 @@ function ExercisesListPage() {
+ + {searchTitleSuggestions.map((t) => ( + setSearchInput(e.target.value)} - autoComplete="off" + autoComplete="on" + name="exercise-fulltext-search" + list="exercise-search-titles" + enterKeyHint="search" style={{ marginBottom: '10px' }} /> @@ -379,7 +393,10 @@ function ExercisesListPage() { placeholder="zweiter Begriff — zusätzliche Volltextsuche (ODER)" value={aiSearchInput} onChange={(e) => setAiSearchInput(e.target.value)} - autoComplete="off" + autoComplete="on" + name="exercise-ai-search" + list="exercise-search-titles" + enterKeyHint="search" />
) : null}

- Vereins-/Trainerfilter folgen später. Fachliche Filter über „Filter“ – zwischen Feldern UND, Auswahl mehrerer Werte je Feld mit ODER. + Trefferliste aktualisiert sich kurz nach Eingabe. Titel der aktuellen Liste erscheinen als Vorschläge (Pfeil im + Feld). Fachliche Filter über „Filter“ – zwischen Feldern UND, Auswahl mehrerer Werte je Feld mit ODER.

@@ -584,7 +602,12 @@ function ExercisesListPage() { )} - {exercises.length === 0 ? ( + {listFetching && exercises.length === 0 ? ( +
+
+

Lade Übungen…

+
+ ) : exercises.length === 0 ? (

Keine Übungen gefunden. @@ -592,6 +615,9 @@ function ExercisesListPage() {

) : ( <> + {listFetching ? ( +

Aktualisiere Treffer…

+ ) : null}

{exercises.length} angezeigt {hasMore ? ' · es gibt weitere Einträge' : ''}