anycoder-23461cd1 / components /SearchEngine.js
00Boobs00's picture
Upload components/SearchEngine.js with huggingface_hub
3270c21 verified
import { useState } from 'react';
import { Search, Globe, Zap } from 'lucide-react';
export default function SearchEngine() {
const [query, setQuery] = useState('');
const [engine, setEngine] = useState('tavily'); // 'tavily' or 'searxng'
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
const handleSearch = async (e) => {
e.preventDefault();
if (!query.trim()) return;
setLoading(true);
setResults([]);
try {
const res = await fetch('/api/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query, engine }),
});
const data = await res.json();
setResults(data.results || []);
} catch (err) {
console.error('Search failed', err);
} finally {
setLoading(false);
}
};
return (
<div className="bg-slate-800 rounded-xl p-6 shadow-xl border border-slate-700">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-2">
<Search className="w-5 h-5 text-yellow-500" />
<h2 className="text-lg font-semibold text-white">Unified Search</h2>
</div>
<div className="flex bg-slate-900 rounded-lg p-1 border border-slate-600">
<button
onClick={() => setEngine('tavily')}
className={`px-3 py-1 rounded-md text-sm flex items-center gap-1.5 transition-all ${
engine === 'tavily'
? 'bg-yellow-600 text-white'
: 'text-slate-400 hover:text-white'
}`}
>
<Zap className="w-3 h-3" /> Tavily
</button>
<button
onClick={() => setEngine('searxng')}
className={`px-3 py-1 rounded-md text-sm flex items-center gap-1.5 transition-all ${
engine === 'searxng'
? 'bg-yellow-600 text-white'
: 'text-slate-400 hover:text-white'
}`}
>
<Globe className="w-3 h-3" /> SearXNG
</button>
</div>
</div>
<form onSubmit={handleSearch} className="relative mb-6">
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder={`Search using ${engine === 'tavily' ? 'Tavily AI' : 'SearXNG'}...`}
className="w-full bg-slate-900 border border-slate-600 rounded-lg pl-10 pr-4 py-3 text-white placeholder-slate-500 focus:ring-2 focus:ring-yellow-500 focus:border-transparent outline-none transition-all"
/>
<Search className="absolute left-3 top-3.5 w-5 h-5 text-slate-500" />
</form>
<div className="space-y-3 max-h-80 overflow-y-auto pr-2 custom-scrollbar">
{loading ? (
<div className="flex items-center justify-center py-8 text-slate-400">
Searching...
</div>
) : results.length > 0 ? (
results.map((result, i) => (
<a
key={i}
href={result.url}
target="_blank"
rel="noopener noreferrer"
className="block p-4 bg-slate-900 rounded-lg border border-slate-700 hover:border-slate-500 hover:bg-slate-850 transition-all group"
>
<h3 className="text-blue-400 font-medium group-hover:underline mb-1">
{result.title}
</h3>
<p className="text-sm text-slate-400 line-clamp-2">
{result.content || result.snippet}
</p>
<span className="text-xs text-slate-600 mt-2 block truncate">
{result.url}
</span>
</a>
))
) : (
<p className="text-slate-500 text-sm text-center py-4">
Enter a query to search the web.
</p>
)}
</div>
</div>
);
}