shit
This commit is contained in:
parent
5c16d12f77
commit
1515ee0589
6 changed files with 118 additions and 28 deletions
|
|
@ -5,7 +5,6 @@ function App() {
|
|||
return (
|
||||
<div className="dark min-h-screen bg-gray-950 text-white flex justify-center pt-12">
|
||||
<ChatLayout />
|
||||
<div></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,22 @@ import React, { useState } from "react";
|
|||
import ChatHeader from "src/components/ui/chat/chat-header";
|
||||
import ChatWindow from "src/components/ui/chat/chat-window";
|
||||
import MessageInput from "src/components/ui/chat/message-input";
|
||||
import { GoogleGenAI } from "@google/genai";
|
||||
import { useChatBackend } from "src/context/chat-backend-context";
|
||||
|
||||
const ai = new GoogleGenAI({ apiKey: import.meta.env.GEMINI_API_KEY });
|
||||
|
||||
async function AIResponse(userInputArray) {
|
||||
const response = await ai.models.generateContent({
|
||||
model: "gemini-2.5-flash",
|
||||
|
||||
contents: userInputArray,
|
||||
});
|
||||
|
||||
return response.text;
|
||||
}
|
||||
|
||||
let userInput = [];
|
||||
|
||||
export default function ChatLayout() {
|
||||
const [messages, setMessages] = useState([
|
||||
|
|
@ -11,29 +27,6 @@ export default function ChatLayout() {
|
|||
},
|
||||
]);
|
||||
|
||||
function addMessage(role, content) {
|
||||
const msg = { role, content };
|
||||
setMessages((s) => [...s, msg]);
|
||||
}
|
||||
|
||||
function handleSend(text) {
|
||||
const userMsg = { role: "user", content: text };
|
||||
setMessages((s) => [...s, userMsg]);
|
||||
|
||||
// fake assistant reply after short delay
|
||||
setTimeout(() => {
|
||||
setMessages((s) => [
|
||||
...s,
|
||||
{ role: "assistant", content: `You said: ${text}` },
|
||||
]);
|
||||
}, 600);
|
||||
}
|
||||
|
||||
function handleDeleteAll() {
|
||||
if (!window.confirm("Delete all messages?")) return;
|
||||
setMessages([]);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col flex-start w-full max-w-3xl gap-4 p-4">
|
||||
<ChatHeader onDeleteAll={handleDeleteAll} />
|
||||
|
|
@ -46,3 +39,42 @@ export default function ChatLayout() {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function addMessage(role, content) {
|
||||
const msg = { role, content };
|
||||
setMessages((s) => [...s, msg]);
|
||||
}
|
||||
|
||||
async function handleSend(text) {
|
||||
const { setMessages } = useChatBackend();
|
||||
const userMsg = { role: "user", content: text };
|
||||
|
||||
switch (setMessages) {
|
||||
case "gemini":
|
||||
userInput.push(text);
|
||||
const res = await AIResponse(userInput);
|
||||
setMessages((s) => [...s, userMsg]);
|
||||
setTimeout(() => {
|
||||
setMessages((s) => [...s, { role: "assistant", content: res }]);
|
||||
}, 600);
|
||||
break;
|
||||
case "rust":
|
||||
setMessages((s) => [...s, userMsg]);
|
||||
|
||||
// fake assistant reply after short delay
|
||||
setTimeout(() => {
|
||||
setMessages((s) => [
|
||||
...s,
|
||||
{ role: "assistant", content: `You said: ${text}` },
|
||||
]);
|
||||
}, 600);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function handleDeleteAll() {
|
||||
if (!window.confirm("Delete all messages?")) return;
|
||||
setMessages([]);
|
||||
}
|
||||
|
|
|
|||
26
web-app/src/components/ui/button/backend-toggle.jsx
Normal file
26
web-app/src/components/ui/button/backend-toggle.jsx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import React from "react";
|
||||
import { motion } from "motion/react";
|
||||
import { Cpu } from "lucide-react";
|
||||
import { useChatBackend } from "src/context/chat-backend-context";
|
||||
|
||||
export default function BackendToggle({ className }) {
|
||||
const { backend, toggleBackend } = useChatBackend();
|
||||
|
||||
return (
|
||||
<motion.button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
toggleBackend();
|
||||
}}
|
||||
className={`bg-gray-700 p-2 rounded-2xl file-input border-2 border-gray-600 text-md flex items-center gap-2 ${className || ""}`}
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
title={`${backend}`}
|
||||
>
|
||||
<Cpu className="w-4 h-4" />
|
||||
<span className="uppercase">
|
||||
{backend === "rust" ? "rust" : "gemini"}
|
||||
</span>
|
||||
</motion.button>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
import React, { useState, useRef, useEffect } from "react";
|
||||
import DownButton from "src/components/ui/button/down-button";
|
||||
import BackendToggle from "src/components/ui/button/backend-toggle";
|
||||
import ChatBackendContext from "src/context/chat-backend-context";
|
||||
import { motion } from "motion/react";
|
||||
import { BotMessageSquare } from "lucide-react";
|
||||
|
||||
|
|
@ -59,7 +61,6 @@ export default function MessageInput({ onSend, onMessage }) {
|
|||
console.error(err);
|
||||
if (onMessage) onMessage("assistant", `Error: ${err.message}`);
|
||||
}
|
||||
|
||||
setText("");
|
||||
}
|
||||
|
||||
|
|
@ -67,9 +68,13 @@ export default function MessageInput({ onSend, onMessage }) {
|
|||
<div className="w-full flex justify-center">
|
||||
<footer className="fixed bottom-6 max-w-3xl w-full px-4">
|
||||
<div className="flex flex-col gap-4">
|
||||
<div>
|
||||
<DownButton></DownButton>
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<DownButton />
|
||||
<BackendToggle />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className="bg-gray-900 rounded-2xl border-2 border-gray-800 shadow-lg shadow-indigo-600"
|
||||
|
|
|
|||
25
web-app/src/context/chat-backend-context.jsx
Normal file
25
web-app/src/context/chat-backend-context.jsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import React, { createContext, useContext, useState } from "react";
|
||||
|
||||
const ChatBackendContext = createContext(null);
|
||||
|
||||
export function ChatBackendProvider({ children }) {
|
||||
const [backend, setBackend] = useState("gemini"); // default
|
||||
|
||||
function toggleBackend() {
|
||||
setBackend((b) => (b === "gemini" ? "rust" : "gemini"));
|
||||
}
|
||||
|
||||
return (
|
||||
<ChatBackendContext.Provider value={{ backend, setBackend, toggleBackend }}>
|
||||
{children}
|
||||
</ChatBackendContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useChatBackend() {
|
||||
const ctx = useContext(ChatBackendContext);
|
||||
if (!ctx) throw new Error("useChatBackend must be used within ChatBackendProvider");
|
||||
return ctx;
|
||||
}
|
||||
|
||||
export default ChatBackendContext;
|
||||
|
|
@ -2,9 +2,12 @@ import { StrictMode } from "react";
|
|||
import { createRoot } from "react-dom/client";
|
||||
import "./index.css";
|
||||
import App from "./app/index.jsx";
|
||||
import { ChatBackendProvider } from "./context/chat-backend-context";
|
||||
|
||||
createRoot(document.getElementById("root")).render(
|
||||
<StrictMode>
|
||||
<ChatBackendProvider>
|
||||
<App />
|
||||
</ChatBackendProvider>
|
||||
</StrictMode>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue