mirror of
https://github.com/sqlchat/sqlchat.git
synced 2025-07-29 18:23:25 +08:00
feat: update ChatView layout
This commit is contained in:
@ -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;
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
);
|
||||
|
Reference in New Issue
Block a user