This commit is contained in:
JK-le-dev 2025-10-19 10:58:57 -05:00
commit 1515ee0589
6 changed files with 118 additions and 28 deletions

View file

@ -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>
);
}

View file

@ -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([]);
}

View 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>
);
}

View file

@ -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"

View 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;

View file

@ -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>
);