CppSensei / templates /index.html
OxSid's picture
Updated the name of bot.
c3e3144 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CPP Bot</title>
<link rel="icon" type="image/svg+xml" href="{{ url_for('static', filename='favicon.svg') }}">
<link rel="alternate icon" href="{{ url_for('static', filename='favicon.ico') }}">
<link rel="apple-touch-icon" href="{{ url_for('static', filename='favicon.png') }}">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
<style>
* { box-sizing: border-box; font-family: "Inter", sans-serif; }
body {
margin: 0;
height: 100vh;
background: radial-gradient(circle at top, #0f172a, #020617);
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
color: #e5e7eb;
}
.card {
width: 420px;
height: 620px;
background: rgba(2, 6, 23, 0.88);
border-radius: 20px;
box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
display: flex;
flex-direction: column;
overflow: hidden;
border: 1px solid rgba(148, 163, 184, 0.15);
backdrop-filter: blur(12px);
position: relative;
}
/* Header */
.header {
padding: 16px 20px;
background: linear-gradient(135deg, #38bdf8, #818cf8);
color: #020617;
font-weight: 800;
font-size: 1.4rem;
letter-spacing: 0.5px;
display: flex;
justify-content: space-between;
align-items: center;
}
.subtitle {
font-size: 0.75rem;
font-weight: 500;
opacity: 0.8;
margin-top: 2px;
}
.clear-btn {
background: none;
border: none;
font-size: 1.3rem;
cursor: pointer;
color: #020617;
}
/* Chat area */
#messages {
flex: 1;
padding: 20px;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 12px;
}
/* Message bubbles */
.bubble {
max-width: 80%;
padding: 12px 14px;
border-radius: 14px;
line-height: 1.4;
animation: fadeIn 0.3s ease;
}
.user {
align-self: flex-end;
background: linear-gradient(135deg, #38bdf8, #60a5fa);
color: #020617;
border-bottom-right-radius: 4px;
}
.bot {
align-self: flex-start;
background: #0f172a;
color: #a7f3d0;
border: 1px solid rgba(148, 163, 184, 0.15);
border-bottom-left-radius: 4px;
}
/* Input bar */
.input-bar {
display: flex;
padding: 14px;
border-top: 1px solid rgba(148, 163, 184, 0.15);
background: rgba(2, 6, 23, 0.95);
}
.input-bar input {
flex: 1;
padding: 10px 12px;
border-radius: 10px;
border: none;
outline: none;
background: #020617;
color: white;
font-size: 0.95rem;
}
.input-bar button {
margin-left: 10px;
padding: 10px 16px;
border-radius: 10px;
border: none;
cursor: pointer;
background: linear-gradient(135deg, #38bdf8, #818cf8);
color: #020617;
font-weight: 600;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.input-bar button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(56, 189, 248, 0.5);
}
/* Footer */
.footer {
padding: 10px 14px;
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid rgba(148, 163, 184, 0.15);
background: rgba(2, 6, 23, 0.95);
font-size: 0.75rem;
}
.footer button {
background: none;
border: none;
color: #93c5fd;
cursor: pointer;
margin-right: 10px;
}
.footer button:hover { text-decoration: underline; }
/* Buy Me a Coffee */
.coffee {
position: fixed;
bottom: 20px;
right: 20px;
background: #facc15;
color: #020617;
padding: 12px 16px;
border-radius: 30px;
font-weight: 700;
text-decoration: none;
box-shadow: 0 10px 30px rgba(250, 204, 21, 0.5);
transition: transform 0.2s ease;
z-index: 999;
}
.coffee:hover { transform: translateY(-3px) scale(1.05); }
/* Modals */
.modal {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.6);
display: none;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
width: 360px;
background: #020617;
padding: 20px;
border-radius: 14px;
border: 1px solid rgba(148, 163, 184, 0.2);
position: relative;
}
.close-modal {
position: absolute;
top: 10px;
right: 12px;
background: none;
border: none;
font-size: 1.2rem;
cursor: pointer;
color: #93c5fd;
}
.modal-content h3 { margin-top: 0; color: #38bdf8; }
.modal-content textarea,
.modal-content input {
width: 100%;
margin-top: 10px;
padding: 8px;
border-radius: 6px;
border: none;
outline: none;
background: #0f172a;
color: white;
}
.modal-content button.submit-btn {
margin-top: 12px;
padding: 8px 14px;
border-radius: 8px;
border: none;
cursor: pointer;
background: linear-gradient(135deg, #38bdf8, #818cf8);
color: #020617;
font-weight: 600;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(4px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
</head>
<body>
<div class="card">
<div class="header">
<div>
CppSensei
<div class="subtitle">Domain‑Trained C++ AI Assistant</div>
</div>
<button class="clear-btn" onclick="clearChat()" title="Clear chat">🗑️</button>
</div>
<div id="messages"></div>
<div class="input-bar">
<input id="question" placeholder="Ask a C++ question…" />
<button onclick="sendQuestion()">Send</button>
</div>
<div class="footer">
<div>
<button onclick="openAbout()">About</button>
<button onclick="openFeedback()">Feedback</button>
</div>
<div>© 2026 C++ Bot</div>
</div>
</div>
<!-- Buy Me a Coffee -->
<a class="coffee" href="https://buymeacoffee.com/siddharthmishra?status=1" target="_blank">☕ Buy me a coffee</a>
<!-- About Modal -->
<div class="modal" id="aboutModal" onclick="backdropClose(event, 'aboutModal')">
<div class="modal-content">
<button class="close-modal" onclick="closeAbout()"></button>
<h3>About C++ Bot</h3>
<p>This is a domain‑trained AI assistant built using Retrieval Augmented Generation with FAISS, Transformers, and Flask. It answers only from a curated C++ knowledge base.</p>
</div>
</div>
<!-- Feedback Modal -->
<div class="modal" id="feedbackModal" onclick="backdropClose(event, 'feedbackModal')">
<div class="modal-content">
<button class="close-modal" onclick="closeFeedback()"></button>
<h3>Send Feedback</h3>
<input id="email" placeholder="Your email (optional)" />
<textarea id="feedback" rows="5" placeholder="Your suggestion or feedback..."></textarea>
<button class="submit-btn" onclick="submitFeedback()">Submit</button>
</div>
</div>
<script>
const messages = document.getElementById("messages");
const input = document.getElementById("question");
input.addEventListener("keydown", function (e) {
if (e.key === "Enter") sendQuestion();
});
document.addEventListener("keydown", function (e) {
if (e.key === "Escape") {
closeAbout();
closeFeedback();
}
});
function addMessage(text, type) {
const div = document.createElement("div");
div.className = `bubble ${type}`;
div.textContent = text;
messages.appendChild(div);
messages.scrollTop = messages.scrollHeight;
}
function clearChat() {
if (confirm("Clear the chat?")) {
messages.innerHTML = "";
}
}
async function sendQuestion() {
const question = input.value.trim();
if (!question) return;
addMessage(question, "user");
input.value = "";
const typing = document.createElement("div");
typing.className = "bubble bot";
typing.textContent = "AI is thinking…";
messages.appendChild(typing);
messages.scrollTop = messages.scrollHeight;
try {
const response = await fetch("/ask", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ question })
});
const data = await response.json();
messages.removeChild(typing);
addMessage(data.answer, "bot");
} catch (error) {
messages.removeChild(typing);
addMessage("Server error. Please try again.", "bot");
}
}
function openAbout() { document.getElementById("aboutModal").style.display = "flex"; }
function closeAbout() { document.getElementById("aboutModal").style.display = "none"; }
function openFeedback() { document.getElementById("feedbackModal").style.display = "flex"; }
function closeFeedback() { document.getElementById("feedbackModal").style.display = "none"; }
function backdropClose(event, modalId) {
if (event.target.id === modalId) {
document.getElementById(modalId).style.display = "none";
}
}
async function submitFeedback() {
const feedback = document.getElementById("feedback").value;
const email = document.getElementById("email").value;
if (!feedback) return alert("Please write some feedback first.");
await fetch("/feedback", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ feedback, email })
});
alert("Thank you for your feedback! 💙");
document.getElementById("feedback").value = "";
document.getElementById("email").value = "";
closeFeedback();
}
</script>
</body>
</html>