console.log("🚀 Cortexa JS Loaded - Production Version");
// ================= API CONFIGURATION - FIXED =================
const BASE_URL = "";
const API_URL = BASE_URL + "/chat";
const ENDPOINTS = {
chat: BASE_URL + "/chat",
uploadDocument: BASE_URL + "/upload-document",
generateAudio: BASE_URL + "/generate-audio",
youtubeSearch: BASE_URL + "/youtube-search",
youtubeVideoInfo: BASE_URL + "/youtube-video-info",
health: BASE_URL + "/health",
models: BASE_URL + "/models",
chats: BASE_URL + "/api/chats"
};
console.log("✅ Backend URL:", BASE_URL);
console.log("✅ Chat API:", API_URL);
// ================= GLOBAL VARIABLES =================
let currentChatId = null;
let currentProjectId = null;
let currentDocument = null;
let currentAudioMode = 'simple';
let mediaRecorder = null;
let audioChunks = [];
let isRecording = false;
let currentAudio = null;
let currentAudioText = null;
// In-memory cache of the currently-loaded chat list (used for both
// logged-in / backend-synced and guest / session-only modes).
let sessionChatsCache = [];
// ================= AUTH HELPERS =================
function getAuthToken() {
return localStorage.getItem("access_token") || null;
}
function isLoggedIn() {
return !!getAuthToken();
}
function authHeaders() {
const token = getAuthToken();
return token ? { "Authorization": "Bearer " + token } : {};
}
function getCurrentUser() {
return localStorage.getItem("email") || "guest";
}
// ================= CHAT STORAGE (backend when logged in, session-only otherwise) =================
// IMPORTANT: chats are never persisted to a shared localStorage key anymore.
// Logged-in users' chats live in the backend, scoped strictly to their
// account by the server (JWT-verified on every request). Guests get an
// in-memory-only chat list that disappears when the tab closes, so nothing
// leaks to the next person who opens the app on a shared device.
async function getChats() {
if (isLoggedIn()) {
try {
const res = await fetch(ENDPOINTS.chats, {
method: "GET",
headers: { ...authHeaders() }
});
if (res.status === 401) {
// Token expired/invalid — treat as logged out
localStorage.removeItem("access_token");
sessionChatsCache = [];
return [];
}
const data = await res.json();
sessionChatsCache = data.chats || [];
return sessionChatsCache;
} catch (err) {
console.error("Failed to load chats from server:", err);
return sessionChatsCache;
}
}
// Guest mode: session-only, never written to a shared localStorage key
return sessionChatsCache;
}
async function persistChat(chatId, title, messages) {
if (isLoggedIn()) {
try {
const res = await fetch(ENDPOINTS.chats, {
method: "POST",
headers: { "Content-Type": "application/json", ...authHeaders() },
body: JSON.stringify({ chat_id: chatId, title: title, messages: messages })
});
const data = await res.json();
return data.chat ? data.chat.id : chatId;
} catch (err) {
console.error("Failed to save chat to server:", err);
return chatId;
}
}
// Guest mode: keep it in memory for this tab/session only
return chatId;
}
async function removeChat(chatId) {
if (isLoggedIn()) {
try {
await fetch(ENDPOINTS.chats + "/" + chatId, {
method: "DELETE",
headers: { ...authHeaders() }
});
} catch (err) {
console.error("Failed to delete chat on server:", err);
}
}
sessionChatsCache = sessionChatsCache.filter(c => c.id !== chatId);
}
// Call this from your logout button handler so nothing lingers for the
// next person on a shared browser.
window.clearLocalSessionOnLogout = function() {
localStorage.removeItem("access_token");
localStorage.removeItem("email");
sessionChatsCache = [];
currentChatId = null;
};
function getProjects() {
const user = getCurrentUser();
return JSON.parse(localStorage.getItem("projects_" + user)) || [];
}
function saveProjects(projects) {
const user = getCurrentUser();
localStorage.setItem("projects_" + user, JSON.stringify(projects));
}
// ================= HELPER FUNCTIONS =================
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
function showToast(message, type) {
type = type || 'info';
let toast = document.getElementById('customToast');
if (!toast) {
toast = document.createElement('div');
toast.id = 'customToast';
toast.className = 'toast-message';
document.body.appendChild(toast);
}
toast.style.background = type === 'error'
? 'linear-gradient(90deg, #ef4444, #dc2626)'
: 'linear-gradient(90deg, #22c55e, #16a34a)';
toast.textContent = message;
toast.style.animation = 'none';
void toast.offsetWidth;
toast.style.animation = 'fadeSlide 3s ease forwards';
}
// ================= FORMAT FUNCTION =================
function formatContent(content) {
if (!content) return '';
var formatted = content.replace(/\n/g, ' ');
formatted = formatted.replace(/\*\*(.*?)\*\*/g, '$1 ');
formatted = formatted.replace(/\*(.*?)\*/g, '$1 ');
formatted = formatted.replace(/^[\•\-\*]\s/gm, '• ');
return formatted;
}
// ================= DISPLAY MESSAGE FUNCTION =================
function displayMessage(text, sender) {
var chatBox = document.getElementById("searchResults");
if (!chatBox) {
console.error("searchResults container not found!");
return;
}
var msgDiv = document.createElement("div");
msgDiv.className = sender === "user" ? "user-bubble" : "ai-bubble";
var formattedText = formatContent(text);
var senderName = sender === "user" ? "You" : "Cortexa";
msgDiv.innerHTML = '
' + senderName + '
' + formattedText + '
';
var id = "msg-" + Date.now() + "-" + Math.random();
msgDiv.id = id;
chatBox.appendChild(msgDiv);
chatBox.scrollTo({
top: chatBox.scrollHeight,
behavior: 'smooth'
});
return id;
}
function updateMessage(id, newText) {
var msg = document.getElementById(id);
if (msg) {
var contentDiv = msg.querySelector(".chat-content");
if (contentDiv) {
contentDiv.innerHTML = formatContent(newText);
}
}
}
// ================= MAIN CHAT FUNCTION =================
window.performSearch = async function() {
console.log("🔵 performSearch called");
var queryInput = document.getElementById('searchInput');
if (!queryInput) {
console.error("❌ searchInput not found!");
return;
}
var query = queryInput.value.trim();
if (!query) {
console.log("Empty query");
return;
}
displayMessage(query, 'user');
queryInput.value = '';
var loadingId = displayMessage('Thinking. . . ', 'bot');
try {
var requestBody = {
message: query,
document_content: currentDocument && currentDocument.content ? currentDocument.content : null,
audio: false
};
console.log("📤 Sending to:", ENDPOINTS.chat);
var response = await fetch(ENDPOINTS.chat, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify(requestBody)
});
const rawText = await response.text();
if (!response.ok) {
throw new Error("HTTP " + response.status + ": " + rawText.substring(0, 300));
}
let data;
try {
data = JSON.parse(rawText);
} catch (jsonError) {
throw new Error("Backend returned invalid JSON: " + rawText.substring(0, 300));
}
if (data.response) {
updateMessage(loadingId, data.response);
await saveCurrentChat(query, data.response);
} else {
updateMessage(loadingId, "⚠️ Backend connected, but no AI response was returned.\n\nResponse: " + JSON.stringify(data));
}
} catch (error) {
console.error("❌ Chat error:", error);
updateMessage(loadingId, "⚠️ Error connecting to AI.\n\nDetails: " + error.message + "\n\nMake sure the backend is running and accessible.");
}
}
// ================= SAVE CHAT (backend-synced when logged in) =================
async function saveCurrentChat(userMessage, aiResponse) {
if (!currentChatId) {
var title = userMessage.substring(0, 30);
var messages = [
{ role: 'user', content: userMessage, timestamp: new Date().toISOString() },
{ role: 'assistant', content: aiResponse, timestamp: new Date().toISOString() }
];
var newId = await persistChat(null, title, messages);
currentChatId = newId;
sessionChatsCache.unshift({
id: newId, title: title, messages: messages,
created_at: new Date().toISOString(), updated_at: new Date().toISOString()
});
} else {
var chatIndex = sessionChatsCache.findIndex(function(c) { return c.id === currentChatId; });
var existingMessages = chatIndex !== -1 ? sessionChatsCache[chatIndex].messages : [];
var newMessages = existingMessages.concat([
{ role: 'user', content: userMessage, timestamp: new Date().toISOString() },
{ role: 'assistant', content: aiResponse, timestamp: new Date().toISOString() }
]);
var title = (chatIndex !== -1 && newMessages.length > 2)
? sessionChatsCache[chatIndex].title
: userMessage.substring(0, 30);
await persistChat(currentChatId, title, newMessages);
if (chatIndex !== -1) {
sessionChatsCache[chatIndex].messages = newMessages;
sessionChatsCache[chatIndex].title = title;
}
}
await loadChats();
}
// ================= ADD WELCOME MESSAGE =================
function addWelcomeMessage() {
var container = document.getElementById("searchResults");
if (!container) return;
if (container.children.length === 0) {
displayMessage("👋 Hi! I'm Cortexa. Ask me anything! 💙", 'bot');
}
}
// ================= LOAD CHATS =================
async function loadChats() {
var container = document.getElementById("chatList");
if (!container) return;
var chats = await getChats();
if (chats.length === 0) {
container.innerHTML = 'No chats yet
';
return;
}
container.innerHTML = "";
chats.slice(0, 20).forEach(function(chat) {
var div = document.createElement("div");
div.className = "chat-item" + (currentChatId === chat.id ? ' active' : '');
div.setAttribute('data-chat-id', chat.id);
div.innerHTML = '💬 ' + escapeHtml(chat.title.substring(0, 35)) + ' ';
container.appendChild(div);
});
}
// ================= LOAD PROJECTS =================
function loadProjects() {
var container = document.getElementById("projectListRight");
if (!container) return;
var projects = getProjects();
if (projects.length === 0) {
container.innerHTML = 'No projects yet
';
return;
}
container.innerHTML = "";
projects.slice(0, 10).forEach(function(project) {
var div = document.createElement("div");
div.className = "project-item";
div.setAttribute('data-project-id', project.id);
div.innerHTML = '📁 ' + escapeHtml(project.name.substring(0, 35));
container.appendChild(div);
});
}
// ================= CHAT MANAGEMENT =================
window.loadChatById = async function(chatId) {
var chats = await getChats();
var chat = chats.find(function(c) { return c.id === chatId; });
if (chat) {
currentChatId = chat.id;
var container = document.getElementById("searchResults");
if (container) {
container.innerHTML = "";
chat.messages.forEach(function(msg) {
displayMessage(msg.content, msg.role === 'user' ? 'user' : 'bot');
});
}
await loadChats();
showToast("Chat loaded!");
}
}
window.deleteChatById = async function(chatId) {
if (confirm("Delete this chat?")) {
await removeChat(chatId);
if (currentChatId === chatId) {
currentChatId = null;
var container = document.getElementById("searchResults");
if (container) {
container.innerHTML = "";
addWelcomeMessage();
}
}
await loadChats();
showToast("🗑️ Chat deleted!");
}
var dropdown = document.getElementById("chat-dropdown-" + chatId);
if (dropdown) dropdown.classList.remove('show');
}
window.startNewChat = function(e) {
if (e) e.preventDefault();
currentChatId = null;
var container = document.getElementById("searchResults");
if (container) {
container.innerHTML = "";
addWelcomeMessage();
}
loadChats();
showToast("✨ New chat started!");
}
window.toggleChatMenu = function(event, chatId) {
event.stopPropagation();
document.querySelectorAll('.chat-dropdown.show').forEach(function(dropdown) {
if (dropdown.id !== "chat-dropdown-" + chatId) {
dropdown.classList.remove('show');
}
});
var dropdown = document.getElementById("chat-dropdown-" + chatId);
if (!dropdown) return;
dropdown.classList.toggle('show');
setTimeout(function() {
dropdown.classList.remove('show');
}, 3000);
}
window.togglePlusDropdown = function() {
var dropdown = document.getElementById('plusDropdown');
if (dropdown) dropdown.classList.toggle('show');
}
window.shareChat = async function() {
if (currentChatId) {
var chats = await getChats();
var chat = chats.find(function(c) { return c.id === currentChatId; });
if (chat) {
var shareText = chat.title + '\n\n' + chat.messages.map(function(m) { return (m.role === 'user' ? 'You' : 'Cortexa') + ': ' + m.content; }).join('\n\n');
navigator.clipboard.writeText(shareText);
showToast("✅ Chat copied to clipboard!");
}
} else {
showToast("❌ No active chat to share!");
}
}
window.deleteChat = async function() {
if (currentChatId) {
if (confirm("Delete this chat?")) {
await removeChat(currentChatId);
currentChatId = null;
var container = document.getElementById("searchResults");
if (container) {
container.innerHTML = "";
addWelcomeMessage();
}
await loadChats();
showToast("🗑️ Current chat deleted!");
}
} else {
showToast("❌ No active chat to delete!");
}
}
window.pinChat = function() {
showToast("📌 Pin feature coming soon!");
}
window.createProject = function() {
var name = prompt("Enter project name:");
if (name && name.trim() !== "") {
var projects = getProjects();
var newProject = {
id: 'project_' + Date.now(),
name: name.trim(),
created_at: new Date().toLocaleString()
};
projects.push(newProject);
saveProjects(projects);
loadProjects();
showToast("✅ Project \"" + name + "\" created!");
}
}
// ================= DOCUMENT CHAT =================
window.documentChat = function() {
var input = document.createElement('input');
input.type = 'file';
input.accept = '.txt,.pdf,.docx';
input.onchange = async function(e) {
var file = e.target.files[0];
if (file) {
var formData = new FormData();
formData.append('file', file);
showToast("📄 Uploading document...");
try {
var response = await fetch(ENDPOINTS.uploadDocument, {
method: 'POST',
body: formData
});
var data = await response.json();
if (!response.ok) {
throw new Error(data.error || "Upload failed");
}
currentDocument = data;
showToast("✅ Document \"" + file.name + "\" loaded! You can now ask questions about it.");
displayMessage("📄 **Document loaded:** " + file.name + "\n\nYou can now ask me questions about this document!", 'bot');
} catch (error) {
console.error("❌ Document upload error:", error);
showToast("❌ Error uploading document: " + error.message, "error");
}
}
};
input.click();
}
// ================= AUDIO MODE =================
window.openAudioMode = function() {
var modal = document.getElementById('audioModal');
if (modal) modal.style.display = 'flex';
}
window.closeAudioMode = function() {
var modal = document.getElementById('audioModal');
if (modal) modal.style.display = 'none';
}
window.setAudioMode = function(mode, btn) {
currentAudioMode = mode;
document.querySelectorAll('.mode-btn').forEach(function(b) { return b.classList.remove('active'); });
btn.classList.add('active');
showToast("🎵 Audio mode: " + mode);
}
window.toggleMicrophone = async function() {
var micBtn = document.getElementById('micButton');
var statusDiv = document.getElementById('micStatus');
if (!isRecording) {
try {
var stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
audioChunks = [];
mediaRecorder.ondataavailable = function(event) {
audioChunks.push(event.data);
};
mediaRecorder.onstop = async function() {
var audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
statusDiv.innerHTML = '🎤 Speech detected! Processing...';
showToast("🎤 Voice input received! Please type your question for now (voice-to-text coming soon)");
statusDiv.innerHTML = 'Click microphone to speak';
isRecording = false;
micBtn.classList.remove('listening');
stream.getTracks().forEach(function(track) { return track.stop(); });
};
mediaRecorder.start();
isRecording = true;
micBtn.classList.add('listening');
statusDiv.innerHTML = '🔴 Recording... Click again to stop';
} catch (err) {
console.error('Microphone error:', err);
statusDiv.innerHTML = '❌ Microphone access denied';
showToast("Microphone access denied", "error");
}
} else {
if (mediaRecorder && isRecording) {
mediaRecorder.stop();
}
}
}
// ================= SEND AUDIO QUERY =================
window.sendAudioQuery = async function() {
var queryInput = document.getElementById('audioQueryInput');
var query = queryInput.value.trim();
if (!query) {
showToast("Please enter a question", "error");
return;
}
var responseArea = document.getElementById('audioResponseArea');
var responseText = document.getElementById('responseText');
responseArea.style.display = 'block';
responseText.innerHTML = 'Generating response... ';
try {
var requestBody = { message: query, audio: true };
var response = await fetch(ENDPOINTS.chat, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody)
});
var data = await response.json();
currentAudioText = data.response;
responseText.innerHTML = formatContent(data.response);
var audioResponse = await fetch(ENDPOINTS.generateAudio, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text: data.response })
});
var audioData = await audioResponse.json();
if (audioData.audio_url) {
var audioPlayer = document.getElementById('audioPlayer');
audioPlayer.src = BASE_URL + audioData.audio_url;
document.getElementById('audioPlayerContainer').style.display = 'block';
}
} catch (error) {
console.error("Audio error:", error);
responseText.innerHTML = '❌ Error generating response';
showToast("Error connecting to AI", "error");
}
}
window.playAudioResponse = function() {
var audio = document.getElementById('audioPlayer');
if (audio && audio.src) {
audio.play();
} else {
showToast("No audio available", "error");
}
}
window.pauseAudioResponse = function() {
var audio = document.getElementById('audioPlayer');
if (audio) audio.pause();
}
window.stopAudioResponse = function() {
var audio = document.getElementById('audioPlayer');
if (audio) {
audio.pause();
audio.currentTime = 0;
}
}
window.downloadAudioResponse = function() {
var audio = document.getElementById('audioPlayer');
if (audio && audio.src) {
var a = document.createElement('a');
a.href = audio.src;
a.download = 'cortexa_audio.mp3';
a.click();
showToast("Downloading audio...");
} else {
showToast("No audio available", "error");
}
}
// ================= VIDEO MODE =================
window.openVideoMode = function() {
var modal = document.getElementById('videoModal');
if (modal) modal.style.display = 'flex';
switchVideoTab('youtube');
}
window.closeVideoMode = function() {
var modal = document.getElementById('videoModal');
if (modal) modal.style.display = 'none';
}
window.switchVideoTab = function(tab) {
var youtubeTab = document.getElementById('youtubeTab');
var libraryTab = document.getElementById('libraryTab');
var btns = document.querySelectorAll('.tab-btn');
btns.forEach(function(btn) { return btn.classList.remove('active'); });
if (tab === 'youtube') {
if (youtubeTab) youtubeTab.style.display = 'block';
if (libraryTab) libraryTab.style.display = 'none';
if (btns[0]) btns[0].classList.add('active');
} else {
if (youtubeTab) youtubeTab.style.display = 'none';
if (libraryTab) libraryTab.style.display = 'block';
if (btns[1]) btns[1].classList.add('active');
loadVideoLibrary();
}
}
// ================= YOUTUBE SEARCH =================
window.searchYouTube = async function() {
var query = document.getElementById('youtubeSearchQuery').value;
if (!query) {
showToast("Please enter a search term", "error");
return;
}
showToast("🔍 Searching YouTube...");
var resultsDiv = document.getElementById('youtubeResults');
if (!resultsDiv) return;
resultsDiv.innerHTML = '🔍 Searching for videos...
';
try {
var response = await fetch(ENDPOINTS.youtubeSearch + "?query=" + encodeURIComponent(query) + "&max_results=12");
var data = await response.json();
if (data.error) {
resultsDiv.innerHTML = '❌ ' + data.error + '
';
showToast(data.error, "error");
return;
}
if (!data.videos || data.videos.length === 0) {
resultsDiv.innerHTML = '😕 No videos found. Try a different search term.
';
return;
}
resultsDiv.innerHTML = '' + data.videos.map(function(video) {
return '
' + (video.duration || 'N/A') + '
' + escapeHtml(video.title.substring(0, 70)) + ' ' + escapeHtml(video.channel) + '
👁️ ' + (video.views || 'N/A') + ' views
🤖 Get AI Summary ▶️ Watch on YouTube ';
}).join('') + '
';
showToast("Found " + data.videos.length + " videos!");
} catch (error) {
console.error('Search error:', error);
resultsDiv.innerHTML = '❌ Failed to search YouTube. Make sure backend is running.
';
showToast("Error connecting to backend", "error");
}
}
// ================= YOUTUBE VIDEO INFO =================
window.getVideoInfoAndSummary = async function(videoId, videoTitle) {
showToast("📹 Getting video information and generating AI summary...");
var infoDiv = document.getElementById('youtubeVideoInfo');
if (!infoDiv) return;
infoDiv.style.display = 'block';
infoDiv.innerHTML = '🧠 Analyzing video content...
';
try {
var infoResponse = await fetch(ENDPOINTS.youtubeVideoInfo + "?video_id=" + videoId);
var videoInfo = await infoResponse.json();
if (videoInfo.error) {
infoDiv.innerHTML = '❌ ' + videoInfo.error + '
';
return;
}
var summaryPrompt = 'Please provide a comprehensive summary of this YouTube video:\n\nTitle: ' + (videoTitle || videoInfo.title) + '\nChannel: ' + (videoInfo.channel || 'Unknown') + '\nDescription: ' + (videoInfo.description || 'No description available') + '\n\nPlease provide:\n1. Main topic/theme of the video\n2. 5-7 key points covered\n3. Important takeaways\n4. Who should watch this video\n5. A brief one-paragraph summary\n\nFormat the response in a clean, organized way with emojis for each section.';
var summaryResponse = await fetch(ENDPOINTS.chat, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
message: summaryPrompt,
document_content: null,
audio: false
})
});
var summaryData = await summaryResponse.json();
var aiSummary = summaryData.response || "Summary generation failed. Please try again.";
infoDiv.innerHTML = '📺 Channel: ' + escapeHtml(videoInfo.channel || 'N/A') + '
👁️ Views: ' + parseInt(videoInfo.views || 0).toLocaleString() + '
👍 Likes: ' + parseInt(videoInfo.likes || 0).toLocaleString() + '
⏱️ Duration: ' + (videoInfo.duration || 'N/A') + '
🤖 AI GENERATED SUMMARY ' + formatContent(aiSummary) + '
📝 Video Description ' + escapeHtml((videoInfo.description || 'No description').substring(0, 1000)) + '
🎬 Watch on YouTube 📋 Copy Summary 💾 Download Summary 💾 Save to Library
';
document.getElementById('youtubeOptions').style.display = 'block';
showToast("✅ AI Summary generated successfully!");
} catch (error) {
console.error('Error:', error);
infoDiv.innerHTML = '❌ Error generating summary. Please try again.
';
showToast("Error generating summary", "error");
}
}
window.closeVideoInfo = function() {
var infoDiv = document.getElementById('youtubeVideoInfo');
if (infoDiv) infoDiv.style.display = 'none';
}
window.openInYouTube = function(videoId) {
var youtubeUrl = 'https://www.youtube.com/watch?v=' + videoId;
window.open(youtubeUrl, '_blank');
showToast("📺 Opening YouTube in new tab...");
}
window.copySummaryToClipboard = function() {
var summaryText = document.querySelector('.summary-text')?.innerText;
if (summaryText) {
navigator.clipboard.writeText(summaryText);
showToast("📋 Summary copied to clipboard!");
} else {
showToast("No summary to copy", "error");
}
}
window.downloadSummaryAsFile = function() {
var summaryText = document.querySelector('.summary-text')?.innerText;
if (summaryText) {
var blob = new Blob([summaryText], { type: 'text/plain' });
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = 'video_summary.txt';
a.click();
URL.revokeObjectURL(url);
showToast("💾 Summary downloaded!");
} else {
showToast("No summary to download", "error");
}
}
window.saveVideoToLibrary = function(videoId, videoTitle) {
var user = getCurrentUser();
var savedVideos = JSON.parse(localStorage.getItem("videos_" + user) || '[]');
if (!savedVideos.some(function(v) { return v.id === videoId; })) {
var newVideo = {
id: videoId,
title: videoTitle,
url: 'https://youtube.com/watch?v=' + videoId,
date: new Date().toLocaleString(),
thumbnail: 'https://img.youtube.com/vi/' + videoId + '/mqdefault.jpg'
};
savedVideos.push(newVideo);
localStorage.setItem("videos_" + user, JSON.stringify(savedVideos));
showToast("💾 Video saved to library!");
loadVideoLibrary();
} else {
showToast("Video already in library!");
}
}
function loadVideoLibrary() {
var user = getCurrentUser();
var libraryDiv = document.getElementById('videoLibraryList');
if (!libraryDiv) return;
var savedVideos = JSON.parse(localStorage.getItem("videos_" + user) || '[]');
if (savedVideos.length === 0) {
libraryDiv.innerHTML = '📭 No saved videos. Search and save videos to see them here!
';
return;
}
libraryDiv.innerHTML = '' + savedVideos.map(function(video) {
return '
' + escapeHtml(video.title.substring(0, 50)) + ' Saved: ' + video.date + '
🤖 Get AI Summary 🗑️ Remove ';
}).join('') + '
';
}
window.removeFromLibrary = function(videoId) {
var user = getCurrentUser();
var savedVideos = JSON.parse(localStorage.getItem("videos_" + user) || '[]');
savedVideos = savedVideos.filter(function(v) { return v.id !== videoId; });
localStorage.setItem("videos_" + user, JSON.stringify(savedVideos));
loadVideoLibrary();
showToast("🗑️ Video removed from library");
}
// ================= REPORT MODE =================
window.openReportMode = function() {
var modal = document.getElementById('reportModal');
if (modal) {
modal.style.display = 'flex';
}
}
window.closeReportMode = function() {
var modal = document.getElementById('reportModal');
if (modal) modal.style.display = 'none';
}
window.generateReport = async function() {
var topic = document.getElementById('reportTopicInput').value;
if (!topic) {
showToast("Please enter a topic", "error");
return;
}
var format = document.getElementById('reportFormat')?.value || 'PDF Document';
var includeCharts = document.getElementById('includeCharts')?.checked || false;
var includeTables = document.getElementById('includeTables')?.checked || false;
var includeExecutive = document.getElementById('includeExecutive')?.checked || true;
var includeRecommendations = document.getElementById('includeRecommendations')?.checked || true;
var includeAppendix = document.getElementById('includeAppendix')?.checked || false;
var progressDiv = document.getElementById('reportProgress');
var progressFill = document.getElementById('reportProgressFill');
var displayDiv = document.getElementById('reportDisplay');
var contentDiv = document.getElementById('reportContent');
if (progressDiv) {
progressDiv.style.display = 'block';
progressDiv.innerHTML = '📊 Generating comprehensive report on "' + topic.substring(0, 50) + '"...
';
}
var width = 0;
var interval = setInterval(function() {
width += 10;
if (progressFill) progressFill.style.width = width + '%';
}, 200);
try {
var prompt = 'Generate a comprehensive, professional report about "' + topic + '". The report should include:';
if (includeExecutive) prompt += '\n- Executive Summary';
prompt += '\n- Introduction';
prompt += '\n- Key Findings (at least 5 points with detailed explanations)';
prompt += '\n- Detailed Analysis';
if (includeCharts) prompt += '\n- Charts and Graphs Analysis (describe what charts would show)';
if (includeTables) prompt += '\n- Data Tables (create relevant data tables)';
prompt += '\n- Challenges and Opportunities';
if (includeRecommendations) prompt += '\n- Recommendations (at least 3 actionable recommendations)';
prompt += '\n- Conclusion';
if (includeAppendix) prompt += '\n- Appendix with References and Sources';
prompt += '\n\nFormat the report with proper headings (## for main sections), subheadings (### for subsections), and bullet points. Make it professional, well-structured, data-driven, and suitable for business/academic audience. Use markdown formatting.';
var response = await fetch(ENDPOINTS.chat, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: prompt, document_content: null, audio: false })
});
var data = await response.json();
var reportContent = data.response || "Failed to generate report.";
reportContent = reportContent.replace(/## (.*?)$/gm, '$1 ');
reportContent = reportContent.replace(/### (.*?)$/gm, '$1 ');
reportContent = reportContent.replace(/\*\*(.*?)\*\*/g, '$1 ');
reportContent = reportContent.replace(/^- (.*?)$/gm, '$1 ');
reportContent = reportContent.replace(/\n/g, ' ');
clearInterval(interval);
if (progressDiv) progressDiv.style.display = 'none';
if (displayDiv) displayDiv.style.display = 'block';
window.currentReport = {
topic: topic,
content: reportContent,
rawContent: data.response,
format: format,
date: new Date().toLocaleString(),
options: { includeCharts: includeCharts, includeTables: includeTables, includeExecutive: includeExecutive, includeRecommendations: includeRecommendations, includeAppendix: includeAppendix }
};
if (contentDiv) {
contentDiv.innerHTML = '📊 ' + escapeHtml(topic) + ' 📅 Generated: ' + new Date().toLocaleString() + ' 📄 Format: ' + format + ' 🤖 Generated by Cortexa AI
' + reportContent + '
';
}
showToast("✅ Report generated successfully!");
} catch (error) {
clearInterval(interval);
if (progressDiv) progressDiv.style.display = 'none';
console.error('Report error:', error);
showToast("Error generating report", "error");
}
}
window.downloadReportAsPDF = function() {
var reportContainer = document.getElementById('reportContainer');
if (!reportContainer) {
showToast("No report to download! Generate a report first.", "error");
return;
}
var printWindow = window.open('', '_blank');
printWindow.document.write('' + (window.currentReport?.topic || 'Report') + ' - Cortexa AI ' + reportContainer.outerHTML + '');
printWindow.print();
printWindow.close();
showToast("📄 Report sent to printer (save as PDF)");
}
window.downloadReportAsDOCX = function() {
if (!window.currentReport) {
showToast("No report to download! Generate a report first.", "error");
return;
}
var reportContent = document.getElementById('reportContentText')?.innerText || window.currentReport.rawContent;
if (!reportContent) {
showToast("No content to download", "error");
return;
}
var docContent = window.currentReport.topic + '\n' + '='.repeat(50) + '\n\nGenerated on: ' + window.currentReport.date + '\nFormat: ' + window.currentReport.format + '\n\n' + reportContent + '\n\n' + '='.repeat(50) + '\nGenerated by Cortexa AI Report Generator';
var blob = new Blob([docContent], { type: 'application/msword' });
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = window.currentReport.topic.replace(/[^a-z0-9]/gi, '_') + '_report.doc';
a.click();
URL.revokeObjectURL(url);
showToast("📄 Report downloaded as DOCX!");
}
window.copyReportToClipboard = function() {
if (!window.currentReport) {
showToast("No report to copy! Generate a report first.", "error");
return;
}
var reportText = document.getElementById('reportContentText')?.innerText || window.currentReport.rawContent;
if (reportText) {
navigator.clipboard.writeText(reportText).then(function() {
showToast("📋 Report copied to clipboard!");
}).catch(function() {
showToast("Failed to copy", "error");
});
} else {
showToast("No content to copy", "error");
}
}
window.shareReport = function() {
if (!window.currentReport) {
showToast("No report to share! Generate a report first.", "error");
return;
}
var shareText = '📊 Report: ' + window.currentReport.topic + '\n\n' + (document.getElementById('reportContentText')?.innerText || window.currentReport.rawContent).substring(0, 500) + '...\n\nGenerated on: ' + window.currentReport.date + '\n\nGenerated by Cortexa AI';
navigator.clipboard.writeText(shareText).then(function() {
showToast("📤 Report summary copied to clipboard! You can now share it anywhere.");
}).catch(function() {
showToast("Failed to copy for sharing", "error");
});
}
window.saveReportToLibrary = function() {
if (!window.currentReport) {
showToast("No report to save! Generate a report first.", "error");
return;
}
var user = getCurrentUser();
var savedReports = JSON.parse(localStorage.getItem("reports_" + user) || '[]');
var reportToSave = {
id: 'report_' + Date.now(),
title: window.currentReport.topic,
content: window.currentReport.rawContent,
formattedContent: window.currentReport.content,
date: window.currentReport.date,
format: window.currentReport.format,
options: window.currentReport.options
};
savedReports.unshift(reportToSave);
localStorage.setItem("reports_" + user, JSON.stringify(savedReports));
showToast("✅ Report \"" + window.currentReport.topic + "\" saved to library!");
}
window.printReport = function() {
var reportContainer = document.getElementById('reportContainer');
if (!reportContainer) {
showToast("No report to print! Generate a report first.", "error");
return;
}
var printWindow = window.open('', '_blank');
printWindow.document.write('' + (window.currentReport?.topic || 'Report') + ' - Cortexa AI ' + reportContainer.outerHTML + '');
printWindow.print();
printWindow.close();
showToast("🖨️ Report sent to printer!");
}
window.loadReportFromLibrary = function(reportId) {
var user = getCurrentUser();
var savedReports = JSON.parse(localStorage.getItem("reports_" + user) || '[]');
var report = savedReports.find(function(r) { return r.id === reportId; });
if (report) {
window.currentReport = {
topic: report.title,
content: report.formattedContent,
rawContent: report.content,
date: report.date,
format: report.format,
options: report.options
};
var contentDiv = document.getElementById('reportContent');
if (contentDiv) {
contentDiv.innerHTML = '📊 ' + escapeHtml(report.title) + ' 📅 Generated: ' + report.date + ' 📄 Format: ' + report.format + '
' + report.formattedContent + '
';
}
document.getElementById('reportDisplay').style.display = 'block';
showToast("✅ Report \"" + report.title + "\" loaded from library!");
} else {
showToast("Report not found!", "error");
}
}
window.openReportLibrary = function() {
var user = getCurrentUser();
var savedReports = JSON.parse(localStorage.getItem("reports_" + user) || '[]');
if (savedReports.length === 0) {
showToast("No saved reports found!", "info");
return;
}
var libraryHTML = '📚 Saved Reports ';
savedReports.forEach(function(report) {
libraryHTML += '
' + escapeHtml(report.title) + ' ' + report.date + '
Load ';
});
libraryHTML += '
Close ';
var modal = document.getElementById('reportLibraryModal');
if (!modal) {
modal = document.createElement('div');
modal.id = 'reportLibraryModal';
modal.className = 'report-library-floating-modal';
document.body.appendChild(modal);
}
modal.innerHTML = libraryHTML;
modal.style.display = 'block';
}
window.closeReportLibrary = function() {
var modal = document.getElementById('reportLibraryModal');
if (modal) modal.style.display = 'none';
}
// ============================================
// LEARNING TOOLS - QUIZ GENERATOR
// ============================================
window.openLearningTools = function() {
var modal = document.getElementById('learningToolsModal');
if (modal) modal.style.display = 'flex';
switchLearningTab('quiz');
}
window.closeLearningTools = function() {
var modal = document.getElementById('learningToolsModal');
if (modal) modal.style.display = 'none';
}
window.switchLearningTab = function(tab) {
var quizTab = document.getElementById('quizTab');
var notesTab = document.getElementById('notesTab');
var btns = document.querySelectorAll('.learning-tab-btn');
btns.forEach(function(btn) { return btn.classList.remove('active'); });
if (tab === 'quiz') {
if (quizTab) quizTab.style.display = 'block';
if (notesTab) notesTab.style.display = 'none';
if (btns[0]) btns[0].classList.add('active');
} else {
if (quizTab) quizTab.style.display = 'none';
if (notesTab) notesTab.style.display = 'block';
if (btns[1]) btns[1].classList.add('active');
}
}
window.generateQuiz = async function() {
var topic = document.getElementById('quizTopicInput').value;
if (!topic) {
showToast("Please enter a topic", "error");
return;
}
var numQuestions = document.getElementById('quizCount')?.value || 5;
var difficulty = document.getElementById('quizDifficulty')?.value || 'medium';
var questionType = document.getElementById('quizType')?.value || 'mixed';
var progressDiv = document.getElementById('quizProgress');
var progressFill = document.getElementById('quizProgressFill');
var displayDiv = document.getElementById('quizDisplay');
var contentDiv = document.getElementById('quizContent');
if (progressDiv) progressDiv.style.display = 'block';
var width = 0;
var interval = setInterval(function() {
width += 10;
if (progressFill) progressFill.style.width = width + '%';
}, 100);
try {
var prompt = 'Generate a quiz about "' + topic + '" with exactly ' + numQuestions + ' questions. Difficulty: ' + difficulty + '. Type: ' + questionType + '.\n\nReturn ONLY valid JSON with this exact format:\n{\n "title": "' + topic + ' Quiz",\n "questions": [\n {\n "id": 1,\n "text": "Question text here",\n "type": "mcq",\n "options": ["Option A", "Option B", "Option C", "Option D"],\n "correctAnswer": "Option A",\n "explanation": "Brief explanation"\n }\n ]\n}\n\nFor true/false, options should be ["True", "False"].\nMake questions educational and appropriate for ' + difficulty + ' difficulty.';
var response = await fetch(ENDPOINTS.chat, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
message: prompt,
document_content: null,
audio: false
})
});
var data = await response.json();
var quizData;
try {
var jsonStr = data.response;
var jsonMatch = jsonStr.match(/\{[\s\S]*\}/);
if (jsonMatch) jsonStr = jsonMatch[0];
quizData = JSON.parse(jsonStr);
} catch (e) {
quizData = {
title: topic + ' Quiz',
questions: Array(parseInt(numQuestions)).fill().map(function(_, i) {
return {
id: i + 1,
text: 'Sample question about ' + topic + ' ' + (i + 1),
type: "mcq",
options: ["Option A", "Option B", "Option C"],
correctAnswer: "Option A",
explanation: "This is a sample explanation."
};
})
};
}
clearInterval(interval);
if (progressDiv) progressDiv.style.display = 'none';
if (displayDiv) displayDiv.style.display = 'block';
window.currentQuizData = quizData;
window.quizAnswers = {};
var quizHTML = '';
quizData.questions.forEach(function(q, idx) {
var qNum = idx + 1;
quizHTML += '
Question ' + qNum + ': ' + escapeHtml(q.text) + '
';
var options = q.options || (q.type === 'truefalse' ? ['True', 'False'] : ['Option A', 'Option B', 'Option C']);
options.forEach(function(opt) {
quizHTML += '' + escapeHtml(opt) + ' ';
});
quizHTML += '
';
});
quizHTML += '
✅ Submit Quiz 🔄 Reset All 📄 Export PDF 📋 Copy 💾 Save to Library
';
if (contentDiv) contentDiv.innerHTML = quizHTML;
showToast("✅ Quiz generated with " + quizData.questions.length + " questions!");
} catch (error) {
clearInterval(interval);
if (progressDiv) progressDiv.style.display = 'none';
console.error('Quiz error:', error);
showToast("Error generating quiz", "error");
}
}
window.saveQuizAnswer = function(questionNum, answer) {
if (!window.quizAnswers) window.quizAnswers = {};
window.quizAnswers[questionNum] = answer;
var questionCard = document.querySelector('.quiz-question-card[data-question-id="' + questionNum + '"]');
if (questionCard) {
questionCard.style.borderLeft = '4px solid #10b981';
}
}
window.submitQuizAnswers = function() {
if (!window.currentQuizData || !window.currentQuizData.questions) {
showToast("No quiz loaded!", "error");
return;
}
var score = 0;
var totalQuestions = window.currentQuizData.questions.length;
var results = [];
window.currentQuizData.questions.forEach(function(q, idx) {
var qNum = idx + 1;
var userAnswer = window.quizAnswers ? window.quizAnswers[qNum] : null;
var isCorrect = userAnswer === q.correctAnswer;
if (isCorrect) {
score++;
}
results.push({
id: qNum,
question: q.text,
userAnswer: userAnswer || "Not answered",
correctAnswer: q.correctAnswer,
isCorrect: isCorrect,
explanation: q.explanation
});
var feedbackDiv = document.getElementById('feedback-' + qNum);
if (feedbackDiv) {
if (userAnswer) {
if (isCorrect) {
feedbackDiv.innerHTML = '✅ Correct! ' + (q.explanation || 'Great job!') + '
';
feedbackDiv.style.backgroundColor = '#d1fae5';
} else {
feedbackDiv.innerHTML = '❌ Incorrect! Your answer: ' + escapeHtml(userAnswer) + ' Correct answer: ' + escapeHtml(q.correctAnswer) + ' ' + (q.explanation ? '📖 ' + q.explanation : '') + '
';
feedbackDiv.style.backgroundColor = '#fee2e2';
}
} else {
feedbackDiv.innerHTML = '⚠️ Not answered! Correct answer: ' + escapeHtml(q.correctAnswer) + ' ' + (q.explanation ? '📖 ' + q.explanation : '') + '
';
feedbackDiv.style.backgroundColor = '#fffbeb';
}
feedbackDiv.style.display = 'block';
feedbackDiv.style.padding = '12px';
feedbackDiv.style.borderRadius = '8px';
feedbackDiv.style.marginTop = '10px';
}
});
var percentage = Math.round((score / totalQuestions) * 100);
var gradeMessage = '';
var gradeIcon = '';
if (percentage >= 90) {
gradeMessage = 'Excellent! You\'re a master of this topic! 🏆';
gradeIcon = '🎉';
} else if (percentage >= 70) {
gradeMessage = 'Good job! You have a solid understanding! 👍';
gradeIcon = '📚';
} else if (percentage >= 50) {
gradeMessage = 'Not bad! Review the material and try again! 💪';
gradeIcon = '📖';
} else {
gradeMessage = 'Keep studying! You\'ll get better with practice! 🌟';
gradeIcon = '⭐';
}
var resultsContainer = document.getElementById('quizResultsContainer');
if (resultsContainer) {
resultsContainer.style.display = 'block';
resultsContainer.innerHTML = '' + score + '/' + totalQuestions + '
' + percentage + '%
' + gradeMessage + '
📖 View Detailed Results ' + results.map(function(r) {
return '
Q' + r.id + ': ' + escapeHtml(r.question) + '
Your answer: ' + escapeHtml(r.userAnswer) + '
Correct: ' + escapeHtml(r.correctAnswer) + '
' + (r.explanation ? '
Explanation: ' + escapeHtml(r.explanation) + '
' : '') + '
';
}).join('') + '
📖 Review Wrong Answers 🔄 Try Again 📄 Export Results
';
}
resultsContainer.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
showToast("Quiz completed! Score: " + score + "/" + totalQuestions + " (" + percentage + "%)");
}
window.resetQuizAnswers = function() {
window.quizAnswers = {};
document.querySelectorAll('#quizQuestionsContainer input[type="radio"]').forEach(function(radio) {
radio.checked = false;
});
document.querySelectorAll('.quiz-feedback').forEach(function(feedback) {
feedback.style.display = 'none';
feedback.innerHTML = '';
});
document.querySelectorAll('.quiz-question-card').forEach(function(card) {
card.style.borderLeft = '';
});
var resultsContainer = document.getElementById('quizResultsContainer');
if (resultsContainer) resultsContainer.style.display = 'none';
showToast("Quiz reset! You can try again.");
}
window.scrollToWrongAnswers = function() {
var wrongFeedbacks = document.querySelectorAll('.wrong-feedback');
if (wrongFeedbacks.length > 0) {
wrongFeedbacks[0].scrollIntoView({ behavior: 'smooth', block: 'center' });
showToast("Reviewing " + wrongFeedbacks.length + " incorrect answers...");
} else {
showToast("🎉 Perfect score! No wrong answers to review!");
}
}
window.exportQuizResults = function() {
if (!window.currentQuizData || !window.quizAnswers) {
showToast("No quiz results to export!", "error");
return;
}
var exportText = '📝 ' + window.currentQuizData.title + '\n';
exportText += '📅 Date: ' + new Date().toLocaleString() + '\n';
exportText += '📊 Total Questions: ' + window.currentQuizData.questions.length + '\n';
exportText += '="\n\n';
var score = 0;
window.currentQuizData.questions.forEach(function(q, idx) {
var qNum = idx + 1;
var userAnswer = window.quizAnswers[qNum] || "Not answered";
var isCorrect = userAnswer === q.correctAnswer;
if (isCorrect) score++;
exportText += qNum + '. ' + q.text + '\n';
exportText += ' Your answer: ' + userAnswer + '\n';
exportText += ' Correct answer: ' + q.correctAnswer + '\n';
exportText += ' Result: ' + (isCorrect ? '✓ CORRECT' : '✗ INCORRECT') + '\n';
if (q.explanation) {
exportText += ' Explanation: ' + q.explanation + '\n';
}
exportText += '\n';
});
var percentage = Math.round((score / window.currentQuizData.questions.length) * 100);
exportText += '="\n';
exportText += 'FINAL SCORE: ' + score + '/' + window.currentQuizData.questions.length + ' (' + percentage + '%)\n';
exportText += 'Grade: ' + (percentage >= 70 ? 'PASSED' : 'NEEDS IMPROVEMENT') + '\n';
var blob = new Blob([exportText], { type: 'text/plain' });
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = window.currentQuizData.title.replace(/ /g, '_') + '_results.txt';
a.click();
URL.revokeObjectURL(url);
showToast("Quiz results exported!");
}
window.exportQuizAsPDF = function() {
var content = document.getElementById('quizContent')?.innerHTML;
if (content) {
var printWindow = window.open('', '_blank');
printWindow.document.write('Quiz ' + content + '');
printWindow.print();
}
}
window.copyQuizToClipboard = function() {
if (!window.currentQuizData) return;
var quizText = window.currentQuizData.title + '\n\n';
window.currentQuizData.questions.forEach(function(q, idx) {
quizText += (idx + 1) + '. ' + q.text + '\n Correct: ' + q.correctAnswer + '\n\n';
});
navigator.clipboard.writeText(quizText);
showToast("Quiz copied!");
}
window.saveQuizToLibrary = function() {
if (!window.currentQuizData) return;
var user = getCurrentUser();
var savedQuizzes = JSON.parse(localStorage.getItem("quizzes_" + user) || '[]');
savedQuizzes.push({
id: 'quiz_' + Date.now(),
title: window.currentQuizData.title,
data: window.currentQuizData,
date: new Date().toLocaleString()
});
localStorage.setItem("quizzes_" + user, JSON.stringify(savedQuizzes));
showToast("Quiz saved to library!");
}
// ============================================
// STUDY NOTES
// ============================================
window.generateStudyNotes = async function() {
var topic = document.getElementById('notesTopicInput').value;
if (!topic) {
showToast("Please enter a topic", "error");
return;
}
var progressDiv = document.getElementById('notesProgress');
var progressFill = document.getElementById('notesProgressFill');
var displayDiv = document.getElementById('notesDisplay');
var contentDiv = document.getElementById('notesContent');
if (progressDiv) progressDiv.style.display = 'block';
var width = 0;
var interval = setInterval(function() {
width += 10;
if (progressFill) progressFill.style.width = width + '%';
}, 100);
try {
var prompt = 'Create comprehensive study notes about "' + topic + '".\n\nInclude:\n1. Key Concepts (at least 5)\n2. Important Definitions\n3. Summary Points\n4. Key Takeaways\n5. Study Tips\n\nFormat with clear headings, bullet points, and emojis for easy reading.\nMake it organized and educational.';
var response = await fetch(ENDPOINTS.chat, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
message: prompt,
document_content: null,
audio: false
})
});
var data = await response.json();
var notesContent = data.response || "Failed to generate notes.";
clearInterval(interval);
if (progressDiv) progressDiv.style.display = 'none';
if (displayDiv) displayDiv.style.display = 'block';
if (contentDiv) {
contentDiv.innerHTML = '' + formatContent(notesContent) + '
';
}
window.currentNotes = { topic: topic, content: notesContent, date: new Date().toLocaleString() };
showToast("✅ Study notes generated!");
} catch (error) {
clearInterval(interval);
if (progressDiv) progressDiv.style.display = 'none';
console.error('Notes error:', error);
showToast("Error generating notes", "error");
}
}
window.exportNotesAsPDF = function() {
var content = document.getElementById('notesContent')?.innerHTML;
if (content) {
var printWindow = window.open('', '_blank');
printWindow.document.write('Study Notes ' + content + '');
printWindow.print();
}
}
window.copyNotesToClipboard = function() {
var content = document.getElementById('notesContent')?.innerText;
if (content) {
navigator.clipboard.writeText(content);
showToast("Notes copied!");
}
}
window.saveNotesToLibrary = function() {
if (!window.currentNotes) return;
var user = getCurrentUser();
var savedNotes = JSON.parse(localStorage.getItem("notes_" + user) || '[]');
savedNotes.push(window.currentNotes);
localStorage.setItem("notes_" + user, JSON.stringify(savedNotes));
showToast("Notes saved to library!");
}
window.printNotes = function() {
var content = document.getElementById('notesContent')?.innerHTML;
if (content) {
var printWindow = window.open('', '_blank');
printWindow.document.write('Notes ' + content + '');
printWindow.print();
}
}
window.useChatForLearning = async function(type) {
if (!currentChatId) {
showToast("No active chat found. Start a chat first!", "error");
return;
}
var chats = await getChats();
var chat = chats.find(function(c) { return c.id === currentChatId; });
if (!chat || !chat.messages || chat.messages.length === 0) {
showToast("No chat content found!", "error");
return;
}
var lastMessages = chat.messages.slice(-5);
var chatContent = lastMessages.map(function(m) { return m.role + ': ' + m.content; }).join('\n\n');
if (type === 'quiz') {
document.getElementById('quizTopicInput').value = "Based on this conversation: " + chatContent.substring(0, 200);
showToast("✅ Chat content loaded! Click Generate Quiz");
} else if (type === 'notes') {
document.getElementById('notesTopicInput').value = "Based on this conversation: " + chatContent.substring(0, 200);
showToast("✅ Chat content loaded! Click Generate Notes");
}
}
window.uploadForLearning = function(type) {
var input = document.createElement('input');
input.type = 'file';
input.accept = '.txt,.pdf,.docx';
input.onchange = function() { showToast("Document uploaded for " + type + " generation!"); };
input.click();
}
// ============================================
// GAMES MODULE
// ============================================
var currentGameType = null;
var currentQuizQuestions = [];
var currentQuizIndex = 0;
var quizScore = 0;
var quizTimer = null;
var timeLeft = 30;
var memoryCards = [];
var memoryFlipped = [];
var memoryLocked = false;
var memoryMatches = 0;
var typingCurrentWord = "";
var typingScore = 0;
var typingRound = 0;
var typingWordsList = [];
var triviaQuestions = [];
var triviaIndex = 0;
var triviaScore = 0;
var scrambleCurrentWord = "";
var scrambleCurrentHint = "";
var scrambleScore = 0;
var scrambleRound = 0;
var scrambleWordsList = [];
var tfQuestions = [];
var tfIndex = 0;
var tfScore = 0;
window.openGamesModal = function() {
console.log("Opening Games Modal");
var modal = document.getElementById('gamesModal');
if (modal) {
modal.style.display = 'flex';
}
showGameSelectionScreen();
}
window.closeGamesModal = function() {
var modal = document.getElementById('gamesModal');
if (modal) modal.style.display = 'none';
if (quizTimer) clearInterval(quizTimer);
}
function showGameSelectionScreen() {
var gameContent = document.getElementById('gameContent');
if (!gameContent) return;
gameContent.innerHTML = '🏆
Quiz Race Test your knowledge with timed quizzes
Play Now → 🎴
Memory Match Match terms with definitions
Play Now → ⌨️
Typing Speed Improve your typing speed
Play Now → ❓
Trivia Challenge Answer random knowledge questions
Play Now → 🔤
Word Scramble Unscramble the letters to form words
Play Now → ✓✗
True or False Test your knowledge with true/false questions
Play Now → ';
}
window.selectGame = function(gameType) {
currentGameType = gameType;
var gameContent = document.getElementById('gameContent');
if (!gameContent) return;
gameContent.innerHTML = '
';
var activeContainer = document.getElementById('activeGameContainer');
switch(gameType) {
case 'quiz-race':
loadQuizRaceGame(activeContainer);
break;
case 'memory-match':
loadMemoryMatchGame(activeContainer);
break;
case 'typing-speed':
loadTypingSpeedGame(activeContainer);
break;
case 'trivia-challenge':
loadTriviaChallengeGame(activeContainer);
break;
case 'word-scramble':
loadWordScrambleGame(activeContainer);
break;
case 'true-false':
loadTrueFalseGame(activeContainer);
break;
default:
showGameSelectionScreen();
}
}
function getGameTitle(gameType) {
var titles = {
'quiz-race': '🏆 Quiz Race',
'memory-match': '🎴 Memory Match',
'typing-speed': '⌨️ Typing Speed',
'trivia-challenge': '❓ Trivia Challenge',
'word-scramble': '🔤 Word Scramble',
'true-false': '✓✗ True or False'
};
return titles[gameType] || 'Game';
}
// ================= QUIZ RACE GAME =================
function loadQuizRaceGame(container) {
currentQuizIndex = 0;
quizScore = 0;
currentQuizQuestions = [
{ question: "What is the capital of France?", options: ["London", "Berlin", "Paris", "Madrid"], correct: "Paris" },
{ question: "Which planet is known as the Red Planet?", options: ["Mars", "Jupiter", "Venus", "Saturn"], correct: "Mars" },
{ question: "Who painted the Mona Lisa?", options: ["Van Gogh", "Picasso", "Da Vinci", "Rembrandt"], correct: "Da Vinci" },
{ question: "What is the largest ocean on Earth?", options: ["Atlantic", "Indian", "Arctic", "Pacific"], correct: "Pacific" },
{ question: "What is the fastest land animal?", options: ["Lion", "Cheetah", "Leopard", "Tiger"], correct: "Cheetah" }
];
displayQuizQuestion(container);
}
function displayQuizQuestion(container) {
if (currentQuizIndex >= currentQuizQuestions.length) {
showQuizResults(container);
return;
}
var q = currentQuizQuestions[currentQuizIndex];
timeLeft = 30;
if (quizTimer) clearInterval(quizTimer);
quizTimer = setInterval(function() {
timeLeft--;
var timerEl = document.getElementById('quizTimer');
if (timerEl) {
timerEl.textContent = timeLeft;
if (timeLeft <= 5) timerEl.style.color = '#ef4444';
if (timeLeft <= 0) {
clearInterval(quizTimer);
moveToNextQuizQuestion(container);
}
}
}, 1000);
container.innerHTML = '' + escapeHtml(q.question) + '
' + q.options.map(function(opt) { return '' + escapeHtml(opt) + ' '; }).join('') + '
';
}
window.checkQuizAnswer = function(selected, btnElement) {
if (quizTimer) clearInterval(quizTimer);
var q = currentQuizQuestions[currentQuizIndex];
var feedback = document.getElementById('gameFeedback');
document.querySelectorAll('.game-option-btn').forEach(function(btn) { btn.disabled = true; });
if (selected === q.correct) {
quizScore += 10;
feedback.innerHTML = '✅ Correct! +10 points
';
showToast("✅ Correct!");
} else {
feedback.innerHTML = '❌ Wrong! Correct answer: ' + q.correct + '
';
showToast("❌ Wrong answer!");
}
setTimeout(function() { moveToNextQuizQuestion(document.getElementById('activeGameContainer')); }, 2000);
}
function moveToNextQuizQuestion(container) {
currentQuizIndex++;
if (currentQuizIndex < currentQuizQuestions.length) {
displayQuizQuestion(container);
} else {
showQuizResults(container);
}
}
function showQuizResults(container) {
var percentage = Math.round((quizScore / (currentQuizQuestions.length * 10)) * 100);
container.innerHTML = '' + (percentage >= 70 ? '🏆' : '📚') + '
Quiz Complete! Final Score: ' + quizScore + '/' + (currentQuizQuestions.length * 10) + '
' + percentage + '%
🔄 Play Again ← Back to Games
';
}
// ================= MEMORY MATCH GAME =================
function loadMemoryMatchGame(container) {
var pairs = [
{ pair1: "HTML", pair2: "Web Page" },
{ pair1: "CSS", pair2: "Styling" },
{ pair1: "JS", pair2: "JavaScript" },
{ pair1: "API", pair2: "Interface" },
{ pair1: "JSON", pair2: "Data Format" },
{ pair1: "DOM", pair2: "Document Object" }
];
memoryCards = [];
pairs.forEach(function(pair, idx) {
memoryCards.push({ id: idx * 2, value: pair.pair1, matched: false, pairId: idx });
memoryCards.push({ id: idx * 2 + 1, value: pair.pair2, matched: false, pairId: idx });
});
for (var i = memoryCards.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = memoryCards[i];
memoryCards[i] = memoryCards[j];
memoryCards[j] = temp;
}
memoryFlipped = [];
memoryLocked = false;
memoryMatches = 0;
renderMemoryGame(container);
}
function renderMemoryGame(container) {
container.innerHTML = '' + memoryCards.map(function(card, idx) {
return '
❓
' + (card.matched ? '✓' : escapeHtml(card.value)) + '
';
}).join('') + '
🔄 New Game ← Back to Games
';
}
window.flipMemoryCard = function(index) {
if (memoryLocked) return;
if (memoryCards[index].matched) return;
if (memoryFlipped.includes(index)) return;
if (memoryFlipped.length === 2) return;
memoryFlipped.push(index);
renderMemoryGame(document.getElementById('activeGameContainer'));
if (memoryFlipped.length === 2) {
checkMemoryMatch();
}
}
function checkMemoryMatch() {
var card1 = memoryCards[memoryFlipped[0]];
var card2 = memoryCards[memoryFlipped[1]];
if (card1.pairId === card2.pairId) {
card1.matched = true;
card2.matched = true;
memoryMatches++;
memoryFlipped = [];
renderMemoryGame(document.getElementById('activeGameContainer'));
showToast("🎉 Match found!");
if (memoryMatches === memoryCards.length / 2) {
setTimeout(function() { showToast("🏆 Congratulations! You completed the game!"); }, 500);
}
} else {
memoryLocked = true;
setTimeout(function() {
memoryFlipped = [];
memoryLocked = false;
renderMemoryGame(document.getElementById('activeGameContainer'));
}, 1000);
}
}
// ================= TYPING SPEED GAME =================
function loadTypingSpeedGame(container) {
typingWordsList = ["javascript", "programming", "developer", "computer", "keyboard", "website", "application", "database"];
typingRound = 0;
typingScore = 0;
loadNextTypingWord(container);
}
function loadNextTypingWord(container) {
if (typingRound >= typingWordsList.length) {
showTypingResults(container);
return;
}
typingCurrentWord = typingWordsList[typingRound];
container.innerHTML = '' + typingCurrentWord + '
Submit ← Back
';
document.getElementById('typingInput')?.focus();
}
window.checkTypingWord = function() {
var input = document.getElementById('typingInput');
var userInput = input?.value.trim().toLowerCase();
var feedback = document.getElementById('typingFeedback');
var container = document.getElementById('activeGameContainer');
if (userInput === typingCurrentWord) {
typingScore += 10;
feedback.innerHTML = '✅ Correct! +10 points
';
showToast("🎉 Correct!");
} else {
feedback.innerHTML = '❌ Wrong! The word was: ' + typingCurrentWord + '
';
showToast("❌ Wrong!");
}
setTimeout(function() {
typingRound++;
loadNextTypingWord(container);
}, 1500);
}
function showTypingResults(container) {
var percentage = Math.round((typingScore / (typingWordsList.length * 10)) * 100);
container.innerHTML = '⌨️
Typing Speed Complete! Score: ' + typingScore + '/' + (typingWordsList.length * 10) + '
' + percentage + '%
🔄 Try Again ← Back to Games
';
}
// ================= TRIVIA CHALLENGE =================
function loadTriviaChallengeGame(container) {
triviaIndex = 0;
triviaScore = 0;
triviaQuestions = [
{ question: "What is the capital of Japan?", options: ["Seoul", "Beijing", "Tokyo", "Bangkok"], correct: "Tokyo", funFact: "Tokyo is the most populous metropolitan area in the world" },
{ question: "Who wrote 'Romeo and Juliet'?", options: ["Charles Dickens", "Jane Austen", "William Shakespeare", "Mark Twain"], correct: "William Shakespeare", funFact: "Written around 1595" },
{ question: "What is the chemical symbol for Gold?", options: ["Go", "Gd", "Au", "Ag"], correct: "Au", funFact: "Au comes from Latin 'aurum'" },
{ question: "Which country gifted the Statue of Liberty to the USA?", options: ["England", "Spain", "France", "Germany"], correct: "France", funFact: "Gifted in 1886" },
{ question: "What is the world's longest river?", options: ["Amazon", "Nile", "Yangtze", "Mississippi"], correct: "Nile", funFact: "The Nile is about 6,650 km long" }
];
displayTriviaQuestion(container);
}
function displayTriviaQuestion(container) {
if (triviaIndex >= triviaQuestions.length) {
showTriviaResults(container);
return;
}
var q = triviaQuestions[triviaIndex];
container.innerHTML = '' + escapeHtml(q.question) + '
' + q.options.map(function(opt) { return '' + escapeHtml(opt) + ' '; }).join('') + '
';
}
window.checkTriviaAnswer = function(selected, btnElement) {
var q = triviaQuestions[triviaIndex];
var feedback = document.getElementById('triviaFeedback');
document.querySelectorAll('.game-option-btn').forEach(function(btn) { btn.disabled = true; });
if (selected === q.correct) {
triviaScore += 10;
feedback.innerHTML = '✅ Correct! ' + (q.funFact || 'Great job!') + '
';
showToast("✅ Correct!");
} else {
feedback.innerHTML = '❌ Wrong! Correct: ' + q.correct + '. ' + (q.funFact || '') + '
';
showToast("❌ Wrong!");
}
setTimeout(function() {
triviaIndex++;
displayTriviaQuestion(document.getElementById('activeGameContainer'));
}, 2000);
}
function showTriviaResults(container) {
var percentage = Math.round((triviaScore / (triviaQuestions.length * 10)) * 100);
container.innerHTML = '' + (percentage >= 70 ? '🏆' : '📚') + '
Trivia Complete! Score: ' + triviaScore + '/' + (triviaQuestions.length * 10) + '
' + percentage + '%
🔄 Play Again ← Back to Games
';
}
// ================= WORD SCRAMBLE =================
function loadWordScrambleGame(container) {
scrambleWordsList = [
{ word: "javascript", hint: "A programming language for web" },
{ word: "computer", hint: "An electronic device" },
{ word: "keyboard", hint: "Used for typing" },
{ word: "monitor", hint: "Displays output" },
{ word: "internet", hint: "Global network" }
];
scrambleRound = 0;
scrambleScore = 0;
loadNextScrambleWord(container);
}
function loadNextScrambleWord(container) {
if (scrambleRound >= scrambleWordsList.length) {
showScrambleResults(container);
return;
}
var wordObj = scrambleWordsList[scrambleRound];
scrambleCurrentWord = wordObj.word;
scrambleCurrentHint = wordObj.hint;
var scrambled = scrambleCurrentWord.split('');
for (var i = scrambled.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = scrambled[i];
scrambled[i] = scrambled[j];
scrambled[j] = temp;
}
container.innerHTML = '' + scrambled.join(' ').toUpperCase() + '
💡 Hint: ' + escapeHtml(scrambleCurrentHint) + '
Submit Guess ← Back
';
document.getElementById('scrambleGuess')?.focus();
}
window.checkScrambleGuess = function() {
var input = document.getElementById('scrambleGuess');
var guess = input?.value.trim().toLowerCase();
var feedback = document.getElementById('scrambleFeedback');
var container = document.getElementById('activeGameContainer');
if (guess === scrambleCurrentWord.toLowerCase()) {
scrambleScore += 10;
feedback.innerHTML = '✅ Correct! +10 points
';
showToast("🎉 Correct!");
} else {
feedback.innerHTML = '❌ Wrong! The word was: ' + scrambleCurrentWord + '
';
showToast("❌ Wrong!");
}
setTimeout(function() {
scrambleRound++;
loadNextScrambleWord(container);
}, 1500);
}
function showScrambleResults(container) {
var percentage = Math.round((scrambleScore / (scrambleWordsList.length * 10)) * 100);
container.innerHTML = '🔤
Word Scramble Complete! Score: ' + scrambleScore + '/' + (scrambleWordsList.length * 10) + '
' + percentage + '%
🔄 Play Again ← Back to Games
';
}
// ================= TRUE OR FALSE GAME =================
function loadTrueFalseGame(container) {
tfIndex = 0;
tfScore = 0;
tfQuestions = [
{ statement: "The sun rises in the east.", answer: true, explanation: "The sun rises in the east and sets in the west" },
{ statement: "Humans have 5 hearts.", answer: false, explanation: "Humans have 1 heart" },
{ statement: "Water is H2O.", answer: true, explanation: "Water molecules consist of 2 hydrogen and 1 oxygen atom" },
{ statement: "Mount Everest is the tallest mountain.", answer: true, explanation: "Mount Everest is 8,848 meters tall" },
{ statement: "The Earth is flat.", answer: false, explanation: "The Earth is actually round (an oblate spheroid)" }
];
displayTrueFalseQuestion(container);
}
function displayTrueFalseQuestion(container) {
if (tfIndex >= tfQuestions.length) {
showTrueFalseResults(container);
return;
}
var q = tfQuestions[tfIndex];
container.innerHTML = '' + escapeHtml(q.statement) + '
✓ True ✗ False
';
}
window.checkTrueFalseAnswer = function(selected) {
var q = tfQuestions[tfIndex];
var feedback = document.getElementById('tfFeedback');
var isCorrect = (selected === q.answer);
document.querySelectorAll('.true-btn-large, .false-btn-large').forEach(function(btn) { btn.disabled = true; });
if (isCorrect) {
tfScore += 10;
feedback.innerHTML = '✅ Correct! ' + q.explanation + '
';
showToast("✅ Correct!");
} else {
feedback.innerHTML = '❌ Wrong! ' + q.explanation + '
';
showToast("❌ Wrong!");
}
setTimeout(function() {
tfIndex++;
displayTrueFalseQuestion(document.getElementById('activeGameContainer'));
}, 2000);
}
function showTrueFalseResults(container) {
var percentage = Math.round((tfScore / (tfQuestions.length * 10)) * 100);
container.innerHTML = '' + (percentage >= 70 ? '🏆' : '📚') + '
True or False Complete! Score: ' + tfScore + '/' + (tfQuestions.length * 10) + '
' + percentage + '%
🔄 Play Again ← Back to Games
';
}
console.log("✅ Cortexa JS Full Version Loaded Successfully!");
console.log("🔗 API URL:", API_URL);
console.log("💡 All endpoints configured for production backend");