63 lines
2.2 KiB
TypeScript
63 lines
2.2 KiB
TypeScript
import { useState, useEffect, useRef } from 'react'
|
|
import { useQuery } from '@tanstack/react-query'
|
|
import { Search } from 'lucide-react'
|
|
import { searchRecipes } from '../api/recipes'
|
|
import { RecipeCardSmall } from '../components/recipe/RecipeCardSmall'
|
|
import { EmptyState } from '../components/ui/EmptyState'
|
|
|
|
export function SearchPage() {
|
|
const [query, setQuery] = useState('')
|
|
const [debouncedQuery, setDebouncedQuery] = useState('')
|
|
const inputRef = useRef<HTMLInputElement>(null)
|
|
|
|
useEffect(() => { inputRef.current?.focus() }, [])
|
|
|
|
useEffect(() => {
|
|
const timer = setTimeout(() => setDebouncedQuery(query), 300)
|
|
return () => clearTimeout(timer)
|
|
}, [query])
|
|
|
|
const { data, isLoading } = useQuery({
|
|
queryKey: ['search', debouncedQuery],
|
|
queryFn: () => searchRecipes(debouncedQuery),
|
|
enabled: debouncedQuery.length >= 2,
|
|
})
|
|
|
|
const results = data?.data ?? (Array.isArray(data) ? data as any[] : [])
|
|
|
|
return (
|
|
<div className="p-4">
|
|
{/* Search Input */}
|
|
<div className="relative mb-4">
|
|
<Search size={18} className="absolute left-3 top-1/2 -translate-y-1/2 text-warm-grey" />
|
|
<input
|
|
ref={inputRef}
|
|
type="text"
|
|
value={query}
|
|
onChange={(e) => setQuery(e.target.value)}
|
|
placeholder="Rezept suchen..."
|
|
className="w-full pl-10 pr-4 py-3 bg-surface rounded-xl border border-sand text-espresso text-sm focus:outline-none focus:border-primary"
|
|
/>
|
|
</div>
|
|
|
|
{/* Results */}
|
|
{debouncedQuery.length < 2 ? (
|
|
<EmptyState icon="🔍" title="Suche starten" description="Gib mindestens 2 Zeichen ein" />
|
|
) : isLoading ? (
|
|
<p className="text-warm-grey text-sm text-center py-8">Suche...</p>
|
|
) : results.length === 0 ? (
|
|
<EmptyState icon="😔" title="Nichts gefunden" description={`Keine Ergebnisse für "${debouncedQuery}"`} />
|
|
) : (
|
|
<>
|
|
<p className="text-warm-grey text-xs mb-3">{results.length} Ergebnis{results.length !== 1 ? 'se' : ''}</p>
|
|
<div className="space-y-3">
|
|
{results.map((recipe: any) => (
|
|
<RecipeCardSmall key={recipe.id} recipe={recipe} />
|
|
))}
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|