initial commit
This commit is contained in:
222
static/js/modules/stats-display.js
Normal file
222
static/js/modules/stats-display.js
Normal file
@@ -0,0 +1,222 @@
|
||||
// Stats Display Module for Index Page
|
||||
class StatsDisplay {
|
||||
constructor() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.setupEventListeners();
|
||||
this.loadStats();
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
// Reset stats modal listeners
|
||||
document.getElementById('reset-stats-btn')?.addEventListener('click', () => {
|
||||
this.showResetStatsModal();
|
||||
});
|
||||
|
||||
document.getElementById('resetStatsModalClose')?.addEventListener('click', () => {
|
||||
this.hideResetStatsModal();
|
||||
});
|
||||
|
||||
document.getElementById('resetStatsModalCancel')?.addEventListener('click', () => {
|
||||
this.hideResetStatsModal();
|
||||
});
|
||||
|
||||
document.getElementById('resetStatsBackdrop')?.addEventListener('click', () => {
|
||||
this.hideResetStatsModal();
|
||||
});
|
||||
|
||||
document.getElementById('confirmResetStats')?.addEventListener('click', () => {
|
||||
this.resetStats();
|
||||
});
|
||||
|
||||
// Keyboard support for modal
|
||||
document.addEventListener('keydown', (e) => {
|
||||
const modal = document.getElementById('resetStatsModal');
|
||||
if (modal && modal.style.display === 'block') {
|
||||
if (e.key === 'Escape') {
|
||||
this.hideResetStatsModal();
|
||||
} else if (e.key === 'Enter') {
|
||||
const focusedElement = document.activeElement;
|
||||
if (focusedElement.id === 'confirmResetStats') {
|
||||
this.resetStats();
|
||||
} else {
|
||||
this.hideResetStatsModal();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadStats() {
|
||||
// Load statistics from localStorage
|
||||
let stats = {
|
||||
total_answered: 0,
|
||||
correct_answers: 0,
|
||||
incorrect_answers: 0,
|
||||
accuracy: 0
|
||||
};
|
||||
|
||||
// Try to load from localStorage
|
||||
try {
|
||||
const savedStats = localStorage.getItem('balotario_stats');
|
||||
if (savedStats) {
|
||||
const parsedStats = JSON.parse(savedStats);
|
||||
stats = {
|
||||
total_answered: parsedStats.totalAnswered || 0,
|
||||
correct_answers: parsedStats.correctAnswers || 0,
|
||||
incorrect_answers: parsedStats.incorrectAnswers || 0,
|
||||
accuracy: parsedStats.accuracy || 0
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Error loading stats from localStorage:', error);
|
||||
}
|
||||
|
||||
// Update UI
|
||||
this.updateStatsDisplay(stats);
|
||||
}
|
||||
|
||||
updateStatsDisplay(stats) {
|
||||
const totalAnsweredEl = document.getElementById('total-answered');
|
||||
const accuracyEl = document.getElementById('accuracy');
|
||||
const accuracyBarEl = document.getElementById('accuracy-bar');
|
||||
const resetBtnEl = document.getElementById('reset-stats-btn');
|
||||
|
||||
if (totalAnsweredEl) totalAnsweredEl.textContent = stats.total_answered;
|
||||
if (accuracyEl) accuracyEl.textContent = stats.accuracy + '%';
|
||||
if (accuracyBarEl) accuracyBarEl.style.width = stats.accuracy + '%';
|
||||
|
||||
// Show/hide reset button based on stats
|
||||
if (resetBtnEl) {
|
||||
if (stats.total_answered > 0) {
|
||||
resetBtnEl.style.display = 'inline-block';
|
||||
} else {
|
||||
resetBtnEl.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
showResetStatsModal() {
|
||||
if (window.Utils) {
|
||||
Utils.playSound('click');
|
||||
}
|
||||
|
||||
const modal = document.getElementById('resetStatsModal');
|
||||
if (modal) {
|
||||
modal.style.display = 'block';
|
||||
document.body.classList.add('modal-open');
|
||||
|
||||
// Focus cancel button for accessibility
|
||||
setTimeout(() => {
|
||||
const cancelBtn = document.getElementById('resetStatsModalCancel');
|
||||
if (cancelBtn) cancelBtn.focus();
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
hideResetStatsModal() {
|
||||
const dialog = document.getElementById('resetStatsDialog');
|
||||
if (dialog) {
|
||||
dialog.classList.add('modal-closing');
|
||||
|
||||
setTimeout(() => {
|
||||
const modal = document.getElementById('resetStatsModal');
|
||||
if (modal) {
|
||||
modal.style.display = 'none';
|
||||
document.body.classList.remove('modal-open');
|
||||
dialog.classList.remove('modal-closing');
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
resetStats() {
|
||||
// Show loading in button
|
||||
const confirmBtn = document.getElementById('confirmResetStats');
|
||||
if (!confirmBtn) return;
|
||||
|
||||
const originalText = confirmBtn.innerHTML;
|
||||
confirmBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Restableciendo...';
|
||||
confirmBtn.disabled = true;
|
||||
|
||||
// Reset statistics directly in localStorage
|
||||
try {
|
||||
// Reset using statsManager if available
|
||||
if (window.statsManager) {
|
||||
window.statsManager.resetStats();
|
||||
} else {
|
||||
// Reset directly in localStorage
|
||||
const resetStats = {
|
||||
totalAnswered: 0,
|
||||
correctAnswers: 0,
|
||||
incorrectAnswers: 0,
|
||||
accuracy: 0,
|
||||
studyTime: 0,
|
||||
examsTaken: 0,
|
||||
bestScore: 0,
|
||||
streak: 0,
|
||||
lastActivity: null
|
||||
};
|
||||
localStorage.setItem('balotario_stats', JSON.stringify(resetStats));
|
||||
}
|
||||
|
||||
// Simulate a small pause for better UX
|
||||
setTimeout(() => {
|
||||
// Reload statistics
|
||||
this.loadStats();
|
||||
|
||||
// Hide modal
|
||||
this.hideResetStatsModal();
|
||||
|
||||
// Restore button
|
||||
confirmBtn.innerHTML = originalText;
|
||||
confirmBtn.disabled = false;
|
||||
|
||||
// Show success notification
|
||||
if (window.Utils) {
|
||||
Utils.showNotification('Estadísticas restablecidas correctamente', 'success', 4000);
|
||||
Utils.playSound('complete');
|
||||
} else {
|
||||
alert('Estadísticas restablecidas correctamente');
|
||||
}
|
||||
|
||||
// Small animation on stats card
|
||||
const statsCard = document.querySelector('.stats-card');
|
||||
if (statsCard) {
|
||||
statsCard.style.transform = 'scale(1.05)';
|
||||
statsCard.style.transition = 'transform 0.3s ease';
|
||||
|
||||
setTimeout(() => {
|
||||
statsCard.style.transform = 'scale(1)';
|
||||
}, 300);
|
||||
}
|
||||
|
||||
}, 800);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error resetting stats:', error);
|
||||
|
||||
// Restore button on error
|
||||
confirmBtn.innerHTML = originalText;
|
||||
confirmBtn.disabled = false;
|
||||
|
||||
if (window.Utils) {
|
||||
Utils.showNotification('Error al restablecer estadísticas', 'danger');
|
||||
} else {
|
||||
alert('Error al restablecer estadísticas');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-initialize when DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (document.getElementById('stats-content')) {
|
||||
window.statsDisplay = new StatsDisplay();
|
||||
}
|
||||
});
|
||||
|
||||
// Export for global use
|
||||
window.StatsDisplay = StatsDisplay;
|
||||
Reference in New Issue
Block a user