import { useState, useRef, useEffect } from 'react'; import ReactMarkdown from 'react-markdown'; import { useUser } from '../context/UserContext'; import { useProject } from '../context/ProjectContext'; import { api } from '../api/client'; import type { Task } from '../types'; interface Message { id: string; role: 'user' | 'assistant'; content: string; timestamp: Date; } interface TaskSolverPageProps { task: Task; onBack: () => void; onTaskCompleted: () => void; } export function TaskSolverPage({ task, onBack, onTaskCompleted }: TaskSolverPageProps) { const { user } = useUser(); const { currentProject } = useProject(); const [messages, setMessages] = useState([]); const [input, setInput] = useState(''); const [isLoading, setIsLoading] = useState(false); const [taskStatus, setTaskStatus] = useState(task.status); const messagesEndRef = useRef(null); // Scroll to bottom when new messages arrive useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages]); // Add initial assistant greeting useEffect(() => { const greeting: Message = { id: 'greeting', role: 'assistant', content: `I'm here to help you with this task: "${task.title}"\n\n${task.description ? `Description: ${task.description}\n\n` : ''}Feel free to ask me questions, share your progress, or request coding help. When you're done, just let me know what you accomplished and I'll help complete the task.`, timestamp: new Date(), }; setMessages([greeting]); }, [task]); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!input.trim() || isLoading || !user || !currentProject) return; const userMessage: Message = { id: `user-${Date.now()}`, role: 'user', content: input.trim(), timestamp: new Date(), }; setMessages((prev) => [...prev, userMessage]); setInput(''); setIsLoading(true); try { // Build conversation history for context const history = messages.map((m) => ({ role: m.role, content: m.content, })); const response = await api.taskChat( currentProject.id, task.id, user.id, input.trim(), history ); const assistantMessage: Message = { id: `assistant-${Date.now()}`, role: 'assistant', content: response.message, timestamp: new Date(), }; setMessages((prev) => [...prev, assistantMessage]); // Check if task was completed by the agent if (response.taskCompleted) { setTaskStatus('done'); onTaskCompleted(); } else if (response.taskStatus && response.taskStatus !== taskStatus) { // response.taskStatus may be a plain string from the API; ensure it's one of the // allowed Task.status values before calling the typed state setter. const isTaskStatus = (s: any): s is Task['status'] => s === 'todo' || s === 'in_progress' || s === 'done'; if (isTaskStatus(response.taskStatus)) { setTaskStatus(response.taskStatus); } } } catch (err) { const errorMessage: Message = { id: `error-${Date.now()}`, role: 'assistant', content: `Sorry, I encountered an error: ${err instanceof Error ? err.message : 'Unknown error'}`, timestamp: new Date(), }; setMessages((prev) => [...prev, errorMessage]); } finally { setIsLoading(false); } }; const getStatusColor = (status: string) => { switch (status) { case 'todo': return 'bg-yellow-500'; case 'in_progress': return 'bg-blue-500'; case 'done': return 'bg-green-500'; default: return 'bg-gray-500'; } }; const getStatusLabel = (status: string) => { switch (status) { case 'todo': return 'Todo'; case 'in_progress': return 'In Progress'; case 'done': return 'Done'; default: return status; } }; return (
{/* Fixed Header */}

{task.title}

{getStatusLabel(taskStatus)} {user && ( {user.firstName} )}
{task.description && (

{task.description}

)}
{/* Chat Area */}
{/* Messages */}
{messages.map((message) => (
{message.role === 'assistant' ? (
{message.content}
) : (

{message.content}

)}

{message.timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}

))} {isLoading && (
)}
{/* Fixed Input Area */}
{taskStatus === 'done' ? (

Task completed!

) : (
setInput(e.target.value)} placeholder="Ask a question, share progress, or describe what you did..." className="flex-1 px-4 py-3 bg-white/5 border border-white/10 rounded-lg text-white placeholder-white/40 focus:outline-none focus:ring-2 focus:ring-purple-500" disabled={isLoading} />
)}
); }