Files
homeschool/public/js/export.js
T
2025-08-13 11:25:12 -04:00

323 lines
12 KiB
JavaScript

// Export functions for Spelling Practice App
// Export report as PDF
window.exportToPDF = function() {
showToast('Preparing PDF export...');
const content = document.getElementById('reportContent');
const reportTitle = document.getElementById('reportTitle').textContent;
// Create a separate div for printing
const printDiv = document.createElement('div');
printDiv.style.padding = '20px';
printDiv.style.backgroundColor = '#ffffff';
printDiv.style.color = '#000000';
printDiv.style.fontFamily = 'Arial, sans-serif';
// Add title
const title = document.createElement('h2');
title.textContent = reportTitle;
title.style.textAlign = 'center';
title.style.marginBottom = '20px';
printDiv.appendChild(title);
// Add timestamp
const timestamp = document.createElement('p');
timestamp.textContent = `Generated on: ${new Date().toLocaleString()}`;
timestamp.style.textAlign = 'center';
timestamp.style.marginBottom = '30px';
timestamp.style.fontSize = '14px';
printDiv.appendChild(timestamp);
// Add latest score
const score = document.createElement('div');
score.innerHTML = `<strong>Latest Score:</strong> ${document.getElementById('reportScore').textContent}`;
score.style.marginBottom = '20px';
score.style.fontSize = '16px';
printDiv.appendChild(score);
// Create two columns for words and badges
const columns = document.createElement('div');
columns.style.display = 'flex';
columns.style.gap = '40px';
columns.style.marginBottom = '30px';
// Words attempted
const wordsCol = document.createElement('div');
wordsCol.style.flex = '1';
const wordsTitle = document.createElement('h3');
wordsTitle.textContent = 'Words Attempted';
wordsTitle.style.marginBottom = '10px';
wordsCol.appendChild(wordsTitle);
const wordsList = document.createElement('ul');
wordsList.style.listStyleType = 'none';
wordsList.style.padding = '0';
document.querySelectorAll('#reportWords li').forEach(item => {
const li = document.createElement('li');
li.textContent = item.textContent;
li.style.marginBottom = '5px';
wordsList.appendChild(li);
});
wordsCol.appendChild(wordsList);
// Badges earned
const badgesCol = document.createElement('div');
badgesCol.style.flex = '1';
const badgesTitle = document.createElement('h3');
badgesTitle.textContent = 'Badges Earned';
badgesTitle.style.marginBottom = '10px';
badgesCol.appendChild(badgesTitle);
const badgesList = document.createElement('ul');
badgesList.style.listStyleType = 'none';
badgesList.style.padding = '0';
document.querySelectorAll('#reportBadges li').forEach(item => {
const li = document.createElement('li');
li.textContent = item.textContent;
li.style.marginBottom = '5px';
badgesList.appendChild(li);
});
badgesCol.appendChild(badgesList);
columns.appendChild(wordsCol);
columns.appendChild(badgesCol);
printDiv.appendChild(columns);
// Add notes section
const notes = document.createElement('div');
notes.style.marginTop = '40px';
notes.style.borderTop = '1px solid #ddd';
notes.style.paddingTop = '20px';
const notesTitle = document.createElement('h3');
notesTitle.textContent = 'Teacher Notes';
notes.appendChild(notesTitle);
const notesText = document.createElement('textarea');
notesText.style.width = '100%';
notesText.style.height = '100px';
notesText.style.padding = '10px';
notesText.style.border = '1px solid #ddd';
notesText.style.borderRadius = '4px';
notesText.style.resize = 'none';
notes.appendChild(notesText);
printDiv.appendChild(notes);
// Footer
const footer = document.createElement('footer');
footer.style.marginTop = '50px';
footer.style.textAlign = 'center';
footer.style.fontSize = '12px';
footer.style.color = '#666';
footer.textContent = 'Generated by Modern Spelling Practice App';
printDiv.appendChild(footer);
// Hide the original content
content.style.display = 'none';
// Add the print div to the body
document.body.appendChild(printDiv);
// Print the page
setTimeout(() => {
window.print();
// Clean up
document.body.removeChild(printDiv);
content.style.display = 'block';
showToast('PDF export complete!');
}, 500);
};
// Export report data as CSV
window.exportToCSV = function() {
const username = document.getElementById('reportTitle').textContent.replace('Report for ', '');
fetch('/getResults')
.then(res => res.json())
.then(results => {
const userResults = results[username];
if (!userResults || !Array.isArray(userResults) || userResults.length === 0) {
showToast('No data available to export');
return;
}
// Create CSV content
let csvContent = 'Date,Score,Total Words,Percentage,Words Attempted,Correct Words\n';
userResults.forEach(result => {
const date = new Date(result.timestamp || Date.now()).toLocaleDateString();
const score = result.score || 0;
const answers = result.answers || [];
const total = answers.length;
const percentage = total > 0 ? Math.round((score / total) * 100) : 0;
// Create a list of words and whether they were correct
const wordList = answers.map(a => `${a.word}(${a.correct ? 'correct' : 'incorrect'})`).join('; ');
const correctWords = answers.filter(a => a.correct).map(a => a.word).join('; ');
csvContent += `${date},${score},${total},${percentage}%,"${wordList}","${correctWords}"\n`;
});
// Create and download the CSV file
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.setAttribute('href', url);
link.setAttribute('download', `${username}_spelling_report.csv`);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
showToast('CSV export complete!');
})
.catch(error => {
console.error('Error exporting data:', error);
showToast('Error exporting data');
});
};
// Export a single session as a nicely formatted HTML report
window.exportSessionReport = function(username, sessionData) {
if (!sessionData) return;
// Create a popup window for the report
const reportWindow = window.open('', '_blank', 'width=800,height=600');
reportWindow.document.write(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Spelling Session Report - ${username}</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
padding: 20px;
max-width: 800px;
margin: 0 auto;
}
.header {
text-align: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 2px solid #eee;
}
.title {
font-size: 24px;
margin: 0;
color: #2563eb;
}
.date {
color: #666;
font-style: italic;
}
.score-box {
background: #f8fafc;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
text-align: center;
}
.score {
font-size: 48px;
font-weight: bold;
color: #2563eb;
margin: 10px 0;
}
.words-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 10px;
margin: 20px 0;
}
.word-item {
padding: 10px;
border-radius: 4px;
background: #f8fafc;
display: flex;
align-items: center;
}
.correct {
border-left: 4px solid #10b981;
}
.incorrect {
border-left: 4px solid #ef4444;
}
.word-item span {
margin-right: 10px;
}
.footer {
text-align: center;
margin-top: 40px;
padding-top: 20px;
border-top: 2px solid #eee;
color: #666;
font-size: 12px;
}
@media print {
body {
padding: 0;
}
button {
display: none;
}
}
</style>
</head>
<body>
<div class="header">
<h1 class="title">Spelling Session Report</h1>
<p class="sub-title">Student: ${username}</p>
<p class="date">Session date: ${new Date(sessionData.timestamp || Date.now()).toLocaleString()}</p>
</div>
<div class="score-box">
<p>Final Score</p>
<div class="score">${sessionData.score || 0}/${(sessionData.answers || []).length}</div>
<p>${(sessionData.answers || []).length > 0
? `${Math.round(((sessionData.score || 0) / (sessionData.answers || []).length) * 100)}%`
: '0%'}
</p>
</div>
<h2>Words Attempted</h2>
<div class="words-list">
${(sessionData.answers || []).map(answer => `
<div class="word-item ${answer.correct ? 'correct' : 'incorrect'}">
<span>${answer.correct ? '✓' : '✗'}</span>
<strong>${answer.word}</strong>
</div>
`).join('')}
</div>
<div style="text-align: center; margin-top: 30px;">
<button onclick="window.print();" style="
background: #2563eb;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
">Print Report</button>
</div>
<div class="footer">
<p>Generated by Modern Spelling Practice App on ${new Date().toLocaleString()}</p>
<p>© ${new Date().getFullYear()} Modern Spelling Practice</p>
</div>
</body>
</html>
`);
reportWindow.document.close();
showToast('Session report generated!');
};