diff --git a/tehriehlbudget-frontend/src/pages/Dashboard.tsx b/tehriehlbudget-frontend/src/pages/Dashboard.tsx index 8b13029..bbb2b77 100644 --- a/tehriehlbudget-frontend/src/pages/Dashboard.tsx +++ b/tehriehlbudget-frontend/src/pages/Dashboard.tsx @@ -27,6 +27,46 @@ function formatCurrency(value: number) { return value < 0 ? `-$${abs}` : `$${abs}`; } +// Owns its own input state so keystrokes don't re-render the parent Dashboard +// — that was reflowing the recharts pie/bar charts and making their labels +// flicker out for ~5s of animation replay on every character typed. +function AdvisorFollowUpForm({ + disabled, + onSubmit, +}: { + disabled: boolean; + onSubmit: (value: string) => Promise; +}) { + const [value, setValue] = useState(''); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + const trimmed = value.trim(); + if (!trimmed || disabled) return; + setValue(''); + await onSubmit(trimmed); + }; + + return ( +
+ setValue(e.target.value)} + placeholder="Ask a follow-up..." + disabled={disabled} + /> + +
+ ); +} + type RangeKey = 'this-month' | 'last-30' | 'last-90' | 'ytd'; const RANGE_LABELS: Record = { @@ -78,7 +118,6 @@ export function Dashboard() { sendMessage, resetConversation, } = useAdvisorStore(); - const [followUp, setFollowUp] = useState(''); const chatScrollRef = useRef(null); useEffect(() => { @@ -87,14 +126,6 @@ export function Dashboard() { } }, [advisorMessages]); - const handleSendFollowUp = async (e: React.FormEvent) => { - e.preventDefault(); - const trimmed = followUp.trim(); - if (!trimmed || advisorLoading) return; - setFollowUp(''); - await sendMessage(trimmed); - }; - const handleRestart = async () => { resetConversation(); await startConversation(); @@ -415,22 +446,10 @@ export function Dashboard() { )} -
- setFollowUp(e.target.value)} - placeholder="Ask a follow-up..." - disabled={advisorLoading} - /> - -
+ )}