fazeel007's picture
initial commit
7c012de
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { Search, Loader2 } from "lucide-react";
import { type SearchRequest } from "@shared/schema";
interface SearchInterfaceProps {
onSearch: (request: SearchRequest) => void;
isLoading?: boolean;
}
export default function SearchInterface({ onSearch, isLoading }: SearchInterfaceProps) {
const [query, setQuery] = useState("");
const [searchType, setSearchType] = useState<"semantic" | "keyword" | "hybrid">("semantic");
const [sourceTypes, setSourceTypes] = useState<string[]>(["pdf", "web", "academic", "code"]);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!query.trim()) return;
onSearch({
query: query.trim(),
searchType,
filters: {
sourceTypes: sourceTypes.length > 0 ? sourceTypes : undefined,
},
limit: 10,
offset: 0,
});
};
const handleSourceTypeChange = (sourceType: string, checked: boolean) => {
setSourceTypes(prev =>
checked
? [...prev, sourceType]
: prev.filter(type => type !== sourceType)
);
};
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
handleSubmit(e);
} else if (e.key === "Escape") {
setQuery("");
}
};
return (
<div className="bg-white dark:bg-slate-800 rounded-xl shadow-sm border border-slate-200 dark:border-slate-700 p-6 mb-6">
<form onSubmit={handleSubmit}>
<div className="flex flex-col lg:flex-row gap-4">
<div className="flex-1">
<Label htmlFor="knowledge-search" className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
Search Knowledge Base
</Label>
<div className="relative">
<Input
id="knowledge-search"
type="text"
placeholder="Enter your query to find relevant documents... (Press Enter to search, Esc to clear)"
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyDown={handleKeyDown}
className="pl-11 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
disabled={isLoading}
aria-label="Search knowledge base"
/>
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-slate-400 w-4 h-4" />
</div>
</div>
<div className="lg:w-auto">
<Label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
Search Type
</Label>
<Select value={searchType} onValueChange={(value: any) => setSearchType(value)}>
<SelectTrigger className="w-full lg:w-40">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="semantic">Semantic Search</SelectItem>
<SelectItem value="keyword">Keyword Search</SelectItem>
<SelectItem value="hybrid">Hybrid Search</SelectItem>
</SelectContent>
</Select>
</div>
<div className="lg:w-auto flex items-end">
<Button
type="submit"
disabled={!query.trim() || isLoading}
className="px-6 py-3 bg-blue-600 hover:bg-blue-700 focus:ring-2 focus:ring-blue-600 focus:ring-offset-2"
aria-label={isLoading ? "Searching knowledge base" : "Search knowledge base"}
>
{isLoading ? (
<>
<Loader2 className="w-4 h-4 mr-2 animate-spin" aria-hidden="true" />
Searching...
</>
) : (
<>
<Search className="w-4 h-4 mr-2" aria-hidden="true" />
Search
</>
)}
</Button>
</div>
</div>
{/* Search Filters */}
<div className="mt-4 pt-4 border-t border-slate-200 dark:border-slate-700">
<div className="flex flex-wrap gap-6">
{[
{ id: "pdf", label: "PDFs" },
{ id: "web", label: "Web Pages" },
{ id: "academic", label: "Academic Papers" },
{ id: "code", label: "Code Repositories" }
].map(({ id, label }) => (
<div key={id} className="flex items-center space-x-2">
<Checkbox
id={`filter-${id}`}
checked={sourceTypes.includes(id)}
onCheckedChange={(checked) => handleSourceTypeChange(id, !!checked)}
/>
<Label
htmlFor={`filter-${id}`}
className="text-sm text-slate-600 dark:text-slate-400 cursor-pointer"
>
{label}
</Label>
</div>
))}
</div>
</div>
</form>
{/* AI Development Tools */}
<div className="mt-4 pt-4 border-t border-slate-200 dark:border-slate-700">
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3">
<div>
<h3 className="text-sm font-medium text-slate-700 dark:text-slate-300">AI Development Tools</h3>
<p className="text-xs text-slate-500 dark:text-slate-400">Access external AI platforms and services</p>
</div>
<div className="flex flex-wrap gap-2">
<Button
type="button"
variant="outline"
size="sm"
onClick={() => window.open('https://studio.nebius.com/', '_blank')}
className="text-xs hover:bg-blue-50 hover:border-blue-300 dark:hover:bg-blue-900/20"
>
πŸš€ Nebius Studio
</Button>
<Button
type="button"
variant="outline"
size="sm"
onClick={() => window.open('https://platform.openai.com/playground', '_blank')}
className="text-xs hover:bg-green-50 hover:border-green-300 dark:hover:bg-green-900/20"
>
πŸ€– OpenAI Playground
</Button>
<Button
type="button"
variant="outline"
size="sm"
onClick={() => window.open('https://huggingface.co/spaces', '_blank')}
className="text-xs hover:bg-orange-50 hover:border-orange-300 dark:hover:bg-orange-900/20"
>
πŸ€— HuggingFace Spaces
</Button>
</div>
</div>
</div>
</div>
);
}