Skip to content

Commit

Permalink
fix /new page
Browse files Browse the repository at this point in the history
  • Loading branch information
yoziru committed Apr 2, 2024
1 parent 3b865e5 commit fa28737
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 219 deletions.
89 changes: 4 additions & 85 deletions src/app/chats/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,95 +2,14 @@

import React from "react";

import { ChatRequestOptions } from "ai";
import { useChat } from "ai/react";
import { toast } from "sonner";
import useLocalStorageState from "use-local-storage-state";

import { ChatLayout } from "@/components/chat/chat-layout";
import { ChatOptions } from "@/components/chat/chat-options";
import { basePath } from "@/lib/utils";
import ChatPage from "@/components/chat/chat-page";

export default function Page({ params }: { params: { id: string } }) {
const {
messages,
input,
handleInputChange,
handleSubmit,
isLoading,
error,
stop,
setMessages,
} = useChat({
api: basePath + "/api/chat",
onError: (error) => {
toast.error("Something went wrong: " + error);
},
});
const [chatId, setChatId] = React.useState<string>("");
const [chatOptions, setChatOptions] = useLocalStorageState<ChatOptions>(
"chatOptions",
{
defaultValue: {
selectedModel: "",
systemPrompt: "",
temperature: 0.9,
},
}
);

React.useEffect(() => {
if (params.id) {
const item = localStorage.getItem(`chat_${params.id}`);
if (item) {
setMessages(JSON.parse(item));
}
setChatId(params.id);
}
}, [setMessages, params.id]);

const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();

setMessages([...messages]);

// Prepare the options object with additional body data, to pass the model.
const requestOptions: ChatRequestOptions = {
options: {
body: {
chatOptions: chatOptions,
},
},
};

// Call the handleSubmit function with the options
handleSubmit(e, requestOptions);
};

// When starting a new chat, append the messages to the local storage
React.useEffect(() => {
if (!isLoading && !error && messages.length > 0) {
localStorage.setItem(`chat_${params.id}`, JSON.stringify(messages));
// Trigger the storage event to update the sidebar component
window.dispatchEvent(new Event("storage"));
}
}, [messages, chatId, isLoading, error, params.id]);

return (
<main className="flex h-[calc(100dvh)] flex-col items-center">
<ChatLayout
chatId={params.id}
chatOptions={chatOptions}
setChatOptions={setChatOptions}
messages={messages}
input={input}
handleInputChange={handleInputChange}
handleSubmit={onSubmit}
isLoading={isLoading}
error={error}
stop={stop}
navCollapsedSize={10}
defaultLayout={[30, 160]}
/>
</main>
);
}, [params.id]);
return <ChatPage chatId={chatId} setChatId={setChatId} />;
}
5 changes: 0 additions & 5 deletions src/app/new/page.tsx

This file was deleted.

89 changes: 2 additions & 87 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,94 +1,9 @@
"use client";

import React from "react";

import { ChatRequestOptions } from "ai";
import { useChat } from "ai/react";
import { toast } from "sonner";
import useLocalStorageState from "use-local-storage-state";
import { v4 as uuidv4 } from "uuid";

import { ChatLayout } from "@/components/chat/chat-layout";
import { ChatOptions } from "@/components/chat/chat-options";
import { basePath } from "@/lib/utils";
import ChatPage from "@/components/chat/chat-page";

export default function Home() {
const {
messages,
input,
handleInputChange,
handleSubmit,
isLoading,
error,
stop,
setMessages,
} = useChat({
api: basePath + "/api/chat",
onError: (error) => {
toast.error("Something went wrong: " + error);
},
});
const [chatId, setChatId] = React.useState<string>("");
const [chatOptions, setChatOptions] = useLocalStorageState<ChatOptions>(
"chatOptions",
{
defaultValue: {
selectedModel: "",
systemPrompt: "",
temperature: 0.9,
},
}
);

React.useEffect(() => {
if (!isLoading && !error && chatId && messages.length > 0) {
// Save messages to local storage
localStorage.setItem(`chat_${chatId}`, JSON.stringify(messages));
// Trigger the storage event to update the sidebar component
window.dispatchEvent(new Event("storage"));
}
}, [messages, chatId, isLoading, error]);

const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();

if (messages.length === 0) {
// Generate a random id for the chat
const id = uuidv4();
setChatId(id);
}

setMessages([...messages]);

// Prepare the options object with additional body data, to pass the model.
const requestOptions: ChatRequestOptions = {
options: {
body: {
chatOptions: chatOptions,
},
},
};

// Call the handleSubmit function with the options
handleSubmit(e, requestOptions);
};

return (
<main className="flex h-[calc(100dvh)] flex-col items-center ">
<ChatLayout
chatId=""
chatOptions={chatOptions}
setChatOptions={setChatOptions}
messages={messages}
input={input}
handleInputChange={handleInputChange}
handleSubmit={onSubmit}
isLoading={isLoading}
error={error}
stop={stop}
navCollapsedSize={10}
defaultLayout={[30, 160]}
/>
</main>
);
return <ChatPage chatId={chatId} setChatId={setChatId} />;
}
14 changes: 10 additions & 4 deletions src/components/chat/chat-bottombar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,29 @@
import React from "react";

import { PaperPlaneIcon, StopIcon } from "@radix-ui/react-icons";
import { ChatRequestOptions } from "ai";
import TextareaAutosize from "react-textarea-autosize";

import { Button } from "../ui/button";
import { ChatProps } from "./chat";

interface ChatBottombarProps extends ChatProps {
interface ChatBottombarProps {
selectedModel: string | undefined;
input: string;
handleInputChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
handleSubmit: (
e: React.FormEvent<HTMLFormElement>,
chatRequestOptions?: ChatRequestOptions
) => void;
isLoading: boolean;
stop: () => void;
}

export default function ChatBottombar({
selectedModel,
messages,
input,
handleInputChange,
handleSubmit,
isLoading,
error,
stop,
}: ChatBottombarProps) {
const inputRef = React.useRef<HTMLTextAreaElement>(null);
Expand Down
4 changes: 3 additions & 1 deletion src/components/chat/chat-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export function ChatLayout({
error,
stop,
chatId,
setChatId,
chatOptions,
setChatOptions,
}: MergedProps) {
Expand Down Expand Up @@ -91,16 +92,17 @@ export function ChatLayout({
>
<Sidebar
isCollapsed={isCollapsed || isMobile}
messages={messages}
isMobile={isMobile}
chatId={chatId}
setChatId={setChatId}
chatOptions={chatOptions}
setChatOptions={setChatOptions}
/>
</ResizablePanel>
<ResizablePanel className="h-full" defaultSize={defaultLayout[1]}>
<Chat
chatId={chatId}
setChatId={setChatId}
chatOptions={chatOptions}
setChatOptions={setChatOptions}
messages={messages}
Expand Down
17 changes: 7 additions & 10 deletions src/components/chat/chat-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ import Image from "next/image";
import { cn } from "@/lib/utils";
import OllamaLogo from "../../../public/ollama.png";
import CodeDisplayBlock from "../code-display-block";
import { ChatProps } from "./chat";
import { Message } from "ai";

export default function ChatList({
messages,
input,
handleInputChange,
handleSubmit,
isLoading,
error,
stop,
}: ChatProps) {
interface ChatListProps {
messages: Message[];
isLoading: boolean;
}

export default function ChatList({ messages, isLoading }: ChatListProps) {
const bottomRef = useRef<HTMLDivElement>(null);

const scrollToBottom = () => {
Expand Down
109 changes: 109 additions & 0 deletions src/components/chat/chat-page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"use client";

import React from "react";

import { ChatRequestOptions } from "ai";
import { useChat } from "ai/react";
import { toast } from "sonner";
import useLocalStorageState from "use-local-storage-state";
import { v4 as uuidv4 } from "uuid";

import { ChatLayout } from "@/components/chat/chat-layout";
import { ChatOptions } from "@/components/chat/chat-options";
import { basePath } from "@/lib/utils";

interface ChatPageProps {
chatId: string;
setChatId: React.Dispatch<React.SetStateAction<string>>;
}
export default function ChatPage({ chatId, setChatId }: ChatPageProps) {
const {
messages,
input,
handleInputChange,
handleSubmit,
isLoading,
error,
stop,
setMessages,
} = useChat({
api: basePath + "/api/chat",
onError: (error) => {
toast.error("Something went wrong: " + error);
},
});
const [chatOptions, setChatOptions] = useLocalStorageState<ChatOptions>(
"chatOptions",
{
defaultValue: {
selectedModel: "",
systemPrompt: "",
temperature: 0.9,
},
}
);

React.useEffect(() => {
if (chatId) {
const item = localStorage.getItem(`chat_${chatId}`);
if (item) {
setMessages(JSON.parse(item));
}
} else {
setMessages([]);
}
}, [setMessages, chatId]);

React.useEffect(() => {
if (!isLoading && !error && chatId && messages.length > 0) {
// Save messages to local storage
localStorage.setItem(`chat_${chatId}`, JSON.stringify(messages));
// Trigger the storage event to update the sidebar component
window.dispatchEvent(new Event("storage"));
}
}, [messages, chatId, isLoading, error]);

const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();

if (messages.length === 0) {
// Generate a random id for the chat
const id = uuidv4();
setChatId(id);
}

setMessages([...messages]);

// Prepare the options object with additional body data, to pass the model.
const requestOptions: ChatRequestOptions = {
options: {
body: {
chatOptions: chatOptions,
},
},
};

// Call the handleSubmit function with the options
handleSubmit(e, requestOptions);
};

return (
<main className="flex h-[calc(100dvh)] flex-col items-center ">
<ChatLayout
chatId={chatId}
setChatId={setChatId}
chatOptions={chatOptions}
setChatOptions={setChatOptions}
messages={messages}
input={input}
handleInputChange={handleInputChange}
handleSubmit={onSubmit}
isLoading={isLoading}
error={error}
stop={stop}
navCollapsedSize={10}
defaultLayout={[30, 160]}
/>
</main>
);
}
Loading

0 comments on commit fa28737

Please sign in to comment.