import { html, useState, useRef } from '../lib/preact.js'; import { getStatusMeta } from '../utils/status.js'; import { OptionButton } from './OptionButton.js'; import { renderContent } from '../lib/markdown.js'; export function QuestionBlock({ questions, sessionId, status, onRespond }) { const [freeformText, setFreeformText] = useState(''); const [focused, setFocused] = useState(false); const [sending, setSending] = useState(false); const [error, setError] = useState(null); const [previewIndex, setPreviewIndex] = useState(0); const textareaRef = useRef(null); const meta = getStatusMeta(status); if (!questions || questions.length === 0) return null; // Only show the first question (sequential, not parallel) const question = questions[0]; const remainingCount = questions.length - 1; const options = question.options || []; // Check if any option has markdown preview content const hasMarkdownPreviews = options.some(opt => opt.markdown); const handleOptionClick = async (optionLabel) => { if (sending) return; setSending(true); setError(null); try { await onRespond(sessionId, optionLabel, false, options.length); } catch (err) { setError('Failed to send response'); console.error('QuestionBlock option error:', err); } finally { setSending(false); } }; const handleFreeformSubmit = async (e) => { e.preventDefault(); e.stopPropagation(); if (freeformText.trim() && !sending) { setSending(true); setError(null); try { await onRespond(sessionId, freeformText.trim(), true, options.length); setFreeformText(''); } catch (err) { setError('Failed to send response'); console.error('QuestionBlock freeform error:', err); } finally { setSending(false); // Refocus the textarea after submission // Use setTimeout to ensure React has re-rendered with disabled=false setTimeout(() => { textareaRef.current?.focus(); }, 0); } } }; // Side-by-side layout when options have markdown previews if (hasMarkdownPreviews) { const currentMarkdown = options[previewIndex]?.markdown || ''; return html`
e.stopPropagation()}> ${error && html`
${error}
`} ${question.header && html` ${question.header} `}

${question.question || question.text}

${options.map((opt, i) => html` <${OptionButton} key=${i} number=${i + 1} label=${opt.label || opt} description=${opt.description} selected=${previewIndex === i} onMouseEnter=${() => setPreviewIndex(i)} onFocus=${() => setPreviewIndex(i)} onClick=${() => handleOptionClick(opt.label || opt)} /> `)}
${currentMarkdown ? (currentMarkdown.trimStart().startsWith('```') ? renderContent(currentMarkdown) : html`
${currentMarkdown}
`) : html`

No preview for this option

` }