|
| 1 | +'use client'; |
| 2 | + |
| 3 | +import React, { useState } from 'react'; |
| 4 | +import { |
| 5 | + Search, |
| 6 | + Filter, |
| 7 | + Settings, |
| 8 | + Sparkles, |
| 9 | + ArrowLeft, |
| 10 | + X, |
| 11 | + History, |
| 12 | + TrendingUp, |
| 13 | + BrainCircuit |
| 14 | +} from 'lucide-react'; |
| 15 | +import { useAdvancedSearch } from '../../hooks/useAdvancedSearch'; |
| 16 | +import { IntelligentAutoComplete } from './IntelligentAutoComplete'; |
| 17 | +import { FacetedFilterSystem } from './FacetedFilterSystem'; |
| 18 | +import { SearchResultsVisualizer } from './SearchResultsVisualizer'; |
| 19 | + |
| 20 | +export const AdvancedSearchInterface: React.FC = () => { |
| 21 | + const { |
| 22 | + query, |
| 23 | + updateSearchText, |
| 24 | + updateFilters, |
| 25 | + updateSort, |
| 26 | + performSearch, |
| 27 | + clearFilters, |
| 28 | + results, |
| 29 | + isSearching, |
| 30 | + history, |
| 31 | + } = useAdvancedSearch(); |
| 32 | + |
| 33 | + const [showFilters, setShowFilters] = useState(false); |
| 34 | + const [hasSearched, setHasSearched] = useState(false); |
| 35 | + |
| 36 | + const handleSearch = (text: string) => { |
| 37 | + updateSearchText(text); |
| 38 | + performSearch(); |
| 39 | + setHasSearched(true); |
| 40 | + }; |
| 41 | + |
| 42 | + const handleReset = () => { |
| 43 | + clearFilters(); |
| 44 | + updateSearchText(''); |
| 45 | + setHasSearched(false); |
| 46 | + }; |
| 47 | + |
| 48 | + return ( |
| 49 | + <div className="max-w-6xl mx-auto px-4 py-12 space-y-12"> |
| 50 | + {/* Search Header Section */} |
| 51 | + <div className="text-center space-y-4 animate-in fade-in slide-in-from-top-4 duration-700"> |
| 52 | + <div className="inline-flex items-center gap-2 px-4 py-1.5 rounded-full bg-primary/10 border border-primary/20 text-primary font-mono text-xs font-bold uppercase tracking-widest mb-2"> |
| 53 | + <BrainCircuit className="w-3.5 h-3.5" /> AI-Powered Discovery |
| 54 | + </div> |
| 55 | + <h1 className="text-4xl md:text-6xl font-black font-sans text-slate-800 tracking-tight"> |
| 56 | + Find <span className="text-transparent bg-clip-text bg-gradient-to-r from-primary to-accent">Expertise</span> Faster. |
| 57 | + </h1> |
| 58 | + <p className="text-slate-500 max-w-2xl mx-auto text-lg"> |
| 59 | + Search across the entire Starknet knowledge ecosystem with multi-dimensional filters and intelligent suggestions. |
| 60 | + </p> |
| 61 | + </div> |
| 62 | + |
| 63 | + {/* Main Search Bar Container */} |
| 64 | + <div className="max-w-3xl mx-auto space-y-6"> |
| 65 | + <div className="flex flex-col sm:flex-row gap-3"> |
| 66 | + <div className="flex-1"> |
| 67 | + <IntelligentAutoComplete |
| 68 | + value={query.text} |
| 69 | + onChange={updateSearchText} |
| 70 | + onSearch={handleSearch} |
| 71 | + history={history} |
| 72 | + /> |
| 73 | + </div> |
| 74 | + <button |
| 75 | + onClick={() => setShowFilters(!showFilters)} |
| 76 | + className={`flex items-center justify-center gap-2 px-6 py-4 rounded-2xl font-mono text-xs uppercase tracking-widest font-bold transition-all h-[56px] border ${showFilters |
| 77 | + ? 'bg-primary text-white border-primary shadow-lg shadow-primary/20' |
| 78 | + : 'bg-white text-slate-600 border-slate-200 hover:border-primary hover:text-primary' |
| 79 | + }`} |
| 80 | + > |
| 81 | + <Filter className={`w-4 h-4 ${showFilters ? 'rotate-180' : ''} transition-transform duration-300`} /> |
| 82 | + {showFilters ? 'HIDE_FILTERS' : 'FILTERS'} |
| 83 | + </button> |
| 84 | + </div> |
| 85 | + |
| 86 | + {/* Quick Insights / Trending Tags */} |
| 87 | + {!hasSearched && !showFilters && ( |
| 88 | + <div className="flex flex-wrap items-center justify-center gap-4 text-slate-400 animate-in fade-in slide-in-from-bottom-2 delay-300 duration-700"> |
| 89 | + <span className="flex items-center gap-1.5 text-[10px] font-mono font-bold uppercase tracking-widest"> |
| 90 | + <TrendingUp className="w-3 h-3" /> Trending: |
| 91 | + </span> |
| 92 | + {['#Cairo1.0', '#StarknetOS', '#ZeroKnowledge', '#L2Scalability'].map(tag => ( |
| 93 | + <button |
| 94 | + key={tag} |
| 95 | + onClick={() => handleSearch(tag)} |
| 96 | + className="text-xs font-medium px-3 py-1 rounded-full bg-slate-50 border border-slate-100 hover:border-primary/30 hover:text-primary transition-all active:scale-95" |
| 97 | + > |
| 98 | + {tag} |
| 99 | + </button> |
| 100 | + ))} |
| 101 | + </div> |
| 102 | + )} |
| 103 | + </div> |
| 104 | + |
| 105 | + {/* Interface Body */} |
| 106 | + <div className="grid grid-cols-1 gap-12"> |
| 107 | + {/* Filters Panel (Collapsible) */} |
| 108 | + {showFilters && ( |
| 109 | + <div className="animate-in fade-in zoom-in-95 duration-500"> |
| 110 | + <FacetedFilterSystem |
| 111 | + filters={query.filters} |
| 112 | + onFilterChange={updateFilters} |
| 113 | + onReset={clearFilters} |
| 114 | + /> |
| 115 | + </div> |
| 116 | + )} |
| 117 | + |
| 118 | + {/* Results Section */} |
| 119 | + <div className={`space-y-8 ${isSearching ? 'opacity-70' : ''} transition-opacity`}> |
| 120 | + {hasSearched ? ( |
| 121 | + <SearchResultsVisualizer |
| 122 | + results={results} |
| 123 | + isSearching={isSearching} |
| 124 | + sortBy={query.sortBy} |
| 125 | + onSortChange={updateSort} |
| 126 | + /> |
| 127 | + ) : ( |
| 128 | + <div className="py-20 text-center space-y-8 max-w-lg mx-auto"> |
| 129 | + <div className="relative inline-block"> |
| 130 | + <div className="absolute inset-0 bg-primary/20 blur-3xl rounded-full scale-150 animate-pulse"></div> |
| 131 | + <div className="relative glass-panel w-24 h-24 rounded-3xl flex items-center justify-center text-primary mb-6 mx-auto rotate-12 hover:rotate-0 transition-transform duration-500"> |
| 132 | + <Sparkles className="w-10 h-10" /> |
| 133 | + </div> |
| 134 | + </div> |
| 135 | + <div className="space-y-2"> |
| 136 | + <h3 className="text-2xl font-bold font-sans text-slate-800 tracking-tight">Ready to explore?</h3> |
| 137 | + <p className="text-slate-500"> |
| 138 | + Discover a curated collection of decentralized knowledge, from beginners tutorials to advanced cryptographic research. |
| 139 | + </p> |
| 140 | + </div> |
| 141 | + <div className="grid grid-cols-2 gap-4"> |
| 142 | + <div className="glass-panel p-4 rounded-2xl border-slate-100 text-left space-y-2 hover:border-primary/20 transition-colors group cursor-pointer"> |
| 143 | + <div className="w-8 h-8 rounded-lg bg-blue-50 flex items-center justify-center text-blue-500 group-hover:bg-primary group-hover:text-white transition-colors"> |
| 144 | + <BrainCircuit className="w-4 h-4" /> |
| 145 | + </div> |
| 146 | + <h4 className="text-sm font-bold font-sans">Learn Cairo</h4> |
| 147 | + <p className="text-[11px] text-slate-400">Master the native language of Starknet.</p> |
| 148 | + </div> |
| 149 | + <div className="glass-panel p-4 rounded-2xl border-slate-100 text-left space-y-2 hover:border-secondary transition-colors group cursor-pointer"> |
| 150 | + <div className="w-8 h-8 rounded-lg bg-emerald-50 flex items-center justify-center text-emerald-500 group-hover:bg-accent group-hover:text-white transition-colors"> |
| 151 | + <Filter className="w-4 h-4" /> |
| 152 | + </div> |
| 153 | + <h4 className="text-sm font-bold font-sans">Find Topics</h4> |
| 154 | + <p className="text-[11px] text-slate-400">Explore categorized knowledge bases.</p> |
| 155 | + </div> |
| 156 | + </div> |
| 157 | + </div> |
| 158 | + )} |
| 159 | + </div> |
| 160 | + </div> |
| 161 | + |
| 162 | + {/* Search Insights Tooltip (Utility) */} |
| 163 | + <div className="fixed bottom-8 left-8"> |
| 164 | + <div className="relative group"> |
| 165 | + <button className="w-12 h-12 bg-white border border-slate-200 rounded-2xl flex items-center justify-center text-slate-400 hover:text-primary hover:border-primary transition-all shadow-xl shadow-slate-200/50 hover:shadow-primary/20 hover:scale-110 active:scale-95"> |
| 166 | + <History className="w-5 h-5" /> |
| 167 | + </button> |
| 168 | + <div className="absolute bottom-full left-0 mb-4 w-64 bg-white rounded-2xl shadow-2xl border border-slate-100 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-300 translate-y-2 group-hover:translate-y-0 p-4"> |
| 169 | + <h4 className="text-[10px] font-mono font-bold uppercase tracking-widest text-slate-400 mb-3 flex items-center gap-2"> |
| 170 | + <History className="w-3 h-3" /> Recent History |
| 171 | + </h4> |
| 172 | + <div className="space-y-2"> |
| 173 | + {history.length > 0 ? ( |
| 174 | + history.slice(0, 5).map((term, i) => ( |
| 175 | + <button |
| 176 | + key={i} |
| 177 | + onClick={() => handleSearch(term)} |
| 178 | + className="w-full text-left p-2 rounded-lg hover:bg-slate-50 text-xs text-slate-600 truncate flex items-center gap-2" |
| 179 | + > |
| 180 | + <div className="w-1 h-1 bg-slate-300 rounded-full"></div> |
| 181 | + {term} |
| 182 | + </button> |
| 183 | + )) |
| 184 | + ) : ( |
| 185 | + <p className="text-[10px] text-slate-300 italic">No recent searches</p> |
| 186 | + )} |
| 187 | + </div> |
| 188 | + </div> |
| 189 | + </div> |
| 190 | + </div> |
| 191 | + </div> |
| 192 | + ); |
| 193 | +}; |
| 194 | + |
| 195 | +export default AdvancedSearchInterface; |
0 commit comments