Spaces:
Sleeping
Sleeping
File size: 4,044 Bytes
4d592a4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
import React, { useState, useCallback, useRef, useEffect } from 'react';
import { Send, Sparkles, X } from 'lucide-react';
import { useApp } from '../../context/AppContext';
const sampleQueries = [
"What is the main topic of my documents?",
"Summarize the key findings",
"Extract important dates and events",
];
export const QueryInput: React.FC = () => {
const { state, handleQuery, dispatch, clearResults } = useApp();
const [showSamples, setShowSamples] = useState(true);
const textareaRef = useRef<HTMLTextAreaElement>(null);
const handleKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleQuery();
}
},
[handleQuery]
);
const handleSubmit = useCallback(() => {
handleQuery();
}, [handleQuery]);
const autoResize = useCallback(() => {
const textarea = textareaRef.current;
if (textarea) {
textarea.style.height = 'auto';
textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
}
}, []);
useEffect(() => {
autoResize();
}, [state.currentQuery, autoResize]);
const handleClear = () => {
clearResults();
setShowSamples(true);
};
return (
<div className="space-y-4">
<div className="card p-1">
<div className="flex items-start gap-2">
<textarea
ref={textareaRef}
value={state.currentQuery}
onChange={e => {
dispatch({ type: 'SET_CURRENT_QUERY', payload: e.target.value });
if (e.target.value && showSamples) {
setShowSamples(false);
}
}}
onKeyDown={handleKeyDown}
placeholder="Ask a question about your documents..."
className="flex-1 min-h-[120px] max-h-[200px] p-4 bg-transparent text-gray-900 dark:text-white placeholder-gray-500 resize-none focus:outline-none"
disabled={state.isLoading}
/>
{state.currentQuery && (
<button
onClick={handleClear}
className="p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors mt-1"
>
<X className="w-4 h-4 text-gray-400" />
</button>
)}
</div>
<div className="flex items-center justify-between px-4 pb-4">
<div className="flex items-center gap-2">
<Sparkles className="w-4 h-4 text-gray-400" />
<span className="text-xs text-gray-500 dark:text-gray-500">
Press Enter to submit, Shift+Enter for new line
</span>
</div>
<button
onClick={handleSubmit}
disabled={!state.currentQuery.trim() || state.isLoading}
className="btn-primary flex items-center gap-2"
>
{state.isLoading ? (
<>
<div className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />
<span>Processing...</span>
</>
) : (
<>
<Send className="w-4 h-4" />
<span>Submit</span>
</>
)}
</button>
</div>
</div>
{showSamples && !state.currentQuery && (
<div className="flex flex-wrap gap-2">
<span className="text-xs text-gray-500 dark:text-gray-500 py-1">
Try:
</span>
{sampleQueries.map((query, index) => (
<button
key={index}
onClick={() => {
dispatch({ type: 'SET_CURRENT_QUERY', payload: query });
setShowSamples(false);
}}
className="text-xs px-3 py-1 bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors"
>
{query}
</button>
))}
</div>
)}
</div>
);
};
|