// /components/GlobalSearch.tsx 'use client'; import { useEffect, useMemo, useState } from 'react'; import { Combobox } from '@headlessui/react'; import { MagnifyingGlassIcon } from '@heroicons/react/20/solid'; import clsx from 'clsx'; type DeviceSearchItem = { inventoryNumber: string; name: string | null; manufacturer: string | null; group: string | null; location: string | null; }; type GlobalSearchProps = { onDeviceSelected?: (inventoryNumber: string) => void; }; export default function GlobalSearch({ onDeviceSelected }: GlobalSearchProps) { const [query, setQuery] = useState(''); const [allDevices, setAllDevices] = useState([]); const [loading, setLoading] = useState(false); const [loadError, setLoadError] = useState(null); const [hasLoaded, setHasLoaded] = useState(false); // Geräte nur einmal laden, wenn das erste Mal gesucht wird useEffect(() => { if (!query.trim() || hasLoaded) return; let cancelled = false; setLoading(true); setLoadError(null); async function loadDevices() { try { const res = await fetch('/api/devices', { method: 'GET', headers: { 'Content-Type': 'application/json' }, cache: 'no-store', }); if (!res.ok) { throw new Error('Geräteliste konnte nicht geladen werden.'); } const data = (await res.json()) as any[]; if (!cancelled) { const mapped: DeviceSearchItem[] = data.map((d) => ({ inventoryNumber: d.inventoryNumber, name: d.name ?? null, manufacturer: d.manufacturer ?? null, group: d.group ?? null, location: d.location ?? null, })); setAllDevices(mapped); setHasLoaded(true); } } catch (err: any) { console.error('Fehler beim Laden der Geräte für die Suche', err); if (!cancelled) { setLoadError( err instanceof Error ? err.message : 'Netzwerkfehler beim Laden der Geräteliste.', ); } } finally { if (!cancelled) { setLoading(false); } } } loadDevices(); return () => { cancelled = true; }; }, [query, hasLoaded]); const filteredDevices = useMemo(() => { const q = query.trim().toLowerCase(); if (!q) return [] as DeviceSearchItem[]; if (!allDevices.length) return [] as DeviceSearchItem[]; const matches = allDevices.filter((d) => { const haystack = [ d.inventoryNumber, d.name ?? '', d.manufacturer ?? '', d.group ?? '', d.location ?? '', ] .join(' ') .toLowerCase(); return haystack.includes(q); }); return matches.slice(0, 10); // max 10 Treffer }, [query, allDevices]); const hasMenu = query.trim().length > 0 && (loading || loadError || filteredDevices.length > 0); const handleSelect = (item: DeviceSearchItem | null) => { if (!item) return; onDeviceSelected?.(item.inventoryNumber); // Query nach Auswahl leeren setQuery(''); }; return (
{/* Suchfeld */}
); }