// Helper function to convert basic markdown to HTML function convertMarkdownToHTML(text) { if (typeof text !== 'string') { return text; } let htmlText = text; htmlText = htmlText.replace(/\*\*(.*?)\*\*/g, '$1'); htmlText = htmlText.replace(/\*(.*?)\*/g, '$1'); htmlText = htmlText.replace(/\n/g, '
'); return htmlText; } document.addEventListener('DOMContentLoaded', () => { const studentSelector = document.getElementById('student-selector'); const generateReportBtn = document.getElementById('generate-report-btn'); const jobApplicationInput = document.getElementById('job-application-input'); const analyzeJobBtn = document.getElementById('analyze-job-btn'); const loadingSpinner = document.getElementById('loading-spinner'); const reportContainer = document.getElementById('reports'); const jobAnalysisContainer = document.getElementById('job-analysis'); const chatbotContainer = document.getElementById('chat'); const chatForm = document.getElementById('chat-form'); const chatInput = document.getElementById('chat-input'); const chatHistory = document.getElementById('chat-history'); const newChatBtn = document.getElementById('new-chat-btn'); const chatSessionsList = document.getElementById('chat-sessions-list'); // Chat State let currentSessionId = null; // Chart Instances let skillsChart = null; let dsaChart = null; let jobMatchChart = null; let cgpaTrendChart = null; let dsaPerformanceChart = null; // Store pan-zoom instances to prevent memory leaks const panZoomInstances = new Map(); // Initialize Mermaid mermaid.initialize({ startOnLoad: false, theme: 'dark', themeVariables: { primaryColor: '#00E5FF', primaryTextColor: '#F0F0F0', primaryBorderColor: '#00E5FF', lineColor: '#00E5FF', secondaryColor: '#0099CC', tertiaryColor: '#2C2C2C' }, flowchart: { useMaxWidth: false, htmlLabels: true, curve: 'basis' } }); // Navigation Elements const navLinks = document.querySelectorAll('.nav-link'); const contentSections = document.querySelectorAll('.content-section'); // --- Sidebar Navigation --- navLinks.forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); const targetId = link.getAttribute('href').substring(1); navLinks.forEach(l => l.classList.remove('active')); link.classList.add('active'); contentSections.forEach(section => { section.classList.add('hidden'); if (section.id === targetId) { section.classList.remove('hidden'); section.classList.add('active'); if (targetId === 'dashboard') { loadDashboardData(); } } else { section.classList.remove('active'); } }); }); }); // --- Tab Navigation for Report Section --- initializeTabs('.ai-analysis-report', 'data-tab'); initializeTabs('.ai-suggestion-channel', 'data-tab'); function initializeTabs(containerSelector, attribute) { const container = document.querySelector(containerSelector); if (!container) return; const tabButtons = container.querySelectorAll('.tab-btn'); const tabContents = container.querySelectorAll('.tab-content'); tabButtons.forEach(button => { button.addEventListener('click', () => { const targetTab = button.getAttribute(attribute); tabButtons.forEach(btn => btn.classList.remove('active')); button.classList.add('active'); tabContents.forEach(content => { content.classList.remove('active'); if (content.id === `${targetTab}-tab`) { content.classList.add('active'); if (targetTab === 'performance' && studentSelector.value) { loadPerformanceCharts(studentSelector.value); } } }); }); }); } // --- Initial Navigation Setup --- const dashboardLink = document.querySelector('.nav-link[href="#dashboard"]'); if (dashboardLink) { dashboardLink.click(); } // --- Populate student dropdown --- fetch('/api/students') .then(response => response.json()) .then(students => { students.forEach(student => { const option = document.createElement('option'); option.value = student.enrollment_no; option.textContent = `${student.name} (${student.enrollment_no})`; studentSelector.appendChild(option); }); }) .catch(error => console.error('Error fetching students:', error)); // --- Enable buttons when inputs are filled --- studentSelector.addEventListener('change', () => { const hasSelection = !!studentSelector.value; generateReportBtn.disabled = !hasSelection; }); jobApplicationInput.addEventListener('input', () => { analyzeJobBtn.disabled = !jobApplicationInput.value.trim(); }); // --- Report History Logic --- const reportHistoryBtn = document.getElementById('report-history-btn'); const reportHistoryModal = document.getElementById('report-history-modal'); const reportHistoryList = document.getElementById('report-history-list'); const closeModalBtn = document.querySelector('.close-modal'); if (reportHistoryBtn) { reportHistoryBtn.addEventListener('click', () => { const enrollmentNo = studentSelector.value; if (!enrollmentNo) { alert('Please select a student first.'); return; } loadReportHistory(enrollmentNo); reportHistoryModal.classList.remove('hidden'); }); } if (closeModalBtn) { closeModalBtn.addEventListener('click', () => { reportHistoryModal.classList.add('hidden'); }); } window.addEventListener('click', (e) => { if (e.target === reportHistoryModal) { reportHistoryModal.classList.add('hidden'); } }); function loadReportHistory(enrollmentNo) { reportHistoryList.innerHTML = '
Loading history...
'; fetch(`/api/reports/history/${enrollmentNo}`) .then(response => response.json()) .then(history => { reportHistoryList.innerHTML = ''; if (history.length === 0) { reportHistoryList.innerHTML = '

No saved reports found.

'; return; } history.forEach(report => { const item = document.createElement('div'); item.className = 'report-item'; const date = new Date(report.timestamp).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); item.innerHTML = `
${report.title}
${date}
`; item.addEventListener('click', () => { loadSavedReport(enrollmentNo, report.id); reportHistoryModal.classList.add('hidden'); }); reportHistoryList.appendChild(item); }); }) .catch(error => { console.error('Error fetching report history:', error); reportHistoryList.innerHTML = '

Failed to load history.

'; }); } function loadSavedReport(enrollmentNo, reportId) { loadingSpinner.classList.remove('hidden'); fetch(`/api/report/load/${enrollmentNo}/${reportId}`) .then(response => response.json()) .then(report => { loadingSpinner.classList.add('hidden'); if (report.error) { alert(`Error loading report: ${report.error}`); } else { displayNewReport(report); } }) .catch(error => { loadingSpinner.classList.add('hidden'); console.error('Error loading saved report:', error); alert('Failed to load report.'); }); } // --- Handle "Generate Report" button click --- generateReportBtn.addEventListener('click', () => { const enrollmentNo = studentSelector.value; if (!enrollmentNo) return; loadingSpinner.classList.remove('hidden'); document.querySelector('.nav-link[href="#reports"]').click(); fetch(`/api/report/${enrollmentNo}`) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); }) .then(report => { loadingSpinner.classList.add('hidden'); if (report.error) { alert(`Error generating report: ${report.error}`); } else { displayNewReport(report); } }) .catch(error => { loadingSpinner.classList.add('hidden'); console.error('Report generation error:', error); alert(`An unexpected error occurred: ${error.message}`); }); if (enrollmentNo) { // Also load chat history for this student loadChatSessions(enrollmentNo); } else { alert('Please select a student first.'); } }); // New Chat Button if (newChatBtn) { newChatBtn.addEventListener('click', () => { currentSessionId = null; chatHistory.innerHTML = ''; // Remove active class from all sessions document.querySelectorAll('.session-item').forEach(item => item.classList.remove('active')); appendMessage('Start a new conversation!', 'ai', false, true); }); } // --- Handle "Analyze Job Application" button click --- analyzeJobBtn.addEventListener('click', () => { const jobDescription = jobApplicationInput.value.trim(); const enrollmentNo = studentSelector.value; if (!jobDescription) { alert('Please paste a job description.'); return; } if (!enrollmentNo) { alert('Please select a student first.'); return; } loadingSpinner.classList.remove('hidden'); jobAnalysisContainer.classList.add('hidden'); fetch('/api/job-analysis', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ enrollment_no: enrollmentNo, job_description: jobDescription }) }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); }) .then(data => { loadingSpinner.classList.add('hidden'); if (data.error) { alert(`Error analyzing job application: ${data.error}`); } else { displayJobAnalysis(data.data); } }) .catch(error => { loadingSpinner.classList.add('hidden'); console.error('Job analysis error:', error); alert(`An unexpected error occurred: ${error.message}`); }); }); // --- Chat form submission --- chatForm.addEventListener('submit', (e) => { e.preventDefault(); const enrollmentNo = studentSelector.value; const question = chatInput.value.trim(); if (!question || !enrollmentNo) { if (!enrollmentNo) alert('Please select a student first.'); return; } // If not already in chat tab, switch to it const chatTabLink = document.querySelector('.nav-link[href="#chat"]'); if (chatTabLink && !chatTabLink.classList.contains('active')) { chatTabLink.click(); } appendMessage(question, 'user'); chatInput.value = ''; appendMessage('Thinking...', 'ai', true); fetch('/api/ask', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ enrollment_no: enrollmentNo, question: question, session_id: currentSessionId }) }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); }) .then(data => { const loadingElement = chatHistory.querySelector('.loading'); if (loadingElement) { loadingElement.parentElement.remove(); } if (data.success) { appendMessage(data.answer, 'ai', false, true); // Update session ID if it was a new session if (!currentSessionId && data.session_id) { currentSessionId = data.session_id; // Reload sessions list to show the new one loadChatSessions(enrollmentNo); } } else { appendMessage(`Error: ${data.error}`, 'ai'); } chatHistory.scrollTop = chatHistory.scrollHeight; }) .catch(error => { console.error('Chat error:', error); const loadingElement = chatHistory.querySelector('.loading'); if (loadingElement) { loadingElement.parentElement.remove(); } appendMessage('Sorry, an error occurred while fetching the answer.', 'ai', false, true); }); }); // --- Chat History Functions --- function loadChatSessions(enrollmentNo) { if (!chatSessionsList) return; fetch(`/api/chat/history/${enrollmentNo}`) .then(res => res.json()) .then(sessions => { chatSessionsList.innerHTML = ''; if (sessions.error) { console.error(sessions.error); return; } if (sessions.length === 0) { chatSessionsList.innerHTML = '
No history
'; return; } sessions.forEach(session => { const el = document.createElement('div'); el.className = `session-item ${session.id === currentSessionId ? 'active' : ''}`; el.innerHTML = `
${session.title}
${new Date(session.timestamp).toLocaleDateString()} ${new Date(session.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
`; el.addEventListener('click', () => { loadChatMessages(session); // Update active state document.querySelectorAll('.session-item').forEach(item => item.classList.remove('active')); el.classList.add('active'); }); chatSessionsList.appendChild(el); }); }) .catch(err => console.error('Error loading chat sessions:', err)); } function loadChatMessages(session) { currentSessionId = session.id; chatHistory.innerHTML = ''; session.messages.forEach(msg => { appendMessage(msg.text, msg.sender, false, true); // Assuming stored messages are markdown safe or plain text }); chatHistory.scrollTop = chatHistory.scrollHeight; } // --- IMPROVED: Initialize Mermaid Flowchart with Pan/Zoom --- function initializeMermaidFlowchart(flowchartId, mermaidCode) { const flowchartCanvas = document.getElementById(flowchartId); if (!flowchartCanvas) { console.error(`Flowchart canvas not found: ${flowchartId}`); return; } // Clean up existing pan-zoom instance if any if (panZoomInstances.has(flowchartId)) { try { panZoomInstances.get(flowchartId).destroy(); panZoomInstances.delete(flowchartId); } catch (e) { console.warn('Error destroying previous pan-zoom instance:', e); } } // Clear existing content flowchartCanvas.innerHTML = ''; // Create mermaid div const mermaidDiv = document.createElement('div'); mermaidDiv.className = 'mermaid'; mermaidDiv.textContent = mermaidCode; flowchartCanvas.appendChild(mermaidDiv); // Render mermaid diagram mermaid.run({ nodes: [mermaidDiv] }).then(() => { // Wait for render to complete setTimeout(() => { const svg = flowchartCanvas.querySelector('svg'); if (!svg) { console.error('SVG not found after mermaid render'); return; } try { // Get the actual SVG dimensions const bbox = svg.getBBox(); const padding = 40; // Set viewBox with padding to prevent cutoff svg.setAttribute('viewBox', `${bbox.x - padding} ${bbox.y - padding} ${bbox.width + padding * 2} ${bbox.height + padding * 2}` ); // Remove fixed dimensions to allow responsive sizing svg.removeAttribute('width'); svg.removeAttribute('height'); svg.style.width = '100%'; svg.style.height = '100%'; svg.style.maxWidth = 'none'; svg.style.maxHeight = 'none'; // Initialize svg-pan-zoom if (typeof svgPanZoom !== 'undefined') { setTimeout(() => { try { const panZoomInstance = svgPanZoom(svg, { zoomEnabled: true, controlIconsEnabled: false, fit: true, center: true, minZoom: 0.1, maxZoom: 10, zoomScaleSensitivity: 0.3, dblClickZoomEnabled: true, mouseWheelZoomEnabled: true, preventMouseEventsDefault: true, panEnabled: true, refreshRate: 'auto' }); // Store instance for cleanup panZoomInstances.set(flowchartId, panZoomInstance); // Apply initial zoom and center setTimeout(() => { panZoomInstance.resize(); panZoomInstance.fit(); panZoomInstance.center(); // Zoom in slightly for better readability panZoomInstance.zoomBy(1.2); }, 100); // Add control instructions if (!flowchartCanvas.querySelector('.flowchart-instructions')) { const instructions = document.createElement('div'); instructions.className = 'flowchart-instructions'; instructions.innerHTML = '🖱️ Drag to pan • Scroll to zoom • Double-click to reset'; flowchartCanvas.appendChild(instructions); } } catch (panZoomError) { console.error('Pan-zoom initialization error:', panZoomError); } }, 300); } } catch (error) { console.error('Error setting up flowchart:', error); } }, 200); }).catch(error => { console.error('Mermaid rendering error:', error); flowchartCanvas.innerHTML = '

Error rendering flowchart. Please check the diagram syntax.

'; }); } // --- Display Report Function --- function displayNewReport(report) { // Update Profile Card document.getElementById('student-name').textContent = report.name || 'Student Name'; document.getElementById('student-id').textContent = `ID: ${report.enrollment_no || 'N/A'}`; document.getElementById('student-phone').textContent = report.phone || '+91 9876543210'; document.getElementById('student-email').textContent = report.email || 'student@example.com'; if (report.photo) { document.getElementById('student-photo').src = report.photo; } // Update Summary Tab document.getElementById('hr-summary').innerHTML = convertMarkdownToHTML(report.overall_summary || 'No summary available.'); const strengthsList = document.getElementById('summary-strengths'); strengthsList.innerHTML = ''; if (report.analysis?.strengths) { report.analysis.strengths.forEach(strength => { const li = document.createElement('li'); li.innerHTML = convertMarkdownToHTML(strength); strengthsList.appendChild(li); }); } const weaknessesList = document.getElementById('summary-weaknesses'); weaknessesList.innerHTML = ''; if (report.analysis?.weaknesses) { report.analysis.weaknesses.forEach(weakness => { const li = document.createElement('li'); li.innerHTML = convertMarkdownToHTML(weakness); weaknessesList.appendChild(li); }); } // Update Skills Tab const skillsList = document.getElementById('skills-list'); skillsList.innerHTML = ''; if (report.skills) { report.skills.forEach(skill => { const skillRow = document.createElement('div'); skillRow.className = 'skill-row'; skillRow.innerHTML = `
${skill.name || 'Skill'}
${skill.category || 'General'}
${skill.performance || 50}%
`; skillsList.appendChild(skillRow); }); } // Update Performance Tab (CGPA Chart) if (report.cgpa_trend) { const ctx = document.getElementById('cgpa-trend-chart'); if (ctx) { if (cgpaTrendChart) { cgpaTrendChart.destroy(); } cgpaTrendChart = new Chart(ctx, { type: 'line', data: { labels: report.cgpa_trend.labels || ['Sem 1', 'Sem 2', 'Sem 3', 'Sem 4', 'Sem 5', 'Sem 6'], datasets: [{ label: 'CGPA', data: report.cgpa_trend.values || [7.5, 7.8, 8.0, 8.2, 8.1, 8.3], backgroundColor: 'rgba(0, 229, 255, 0.2)', borderColor: 'rgba(0, 229, 255, 1)', borderWidth: 2, tension: 0.4, fill: true }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: false, min: 6, max: 10 } }, plugins: { legend: { display: false } } } }); } } // Update Action Plan Tab with IMPROVED flowchart rendering const actionPlanContent = document.querySelector('.action-plan-content'); actionPlanContent.innerHTML = ''; if (report.actionable_advice?.recommendations) { report.actionable_advice.recommendations.forEach((recommendation, index) => { const actionItem = document.createElement('div'); actionItem.className = 'action-item'; const flowchartId = `flowchart-${index}`; actionItem.innerHTML = `

${recommendation.title || 'Action Item'}

${convertMarkdownToHTML(recommendation.description || '')}

${recommendation.mermaid_flowchart ? `
` : ''} `; actionPlanContent.appendChild(actionItem); // Render Mermaid diagram using improved function if (recommendation.mermaid_flowchart) { // Delay to ensure DOM is ready setTimeout(() => { initializeMermaidFlowchart(flowchartId, recommendation.mermaid_flowchart); }, 100); } }); } // Update Learning Path Tab const learningPathContent = document.querySelector('.learning-path-content'); learningPathContent.innerHTML = ''; if (report.learning_path) { report.learning_path.forEach(path => { const pathItem = document.createElement('div'); pathItem.className = 'path-item'; pathItem.innerHTML = `

${path.title || 'Learning Path'}

${convertMarkdownToHTML(path.description || '')}

`; if (path.resources) { const resourcesDiv = document.createElement('div'); resourcesDiv.className = 'recommended-resources'; resourcesDiv.innerHTML = '
Recommended Resources:
'; path.resources.forEach(resource => { const resourceItem = document.createElement('div'); resourceItem.className = 'resource-item'; resourceItem.innerHTML = `
${resource.title || 'Resource'}

${resource.description || ''}

`; resourcesDiv.appendChild(resourceItem); }); pathItem.appendChild(resourcesDiv); } learningPathContent.appendChild(pathItem); }); } } // --- Load Performance Charts --- async function loadPerformanceCharts(enrollmentNo) { if (!enrollmentNo) return; if (dsaPerformanceChart) { dsaPerformanceChart.destroy(); dsaPerformanceChart = null; } try { const response = await fetch(`/api/dashboard/metrics/${enrollmentNo}`); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const dashboardData = await response.json(); const dsaCtx = document.getElementById('dsa-performance-chart'); if (dsaCtx && dashboardData.coding_profiles?.leetcode?.score !== undefined) { dsaPerformanceChart = new Chart(dsaCtx, { type: 'bar', data: { labels: ['DSA Score'], datasets: [{ label: 'DSA Performance (0-10)', data: [dashboardData.coding_profiles.leetcode.score], backgroundColor: 'rgba(75, 192, 192, 0.2)', borderColor: 'rgb(75, 192, 192)', borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true, max: 10 } } } }); } } catch (error) { console.error('Error loading performance charts:', error); } } // --- Load Dashboard Metrics --- async function loadDashboardData() { const totalStudentsEl = document.getElementById('total-students-count'); const reportsGeneratedEl = document.getElementById('reports-generated-count'); const jobAnalysesEl = document.getElementById('job-analyses-count'); try { const studentsResponse = await fetch('/api/students'); const students = await studentsResponse.json(); if (totalStudentsEl) totalStudentsEl.textContent = students.length; if (reportsGeneratedEl) reportsGeneratedEl.textContent = '0'; if (jobAnalysesEl) jobAnalysesEl.textContent = '0'; } catch (error) { console.error('Error loading dashboard metrics:', error); } } // --- Helper Functions --- function appendMessage(text, sender, isLoading = false, useMarkdown = false) { const messageWrapper = document.createElement('div'); messageWrapper.classList.add('chat-message', `${sender}-message`); const messageP = document.createElement('p'); if (useMarkdown) { messageP.innerHTML = convertMarkdownToHTML(text); } else { messageP.textContent = text; } if (isLoading) { messageP.classList.add('loading'); } messageWrapper.appendChild(messageP); chatHistory.appendChild(messageWrapper); chatHistory.scrollTop = chatHistory.scrollHeight; } // --- Keep existing display functions for backward compatibility --- function displayReport(report) { console.warn('displayReport is deprecated. Use displayNewReport instead.'); displayNewReport(report); } // --- Display Job Analysis Results --- function displayJobAnalysis(data) { console.log("Job Analysis Data:", data); const strengthsList = document.getElementById('job-strengths-list'); if (strengthsList && data.your_core_strengths_for_this_role) { strengthsList.innerHTML = ''; data.your_core_strengths_for_this_role.forEach(strength => { const li = document.createElement('li'); const text = typeof strength === 'string' ? strength : (strength.strength || strength.text || strength.description || JSON.stringify(strength)); li.textContent = text; strengthsList.appendChild(li); }); } const weaknessesList = document.getElementById('job-weaknesses-list'); if (weaknessesList && data.strategic_areas_for_growth) { weaknessesList.innerHTML = ''; data.strategic_areas_for_growth.forEach(area => { const li = document.createElement('li'); const text = typeof area === 'string' ? area : (area.area_to_develop || JSON.stringify(area)); li.textContent = text; weaknessesList.appendChild(li); }); } const enhancementsList = document.getElementById('job-enhancements-list'); if (enhancementsList && data.strategic_overview) { enhancementsList.innerHTML = ''; if (data.strategic_overview.summary) { const summaryItem = document.createElement('div'); summaryItem.className = 'enhancement-item'; summaryItem.innerHTML = `Summary: ${data.strategic_overview.summary}`; enhancementsList.appendChild(summaryItem); } if (data.strategic_overview.your_key_opportunity) { const opportunityItem = document.createElement('div'); opportunityItem.className = 'enhancement-item'; opportunityItem.innerHTML = `Key Opportunity: ${data.strategic_overview.your_key_opportunity}`; enhancementsList.appendChild(opportunityItem); } } const youtubeContainer = document.getElementById('job-youtube-recommendations'); if (youtubeContainer && data.video_recommendations) { youtubeContainer.innerHTML = ''; data.video_recommendations.forEach(topic => { // Create Topic Section const topicSection = document.createElement('div'); topicSection.className = 'video-topic-section'; const topicTitle = document.createElement('h4'); topicTitle.className = 'video-topic-title'; topicTitle.textContent = topic.topic || 'Recommended Topic'; topicSection.appendChild(topicTitle); const topicReason = document.createElement('p'); topicReason.className = 'video-topic-reason'; topicReason.textContent = topic.reason || ''; topicSection.appendChild(topicReason); // Video Grid for this topic const videoGrid = document.createElement('div'); videoGrid.className = 'video-grid'; if (topic.videos && topic.videos.length > 0) { topic.videos.forEach(video => { const videoCard = document.createElement('div'); videoCard.className = 'youtube-card'; const embedUrl = video.embed_url || video.url.replace('watch?v=', 'embed/'); const title = video.title || 'Video Tutorial'; videoCard.innerHTML = `
${title}

${video.reason || ''}

`; videoGrid.appendChild(videoCard); }); } else { videoGrid.innerHTML = '

No videos found for this topic.

'; } topicSection.appendChild(videoGrid); youtubeContainer.appendChild(topicSection); }); } } // --- Dashboard Logic --- const refreshDashboardBtn = document.getElementById('refresh-dashboard-btn'); if (refreshDashboardBtn) { refreshDashboardBtn.addEventListener('click', loadDashboardData); } function loadDashboardData() { console.log("Loading dashboard data..."); fetch('/api/dashboard/students') .then(response => response.json()) .then(data => { if (data.error) { console.error("Error loading dashboard:", data.error); return; } // Update Summary Cards const totalStudentsEl = document.getElementById('total-students-count'); if (totalStudentsEl) totalStudentsEl.textContent = data.total_students; const classAvgEl = document.getElementById('class-avg-cgpa'); if (classAvgEl) classAvgEl.textContent = data.class_average_cgpa; // Count reports ready const reportsReady = data.students.filter(s => s.report_status === 'Generated').length; const reportsReadyEl = document.getElementById('reports-ready-count'); if (reportsReadyEl) reportsReadyEl.textContent = reportsReady; // Populate Student Table const tableBody = document.getElementById('student-table-body'); if (tableBody) { tableBody.innerHTML = ''; data.students.forEach(student => { const row = document.createElement('tr'); // Status Badges const reportBadgeClass = student.report_status === 'Generated' ? 'badge-success' : 'badge-pending'; const cgpaClass = parseFloat(student.cgpa) >= 8.0 ? 'text-success' : (parseFloat(student.cgpa) >= 6.0 ? 'text-warning' : 'text-danger'); row.innerHTML = `
${student.name}
${student.enrollment_no} ${student.cgpa}
${student.key_skills.map(skill => `${skill}`).join('')}
${student.report_status} ${student.resume_count} Resumes `; tableBody.appendChild(row); }); // Add Event Listeners to "View Profile" buttons document.querySelectorAll('.view-profile-btn').forEach(btn => { btn.addEventListener('click', (e) => { const enrollmentNo = e.target.getAttribute('data-enrollment'); // Switch to Reports tab const reportsTab = document.querySelector('.nav-link[href="#reports"]'); if (reportsTab) reportsTab.click(); // Select student in dropdown if (studentSelector) { studentSelector.value = enrollmentNo; // Trigger change event to load student data studentSelector.dispatchEvent(new Event('change')); } }); }); } }) .catch(err => console.error("Failed to load dashboard data:", err)); } // Initial load if dashboard is active if (document.querySelector('#dashboard.active')) { loadDashboardData(); } }); // End of DOMContentLoaded