matt HOFFNER
redesign, working on mobile still
2c3d303
raw
history blame
4.23 kB
"use client";
import styles from './page.module.css';
import { useEffect, useRef, useState } from 'react';
import { useChat } from 'ai/react';
import { Message } from 'ai';
import ReactMarkdown from "react-markdown";
import { functionCallHandler } from './hooks/useFunctions';
import Input from './input';
const Page: React.FC = () => {
// Ref for the messages container
const messagesRef = useRef<HTMLDivElement>(null);
const [keyboardHeight, setKeyboardHeight] = useState(0);
const [isKeyboardVisible, setIsKeyboardVisible] = useState(false);
const { messages, input, setInput, handleSubmit, isLoading } = useChat({
experimental_onFunctionCall: functionCallHandler,
onError: (error: any) => {
console.log(error);
},
});
const inputRef = useRef(null);
useEffect(() => {
if (messagesRef.current) {
messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
}
}, [messages]);
const [isExpanded, setIsExpanded] = useState(false);
const toggleExpand = () => {
setIsExpanded(!isExpanded);
};
const roleUIConfig: {
[key: string]: {
bgColor: string;
avatarColor: string;
// eslint-disable-next-line no-unused-vars
dialogComponent: (message: Message) => JSX.Element;
};
} = {
user: {
bgColor: "bg-white",
avatarColor: "bg-black",
dialogComponent: (message: Message) => (
<div className="message-content-container">
<ReactMarkdown
className=""
components={{
a: (props) => (
<a {...props} target="_blank" rel="noopener noreferrer" />
),
}}
>
{message.content}
</ReactMarkdown>
</div>
),
},
assistant: {
bgColor: "bg-gray-100",
avatarColor: "bg-green-500",
dialogComponent: (message: Message) => (
<div className="message-content-container">
<ReactMarkdown
className=""
components={{
a: (props) => (
<a {...props} target="_blank" rel="noopener noreferrer" />
),
}}
>
{message.content}
</ReactMarkdown>
</div>
),
},
function: {
bgColor: "bg-gray-200",
avatarColor: "bg-blue-500",
dialogComponent: (message: Message) => {
return (
<div className="flex flex-col">
{isExpanded && (
<div className="py-1">{message.content}</div>
)}
</div>
);
},
}
};
return (
<main className={styles.main}>
<div className={styles.messages} ref={messagesRef}>
{messages.length > 0 ? (
messages.map((message, i) => {
const messageClass = `${styles.message} ${message.role === 'user' ? styles['message-user'] : ''}`;
return (
<div key={i} className={messageClass} style={{ display: 'flex', alignItems: 'center' }}>
{message.content === "" && message.function_call != undefined ? (
typeof message.function_call === "object" ? (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<div>
Using{" "}
<span className="font-bold">
{message.function_call.name}
</span>{" "}
...
</div>
<div>
{message.function_call.arguments}
</div>
</div>
) : (
<div className="function-call">{message.function_call}</div>
)
) : (
<div className="message-text">
{roleUIConfig[message.role].dialogComponent(message)}
</div>
)}
</div>
);
})
) : null}
</div>
<Input inputRef={inputRef} handleSubmit={handleSubmit as any} setInput={setInput} input={input} />
</main>
);
}
export default Page;