// EduCat: AI Study Buddy - Initial JS
// --- PAGE ROUTING LOGIC ---
const pages = {
main: `
`,
upload: `
π€ Upload Materials & AI Summary π±
`,
quiz: `
`,
chatbot: `
`
};
function renderPage(page) {
document.body.innerHTML = `
${pages[page]}
`;
document.querySelectorAll('.nav-btn').forEach(btn => {
btn.onclick = () => renderPage(btn.dataset.page);
});
// Re-initialize page content
if (page === 'main') {
renderDashboard();
renderReminders();
renderChatbot();
} else if (page === 'upload') {
renderUpload();
renderSummary();
} else if (page === 'quiz') {
renderQuiz();
} else if (page === 'chatbot') {
renderChatbot();
}
}
// --- COMPONENT RENDERERS ---
function renderDashboard() {
const progressSection = document.getElementById('dashboard-section');
if (!progressSection) return;
progressSection.innerHTML = `
π Progress Dashboard πΎ
π Study Sessions
5 sessions this week
β
Quizzes Completed
3 / 5 this week
π Streak
4 days in a row
π‘ Motivation
βKeep going, youβre doing great!β
`;
}
function renderReminders() {
const reminderSection = document.getElementById('reminder-section');
if (!reminderSection) return;
reminderSection.innerHTML = `
β° Study Reminders π±
- π
Next quiz: Friday, 3pm
- β° Review notes for Math tonight
- π Complete 2 practice quizzes by Sunday
- π§ Take a short break every 45 minutes!
`;
const reminderList = document.getElementById('reminder-list');
const reminderForm = document.getElementById('reminder-form');
const reminderInput = document.getElementById('reminder-input');
reminderForm.addEventListener('submit', function(e) {
e.preventDefault();
const val = reminderInput.value.trim();
if (val) {
const li = document.createElement('li');
li.textContent = val;
reminderList.appendChild(li);
reminderInput.value = '';
}
});
}
function renderChatbot() {
const chatSection = document.getElementById('chat-section');
if (!chatSection) return;
chatSection.innerHTML = `
EduCat Chatbot
`;
const chatWindow = document.getElementById('chat-window');
const chatInput = document.getElementById('chat-input');
const sendBtn = document.getElementById('chat-send');
function addBubble(text, sender) {
const bubble = document.createElement('div');
bubble.className = sender === 'user' ? 'bubble user-bubble' : 'bubble ai-bubble';
bubble.innerHTML = text;
chatWindow.appendChild(bubble);
chatWindow.scrollTop = chatWindow.scrollHeight;
}
function showTyping() {
const typing = document.createElement('div');
typing.className = 'bubble ai-bubble typing';
typing.id = 'ai-typing';
typing.innerHTML = ' EduCat is typing...';
chatWindow.appendChild(typing);
chatWindow.scrollTop = chatWindow.scrollHeight;
}
function hideTyping() {
const typing = document.getElementById('ai-typing');
if (typing) typing.remove();
}
sendBtn.addEventListener('click', sendMessage);
chatInput.addEventListener('keydown', e => { if (e.key === 'Enter') sendMessage(); });
function sendMessage() {
const msg = chatInput.value.trim();
if (!msg) return;
addBubble(msg, 'user');
chatInput.value = '';
showTyping();
fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: msg })
})
.then(res => res.json())
.then(data => {
hideTyping();
setTimeout(() => {
addBubble(data.reply || data.error, 'ai');
}, 500); // Simulate slight delay for realism
})
.catch(() => {
hideTyping();
addBubble('Error contacting chatbot.', 'ai');
});
}
// Add styles for bubbles and typing
const style = document.createElement('style');
style.innerHTML = `
#chat-window { font-size: 1rem; }
.bubble {
display: inline-block;
padding: 0.6em 1em;
margin: 0.3em 0;
border-radius: 18px;
max-width: 80%;
word-break: break-word;
clear: both;
position: relative;
animation: fadeIn 0.2s;
}
.user-bubble {
background: #6a82fb;
color: #fff;
align-self: flex-end;
float: right;
margin-left: 20%;
}
.ai-bubble {
background: #fff;
color: #222;
border: 1px solid #e0e0e0;
align-self: flex-start;
float: left;
margin-right: 20%;
}
.typing {
opacity: 0.7;
font-style: italic;
}
.dot {
display: inline-block;
width: 8px;
height: 8px;
margin-right: 2px;
background: #6a82fb;
border-radius: 50%;
animation: blink 1.4s infinite both;
}
.dot:nth-child(2) { animation-delay: 0.2s; }
.dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes blink {
0%, 80%, 100% { opacity: 0.2; }
40% { opacity: 1; }
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: none; }
}
`;
document.head.appendChild(style);
}
function renderUpload() {
const uploadSection = document.getElementById('upload-section');
if (!uploadSection) return;
uploadSection.innerHTML = `
π€ Upload Study Materials πΎ
`;
document.getElementById('upload-btn').addEventListener('click', async () => {
const fileInput = document.getElementById('file-upload');
const statusDiv = document.getElementById('upload-status');
if (!fileInput.files.length) {
statusDiv.textContent = 'Please select at least one file.';
return;
}
const file = fileInput.files[0];
const formData = new FormData();
formData.append('file', file);
statusDiv.textContent = 'Uploading...';
try {
const response = await fetch('/api/upload', {
method: 'POST',
body: formData
});
const result = await response.json();
if (response.ok) {
statusDiv.textContent = 'File uploaded! Getting summary...';
// Call Flowise summarization endpoint
const summaryRes = await fetch('/api/flowise', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ filename: result.filename })
});
const summaryData = await summaryRes.json();
document.getElementById('summary-output').textContent = summaryData.summary || 'No summary available.';
} else {
statusDiv.textContent = result.error || 'Upload failed.';
}
} catch (err) {
statusDiv.textContent = 'Error uploading file.';
}
});
}
function renderSummary() {
const summarySection = document.getElementById('summary-section');
if (!summarySection) return;
summarySection.innerHTML = `
π AI Summary π±
Upload your notes to see a summary here.
`;
}
function renderQuiz() {
const quizSection = document.getElementById('quiz-section');
if (!quizSection) return;
// Subjects and questions
const subjects = {
Math: [
{
q: 'What is the value of Ο (pi) rounded to 2 decimal places?',
opts: ['A. 3.12', 'B. 3.14', 'C. 3.16', 'D. 3.18'],
ans: 'B. 3.14'
},
{
q: 'Solve: 5 Γ 6 = ?',
opts: ['A. 11', 'B. 30', 'C. 56', 'D. 26'],
ans: 'B. 30'
}
],
Science: [
{
q: 'What planet is known as the Red Planet?',
opts: ['A. Venus', 'B. Mars', 'C. Jupiter', 'D. Saturn'],
ans: 'B. Mars'
},
{
q: 'What is H2O commonly known as?',
opts: ['A. Oxygen', 'B. Hydrogen', 'C. Water', 'D. Helium'],
ans: 'C. Water'
}
],
History: [
{
q: 'Who was the first President of the United States?',
opts: ['A. Abraham Lincoln', 'B. George Washington', 'C. John Adams', 'D. Thomas Jefferson'],
ans: 'B. George Washington'
},
{
q: 'In which year did World War II end?',
opts: ['A. 1942', 'B. 1945', 'C. 1948', 'D. 1950'],
ans: 'B. 1945'
}
]
};
let selectedSubject = Object.keys(subjects)[0];
let currentQ = 0;
quizSection.innerHTML = `
Practice Quiz πΎ
`;
const subjectSelect = document.getElementById('subject-select');
const quizQ = quizSection.querySelector('.quiz-q');
const quizOpts = quizSection.querySelector('.quiz-options');
const quizFeedback = quizSection.querySelector('.quiz-feedback');
const quizProgress = quizSection.querySelector('.quiz-progress');
const prevBtn = document.getElementById('prev-q');
const nextBtn = document.getElementById('next-q');
function renderQuestion() {
const qArr = subjects[selectedSubject];
const qObj = qArr[currentQ];
quizQ.innerHTML = `Q${currentQ + 1} of ${qArr.length} ${qObj.q}`;
quizOpts.innerHTML = qObj.opts.map(opt => ``).join('');
quizFeedback.textContent = '';
quizProgress.innerHTML = ``;
prevBtn.style.visibility = currentQ === 0 ? 'hidden' : 'visible';
nextBtn.style.display = currentQ === qArr.length - 1 ? 'none' : 'inline-block';
}
renderQuestion();
quizOpts.addEventListener('click', function(e) {
if (e.target.classList.contains('quiz-opt')) {
const qObj = subjects[selectedSubject][currentQ];
if (e.target.textContent === qObj.ans) {
quizFeedback.textContent = 'β
Correct!';
quizFeedback.style.color = '#2ecc40';
} else {
quizFeedback.textContent = 'β Try again!';
quizFeedback.style.color = '#fc5c7d';
}
}
});
subjectSelect.addEventListener('change', function() {
selectedSubject = this.value;
currentQ = 0;
renderQuestion();
});
prevBtn.addEventListener('click', function() {
if (currentQ > 0) {
currentQ--;
renderQuestion();
}
});
nextBtn.addEventListener('click', function() {
if (currentQ < subjects[selectedSubject].length - 1) {
currentQ++;
renderQuestion();
}
});
// Add/Update styles for enhanced quiz UI
const quizStyle = document.createElement('style');
quizStyle.innerHTML = `
.enhanced-quiz-card {
background: #fff;
border-radius: 16px;
box-shadow: 0 4px 16px rgba(106,130,251,0.10);
padding: 1.5rem 1.2rem 1.2rem 1.2rem;
max-width: 480px;
margin: 0 auto;
display: flex;
flex-direction: column;
align-items: stretch;
}
.quiz-q {
font-weight: bold;
margin-bottom: 1.1rem;
font-size: 1.15rem;
color: #6a82fb;
display: flex;
align-items: center;
gap: 0.7em;
}
.quiz-q-num {
background: #f0f4fa;
color: #6a82fb;
border-radius: 8px;
padding: 0.2em 0.7em;
font-size: 0.95em;
margin-right: 0.5em;
}
.quiz-options {
display: flex;
flex-direction: column;
gap: 0.7em;
margin-bottom: 1.1rem;
}
.quiz-opt {
background: #f7f9fb;
border: 2px solid #6a82fb;
color: #6a82fb;
border-radius: 8px;
padding: 0.7em 1.2em;
font-size: 1.05em;
cursor: pointer;
transition: background 0.2s, color 0.2s, border 0.2s;
text-align: left;
}
.quiz-opt:hover {
background: #6a82fb;
color: #fff;
border: 2px solid #fc5c7d;
}
.quiz-feedback {
font-size: 1.1em;
margin-top: 0.5em;
min-height: 1.5em;
}
.quiz-bar-bg {
width: 100%;
height: 10px;
background: #e0e7fa;
border-radius: 5px;
margin: 0.7em 0 0.2em 0;
overflow: hidden;
}
.quiz-bar-fg {
height: 100%;
background: linear-gradient(90deg, #6a82fb 0%, #fc5c7d 100%);
border-radius: 5px;
transition: width 0.4s;
}
#prev-q, #next-q {
background: #6a82fb;
color: #fff;
border: none;
padding: 0.5em 1.2em;
border-radius: 6px;
font-size: 1em;
cursor: pointer;
transition: background 0.2s;
}
#prev-q[style*="hidden"] {
opacity: 0.5;
pointer-events: none;
}
#next-q {
background: #fc5c7d;
}
#next-q[style*="none"] {
display: none !important;
}
`;
document.head.appendChild(quizStyle);
}
// --- INITIALIZE APP ---
renderPage('main');
// Placeholder for AI summary, quiz, reminders, and progress dashboard
// TODO: Connect to backend APIs (Perplexity, Gemini Dev, Telegram/Discord bots, etc.)