// Admin Badge Enhancement Functions // Print a certificate for the student's badges function printBadgeCertificate(username) { fetch('/getBadges') .then(res => res.json()) .then(data => { const userBadgeData = data[username]; let badges = []; // Handle different badge data formats if (!userBadgeData) { badges = []; } else if (Array.isArray(userBadgeData)) { // Old format badges = userBadgeData.map(name => ({ name, icon: "🏅", color: "#4a5568" })); } else if (userBadgeData.earned) { // New format badges = userBadgeData.earned; } if (badges.length === 0) { alert("No badges to print for this student."); return; } // Create certificate window const printWindow = window.open('', '_blank'); printWindow.document.write(` Spelling Achievement Certificate - ${username}

Spelling Achievement Certificate

For Excellence in Vocabulary & Spelling

This certificate recognizes the outstanding achievements in spelling practice by:

${username}

Earned ${badges.length} Badge${badges.length !== 1 ? 's' : ''}

${badges.map(badge => `
${badge.icon || '🏅'} ${badge.name}
`).join('')}

Keep up the great work and continue building your vocabulary skills!

Teacher Signature
School Administrator
Date: ${new Date().toLocaleDateString()}
`); printWindow.document.close(); }); } // Show modal for awarding custom badges function showCustomBadgeModal(username) { // Create modal element if it doesn't exist let modal = document.getElementById('customBadgeModal'); if (!modal) { modal = document.createElement('div'); modal.id = 'customBadgeModal'; modal.className = 'modal'; modal.innerHTML = ` `; document.body.appendChild(modal); // Set up event listeners for the modal modal.querySelector('.modal-close').addEventListener('click', () => { modal.classList.remove('show'); }); // Set up icon selector document.querySelectorAll('.icon-option').forEach(button => { button.addEventListener('click', function() { document.querySelectorAll('.icon-option').forEach(b => b.classList.remove('selected')); this.classList.add('selected'); document.getElementById('badgeIcon').value = this.getAttribute('data-icon'); updateBadgePreview(); }); }); // Set up color selector document.querySelectorAll('.color-option').forEach(button => { button.addEventListener('click', function() { document.querySelectorAll('.color-option').forEach(b => b.classList.remove('selected')); this.classList.add('selected'); document.getElementById('badgeColor').value = this.getAttribute('data-color'); updateBadgePreview(); }); }); // Set up live preview document.getElementById('badgeName').addEventListener('input', updateBadgePreview); document.getElementById('badgeDescription').addEventListener('input', updateBadgePreview); // Award badge button document.getElementById('awardBadgeButton').addEventListener('click', () => { const name = document.getElementById('badgeName').value.trim(); if (!name) { alert('Please enter a badge name.'); return; } const badgeData = { id: name.toLowerCase().replace(/\s/g, '_'), name: name, description: document.getElementById('badgeDescription').value.trim(), icon: document.getElementById('badgeIcon').value, color: document.getElementById('badgeColor').value, category: document.getElementById('badgeCategory').value }; // Send request to award badge fetch('/awardBadges', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: username, badges: [badgeData] }) }) .then(res => res.text()) .then(() => { modal.classList.remove('show'); // Refresh the badge display showUserBadges(username); }) .catch(err => { console.error('Error awarding badge:', err); alert('Error awarding badge. Please try again.'); }); }); // Function to update badge preview function updateBadgePreview() { const previewIcon = document.querySelector('#badgePreview .admin-badge-icon span'); const previewTitle = document.querySelector('#badgePreview .admin-badge-info h4'); const previewDesc = document.querySelector('#badgePreview .admin-badge-desc'); const previewIconBg = document.querySelector('#badgePreview .admin-badge-icon'); const previewCard = document.querySelector('#badgePreview'); const icon = document.getElementById('badgeIcon').value; const color = document.getElementById('badgeColor').value; const name = document.getElementById('badgeName').value.trim() || 'Badge Title'; const description = document.getElementById('badgeDescription').value.trim() || 'Badge description will appear here'; previewIcon.textContent = icon; previewTitle.textContent = name; previewDesc.textContent = description; previewIconBg.style.backgroundColor = `${color}40`; previewCard.style.borderColor = color; } } // Update modal title with username modal.querySelector('.modal-header h3').textContent = `Award Custom Badge to ${username}`; // Show modal modal.classList.add('show'); } // Additional styling for the modal const modalStyle = document.createElement('style'); modalStyle.textContent = ` .modal { display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); overflow: auto; } .modal.show { display: flex; align-items: center; justify-content: center; } .modal-content { background-color: var(--bg-primary); border-radius: var(--radius); max-width: 600px; width: 100%; box-shadow: 0 10px 25px rgba(0,0,0,0.2); animation: modalFadeIn 0.3s; } @keyframes modalFadeIn { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } } .modal-header { padding: 1rem 1.5rem; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; } .modal-header h3 { margin: 0; } .modal-close { background: transparent; border: none; font-size: 1.5rem; cursor: pointer; color: var(--text-secondary); } .modal-body { padding: 1.5rem; max-height: 70vh; overflow-y: auto; } .modal-footer { padding: 1rem 1.5rem; border-top: 1px solid var(--border); display: flex; justify-content: flex-end; gap: 0.75rem; } .form-group { margin-bottom: 1.25rem; } .form-group label { display: block; margin-bottom: 0.5rem; font-weight: 600; } .icon-selector, .color-selector { display: flex; flex-wrap: wrap; gap: 0.5rem; } .icon-option { width: 40px; height: 40px; font-size: 1.5rem; display: flex; align-items: center; justify-content: center; background: var(--bg-secondary); border: 2px solid var(--border); border-radius: var(--radius); cursor: pointer; } .icon-option.selected { border-color: var(--primary); background: var(--primary-light); } .color-option { width: 40px; height: 40px; border: 2px solid var(--border); border-radius: 50%; cursor: pointer; } .color-option.selected { border-color: var(--text-primary); transform: scale(1.1); box-shadow: 0 0 0 2px var(--bg-primary), 0 0 0 4px var(--primary); } .badge-preview { margin-top: 2rem; border-top: 1px solid var(--border); padding-top: 1rem; } .badge-preview h4 { margin-top: 0; margin-bottom: 1rem; color: var(--text-secondary); font-size: 0.9rem; text-transform: uppercase; letter-spacing: 1px; } `; document.head.appendChild(modalStyle);