From 788b092dffbad39a4fbe2291ba10ebe2b1388035 Mon Sep 17 00:00:00 2001 From: Chandrapal Badshah <12944530+Chan9390@users.noreply.github.com> Date: Wed, 4 Jun 2025 15:27:50 +0530 Subject: [PATCH] Use CustomTextarea component --- ui/components/lighthouse/chat.tsx | 167 ++++++++++++++++++------------ 1 file changed, 100 insertions(+), 67 deletions(-) diff --git a/ui/components/lighthouse/chat.tsx b/ui/components/lighthouse/chat.tsx index 5797d4b959..4ed1aefd1b 100644 --- a/ui/components/lighthouse/chat.tsx +++ b/ui/components/lighthouse/chat.tsx @@ -3,9 +3,11 @@ import { useChat } from "@ai-sdk/react"; import Link from "next/link"; import { useEffect, useRef } from "react"; +import { useForm } from "react-hook-form"; import { MemoizedMarkdown } from "@/components/lighthouse/memoized-markdown"; -import { CustomButton } from "@/components/ui/custom"; +import { CustomButton, CustomTextarea } from "@/components/ui/custom"; +import { Form } from "@/components/ui/form"; interface SuggestedAction { title: string; @@ -17,9 +19,13 @@ interface ChatProps { hasApiKey: boolean; } +interface ChatFormData { + message: string; +} + export const Chat = ({ hasApiKey }: ChatProps) => { - const { messages, input, handleSubmit, handleInputChange, append, status } = - useChat({ + const { messages, handleSubmit, handleInputChange, append, status } = useChat( + { api: "/api/lighthouse/analyst", credentials: "same-origin", experimental_throttle: 100, @@ -27,10 +33,67 @@ export const Chat = ({ hasApiKey }: ChatProps) => { onFinish: () => { // Handle chat completion }, - onError: () => { - console.log("An error occurred, please try again!"); + onError: (error) => { + console.error("Chat error:", error); }, - }); + }, + ); + + const form = useForm({ + defaultValues: { + message: "", + }, + }); + + const messageValue = form.watch("message"); + const messagesContainerRef = useRef(null); + const latestUserMsgRef = useRef(null); + + // Sync form value with chat input + useEffect(() => { + const syntheticEvent = { + target: { value: messageValue }, + } as React.ChangeEvent; + handleInputChange(syntheticEvent); + }, [messageValue, handleInputChange]); + + // Reset form when message is sent + useEffect(() => { + if (status === "submitted") { + form.reset({ message: "" }); + } + }, [status, form]); + + const onFormSubmit = form.handleSubmit((data) => { + if (data.message.trim()) { + handleSubmit(); + } + }); + + // Global keyboard shortcut handler + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if ((e.metaKey || e.ctrlKey) && e.key === "Enter") { + e.preventDefault(); + if (messageValue?.trim()) { + onFormSubmit(); + } + } + }; + + document.addEventListener("keydown", handleKeyDown); + return () => document.removeEventListener("keydown", handleKeyDown); + }, [messageValue, onFormSubmit]); + + useEffect(() => { + if (messagesContainerRef.current && latestUserMsgRef.current) { + const container = messagesContainerRef.current; + const userMsg = latestUserMsgRef.current; + const containerPadding = 16; // p-4 in Tailwind = 16px + container.scrollTop = + userMsg.offsetTop - container.offsetTop - containerPadding; + } + }, [messages]); const suggestedActions: SuggestedAction[] = [ { @@ -56,36 +119,6 @@ export const Chat = ({ hasApiKey }: ChatProps) => { }, ]; - const textareaRef = useRef(null); - const messagesContainerRef = useRef(null); - const latestUserMsgRef = useRef(null); - - useEffect(() => { - if (messagesContainerRef.current && latestUserMsgRef.current) { - const container = messagesContainerRef.current; - const userMsg = latestUserMsgRef.current; - const containerPadding = 16; // p-4 in Tailwind = 16px - container.scrollTop = - userMsg.offsetTop - container.offsetTop - containerPadding; - } - }, [messages]); - - const handleAutoResizeInputChange = ( - e: React.ChangeEvent, - ) => { - handleInputChange(e); - const textarea = textareaRef.current; - if (textarea) { - textarea.style.height = "auto"; - textarea.style.height = textarea.scrollHeight + "px"; - if (textarea.scrollHeight > textarea.clientHeight + 1) { - textarea.style.overflowY = "auto"; - } else { - textarea.style.overflowY = "hidden"; - } - } - }; - return (
{!hasApiKey && ( @@ -181,38 +214,38 @@ export const Chat = ({ hasApiKey }: ChatProps) => {
)} -
-
-