00Boobs00 commited on
Commit
3270c21
·
verified ·
1 Parent(s): 7308563

Upload components/SearchEngine.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. components/SearchEngine.js +109 -0
components/SearchEngine.js ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState } from 'react';
2
+ import { Search, Globe, Zap } from 'lucide-react';
3
+
4
+ export default function SearchEngine() {
5
+ const [query, setQuery] = useState('');
6
+ const [engine, setEngine] = useState('tavily'); // 'tavily' or 'searxng'
7
+ const [results, setResults] = useState([]);
8
+ const [loading, setLoading] = useState(false);
9
+
10
+ const handleSearch = async (e) => {
11
+ e.preventDefault();
12
+ if (!query.trim()) return;
13
+
14
+ setLoading(true);
15
+ setResults([]);
16
+
17
+ try {
18
+ const res = await fetch('/api/search', {
19
+ method: 'POST',
20
+ headers: { 'Content-Type': 'application/json' },
21
+ body: JSON.stringify({ query, engine }),
22
+ });
23
+
24
+ const data = await res.json();
25
+ setResults(data.results || []);
26
+ } catch (err) {
27
+ console.error('Search failed', err);
28
+ } finally {
29
+ setLoading(false);
30
+ }
31
+ };
32
+
33
+ return (
34
+ <div className="bg-slate-800 rounded-xl p-6 shadow-xl border border-slate-700">
35
+ <div className="flex items-center justify-between mb-4">
36
+ <div className="flex items-center gap-2">
37
+ <Search className="w-5 h-5 text-yellow-500" />
38
+ <h2 className="text-lg font-semibold text-white">Unified Search</h2>
39
+ </div>
40
+
41
+ <div className="flex bg-slate-900 rounded-lg p-1 border border-slate-600">
42
+ <button
43
+ onClick={() => setEngine('tavily')}
44
+ className={`px-3 py-1 rounded-md text-sm flex items-center gap-1.5 transition-all ${
45
+ engine === 'tavily'
46
+ ? 'bg-yellow-600 text-white'
47
+ : 'text-slate-400 hover:text-white'
48
+ }`}
49
+ >
50
+ <Zap className="w-3 h-3" /> Tavily
51
+ </button>
52
+ <button
53
+ onClick={() => setEngine('searxng')}
54
+ className={`px-3 py-1 rounded-md text-sm flex items-center gap-1.5 transition-all ${
55
+ engine === 'searxng'
56
+ ? 'bg-yellow-600 text-white'
57
+ : 'text-slate-400 hover:text-white'
58
+ }`}
59
+ >
60
+ <Globe className="w-3 h-3" /> SearXNG
61
+ </button>
62
+ </div>
63
+ </div>
64
+
65
+ <form onSubmit={handleSearch} className="relative mb-6">
66
+ <input
67
+ type="text"
68
+ value={query}
69
+ onChange={(e) => setQuery(e.target.value)}
70
+ placeholder={`Search using ${engine === 'tavily' ? 'Tavily AI' : 'SearXNG'}...`}
71
+ 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"
72
+ />
73
+ <Search className="absolute left-3 top-3.5 w-5 h-5 text-slate-500" />
74
+ </form>
75
+
76
+ <div className="space-y-3 max-h-80 overflow-y-auto pr-2 custom-scrollbar">
77
+ {loading ? (
78
+ <div className="flex items-center justify-center py-8 text-slate-400">
79
+ Searching...
80
+ </div>
81
+ ) : results.length > 0 ? (
82
+ results.map((result, i) => (
83
+ <a
84
+ key={i}
85
+ href={result.url}
86
+ target="_blank"
87
+ rel="noopener noreferrer"
88
+ className="block p-4 bg-slate-900 rounded-lg border border-slate-700 hover:border-slate-500 hover:bg-slate-850 transition-all group"
89
+ >
90
+ <h3 className="text-blue-400 font-medium group-hover:underline mb-1">
91
+ {result.title}
92
+ </h3>
93
+ <p className="text-sm text-slate-400 line-clamp-2">
94
+ {result.content || result.snippet}
95
+ </p>
96
+ <span className="text-xs text-slate-600 mt-2 block truncate">
97
+ {result.url}
98
+ </span>
99
+ </a>
100
+ ))
101
+ ) : (
102
+ <p className="text-slate-500 text-sm text-center py-4">
103
+ Enter a query to search the web.
104
+ </p>
105
+ )}
106
+ </div>
107
+ </div>
108
+ );
109
+ }