skbeta/components/chat.tsx
Christopher Arraya c55ab3d49e initial commit
2024-01-13 20:55:51 -05:00

152 lines
4.1 KiB
TypeScript

"use client";
import { useEffect, useState, useRef } from "react";
import { Send } from "lucide-react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardFooter,
CardHeader,
} from "@/components/ui/card";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Input } from "@/components/ui/input";
import { useChat } from "ai/react";
export default function Chat({ projectInfo, featureInfo, taskInfo }: any) {
// console.log("projectInfo", projectInfo);
// console.log("featureInfo", featureInfo);
// console.log("taskInfo", taskInfo);
const { messages, input, handleInputChange, handleSubmit, setMessages } =
useChat({
body: {
projectInfo,
featureInfo,
taskInfo,
},
api: "/chat",
onResponse: async (res) => {
try {
console.log("RESPONSE ===>", res);
const task_id = taskInfo.task_id;
const data = await fetch(`/chat/add`, {
method: "POST",
body: JSON.stringify({
content: input,
role: "user",
task_id: task_id,
}),
});
} catch (err) {
console.error(err);
}
},
onFinish: async (message) => {
try {
console.log("FINISH ===>", message);
const data = await fetch(`/chat/add`, {
method: "POST",
body: JSON.stringify({
content: message.content,
role: "assistant",
task_id: taskInfo.task_id,
}),
});
} catch (err) {
console.error(err);
}
},
onError: (err) => {
console.error("CHAT HOOK ERROR ===>", err);
},
});
useEffect(() => {
async function getMessages() {
try {
const res = await fetch(`/chat/${taskInfo.task_id}`);
const data = await res.json();
console.log("CLIENT RAW RES ===>", data);
setMessages(data.messages);
return data;
} catch (err) {
console.error(err);
}
}
getMessages();
}, [setMessages, taskInfo.task_id]);
const scrollRef = useRef(null);
useEffect(() => {
// Function to scroll to the bottom of the chat
// add typing
const scrollToBottom = () => {
const scroll = scrollRef.current as any;
if (scroll) {
scroll.scrollTop = scroll.scrollHeight;
}
};
// Call scrollToBottom whenever messages change
scrollToBottom();
}, [messages]);
const inputLength = input.trim().length;
return (
<>
<Card className="rounded-md">
<CardHeader className="flex flex-row items-center">
<h1 className="font-semibold text-xl">Chat with this task.</h1>
</CardHeader>
<CardContent>
<ScrollArea ref={scrollRef} className="max-h-[20rem] overflow-y-auto">
<div className="space-y-4">
{messages.map((message, index) => (
<div
key={index}
className={cn(
"flex w-fit max-w-[75%] flex-col gap-2 rounded-md px-3 py-2 text-sm",
message.role === "user"
? "ml-auto bg-primary text-primary-foreground"
: "bg-muted"
)}
>
{message.content}
</div>
))}
</div>
</ScrollArea>
</CardContent>
<CardFooter>
<form
onSubmit={handleSubmit}
className="flex w-full items-center space-x-2"
>
<Input
id="message"
placeholder="Type your message..."
className="flex-1"
autoComplete="off"
value={input}
onChange={handleInputChange}
/>
<Button type="submit" size="icon" disabled={inputLength === 0}>
<Send className="h-4 w-4" />
<span className="sr-only">Send</span>
</Button>
</form>
</CardFooter>
</Card>
</>
);
}