feat: Add Chat LLM functionality with message input and display components

This commit is contained in:
2025-06-16 23:18:18 +02:00
parent 9c638fc3e5
commit 6d6fab5634
7 changed files with 123 additions and 5 deletions
+1 -1
View File
@@ -21,4 +21,4 @@ app.add_middleware(
# Incluye las rutas de tu API
app.include_router(router)
app.include_router(router, prefix="/api/v1", tags=["v1"])
+3 -3
View File
@@ -7,6 +7,6 @@ from backend.domains.text_manager import text_manager_endpoint_v1
router = APIRouter()
router.include_router(ping_endpoint_v1.router, prefix="/api/v1/ping")
router.include_router(text_manager_endpoint_v1.router, prefix="/api/v1/text_manager")
router.include_router(charts.router, prefix="/api/v1/charts")
router.include_router(ping_endpoint_v1.router, prefix="/ping")
router.include_router(text_manager_endpoint_v1.router, prefix="/text_manager")
router.include_router(charts.router, prefix="/charts")
+11 -1
View File
@@ -7,7 +7,7 @@ import { Biblioteca } from './domains/TextEditor/Biblioteca';
import { VisualizacionesRandom } from './domains/Experiments/Visualizaciones_Random';
import { Camara_noir } from './domains/CamaraNoir/Camaras_noir';
import EditorTest from "./domains/TextEditor/Editor_Test";
import { ChatPage } from './domains/Llms/Chat/ChatPage';
const router = createBrowserRouter([
@@ -33,6 +33,16 @@ const router = createBrowserRouter([
},
// Chat LLM
{
path: '/llms/chat',
element: <ChatPage />,
},
// CamaraNoir
{
@@ -0,0 +1,27 @@
import { useState } from "react";
import { Textarea, Button, Group } from "@mantine/core";
export function ChatInput({ onSend }: { onSend: (text: string) => void }) {
const [text, setText] = useState("");
const handleSend = () => {
if (!text.trim()) return;
onSend(text.trim());
setText("");
};
return (
<Group>
<Textarea
value={text}
onChange={(e) => setText(e.currentTarget.value)}
autosize
minRows={1}
maxRows={4}
placeholder="Escribe tu mensaje..."
style={{ flex: 1 }}
/>
<Button onClick={handleSend}>Enviar</Button>
</Group>
);
}
@@ -0,0 +1,41 @@
import { useState } from "react";
import { Container, Stack, Paper, ScrollArea, Title } from "@mantine/core";
import { ChatInput } from "./ChatInput";
import { MessageList } from "./MessageList";
import { AppShellWithMenu } from "../../FitzStudio/Appshell/Appshell";
export function ChatPage() {
const [messages, setMessages] = useState([
{ sender: "bot", content: "Hola, ¿en qué puedo ayudarte hoy?" },
]);
const handleSend = async (content: string) => {
const newMessages = [...messages, { sender: "user", content }];
setMessages(newMessages);
const response = await fetch("/api/chat", {
method: "POST",
body: JSON.stringify({ messages: newMessages }),
headers: { "Content-Type": "application/json" },
});
const data = await response.json();
setMessages([...newMessages, { sender: "bot", content: data.reply }]);
};
return (
<AppShellWithMenu>
<Container size="sm" p="md">
<Stack>
<Title order={2}>Chat LLM</Title>
<Paper shadow="xs" p="md" withBorder>
<ScrollArea h={400}>
<MessageList messages={messages} />
</ScrollArea>
</Paper>
<ChatInput onSend={handleSend} />
</Stack>
</Container>
</AppShellWithMenu>
);
}
@@ -0,0 +1,28 @@
import { Paper, Text, useMantineTheme, useMantineColorScheme } from "@mantine/core";
export function MessageBubble({ sender, content }: { sender: string; content: string }) {
const theme = useMantineTheme();
const { colorScheme } = useMantineColorScheme();
const isUser = sender === "user";
const userBg = theme.colors[theme.primaryColor][0];
const botBg = colorScheme === "dark" ? theme.colors.dark[6] : theme.colors.gray[0];
const userTextColor = theme.colors[theme.primaryColor][9];
return (
<Paper
p="sm"
radius="md"
withBorder
style={{
alignSelf: isUser ? "flex-end" : "flex-start",
backgroundColor: isUser ? userBg : botBg,
maxWidth: "80%",
}}
>
<Text size="sm" c={isUser ? userTextColor : undefined}>
{content}
</Text>
</Paper>
);
}
@@ -0,0 +1,12 @@
import { Stack } from "@mantine/core";
import { MessageBubble } from "./MessageBubble";
export function MessageList({ messages }: { messages: { sender: string; content: string }[] }) {
return (
<Stack>
{messages.map((msg, i) => (
<MessageBubble key={i} sender={msg.sender} content={msg.content} />
))}
</Stack>
);
}