mirror of
https://github.com/eliasstepanik/core.git
synced 2026-01-10 08:58:31 +00:00
* Feat: v2 * feat: add chat functionality * First cut: integrations * Feat: add conversation API * Enhance conversation handling and memory management * Feat: added conversation --------- Co-authored-by: Manoj K <saimanoj58@gmail.com>
152 lines
5.4 KiB
TypeScript
152 lines
5.4 KiB
TypeScript
import { EditorRoot, EditorContent, Placeholder } from "novel";
|
|
import { useState, useRef, useCallback } from "react";
|
|
import { Form, useNavigate, useSubmit } from "@remix-run/react";
|
|
import { cn } from "~/lib/utils";
|
|
import { Document } from "@tiptap/extension-document";
|
|
import HardBreak from "@tiptap/extension-hard-break";
|
|
import { History } from "@tiptap/extension-history";
|
|
import { Paragraph } from "@tiptap/extension-paragraph";
|
|
import { Text } from "@tiptap/extension-text";
|
|
import { Button } from "../ui";
|
|
import {
|
|
ResizableHandle,
|
|
ResizablePanel,
|
|
ResizablePanelGroup,
|
|
} from "../ui/resizable";
|
|
import { ConversationList } from "./conversation-list";
|
|
|
|
export const ConversationNew = ({
|
|
user,
|
|
}: {
|
|
user: { name: string | null };
|
|
}) => {
|
|
const [content, setContent] = useState("");
|
|
const editorRef = useRef<any>(null);
|
|
|
|
const submit = useSubmit();
|
|
|
|
// Send message to API
|
|
const submitForm = useCallback(
|
|
async (e: React.FormEvent<HTMLFormElement>) => {
|
|
if (!content.trim()) return;
|
|
|
|
submit(
|
|
{ message: content, title: content },
|
|
{
|
|
action: "/home/conversation",
|
|
method: "post",
|
|
},
|
|
);
|
|
e.preventDefault();
|
|
},
|
|
[content],
|
|
);
|
|
|
|
return (
|
|
<ResizablePanelGroup direction="horizontal" className="bg-background-2">
|
|
<ResizablePanel
|
|
maxSize={50}
|
|
defaultSize={16}
|
|
minSize={16}
|
|
collapsible
|
|
collapsedSize={16}
|
|
className="border-border h-[calc(100vh_-_60px)] min-w-[200px] border-r-1"
|
|
>
|
|
<ConversationList />
|
|
</ResizablePanel>
|
|
<ResizableHandle className="w-1" />
|
|
|
|
<ResizablePanel
|
|
collapsible
|
|
collapsedSize={0}
|
|
className="flex h-[calc(100vh_-_24px)] w-full flex-col"
|
|
>
|
|
<Form
|
|
action="/home/conversation"
|
|
method="post"
|
|
onSubmit={(e) => submitForm(e)}
|
|
className="pt-2"
|
|
>
|
|
<div className={cn("flex h-[calc(100vh_-_60px)] flex-col")}>
|
|
<div className="flex h-full w-full flex-col items-start justify-start overflow-y-auto p-4">
|
|
<div className="flex w-full flex-col items-center">
|
|
<div className="w-full max-w-[90ch]">
|
|
<h1 className="mx-1 mb-4 text-left text-[32px] font-medium">
|
|
Hello <span className="text-primary">{user.name}</span>
|
|
</h1>
|
|
<div className="bg-background-3 border-border rounded-lg border-1 py-2">
|
|
<EditorRoot>
|
|
<EditorContent
|
|
ref={editorRef}
|
|
autofocus
|
|
extensions={[
|
|
Placeholder.configure({
|
|
placeholder: () => {
|
|
return "Ask sol...";
|
|
},
|
|
includeChildren: true,
|
|
}),
|
|
Document,
|
|
Paragraph,
|
|
Text,
|
|
HardBreak.configure({
|
|
keepMarks: true,
|
|
}),
|
|
History,
|
|
]}
|
|
editorProps={{
|
|
attributes: {
|
|
class: `prose prose-lg dark:prose-invert prose-headings:font-title font-default focus:outline-none max-w-full`,
|
|
},
|
|
handleKeyDown: (_view: any, event: KeyboardEvent) => {
|
|
// This is the ProseMirror event, not React's
|
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
event.preventDefault();
|
|
|
|
if (content) {
|
|
submit(
|
|
{ message: content, title: content },
|
|
{
|
|
action: "/home/conversation",
|
|
method: "post",
|
|
},
|
|
);
|
|
|
|
setContent("");
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
}}
|
|
immediatelyRender={false}
|
|
className={cn(
|
|
"editor-container text-md max-h-[400px] min-h-[30px] w-full min-w-full overflow-auto px-3 pt-1 sm:rounded-lg",
|
|
)}
|
|
onUpdate={({ editor }: { editor: any }) => {
|
|
const html = editor.getHTML();
|
|
setContent(html);
|
|
}}
|
|
/>
|
|
</EditorRoot>
|
|
<div className="flex justify-end px-3">
|
|
<Button
|
|
variant="default"
|
|
className="gap-1 shadow-none transition-all duration-500 ease-in-out"
|
|
type="submit"
|
|
size="lg"
|
|
>
|
|
Chat
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Form>
|
|
</ResizablePanel>
|
|
</ResizablePanelGroup>
|
|
);
|
|
};
|