323 lines
12 KiB
JavaScript
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!');
|
|
};
|