From 5ff430fe34866b3dd6b184048c87ec200e9c63a5 Mon Sep 17 00:00:00 2001 From: steven Date: Thu, 16 Mar 2023 17:01:38 +0800 Subject: [PATCH] feat: implement stores and basic chat logic --- components/ChatView/MessageView.tsx | 13 +++ components/ChatView/Sidebar.tsx | 32 +++++++ components/ChatView/Textarea.tsx | 59 ++++++++++++ components/ChatView/index.tsx | 28 ++++++ components/Icon.tsx | 3 + package.json | 9 +- pages/_app.tsx | 2 +- pages/api/chat.ts | 7 +- pages/chat.tsx | 11 +-- pages/index.tsx | 10 +- pnpm-lock.yaml | 92 ++++++++++++++++++- store/chat.ts | 31 +++++++ store/index.ts | 3 + store/message.ts | 14 +++ store/user.ts | 36 ++++++++ pages/styles/globals.css => styles/global.css | 0 types/chat.ts | 6 ++ types/common.ts | 2 + types/index.ts | 4 + types/message.ts | 9 ++ types/user.ts | 13 +++ utils/index.ts | 5 + {pages/api => utils}/openai-api.ts | 1 + 23 files changed, 372 insertions(+), 18 deletions(-) create mode 100644 components/ChatView/MessageView.tsx create mode 100644 components/ChatView/Sidebar.tsx create mode 100644 components/ChatView/Textarea.tsx create mode 100644 components/ChatView/index.tsx create mode 100644 components/Icon.tsx create mode 100644 store/chat.ts create mode 100644 store/index.ts create mode 100644 store/message.ts create mode 100644 store/user.ts rename pages/styles/globals.css => styles/global.css (100%) create mode 100644 types/chat.ts create mode 100644 types/common.ts create mode 100644 types/index.ts create mode 100644 types/message.ts create mode 100644 types/user.ts create mode 100644 utils/index.ts rename {pages/api => utils}/openai-api.ts (99%) diff --git a/components/ChatView/MessageView.tsx b/components/ChatView/MessageView.tsx new file mode 100644 index 0000000..1d52385 --- /dev/null +++ b/components/ChatView/MessageView.tsx @@ -0,0 +1,13 @@ +import { Message } from "../../types"; + +interface Props { + message: Message; +} + +const Message = (props: Props) => { + const message = props.message; + + return
{message.content}
; +}; + +export default Message; diff --git a/components/ChatView/Sidebar.tsx b/components/ChatView/Sidebar.tsx new file mode 100644 index 0000000..72ca290 --- /dev/null +++ b/components/ChatView/Sidebar.tsx @@ -0,0 +1,32 @@ +import { useChatStore, useUserStore } from "../../store"; +import { User } from "../../types"; + +const Sidebar = () => { + const userStore = useUserStore(); + const chatStore = useChatStore(); + + const handleAssistantClick = (user: User) => { + for (const chat of chatStore.chatList) { + if (chat.userId === user.id) { + chatStore.setCurrentChat(chat); + return; + } + } + chatStore.createChat(user); + }; + + return ( +
+

Assistant list

+
+ {userStore.assistantList.map((assistant) => ( +

handleAssistantClick(assistant)} key={assistant.id}> + {assistant.name} +

+ ))} +
+
+ ); +}; + +export default Sidebar; diff --git a/components/ChatView/Textarea.tsx b/components/ChatView/Textarea.tsx new file mode 100644 index 0000000..cb50e13 --- /dev/null +++ b/components/ChatView/Textarea.tsx @@ -0,0 +1,59 @@ +import axios from "axios"; +import { useRef, useState } from "react"; +import { useChatStore, useMessageStore, useUserStore } from "../../store"; +import { UserRole } from "../../types"; +import { generateUUID } from "../../utils"; +import Icon from "../Icon"; + +const Textarea = () => { + const userStore = useUserStore(); + const chatStore = useChatStore(); + const messageStore = useMessageStore(); + const [value, setValue] = useState(""); + const textareaRef = useRef(null); + + const handleChange = (e: React.ChangeEvent) => { + setValue(e.target.value); + }; + + const handleSend = async () => { + if (!chatStore.currentChat) { + return; + } + + const currentChat = chatStore.currentChat; + messageStore.addMessage({ + id: generateUUID(), + chatId: currentChat.id, + creatorId: userStore.currentUser.id, + createdAt: Date.now(), + content: value, + }); + setValue(""); + textareaRef.current!.value = ""; + + const messageList = messageStore.getState().messageList.filter((message) => message.chatId === currentChat.id); + const { data } = await axios.post("/api/chat", { + messages: messageList.map((message) => ({ + role: message.creatorId === userStore.currentUser.id ? UserRole.User : UserRole.Assistant, + content: message.content, + })), + }); + messageStore.addMessage({ + id: generateUUID(), + chatId: currentChat.id, + creatorId: currentChat.userId, + createdAt: Date.now(), + content: data, + }); + }; + + return ( +
+