import React, { useState, useEffect, useRef } from "react"; import { motion } from "framer-motion"; import { LuSendHorizontal } from "react-icons/lu"; import { Prompt } from "../../../../hooks/usePrompts"; import { useWorkflowOperations, useWorkflowMessages, useWorkflowStatus } from "../../../../hooks/useWorkflows"; import styles from './DashboardChatArea.module.css'; interface DashboardChatAreaProps { selectedPrompt?: Prompt | null; onPromptUsed?: () => void; onWorkflowIdChange?: (workflowId: string | null) => void; resumeWorkflowId?: string | null; } const DashboardChatArea: React.FC = ({ selectedPrompt, onPromptUsed, onWorkflowIdChange, resumeWorkflowId }) => { const [inputValue, setInputValue] = useState(""); const [currentWorkflowId, setCurrentWorkflowId] = useState(null); const [workflowCompleted, setWorkflowCompleted] = useState(false); const inputRef = useRef(null); const messagesEndRef = useRef(null); const { startWorkflow, startingWorkflow, startError } = useWorkflowOperations(); const { messages, loading: messagesLoading, error: messagesError, refetch: refetchMessages } = useWorkflowMessages(currentWorkflowId); const { status: workflowStatus, refetch: refetchStatus } = useWorkflowStatus(currentWorkflowId); // Update input value when a prompt is selected useEffect(() => { if (selectedPrompt) { setInputValue(selectedPrompt.content); // Focus the input field if (inputRef.current) { inputRef.current.focus(); } } }, [selectedPrompt]); // Auto-scroll to bottom when new messages arrive useEffect(() => { if (messagesEndRef.current) { messagesEndRef.current.scrollIntoView({ behavior: 'smooth' }); } }, [messages]); // Polling logic for fetching messages and status useEffect(() => { if (!currentWorkflowId || workflowCompleted) return; const interval = setInterval(() => { refetchMessages(); refetchStatus(); }, 1000); // Poll every second return () => clearInterval(interval); }, [currentWorkflowId, workflowCompleted, refetchMessages, refetchStatus]); // Check if workflow is completed based on status or messages useEffect(() => { if (workflowStatus && ( workflowStatus.status === 'completed' || workflowStatus.status === 'finished' || workflowStatus.status === 'done' || workflowStatus.status === 'stopped' )) { setWorkflowCompleted(true); return; } if (messages.length > 0) { const lastMessage = messages[messages.length - 1]; // Check if the last message indicates completion if (lastMessage.role === 'assistant' && (lastMessage.content.toLowerCase().includes('completed') || lastMessage.content.toLowerCase().includes('finished') || lastMessage.content.toLowerCase().includes('done') || lastMessage.content.toLowerCase().includes('workflow completed'))) { setWorkflowCompleted(true); } } }, [messages, workflowStatus]); const handleSend = async () => { if (inputValue.trim()) { console.log('Sending message:', inputValue); try { let result; // If we have a completed workflow, send as follow-up using the existing workflow ID if (workflowCompleted && currentWorkflowId) { console.log('Sending follow-up message to workflow:', currentWorkflowId); result = await startWorkflow({ prompt: inputValue, listFileId: [] }, currentWorkflowId); if (result.success) { console.log('Follow-up message sent successfully'); // Reset workflow completion state to resume polling setWorkflowCompleted(false); } } else { // Start a new workflow console.log('Starting new workflow'); // Reset previous workflow state when starting a new one setCurrentWorkflowId(null); setWorkflowCompleted(false); result = await startWorkflow({ prompt: inputValue, listFileId: [] }); if (result.success && result.data) { console.log('Workflow started successfully:', result.data); // Set the workflow ID to start polling for messages setCurrentWorkflowId(result.data.id); setWorkflowCompleted(false); } } if (result.success) { // Clear the input after successful send setInputValue(""); // Call onPromptUsed if a prompt was used if (selectedPrompt && onPromptUsed) { onPromptUsed(); } } else { console.error('Failed to send message:', result.error); } } catch (error) { console.error('Error sending message:', error); } } }; const handleKeyPress = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); } }; const startNewWorkflow = () => { setCurrentWorkflowId(null); setWorkflowCompleted(false); setInputValue(""); if (onWorkflowIdChange) { onWorkflowIdChange(null); } }; useEffect(() => { if (currentWorkflowId && onWorkflowIdChange) { onWorkflowIdChange(currentWorkflowId); } }, [currentWorkflowId, onWorkflowIdChange]); // Handle workflow resumption useEffect(() => { if (resumeWorkflowId && resumeWorkflowId !== currentWorkflowId) { console.log('Resuming workflow:', resumeWorkflowId); setCurrentWorkflowId(resumeWorkflowId); setWorkflowCompleted(false); setInputValue(""); } }, [resumeWorkflowId, currentWorkflowId]); return (
{startingWorkflow && (

{workflowCompleted && currentWorkflowId ? 'Sending follow-up message...' : 'Sending message...'}

)} {startError && (

Error: {startError}

)} {messagesError && (

Error loading messages: {messagesError}

)} {currentWorkflowId && messagesLoading && messages.length === 0 && (

Loading workflow messages...

)} {messages.length > 0 ? ( messages.map((message, index) => (
{message.role === 'user' ? 'You' : message.role === 'assistant' ? 'Assistant' : 'System'}
{message.content}
{message.timestamp && (
{new Date(message.timestamp).toLocaleTimeString()}
)}
)) ) : !currentWorkflowId ? (

Start a conversation by typing a message...

) : null} {currentWorkflowId && !workflowCompleted && (

Workflow {currentWorkflowId.substring(0, 8)}... is {workflowStatus?.status || 'running'} {workflowStatus?.currentRound && ` (Round ${workflowStatus.currentRound})`}

)} {workflowCompleted && (

Workflow completed! You can continue the conversation or start a new workflow.

)}
setInputValue(e.target.value)} onKeyPress={handleKeyPress} placeholder={workflowCompleted ? "Continue the conversation..." : "Type your message..."} className={styles.message_input} disabled={startingWorkflow} />
); }; export default DashboardChatArea;