feat: update ChatView layout

This commit is contained in:
Steven
2023-03-16 21:29:19 +08:00
parent 5ff430fe34
commit 4ea6ce143f
12 changed files with 154 additions and 34 deletions

View File

@ -1,17 +1,24 @@
import axios from "axios";
import { useRef, useState } from "react";
import { useEffect, useRef, useState } from "react";
import TextareaAutosize from "react-textarea-autosize";
import { useChatStore, useMessageStore, useUserStore } from "../../store";
import { UserRole } from "../../types";
import { generateUUID } from "../../utils";
import Icon from "../Icon";
const Textarea = () => {
const MessageTextarea = () => {
const userStore = useUserStore();
const chatStore = useChatStore();
const messageStore = useMessageStore();
const [value, setValue] = useState<string>("");
const textareaRef = useRef<HTMLTextAreaElement>(null);
useEffect(() => {
if (textareaRef.current) {
textareaRef.current.focus();
}
}, []);
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setValue(e.target.value);
};
@ -49,11 +56,20 @@ const Textarea = () => {
};
return (
<div className="w-full h-auto border-t relative">
<textarea ref={textareaRef} className="w-full h-full outline-none pt-2 px-2 resize-none" onChange={handleChange} rows={1} />
<Icon.Send className="absolute bottom-2 right-2" onClick={handleSend} />
<div className="w-full h-auto border rounded-md mb-4 px-2 py-1 relative shadow bg-white">
<TextareaAutosize
ref={textareaRef}
className="w-full h-full outline-none border-none bg-transparent pt-1 mt-1 px-2 resize-none hide-scrollbar"
rows={1}
minRows={1}
maxRows={5}
onChange={handleChange}
/>
<div className="absolute bottom-2 right-2 w-8 p-1 cursor-pointer rounded-md hover:shadow hover:bg-gray-100" onClick={handleSend}>
<Icon.Send className="w-full h-auto text-blue-800" />
</div>
</div>
);
};
export default Textarea;
export default MessageTextarea;

View File

@ -1,4 +1,7 @@
import { marked } from "marked";
import { useUserStore } from "../../store";
import { Message } from "../../types";
import "highlight.js/styles/github.css";
interface Props {
message: Message;
@ -6,8 +9,22 @@ interface Props {
const Message = (props: Props) => {
const message = props.message;
const userStore = useUserStore();
const currentUser = userStore.currentUser;
const isCurrentUser = message.creatorId === currentUser.id;
return <div>{message.content}</div>;
return (
<div className={`w-full flex flex-row justify-start items-start my-4 ${isCurrentUser ? "justify-end pl-8 sm:pl-16" : "pr-8 sm:pr-16"}`}>
{isCurrentUser ? (
<div className="w-auto max-w-full bg-white px-3 py-2 rounded-lg rounded-tr-none shadow">{message.content}</div>
) : (
<div
className="w-auto max-w-full bg-white px-3 py-2 rounded-lg rounded-tl-none shadow"
dangerouslySetInnerHTML={{ __html: marked.parse(message.content) }}
></div>
)}
</div>
);
};
export default Message;

View File

@ -4,6 +4,7 @@ import { User } from "../../types";
const Sidebar = () => {
const userStore = useUserStore();
const chatStore = useChatStore();
const currentChatUserId = chatStore.currentChat.userId;
const handleAssistantClick = (user: User) => {
for (const chat of chatStore.chatList) {
@ -16,13 +17,19 @@ const Sidebar = () => {
};
return (
<div className="w-full border-r p-2">
<h2>Assistant list</h2>
<div>
<div className="w-52 lg:w-64 h-full transition-all shrink-0 border-r p-2 sticky top-0">
<h2 className="pt-2 pb-4 w-full text-center">Assistant list</h2>
<div className="w-full mt-2 flex flex-col justify-start items-start">
{userStore.assistantList.map((assistant) => (
<p onClick={() => handleAssistantClick(assistant)} key={assistant.id}>
<div
className={`w-full py-2 px-3 rounded-md mb-2 cursor-pointer hover:opacity-80 hover:bg-gray-100 ${
currentChatUserId === assistant.id && "shadow bg-gray-100 font-medium"
}`}
onClick={() => handleAssistantClick(assistant)}
key={assistant.id}
>
{assistant.name}
</p>
</div>
))}
</div>
</div>

View File

@ -1,7 +1,7 @@
import { useChatStore, useMessageStore, useUserStore } from "../../store";
import MessageView from "./MessageView";
import Sidebar from "./Sidebar";
import Textarea from "./Textarea";
import MessageTextarea from "./MessageTextarea";
const ChatView = () => {
const chatStore = useChatStore();
@ -12,14 +12,16 @@ const ChatView = () => {
const messageList = messageStore.messageList.filter((message) => message.chatId === currentChat?.id);
return (
<div className="w-full max-w-full lg:max-w-3xl border rounded-md grid grid-cols-[192px_1fr]">
<div className="relative w-full max-w-full h-full rounded-md flex flex-row justify-start items-start">
<Sidebar />
<main className="w-full">
<p className="w-full text-center py-2 border-b">{chatTitle}</p>
<div className="py-2">
{messageList.length === 0 ? <p>no message</p> : messageList.map((message) => <MessageView key={message.id} message={message} />)}
<main className="relative grow w-auto h-full max-h-full flex flex-col justify-start items-start overflow-y-auto bg-gray-100">
<p className="sticky top-0 w-full text-center py-4 border-b bg-white">{chatTitle}</p>
<div className="p-2 w-full h-auto grow max-w-3xl py-1 px-4 mx-auto">
{messageList.length === 0 ? <></> : messageList.map((message) => <MessageView key={message.id} message={message} />)}
</div>
<div className="sticky bottom-0 w-full max-w-3xl py-1 px-4 mx-auto">
<MessageTextarea />
</div>
<Textarea />
</main>
</div>
);