ui-nyla/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaInput.tsx
idittrich-valueon 84764f932b new dashboard
2025-07-23 10:37:07 +02:00

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;