Skip to content

Commit 6a55225

Browse files
committed
Merge branch 'prav10140-main'
2 parents 4dda65a + 5cf7527 commit 6a55225

7 files changed

Lines changed: 775 additions & 1 deletion

File tree

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
"react": "^19.0.0",
2222
"react-dom": "^19.0.0",
2323
"react-icons": "^5.5.0",
24-
"react-router-dom": "^7.12.0",
2524
"react-markdown": "^10.1.0",
2625
"react-syntax-highlighter": "^16.1.0"
2726
},
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// src/components/ChatBot/ChatBubble.jsx
2+
import React from "react";
3+
import ReactMarkdown from "react-markdown";
4+
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
5+
import { materialDark } from "react-syntax-highlighter/dist/esm/styles/prism";
6+
7+
export default function ChatBubble({ message }) {
8+
return (
9+
<div
10+
className={`chat-bubble ${message.role} break-words`}
11+
style={{ marginBottom: "12px" }}
12+
>
13+
<ReactMarkdown
14+
components={{
15+
code({ node, inline, className, children, ...props }) {
16+
return !inline ? (
17+
<SyntaxHighlighter
18+
style={materialDark}
19+
language={className?.replace("language-", "") || "javascript"}
20+
{...props}
21+
>
22+
{children}
23+
</SyntaxHighlighter>
24+
) : (
25+
<code
26+
className="inline-code"
27+
style={{ backgroundColor: "#2b2b3b", padding: "2px 4px", borderRadius: "4px" }}
28+
{...props}
29+
>
30+
{children}
31+
</code>
32+
);
33+
},
34+
}}
35+
>
36+
{message.content}
37+
</ReactMarkdown>
38+
</div>
39+
);
40+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// src/components/ChatBot/ChatInput.jsx
2+
import React, { useState } from "react";
3+
4+
export default function ChatInput({ onSend }) {
5+
const [text, setText] = useState("");
6+
7+
const handleSend = () => {
8+
if (text.trim()) {
9+
onSend(text);
10+
setText("");
11+
}
12+
};
13+
14+
const handleKeyDown = (e) => {
15+
if (e.key === "Enter" && !e.shiftKey) {
16+
e.preventDefault();
17+
handleSend();
18+
}
19+
};
20+
21+
return (
22+
<div className="chat-input">
23+
<textarea
24+
value={text}
25+
onChange={(e) => setText(e.target.value)}
26+
onKeyDown={handleKeyDown}
27+
placeholder="Ask CodeMate..."
28+
/>
29+
<button onClick={handleSend}>Send</button>
30+
</div>
31+
);
32+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import React, { useState } from "react";
2+
import ChatBubble from "./ChatBubble";
3+
import ChatInput from "./ChatInput";
4+
import { askCodeMate } from "./chatApi";
5+
import "./chatbot.css";
6+
7+
const LANGUAGES = ["javascript", "python", "cpp", "java"]; // add more if needed
8+
9+
export default function CodeMate() {
10+
const [open, setOpen] = useState(false);
11+
const [fullScreen, setFullScreen] = useState(false);
12+
const [selectedLang, setSelectedLang] = useState("javascript");
13+
14+
const [messages, setMessages] = useState([
15+
{
16+
role: "system",
17+
content: `
18+
You are CodeMate, an AI coding assistant inside an online compiler.
19+
20+
Strict rules:
21+
1. Always provide **three approaches** for every logic question:
22+
1. Brute Force
23+
2. Better Approach
24+
3. Optimal Approach
25+
2. Always explain **time and space complexity** for each approach.
26+
3. Always write code in the **programming language selected by the user** (use the variable "selectedLang").
27+
4. Respond in simple, beginner-friendly language.
28+
5. Use Markdown formatting with numbered lists and code blocks.
29+
30+
Example:
31+
1. Brute Force
32+
\`\`\`${selectedLang}
33+
// code here
34+
\`\`\`
35+
Time Complexity: O(...)
36+
Space Complexity: O(...)
37+
38+
2. Better Approach
39+
\`\`\`${selectedLang}
40+
// code here
41+
\`\`\`
42+
Time Complexity: O(...)
43+
Space Complexity: O(...)
44+
45+
3. Optimal Approach
46+
\`\`\`${selectedLang}
47+
// code here
48+
\`\`\`
49+
Time Complexity: O(...)
50+
Space Complexity: O(...)
51+
`
52+
},
53+
{
54+
role: "assistant",
55+
content: "Hi 👋 I'm CodeMate. Ask me about logic, optimization, or errors."
56+
}
57+
]);
58+
59+
const sendMessage = async (text) => {
60+
if (!text.trim()) return;
61+
62+
const userMsg = { role: "user", content: text };
63+
const updated = [...messages, userMsg];
64+
setMessages(updated);
65+
66+
try {
67+
// Always pass the language to the prompt
68+
const reply = await askCodeMate([
69+
...updated,
70+
{ role: "system", content: `Use ${selectedLang} for all code.` }
71+
]);
72+
73+
setMessages((prev) => [...prev, { role: "assistant", content: reply }]);
74+
} catch (err) {
75+
setMessages((prev) => [
76+
...prev,
77+
{ role: "assistant", content: "⚠️ Error connecting to Groq API." },
78+
]);
79+
}
80+
};
81+
82+
return (
83+
<>
84+
<button className="chat-toggle" onClick={() => setOpen(!open)}>
85+
💬
86+
</button>
87+
88+
{open && (
89+
<div className={`chat-container ${fullScreen ? "fullscreen" : ""}`}>
90+
<div className="chat-header">
91+
<span>CodeMate AI</span>
92+
<div className="chat-header-buttons">
93+
<select
94+
value={selectedLang}
95+
onChange={(e) => setSelectedLang(e.target.value)}
96+
className="language-select"
97+
>
98+
{LANGUAGES.map((lang) => (
99+
<option key={lang} value={lang}>
100+
{lang.toUpperCase()}
101+
</option>
102+
))}
103+
</select>
104+
<button onClick={() => setFullScreen(!fullScreen)}>
105+
{fullScreen ? "🗗" : "🗖"}
106+
</button>
107+
<button onClick={() => setOpen(false)}></button>
108+
</div>
109+
</div>
110+
111+
<div className="chat-body">
112+
{messages
113+
.filter((m) => m.role !== "system")
114+
.map((msg, i) => (
115+
<ChatBubble key={i} message={msg} />
116+
))}
117+
</div>
118+
119+
<ChatInput onSend={sendMessage} />
120+
</div>
121+
)}
122+
</>
123+
);
124+
}

src/components/ChatBot/chatApi.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// src/components/ChatBot/chatApi.js
2+
import Groq from "groq-sdk";
3+
4+
// Initialize Groq with your API key
5+
const groq = new Groq({
6+
apiKey: import.meta.env.VITE_GROQ_API_KEY,
7+
dangerouslyAllowBrowser: true, // required to call from frontend
8+
});
9+
10+
// Set your model
11+
const MODEL_NAME = "llama-3.3-70b-versatile";
12+
13+
// Function to send messages to Groq
14+
export async function askCodeMate(messages) {
15+
try {
16+
const chat = await groq.chat.completions.create({
17+
model: MODEL_NAME,
18+
messages: messages,
19+
temperature: 0.3, // Adjust creativity
20+
});
21+
22+
// Return the assistant's reply
23+
return chat.choices[0].message.content;
24+
} catch (err) {
25+
console.error("Groq API Error:", err);
26+
throw new Error("Error connecting to Groq API.");
27+
}
28+
}

0 commit comments

Comments
 (0)