diff --git a/src/features/gemini/gemini.js b/src/features/gemini/gemini.js new file mode 100644 index 0000000..60ab8c1 --- /dev/null +++ b/src/features/gemini/gemini.js @@ -0,0 +1,4 @@ +import { createPartFromUri, GoogleGenAI } from "@google/genai" +import 'dotenv/config' + +const ai = new GoogleGenAI({ apiKey: ${} }) \ No newline at end of file diff --git a/web-app/index.html b/web-app/index.html index ddadf4a..12f80c9 100644 --- a/web-app/index.html +++ b/web-app/index.html @@ -4,7 +4,6 @@ - codered-astra diff --git a/web-app/package.json b/web-app/package.json index 91388fc..7027cf2 100644 --- a/web-app/package.json +++ b/web-app/package.json @@ -1,5 +1,6 @@ { "name": "codered-astra", + "type": "module", "private": true, "scripts": { "build": "vite build", diff --git a/web-app/public/pdfs/SRHB.pdf b/web-app/public/pdfs/SRHB.pdf new file mode 100644 index 0000000..5bb4f78 Binary files /dev/null and b/web-app/public/pdfs/SRHB.pdf differ diff --git a/web-app/public/pdfs/falcon-users-guide-2025-05-09.pdf b/web-app/public/pdfs/falcon-users-guide-2025-05-09.pdf new file mode 100644 index 0000000..4d835a6 Binary files /dev/null and b/web-app/public/pdfs/falcon-users-guide-2025-05-09.pdf differ diff --git a/web-app/public/pdfs/spacex-falcon-9-data-sheet.pdf b/web-app/public/pdfs/spacex-falcon-9-data-sheet.pdf new file mode 100644 index 0000000..d6ce2ae Binary files /dev/null and b/web-app/public/pdfs/spacex-falcon-9-data-sheet.pdf differ diff --git a/web-app/public/pdfs/system-safety-handbook.pdf b/web-app/public/pdfs/system-safety-handbook.pdf new file mode 100644 index 0000000..7d076f2 Binary files /dev/null and b/web-app/public/pdfs/system-safety-handbook.pdf differ diff --git a/web-app/public/vite.svg b/web-app/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/web-app/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/web-app/src/app/index.jsx b/web-app/src/app/index.jsx index 9d0b576..8ce7147 100644 --- a/web-app/src/app/index.jsx +++ b/web-app/src/app/index.jsx @@ -3,7 +3,7 @@ import ChatLayout from "src/components/layouts/chat-layout"; function App() { return ( -
+
); diff --git a/web-app/src/components/layouts/chat-layout.jsx b/web-app/src/components/layouts/chat-layout.jsx index e6cab2e..72b77a9 100644 --- a/web-app/src/components/layouts/chat-layout.jsx +++ b/web-app/src/components/layouts/chat-layout.jsx @@ -25,7 +25,7 @@ export default function ChatLayout() { } return ( -
+
diff --git a/web-app/src/components/layouts/dashboard-layout.jsx b/web-app/src/components/layouts/dashboard-layout.jsx deleted file mode 100644 index e69de29..0000000 diff --git a/web-app/src/components/ui/Button/ActionButton.css b/web-app/src/components/ui/Button/ActionButton.css deleted file mode 100644 index 499ef30..0000000 --- a/web-app/src/components/ui/Button/ActionButton.css +++ /dev/null @@ -1,29 +0,0 @@ -.action-btn { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 6px 12px; - border: 2px solid var(--btn-color); - border-radius: 6px; - background-color: white; - color: var(--btn-color); - font-weight: 500; - cursor: pointer; - transition: all 0.25s ease; -} - -.action-btn:hover, -.action-btn:focus { - background-color: var(--btn-color); - color: white; - border-color: var(--btn-color); -} - -.action-btn svg { - fill: currentColor; - transition: fill 0.25s ease; -} - -.action-btn:hover { - transform: translateY(-1px); -} diff --git a/web-app/src/components/ui/Button/ActionButton.jsx b/web-app/src/components/ui/Button/ActionButton.jsx deleted file mode 100644 index 334f9e8..0000000 --- a/web-app/src/components/ui/Button/ActionButton.jsx +++ /dev/null @@ -1,63 +0,0 @@ -import './ActionButton.css'; - -export default function ActionButton({ - onClick, - children, - type = 'add', // 'add' or 'delete' or 'send' - ...props -}) { - // Define color and icon based on type - const config = { - add: { - color: '#0F2862', - svg: ( - - - - ), - }, - delete: { - color: '#9E363A', - svg: ( - - - - ), - }, - submit: { - color: '#3949AB', - svg: ( - - ), - }, - }; - - const { color, svg } = config[type] || config.add; - - return ( - - ); -} diff --git a/web-app/src/components/ui/button/delete-button.jsx b/web-app/src/components/ui/button/delete-button.jsx new file mode 100644 index 0000000..53a5367 --- /dev/null +++ b/web-app/src/components/ui/button/delete-button.jsx @@ -0,0 +1,9 @@ +import { Flame } from "lucide-react"; + +export default function FlameButton({ onClick }) { + return ( + + ); +} diff --git a/web-app/src/components/ui/button/down-button.jsx b/web-app/src/components/ui/button/down-button.jsx new file mode 100644 index 0000000..e402e8f --- /dev/null +++ b/web-app/src/components/ui/button/down-button.jsx @@ -0,0 +1,10 @@ +import React from "react"; +import { ArrowDown } from "lucide-react"; + +export default function DownButton({ onClick }) { + return ( + + ); +} diff --git a/web-app/src/components/ui/chat/chat-header.jsx b/web-app/src/components/ui/chat/chat-header.jsx index 6240539..9a329b4 100644 --- a/web-app/src/components/ui/chat/chat-header.jsx +++ b/web-app/src/components/ui/chat/chat-header.jsx @@ -1,46 +1,11 @@ import React from "react"; -import ActionButton from "src/components/ui/Button/ActionButton.jsx"; - -export default function ChatHeader({ title = "AI Assistant" }) { - // Delete chat log (frontend + backend) - const handleDeleteChat = async () => { - if (!window.confirm("Delete all messages?")) return; - await fetch(`/api/chat/${conversationId}`, { method: "DELETE" }); - setMessages([]); - }; - - // Restart chat (new conversation) - const handleNewChat = async () => { - const res = await fetch("/api/chat/new", { method: "POST" }); - const data = await res.json(); - if (data.success) { - setConversationId(data.conversationId); - setMessages([]); - } - }; +export default function ChatHeader({ title = "Title of Chat" }) { return ( -
-
-
- AI -
-
-

{title}

-

- Ask anything — AI is listening -

-
-
- -
- - New Chat - - - Delete Chat - -
+
+

+ {title} +

); } diff --git a/web-app/src/components/ui/chat/chat-window.jsx b/web-app/src/components/ui/chat/chat-window.jsx index 39a3a0a..49c689e 100644 --- a/web-app/src/components/ui/chat/chat-window.jsx +++ b/web-app/src/components/ui/chat/chat-window.jsx @@ -4,10 +4,10 @@ function MessageBubble({ message }) { const isUser = message.role === "user"; return (
{message.content}
@@ -16,22 +16,13 @@ function MessageBubble({ message }) { } export default function ChatWindow({ messages }) { - const chatRef = useRef(null); - // Auto-scroll to bottom when new messages appear - useEffect(() => { - chatRef.current?.scrollTo({ - top: chatRef.current.scrollHeight, - behavior: "smooth", - }); - }, [messages]); - return ( -
-
+
+
{messages.map((m, i) => ( ))}
-
+
); } diff --git a/web-app/src/components/ui/chat/message-input.jsx b/web-app/src/components/ui/chat/message-input.jsx index 3dd4f84..16dbe1c 100644 --- a/web-app/src/components/ui/chat/message-input.jsx +++ b/web-app/src/components/ui/chat/message-input.jsx @@ -1,5 +1,7 @@ import React, { useState } from "react"; -import ActionButton from "../Button/ActionButton"; +import DeleteButton from "src/components/ui/button/delete-button"; +import DownButton from "../button/down-button"; + export default function MessageInput({ onSend }) { const [text, setText] = useState(""); @@ -11,17 +13,27 @@ export default function MessageInput({ onSend }) { } return ( -
-
- setText(e.target.value)} - placeholder="Type a message..." - className="flex-1 rounded-md bg-slate-800 border border-slate-700 px-3 py-2 text-white focus:outline-none focus:ring-2 focus:ring-indigo-500" - /> - - +
+
+ +
- +
+
+ setText(e.target.value)} + placeholder="Type a message..." + className="flex-1 mx-2 rounded-md shadow-2sx border-none focus:border-none focus:outline-none" + /> + +
+
+
); } diff --git a/web-app/src/features/gemini/gemini.js b/web-app/src/features/gemini/gemini.js new file mode 100644 index 0000000..4e2d761 --- /dev/null +++ b/web-app/src/features/gemini/gemini.js @@ -0,0 +1,65 @@ +import { createPartFromUri, GoogleGenAI } from "@google/genai" +import 'dotenv/config' +import fs from "fs" + +const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY }) + +async function uploadLocalPDFs() { + var pdfList = fs.readdirSync("public/pdfs") + + // Upload each file in /public + pdfList.forEach(async (path) => { + console.log("file names: " + path) + console.log("file names: " + path.slice(0, path.length - 4)) + + console.log("UPLOADING") + const file = await ai.files.upload({ + file: "public/pdfs/" + path, + config: { + displayName: path.slice(0, path.length - 4) + } + }) + + console.log("FETCHING: public/pdfs/" + path) + + // Wait for the file to be processed + let getFile = await ai.files.get({ + name: file.name + }) + + while (getFile.state === "PROCESSING") { + let getFile = await ai.files.get({ + name: file.name + }) + console.log(`Current file status: ${getFile.state}`) + console.log("File is currently processing, retrying in 5 seconds") + + await new Promise((resolve) => { + setTimeout(resolve, 5000) // Checks every 5 seconds + }) + + // Error handling + if (getFile.state === "FAILED") { + throw new Error("File has failed to process!") + } + return file + } + }) +} + +async function main() { + const prompts = [ + "If possible, using Gemini's Javascript API, how would you grab an image from a PDF sent to the API?" + ] + + const response = await ai.models.generateContent({ + model: "gemini-2.5-flash", + contents: prompts + }) + + console.log(response.text) +} + +uploadLocalPDFs() +main() + diff --git a/web-app/src/index.css b/web-app/src/index.css index 104725b..2b88b1a 100644 --- a/web-app/src/index.css +++ b/web-app/src/index.css @@ -1,19 +1,16 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import "tailwindcss"; -:root { - --color-primary: 15 40 98; - --color-secondary: 79 95 118; - --color-accent: 158 54 58; - --color-paragraph: 255 255 255; - --color-background: 9 31 54; +.dark { + --paragraph: 235, 236, 239; + --background: 15, 16, 26; + --primary: 158, 166, 214; + --secondary: 35, 50, 133; + --accent: 52, 75, 223; + background: rgba(var(--background)); } body { margin: 0; - background-color: rgb(var(--color-background)); - color: rgb(var(--color-paragraph)); font-family: ui-sans-serif, system-ui, diff --git a/web-app/src/styles/theme.css b/web-app/src/styles/theme.css deleted file mode 100644 index 5287314..0000000 --- a/web-app/src/styles/theme.css +++ /dev/null @@ -1,7 +0,0 @@ -@theme { - --color-primary: rgba(15, 40, 98); - --color-secondary: rgba(79, 95, 118); - --color-accent: rgba(158, 54, 58); - --color-paragraph: rgba(255, 255, 255); - --color-background: rgba(9, 31, 54); -}