187 lines
6.5 KiB
TypeScript
187 lines
6.5 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import { useWorkflowOperations } from '../../../../hooks/useWorkflows';
|
|
import { Prompt } from '../../../../hooks/usePrompts';
|
|
import FileAttachmentPopup from './FileAttachmentPopup';
|
|
|
|
interface InputAreaProps {
|
|
selectedPrompt?: Prompt | null;
|
|
onPromptUsed?: () => void;
|
|
onWorkflowIdChange?: (workflowId: string | null) => void;
|
|
onAttachedFilesChange?: (files: AttachedFile[]) => void;
|
|
attachedFiles?: AttachedFile[];
|
|
}
|
|
|
|
interface AttachedFile {
|
|
id: number;
|
|
name: string;
|
|
size: number;
|
|
type: string;
|
|
fileData?: File;
|
|
objectUrl?: string;
|
|
}
|
|
|
|
const InputArea: React.FC<InputAreaProps> = ({
|
|
selectedPrompt,
|
|
onPromptUsed,
|
|
onWorkflowIdChange,
|
|
onAttachedFilesChange,
|
|
attachedFiles: externalAttachedFiles = []
|
|
}) => {
|
|
const [inputValue, setInputValue] = useState('');
|
|
const [showFilePopup, setShowFilePopup] = useState(false);
|
|
|
|
// Always use external attached files from parent component
|
|
const currentAttachedFiles = externalAttachedFiles;
|
|
const { startWorkflow, startingWorkflow, startError } = useWorkflowOperations();
|
|
|
|
// Auto-fill input when prompt is selected
|
|
useEffect(() => {
|
|
if (selectedPrompt) {
|
|
setInputValue(selectedPrompt.content);
|
|
}
|
|
}, [selectedPrompt]);
|
|
|
|
const handleSend = async () => {
|
|
if (!inputValue.trim() || startingWorkflow) return;
|
|
|
|
try {
|
|
const result = await startWorkflow({
|
|
prompt: inputValue,
|
|
listFileId: currentAttachedFiles.map(f => f.id)
|
|
});
|
|
|
|
if (result.success) {
|
|
setInputValue('');
|
|
if (onAttachedFilesChange) {
|
|
onAttachedFilesChange([]);
|
|
}
|
|
if (onPromptUsed) onPromptUsed();
|
|
if (onWorkflowIdChange && result.data?.id) {
|
|
onWorkflowIdChange(result.data.id);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to start workflow:', error);
|
|
}
|
|
};
|
|
|
|
const handleKeyPress = (e: React.KeyboardEvent) => {
|
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
e.preventDefault();
|
|
handleSend();
|
|
}
|
|
};
|
|
|
|
const handleFilesAttached = (files: AttachedFile[]) => {
|
|
setShowFilePopup(false);
|
|
if (onAttachedFilesChange) {
|
|
onAttachedFilesChange(files);
|
|
}
|
|
};
|
|
|
|
const formatFileSize = (bytes: number): string => {
|
|
if (bytes < 1024) return bytes + ' B';
|
|
if (bytes < 1024 * 1024) return Math.round(bytes / 1024) + ' KB';
|
|
return Math.round(bytes / (1024 * 1024)) + ' MB';
|
|
};
|
|
|
|
return (
|
|
<div style={{ padding: '16px', height: '100%', display: 'flex', flexDirection: 'column' }}>
|
|
<h3>Input</h3>
|
|
|
|
{startError && (
|
|
<div style={{
|
|
padding: '8px',
|
|
backgroundColor: '#ffe6e6',
|
|
color: '#d00',
|
|
borderRadius: '4px',
|
|
marginBottom: '12px'
|
|
}}>
|
|
Error: {startError}
|
|
</div>
|
|
)}
|
|
|
|
{/* Show attached files count */}
|
|
{currentAttachedFiles.length > 0 && (
|
|
<div style={{
|
|
marginBottom: '8px',
|
|
padding: '6px 10px',
|
|
backgroundColor: '#e3f2fd',
|
|
borderRadius: '4px',
|
|
fontSize: '12px',
|
|
color: '#1976d2',
|
|
textAlign: 'center'
|
|
}}>
|
|
📎 {currentAttachedFiles.length} file{currentAttachedFiles.length !== 1 ? 's' : ''} attached
|
|
</div>
|
|
)}
|
|
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px', flex: 1 }}>
|
|
<textarea
|
|
value={inputValue}
|
|
onChange={(e) => setInputValue(e.target.value)}
|
|
onKeyPress={handleKeyPress}
|
|
placeholder="Enter your message or prompt..."
|
|
disabled={startingWorkflow}
|
|
style={{
|
|
flex: 1,
|
|
padding: '12px',
|
|
border: '1px solid var(--color-gray-disabled)',
|
|
borderRadius: '8px',
|
|
resize: 'none',
|
|
fontSize: '14px',
|
|
fontFamily: 'inherit'
|
|
}}
|
|
/>
|
|
|
|
<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
|
|
<button
|
|
onClick={() => setShowFilePopup(true)}
|
|
style={{
|
|
padding: '8px 12px',
|
|
backgroundColor: 'var(--color-surface)',
|
|
border: '1px solid var(--color-gray-disabled)',
|
|
borderRadius: '6px',
|
|
cursor: 'pointer',
|
|
fontSize: '14px'
|
|
}}
|
|
>
|
|
📎 Attach Files
|
|
</button>
|
|
|
|
<button
|
|
onClick={handleSend}
|
|
disabled={!inputValue.trim() || startingWorkflow}
|
|
style={{
|
|
padding: '8px 16px',
|
|
backgroundColor: startingWorkflow ? 'var(--color-gray-disabled)' : 'var(--color-secondary)',
|
|
color: 'white',
|
|
border: 'none',
|
|
borderRadius: '6px',
|
|
cursor: startingWorkflow ? 'not-allowed' : 'pointer'
|
|
}}
|
|
>
|
|
{startingWorkflow ? 'Starting...' : 'Send'}
|
|
</button>
|
|
|
|
{selectedPrompt && (
|
|
<span style={{ fontSize: '12px', color: 'var(--color-gray)' }}>
|
|
Using prompt: {selectedPrompt.name}
|
|
</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* File Attachment Popup */}
|
|
{showFilePopup && (
|
|
<FileAttachmentPopup
|
|
onClose={() => setShowFilePopup(false)}
|
|
onFilesSelected={handleFilesAttached}
|
|
currentAttachedFiles={currentAttachedFiles}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default InputArea;
|