feat(frontend): display submitted question below input (sub-phase 2.2)
Show submitted question as italic text below the input area after clicking submit. Clears when user starts typing a new question. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
parent
0ba8ff2e24
commit
87acb8816a
|
|
@ -7,12 +7,14 @@ export interface QueryInputProps {
|
||||||
|
|
||||||
export const QueryInput: React.FC<QueryInputProps> = ({ onSubmit, isLoading }) => {
|
export const QueryInput: React.FC<QueryInputProps> = ({ onSubmit, isLoading }) => {
|
||||||
const [question, setQuestion] = useState<string>('')
|
const [question, setQuestion] = useState<string>('')
|
||||||
|
const [submittedQuestion, setSubmittedQuestion] = useState<string | null>(null)
|
||||||
|
|
||||||
const handleSubmit = (e: FormEvent): void => {
|
const handleSubmit = (e: FormEvent): void => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const trimmed = question.trim()
|
const trimmed = question.trim()
|
||||||
if (trimmed && !isLoading) {
|
if (trimmed && !isLoading) {
|
||||||
onSubmit(trimmed)
|
onSubmit(trimmed)
|
||||||
|
setSubmittedQuestion(trimmed)
|
||||||
setQuestion('')
|
setQuestion('')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -24,19 +26,27 @@ export const QueryInput: React.FC<QueryInputProps> = ({ onSubmit, isLoading }) =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>): void => {
|
||||||
|
setQuestion(e.target.value)
|
||||||
|
if (e.target.value.trim() !== '') {
|
||||||
|
setSubmittedQuestion(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const isDisabled = isLoading || question.trim() === ''
|
const isDisabled = isLoading || question.trim() === ''
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit} className="space-y-3">
|
<form onSubmit={handleSubmit} className="space-y-3">
|
||||||
<textarea
|
<textarea
|
||||||
value={question}
|
value={question}
|
||||||
onChange={(e) => setQuestion(e.target.value)}
|
onChange={handleChange}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
placeholder="Ask a question about your documents..."
|
placeholder="Ask a question about your documents..."
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
rows={3}
|
rows={3}
|
||||||
className="w-full rounded border border-gray-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed"
|
className="w-full rounded border border-gray-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed"
|
||||||
/>
|
/>
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
|
|
@ -44,6 +54,12 @@ export const QueryInput: React.FC<QueryInputProps> = ({ onSubmit, isLoading }) =
|
||||||
>
|
>
|
||||||
{isLoading ? 'Processing...' : 'Submit'}
|
{isLoading ? 'Processing...' : 'Submit'}
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
{submittedQuestion && (
|
||||||
|
<p data-testid="submitted-question" className="text-sm text-gray-500 italic">
|
||||||
|
Your question: “{submittedQuestion}”
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</form>
|
</form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,4 +111,46 @@ describe('QueryInput', () => {
|
||||||
|
|
||||||
expect(mockOnSubmit).not.toHaveBeenCalled()
|
expect(mockOnSubmit).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('shows submitted question after clicking submit', () => {
|
||||||
|
render(<QueryInput onSubmit={mockOnSubmit} isLoading={false} />)
|
||||||
|
const textarea = screen.getByPlaceholderText('Ask a question about your documents...')
|
||||||
|
const button = screen.getByRole('button', { name: /submit/i })
|
||||||
|
|
||||||
|
fireEvent.change(textarea, { target: { value: 'What is NEC4?' } })
|
||||||
|
fireEvent.click(button)
|
||||||
|
|
||||||
|
expect(screen.getByTestId('submitted-question')).toHaveTextContent('What is NEC4?')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clears submitted question when user starts typing a new question', () => {
|
||||||
|
render(<QueryInput onSubmit={mockOnSubmit} isLoading={false} />)
|
||||||
|
const textarea = screen.getByPlaceholderText('Ask a question about your documents...')
|
||||||
|
const button = screen.getByRole('button', { name: /submit/i })
|
||||||
|
|
||||||
|
fireEvent.change(textarea, { target: { value: 'First question' } })
|
||||||
|
fireEvent.click(button)
|
||||||
|
expect(screen.getByTestId('submitted-question')).toBeInTheDocument()
|
||||||
|
|
||||||
|
fireEvent.change(textarea, { target: { value: 'New question' } })
|
||||||
|
expect(screen.queryByTestId('submitted-question')).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not show submitted question before any submission', () => {
|
||||||
|
render(<QueryInput onSubmit={mockOnSubmit} isLoading={false} />)
|
||||||
|
expect(screen.queryByTestId('submitted-question')).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not clear submitted question when typing only whitespace', () => {
|
||||||
|
render(<QueryInput onSubmit={mockOnSubmit} isLoading={false} />)
|
||||||
|
const textarea = screen.getByPlaceholderText('Ask a question about your documents...')
|
||||||
|
const button = screen.getByRole('button', { name: /submit/i })
|
||||||
|
|
||||||
|
fireEvent.change(textarea, { target: { value: 'My question' } })
|
||||||
|
fireEvent.click(button)
|
||||||
|
expect(screen.getByTestId('submitted-question')).toBeInTheDocument()
|
||||||
|
|
||||||
|
fireEvent.change(textarea, { target: { value: ' ' } })
|
||||||
|
expect(screen.getByTestId('submitted-question')).toBeInTheDocument()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue