From 5c7112ecd2b771007b0e80c0dcd29a0bc9b0a38f Mon Sep 17 00:00:00 2001 From: Florian Wilde Date: Fri, 17 Jul 2026 23:53:12 +0200 Subject: [PATCH] Gerichte: Live-Suche MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Filtert die Liste bereits während des Tippens (Name, ohne Groß-/ Kleinschreibung). "Alle auswählen" bezieht sich auf die gefilterte Liste, Treffer-Hinweis bei leerem Ergebnis. --- components/DishManager.tsx | 39 +++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/components/DishManager.tsx b/components/DishManager.tsx index 11f4e9a..8af6ec9 100644 --- a/components/DishManager.tsx +++ b/components/DishManager.tsx @@ -21,6 +21,13 @@ export default function DishManager() { const [loading, setLoading] = useState(true); const [selected, setSelected] = useState>(new Set()); const [bulkBusy, setBulkBusy] = useState(false); + const [search, setSearch] = useState(""); + + // Live-Suche: filtert die Liste bereits während des Tippens + const visible = useMemo(() => { + const q = search.trim().toLowerCase(); + return q ? dishes.filter((d) => d.name.toLowerCase().includes(q)) : dishes; + }, [dishes, search]); const load = useCallback(async () => { const { data, error } = await supabase @@ -83,10 +90,16 @@ export default function DishManager() { }); } + // "Alle auswählen" bezieht sich auf die aktuell gefilterte Liste function toggleAll() { - setSelected((prev) => - prev.size === dishes.length ? new Set() : new Set(dishes.map((d) => d.id)) - ); + setSelected((prev) => { + const next = new Set(prev); + const everyVisibleSelected = visible.every((d) => next.has(d.id)); + visible.forEach((d) => + everyVisibleSelected ? next.delete(d.id) : next.add(d.id) + ); + return next; + }); } async function removeSelected() { @@ -109,7 +122,8 @@ export default function DishManager() { await load(); } - const allSelected = dishes.length > 0 && selected.size === dishes.length; + const allSelected = + visible.length > 0 && visible.every((d) => selected.has(d.id)); return (
@@ -182,6 +196,16 @@ export default function DishManager() {

Lade Gerichte…

) : ( <> + {dishes.length > 0 && ( + setSearch(e.target.value)} + aria-label="Gerichte durchsuchen" + /> + )} {dishes.length > 0 && (
)}
    - {dishes.map((dish) => ( + {visible.map((dish) => (
  • )} + {dishes.length > 0 && visible.length === 0 && ( +
  • + Keine Treffer für „{search}“. +
  • + )}
)}