🔧 Fix settings modal: Load current user preferences

- Added show_in_leaderboard to user-player API response
- Improved loadSettings() function with better error handling
- Added console logging for debugging
- Settings modal now shows current user preference instead of always 'off'
- Fixed dependency on currentPlayerId (now uses currentUser.id directly)
This commit is contained in:
2025-09-08 19:18:35 +02:00
parent fbd8677709
commit 2becf784bd
2 changed files with 108 additions and 101 deletions

View File

@@ -13,7 +13,7 @@ async function initDashboard() {
try { try {
// Get current session // Get current session
const { data: { session }, error } = await supabase.auth.getSession(); const { data: { session }, error } = await supabase.auth.getSession();
if (error) { if (error) {
console.error('Error checking authentication:', error); console.error('Error checking authentication:', error);
// Temporarily show dashboard for testing // Temporarily show dashboard for testing
@@ -42,10 +42,10 @@ async function initDashboard() {
displayUserInfo({ email: 'admin@speedrun-arena.com' }); displayUserInfo({ email: 'admin@speedrun-arena.com' });
} }
showDashboard(); showDashboard();
// Load times section // Load times section
checkLinkStatusAndLoadTimes(); checkLinkStatusAndLoadTimes();
} catch (error) { } catch (error) {
console.error('An unexpected error occurred:', error); console.error('An unexpected error occurred:', error);
// window.location.href = '/login'; // window.location.href = '/login';
@@ -56,7 +56,7 @@ async function initDashboard() {
function displayUserInfo(user) { function displayUserInfo(user) {
const userEmail = document.getElementById('userEmail'); const userEmail = document.getElementById('userEmail');
const userAvatar = document.getElementById('userAvatar'); const userAvatar = document.getElementById('userAvatar');
userEmail.textContent = user.email; userEmail.textContent = user.email;
userAvatar.textContent = user.email.charAt(0).toUpperCase(); userAvatar.textContent = user.email.charAt(0).toUpperCase();
} }
@@ -106,7 +106,7 @@ function closeModal(modalId) {
} }
// Close modal when clicking outside // Close modal when clicking outside
window.onclick = function(event) { window.onclick = function (event) {
if (event.target.classList.contains('modal')) { if (event.target.classList.contains('modal')) {
closeModal(event.target.id); closeModal(event.target.id);
} }
@@ -133,12 +133,12 @@ async function checkLinkStatusAndLoadTimes() {
try { try {
// Check if user has a linked player // Check if user has a linked player
const response = await fetch(`/api/v1/public/user-player/${currentUser.id}?t=${Date.now()}`); const response = await fetch(`/api/v1/public/user-player/${currentUser.id}?t=${Date.now()}`);
if (response.ok) { if (response.ok) {
const result = await response.json(); const result = await response.json();
// User is linked, load times // User is linked, load times
await loadUserTimesSection(result.data); await loadUserTimesSection(result.data);
} else { } else {
// User is not linked // User is not linked
showTimesNotLinked(); showTimesNotLinked();
@@ -153,36 +153,36 @@ async function checkLinkStatusAndLoadTimes() {
async function startQRScanner() { async function startQRScanner() {
try { try {
// Request camera access // Request camera access
qrStream = await navigator.mediaDevices.getUserMedia({ qrStream = await navigator.mediaDevices.getUserMedia({
video: { video: {
facingMode: 'environment', // Use back camera if available facingMode: 'environment', // Use back camera if available
width: { ideal: 1280 }, width: { ideal: 1280 },
height: { ideal: 720 } height: { ideal: 720 }
} }
}); });
const video = document.getElementById('qrVideo'); const video = document.getElementById('qrVideo');
const canvas = document.getElementById('qrCanvas'); const canvas = document.getElementById('qrCanvas');
const context = canvas.getContext('2d'); const context = canvas.getContext('2d');
video.srcObject = qrStream; video.srcObject = qrStream;
video.play(); video.play();
// Show camera container and update buttons // Show camera container and update buttons
document.getElementById('cameraContainer').style.display = 'block'; document.getElementById('cameraContainer').style.display = 'block';
document.getElementById('startScanBtn').style.display = 'none'; document.getElementById('startScanBtn').style.display = 'none';
document.getElementById('stopScanBtn').style.display = 'inline-block'; document.getElementById('stopScanBtn').style.display = 'inline-block';
document.getElementById('scanningStatus').style.display = 'block'; document.getElementById('scanningStatus').style.display = 'block';
qrScanning = true; qrScanning = true;
// Start scanning loop // Start scanning loop
video.addEventListener('loadedmetadata', () => { video.addEventListener('loadedmetadata', () => {
canvas.width = video.videoWidth; canvas.width = video.videoWidth;
canvas.height = video.videoHeight; canvas.height = video.videoHeight;
scanQRCode(); scanQRCode();
}); });
} catch (error) { } catch (error) {
console.error('Error accessing camera:', error); console.error('Error accessing camera:', error);
showMessage('rfidMessage', 'Kamera-Zugriff fehlgeschlagen. Bitte verwende die manuelle Eingabe.', 'error'); showMessage('rfidMessage', 'Kamera-Zugriff fehlgeschlagen. Bitte verwende die manuelle Eingabe.', 'error');
@@ -192,12 +192,12 @@ async function startQRScanner() {
// Stop QR Scanner // Stop QR Scanner
function stopQRScanner() { function stopQRScanner() {
qrScanning = false; qrScanning = false;
if (qrStream) { if (qrStream) {
qrStream.getTracks().forEach(track => track.stop()); qrStream.getTracks().forEach(track => track.stop());
qrStream = null; qrStream = null;
} }
// Reset UI // Reset UI
document.getElementById('cameraContainer').style.display = 'none'; document.getElementById('cameraContainer').style.display = 'none';
document.getElementById('startScanBtn').style.display = 'inline-block'; document.getElementById('startScanBtn').style.display = 'inline-block';
@@ -208,26 +208,26 @@ function stopQRScanner() {
// Scan QR Code from video stream // Scan QR Code from video stream
function scanQRCode() { function scanQRCode() {
if (!qrScanning) return; if (!qrScanning) return;
const video = document.getElementById('qrVideo'); const video = document.getElementById('qrVideo');
const canvas = document.getElementById('qrCanvas'); const canvas = document.getElementById('qrCanvas');
const context = canvas.getContext('2d'); const context = canvas.getContext('2d');
if (video.readyState === video.HAVE_ENOUGH_DATA) { if (video.readyState === video.HAVE_ENOUGH_DATA) {
canvas.width = video.videoWidth; canvas.width = video.videoWidth;
canvas.height = video.videoHeight; canvas.height = video.videoHeight;
context.drawImage(video, 0, 0, canvas.width, canvas.height); context.drawImage(video, 0, 0, canvas.width, canvas.height);
const imageData = context.getImageData(0, 0, canvas.width, canvas.height); const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
const code = jsQR(imageData.data, imageData.width, imageData.height); const code = jsQR(imageData.data, imageData.width, imageData.height);
if (code) { if (code) {
console.log('QR Code detected:', code.data); console.log('QR Code detected:', code.data);
handleQRCodeDetected(code.data); handleQRCodeDetected(code.data);
return; return;
} }
} }
// Continue scanning // Continue scanning
if (qrScanning) { if (qrScanning) {
requestAnimationFrame(scanQRCode); requestAnimationFrame(scanQRCode);
@@ -238,7 +238,7 @@ function scanQRCode() {
function formatRfidUid(rawUid) { function formatRfidUid(rawUid) {
// Remove any existing formatting (spaces, colons, etc.) // Remove any existing formatting (spaces, colons, etc.)
let cleanUid = rawUid.replace(/[^a-fA-F0-9]/g, '').toUpperCase(); let cleanUid = rawUid.replace(/[^a-fA-F0-9]/g, '').toUpperCase();
// Handle different UID lengths // Handle different UID lengths
if (cleanUid.length === 6) { if (cleanUid.length === 6) {
// Pad 6-digit UID to 8 digits by adding leading zeros // Pad 6-digit UID to 8 digits by adding leading zeros
@@ -251,7 +251,7 @@ function formatRfidUid(rawUid) {
} else { } else {
throw new Error(`Ungültige RFID UID Länge: ${cleanUid.length} Zeichen (unterstützt: 6-8)`); throw new Error(`Ungültige RFID UID Länge: ${cleanUid.length} Zeichen (unterstützt: 6-8)`);
} }
// Format as XX:XX:XX:XX // Format as XX:XX:XX:XX
return cleanUid.match(/.{2}/g).join(':'); return cleanUid.match(/.{2}/g).join(':');
} }
@@ -259,24 +259,24 @@ function formatRfidUid(rawUid) {
// Handle detected QR code // Handle detected QR code
async function handleQRCodeDetected(qrData) { async function handleQRCodeDetected(qrData) {
stopQRScanner(); stopQRScanner();
try { try {
// Extract and format RFID UID from QR code // Extract and format RFID UID from QR code
const rawUid = qrData.trim(); const rawUid = qrData.trim();
if (!rawUid) { if (!rawUid) {
showMessage('rfidMessage', 'QR-Code enthält keine gültige RFID UID', 'error'); showMessage('rfidMessage', 'QR-Code enthält keine gültige RFID UID', 'error');
return; return;
} }
// Format the UID to match database format (XX:XX:XX:XX) // Format the UID to match database format (XX:XX:XX:XX)
const formattedUid = formatRfidUid(rawUid); const formattedUid = formatRfidUid(rawUid);
showMessage('rfidMessage', `QR-Code erkannt: ${rawUid}${formattedUid}`, 'info'); showMessage('rfidMessage', `QR-Code erkannt: ${rawUid}${formattedUid}`, 'info');
// Link the user using the formatted RFID UID // Link the user using the formatted RFID UID
await linkUserByRfidUid(formattedUid); await linkUserByRfidUid(formattedUid);
} catch (error) { } catch (error) {
console.error('Error formatting RFID UID:', error); console.error('Error formatting RFID UID:', error);
showMessage('rfidMessage', `Fehler beim Formatieren der RFID UID: ${error.message}`, 'error'); showMessage('rfidMessage', `Fehler beim Formatieren der RFID UID: ${error.message}`, 'error');
@@ -286,20 +286,20 @@ async function handleQRCodeDetected(qrData) {
// Manual RFID linking // Manual RFID linking
async function linkManualRfid() { async function linkManualRfid() {
const rawUid = document.getElementById('manualRfidInput').value.trim(); const rawUid = document.getElementById('manualRfidInput').value.trim();
if (!rawUid) { if (!rawUid) {
showMessage('rfidMessage', 'Bitte gib eine RFID UID ein', 'error'); showMessage('rfidMessage', 'Bitte gib eine RFID UID ein', 'error');
return; return;
} }
try { try {
// Format the UID to match database format // Format the UID to match database format
const formattedUid = formatRfidUid(rawUid); const formattedUid = formatRfidUid(rawUid);
showMessage('rfidMessage', `Formatiert: ${rawUid}${formattedUid}`, 'info'); showMessage('rfidMessage', `Formatiert: ${rawUid}${formattedUid}`, 'info');
await linkUserByRfidUid(formattedUid); await linkUserByRfidUid(formattedUid);
} catch (error) { } catch (error) {
console.error('Error formatting manual RFID UID:', error); console.error('Error formatting manual RFID UID:', error);
showMessage('rfidMessage', `Fehler beim Formatieren: ${error.message}`, 'error'); showMessage('rfidMessage', `Fehler beim Formatieren: ${error.message}`, 'error');
@@ -327,7 +327,7 @@ async function linkUserByRfidUid(rfidUid) {
}); });
const result = await response.json(); const result = await response.json();
if (response.ok) { if (response.ok) {
showMessage('rfidMessage', `✅ RFID erfolgreich verknüpft!\nSpieler: ${result.data.firstname} ${result.data.lastname}`, 'success'); showMessage('rfidMessage', `✅ RFID erfolgreich verknüpft!\nSpieler: ${result.data.firstname} ${result.data.lastname}`, 'success');
setTimeout(() => { setTimeout(() => {
@@ -365,27 +365,27 @@ async function loadUserTimesSection(playerData) {
try { try {
const response = await fetch(`/api/v1/public/user-times/${currentUser.id}?t=${Date.now()}`); const response = await fetch(`/api/v1/public/user-times/${currentUser.id}?t=${Date.now()}`);
const result = await response.json(); const result = await response.json();
if (!response.ok) { if (!response.ok) {
throw new Error(result.message || 'Failed to load times'); throw new Error(result.message || 'Failed to load times');
} }
const times = result.data || result; const times = result.data || result;
// Update stats // Update stats
updateTimesStats(times, playerData); updateTimesStats(times, playerData);
// Display times // Display times
displayUserTimes(times); displayUserTimes(times);
// Show the times display // Show the times display
document.getElementById('timesLoading').style.display = 'none'; document.getElementById('timesLoading').style.display = 'none';
document.getElementById('timesNotLinked').style.display = 'none'; document.getElementById('timesNotLinked').style.display = 'none';
document.getElementById('timesDisplay').style.display = 'block'; document.getElementById('timesDisplay').style.display = 'block';
// Initialize achievements for this player // Initialize achievements for this player
initializeAchievements(playerData.id); initializeAchievements(playerData.id);
} catch (error) { } catch (error) {
console.error('Error loading user times:', error); console.error('Error loading user times:', error);
showTimesNotLinked(); showTimesNotLinked();
@@ -396,7 +396,7 @@ async function loadUserTimesSection(playerData) {
function updateTimesStats(times, playerData) { function updateTimesStats(times, playerData) {
// Total runs // Total runs
document.getElementById('totalRuns').textContent = times.length; document.getElementById('totalRuns').textContent = times.length;
// Best time // Best time
if (times.length > 0) { if (times.length > 0) {
const bestTimeValue = times.reduce((best, current) => { const bestTimeValue = times.reduce((best, current) => {
@@ -408,11 +408,11 @@ function updateTimesStats(times, playerData) {
} else { } else {
document.getElementById('bestTime').textContent = '--:--'; document.getElementById('bestTime').textContent = '--:--';
} }
// Unique locations count // Unique locations count
const uniqueLocations = [...new Set(times.map(time => time.location_name))]; const uniqueLocations = [...new Set(times.map(time => time.location_name))];
document.getElementById('locationsCount').textContent = uniqueLocations.length; document.getElementById('locationsCount').textContent = uniqueLocations.length;
// Linked player name // Linked player name
document.getElementById('linkedPlayer').textContent = `${playerData.firstname} ${playerData.lastname}`; document.getElementById('linkedPlayer').textContent = `${playerData.firstname} ${playerData.lastname}`;
} }
@@ -420,7 +420,7 @@ function updateTimesStats(times, playerData) {
// Display user times in grid // Display user times in grid
function displayUserTimes(times) { function displayUserTimes(times) {
const timesGrid = document.getElementById('userTimesGrid'); const timesGrid = document.getElementById('userTimesGrid');
if (times.length === 0) { if (times.length === 0) {
timesGrid.innerHTML = ` timesGrid.innerHTML = `
<div style="grid-column: 1 / -1; text-align: center; padding: 3rem; color: #8892b0;"> <div style="grid-column: 1 / -1; text-align: center; padding: 3rem; color: #8892b0;">
@@ -454,7 +454,7 @@ function displayUserTimes(times) {
const allRunsHtml = sortedTimes.map((run, runIndex) => { const allRunsHtml = sortedTimes.map((run, runIndex) => {
let rankBadge = ''; let rankBadge = '';
let rankClass = ''; let rankClass = '';
if (runIndex === 0) { if (runIndex === 0) {
rankBadge = '🥇 Beste'; rankBadge = '🥇 Beste';
rankClass = 'best'; rankClass = 'best';
@@ -512,14 +512,14 @@ function displayUserTimes(times) {
// Toggle time card expansion // Toggle time card expansion
function toggleTimeCard(cardElement) { function toggleTimeCard(cardElement) {
const isExpanded = cardElement.classList.contains('expanded'); const isExpanded = cardElement.classList.contains('expanded');
// Close all other cards first // Close all other cards first
document.querySelectorAll('.user-time-card.expanded').forEach(card => { document.querySelectorAll('.user-time-card.expanded').forEach(card => {
if (card !== cardElement) { if (card !== cardElement) {
card.classList.remove('expanded'); card.classList.remove('expanded');
} }
}); });
// Toggle current card // Toggle current card
if (isExpanded) { if (isExpanded) {
cardElement.classList.remove('expanded'); cardElement.classList.remove('expanded');
@@ -552,7 +552,7 @@ function formatTime(interval) {
const totalSeconds = hours * 3600 + minutes * 60 + seconds; const totalSeconds = hours * 3600 + minutes * 60 + seconds;
return formatSeconds(totalSeconds); return formatSeconds(totalSeconds);
} }
// Fallback for string format // Fallback for string format
if (typeof interval === 'string') { if (typeof interval === 'string') {
// Parse format like "00:01:23.45" // Parse format like "00:01:23.45"
@@ -565,14 +565,14 @@ function formatTime(interval) {
return formatSeconds(totalSeconds); return formatSeconds(totalSeconds);
} }
} }
return interval; return interval;
} }
function formatSeconds(totalSeconds) { function formatSeconds(totalSeconds) {
const minutes = Math.floor(totalSeconds / 60); const minutes = Math.floor(totalSeconds / 60);
const seconds = (totalSeconds % 60).toFixed(2); const seconds = (totalSeconds % 60).toFixed(2);
if (minutes > 0) { if (minutes > 0) {
return `${minutes}:${seconds.padStart(5, '0')}`; return `${minutes}:${seconds.padStart(5, '0')}`;
} else { } else {
@@ -625,7 +625,7 @@ async function loadPlayerAchievements() {
// Show achievements // Show achievements
displayAchievementStats(); displayAchievementStats();
displayAchievements(); displayAchievements();
// Hide loading state // Hide loading state
document.getElementById('achievementsLoading').style.display = 'none'; document.getElementById('achievementsLoading').style.display = 'none';
document.getElementById('achievementStats').style.display = 'flex'; document.getElementById('achievementStats').style.display = 'flex';
@@ -656,7 +656,7 @@ function displayAchievementStats() {
if (!window.achievementStats) return; if (!window.achievementStats) return;
const stats = window.achievementStats; const stats = window.achievementStats;
document.getElementById('totalPoints').textContent = stats.total_points; document.getElementById('totalPoints').textContent = stats.total_points;
document.getElementById('completedAchievements').textContent = `${stats.completed_achievements}/${stats.total_achievements}`; document.getElementById('completedAchievements').textContent = `${stats.completed_achievements}/${stats.total_achievements}`;
document.getElementById('achievementsToday').textContent = stats.achievements_today; document.getElementById('achievementsToday').textContent = stats.achievements_today;
@@ -666,7 +666,7 @@ function displayAchievementStats() {
// Display achievements in grid // Display achievements in grid
function displayAchievements() { function displayAchievements() {
const achievementsGrid = document.getElementById('achievementsGrid'); const achievementsGrid = document.getElementById('achievementsGrid');
if (!window.allAchievements || window.allAchievements.length === 0) { if (!window.allAchievements || window.allAchievements.length === 0) {
achievementsGrid.innerHTML = ` achievementsGrid.innerHTML = `
<div class="no-achievements"> <div class="no-achievements">
@@ -681,7 +681,7 @@ function displayAchievements() {
// Filter achievements by category // Filter achievements by category
let filteredAchievements = window.allAchievements; let filteredAchievements = window.allAchievements;
if (currentAchievementCategory !== 'all') { if (currentAchievementCategory !== 'all') {
filteredAchievements = window.allAchievements.filter(achievement => filteredAchievements = window.allAchievements.filter(achievement =>
achievement.category === currentAchievementCategory achievement.category === currentAchievementCategory
); );
} }
@@ -691,16 +691,16 @@ function displayAchievements() {
const isCompleted = achievement.is_completed; const isCompleted = achievement.is_completed;
const progress = achievement.progress || 0; const progress = achievement.progress || 0;
const earnedAt = achievement.earned_at; const earnedAt = achievement.earned_at;
// Debug logging // Debug logging
if (achievement.name === 'Tageskönig') { if (achievement.name === 'Tageskönig') {
console.log('Tageskönig Debug:', { isCompleted, progress, earnedAt }); console.log('Tageskönig Debug:', { isCompleted, progress, earnedAt });
} }
let progressText = ''; let progressText = '';
if (isCompleted) { if (isCompleted) {
progressText = earnedAt ? progressText = earnedAt ?
`Erreicht am ${new Date(earnedAt).toLocaleDateString('de-DE')}` : `Erreicht am ${new Date(earnedAt).toLocaleDateString('de-DE')}` :
'Abgeschlossen'; 'Abgeschlossen';
} else if (progress > 0) { } else if (progress > 0) {
// Show progress for incomplete achievements // Show progress for incomplete achievements
@@ -754,13 +754,13 @@ function getAchievementConditionValue(achievementName) {
// Show achievement category // Show achievement category
function showAchievementCategory(category) { function showAchievementCategory(category) {
currentAchievementCategory = category; currentAchievementCategory = category;
// Update active tab // Update active tab
document.querySelectorAll('.category-tab').forEach(tab => { document.querySelectorAll('.category-tab').forEach(tab => {
tab.classList.remove('active'); tab.classList.remove('active');
}); });
document.querySelector(`[data-category="${category}"]`).classList.add('active'); document.querySelector(`[data-category="${category}"]`).classList.add('active');
// Display filtered achievements // Display filtered achievements
displayAchievements(); displayAchievements();
} }
@@ -790,7 +790,7 @@ async function checkPlayerAchievements() {
const response = await fetch(`/api/achievements/check/${currentPlayerId}?t=${Date.now()}`, { const response = await fetch(`/api/achievements/check/${currentPlayerId}?t=${Date.now()}`, {
method: 'POST' method: 'POST'
}); });
if (response.ok) { if (response.ok) {
const result = await response.json(); const result = await response.json();
if (result.data.count > 0) { if (result.data.count > 0) {
@@ -820,10 +820,10 @@ function showAchievementNotification(newAchievements) {
<button class="notification-close" onclick="this.parentElement.parentElement.remove()">×</button> <button class="notification-close" onclick="this.parentElement.parentElement.remove()">×</button>
</div> </div>
`; `;
// Add to page // Add to page
document.body.appendChild(notification); document.body.appendChild(notification);
// Auto-remove after 5 seconds // Auto-remove after 5 seconds
setTimeout(() => { setTimeout(() => {
if (notification.parentElement) { if (notification.parentElement) {
@@ -848,14 +848,14 @@ function showWebNotification(title, message, icon = '🏆') {
tag: 'ninjacross-achievement', tag: 'ninjacross-achievement',
requireInteraction: true requireInteraction: true
}); });
// Auto-close after 10 seconds // Auto-close after 10 seconds
setTimeout(() => { setTimeout(() => {
notification.close(); notification.close();
}, 10000); }, 10000);
// Handle click // Handle click
notification.onclick = function() { notification.onclick = function () {
window.focus(); window.focus();
notification.close(); notification.close();
}; };
@@ -867,10 +867,10 @@ async function checkBestTimeNotifications() {
try { try {
const response = await fetch('/api/v1/public/best-times'); const response = await fetch('/api/v1/public/best-times');
const result = await response.json(); const result = await response.json();
if (result.success && result.data) { if (result.success && result.data) {
const { daily, weekly, monthly } = result.data; const { daily, weekly, monthly } = result.data;
// Check if current player has best times // Check if current player has best times
if (currentPlayerId) { if (currentPlayerId) {
if (daily && daily.player_id === currentPlayerId) { if (daily && daily.player_id === currentPlayerId) {
@@ -880,7 +880,7 @@ async function checkBestTimeNotifications() {
'👑' '👑'
); );
} }
if (weekly && weekly.player_id === currentPlayerId) { if (weekly && weekly.player_id === currentPlayerId) {
showWebNotification( showWebNotification(
'🏆 Wochenchampion!', '🏆 Wochenchampion!',
@@ -888,7 +888,7 @@ async function checkBestTimeNotifications() {
'🏆' '🏆'
); );
} }
if (monthly && monthly.player_id === currentPlayerId) { if (monthly && monthly.player_id === currentPlayerId) {
showWebNotification( showWebNotification(
'🏆 Monatsmeister!', '🏆 Monatsmeister!',
@@ -907,10 +907,10 @@ async function checkBestTimeNotifications() {
async function checkAchievementNotifications() { async function checkAchievementNotifications() {
try { try {
if (!currentPlayerId) return; if (!currentPlayerId) return;
const response = await fetch(`/api/achievements/player/${currentPlayerId}?t=${Date.now()}`); const response = await fetch(`/api/achievements/player/${currentPlayerId}?t=${Date.now()}`);
const result = await response.json(); const result = await response.json();
if (result.success && result.data) { if (result.success && result.data) {
const newAchievements = result.data.filter(achievement => { const newAchievements = result.data.filter(achievement => {
// Check if achievement was earned in the last 5 minutes // Check if achievement was earned in the last 5 minutes
@@ -918,7 +918,7 @@ async function checkAchievementNotifications() {
const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000); const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
return earnedAt > fiveMinutesAgo; return earnedAt > fiveMinutesAgo;
}); });
if (newAchievements.length > 0) { if (newAchievements.length > 0) {
newAchievements.forEach(achievement => { newAchievements.forEach(achievement => {
showWebNotification( showWebNotification(
@@ -952,21 +952,28 @@ function showSettings() {
async function loadSettings() { async function loadSettings() {
try { try {
if (!currentPlayerId) { if (!currentUser || !currentUser.id) {
console.error('No player ID available'); console.error('No user ID available');
return; return;
} }
// Load current player settings // Load current player settings using user ID
const response = await fetch(`/api/v1/public/user-player/${currentUser.id}`); const response = await fetch(`/api/v1/public/user-player/${currentUser.id}`);
const result = await response.json(); const result = await response.json();
if (result.success && result.data) { if (result.success && result.data) {
const showInLeaderboard = result.data.show_in_leaderboard || false; const showInLeaderboard = result.data.show_in_leaderboard || false;
document.getElementById('showInLeaderboard').checked = showInLeaderboard; document.getElementById('showInLeaderboard').checked = showInLeaderboard;
console.log('Loaded settings - showInLeaderboard:', showInLeaderboard);
} else {
console.error('Failed to load player settings:', result.message);
// Set default to false if loading fails
document.getElementById('showInLeaderboard').checked = false;
} }
} catch (error) { } catch (error) {
console.error('Error loading settings:', error); console.error('Error loading settings:', error);
// Set default to false if loading fails
document.getElementById('showInLeaderboard').checked = false;
} }
} }
@@ -981,9 +988,9 @@ async function saveSettings() {
console.error('No player ID available'); console.error('No player ID available');
return; return;
} }
const showInLeaderboard = document.getElementById('showInLeaderboard').checked; const showInLeaderboard = document.getElementById('showInLeaderboard').checked;
// Update player settings using public endpoint (no API key needed) // Update player settings using public endpoint (no API key needed)
const response = await fetch(`/api/v1/public/update-player-settings`, { const response = await fetch(`/api/v1/public/update-player-settings`, {
method: 'POST', method: 'POST',
@@ -995,9 +1002,9 @@ async function saveSettings() {
show_in_leaderboard: showInLeaderboard show_in_leaderboard: showInLeaderboard
}) })
}); });
const result = await response.json(); const result = await response.json();
if (result.success) { if (result.success) {
showNotification('Einstellungen erfolgreich gespeichert!', 'success'); showNotification('Einstellungen erfolgreich gespeichert!', 'success');
closeModal('settingsModal'); closeModal('settingsModal');
@@ -1028,9 +1035,9 @@ function showNotification(message, type = 'info') {
font-weight: 500; font-weight: 500;
`; `;
notification.textContent = message; notification.textContent = message;
document.body.appendChild(notification); document.body.appendChild(notification);
// Remove notification after 3 seconds // Remove notification after 3 seconds
setTimeout(() => { setTimeout(() => {
if (notification.parentNode) { if (notification.parentNode) {
@@ -1039,11 +1046,11 @@ function showNotification(message, type = 'info') {
}, 3000); }, 3000);
} }
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function () {
// Add cookie settings button functionality // Add cookie settings button functionality
const cookieSettingsBtn = document.getElementById('cookie-settings-footer'); const cookieSettingsBtn = document.getElementById('cookie-settings-footer');
if (cookieSettingsBtn) { if (cookieSettingsBtn) {
cookieSettingsBtn.addEventListener('click', function() { cookieSettingsBtn.addEventListener('click', function () {
if (window.cookieConsent) { if (window.cookieConsent) {
window.cookieConsent.resetConsent(); window.cookieConsent.resetConsent();
} }

View File

@@ -1256,7 +1256,7 @@ router.get('/v1/public/user-player/:supabase_user_id', async (req, res) => {
try { try {
const result = await pool.query( const result = await pool.query(
'SELECT id, firstname, lastname, birthdate, rfiduid FROM players WHERE supabase_user_id = $1', 'SELECT id, firstname, lastname, birthdate, rfiduid, show_in_leaderboard FROM players WHERE supabase_user_id = $1',
[supabase_user_id] [supabase_user_id]
); );
@@ -2915,14 +2915,14 @@ router.get('/achievements/leaderboard', async (req, res) => {
router.post('/v1/public/update-player-settings', async (req, res) => { router.post('/v1/public/update-player-settings', async (req, res) => {
try { try {
const { player_id, show_in_leaderboard } = req.body; const { player_id, show_in_leaderboard } = req.body;
if (!player_id) { if (!player_id) {
return res.status(400).json({ return res.status(400).json({
success: false, success: false,
message: 'Player ID ist erforderlich' message: 'Player ID ist erforderlich'
}); });
} }
// Update player settings // Update player settings
const updateQuery = ` const updateQuery = `
UPDATE players UPDATE players
@@ -2930,22 +2930,22 @@ router.post('/v1/public/update-player-settings', async (req, res) => {
WHERE id = $2 WHERE id = $2
RETURNING id, firstname, lastname, show_in_leaderboard RETURNING id, firstname, lastname, show_in_leaderboard
`; `;
const result = await pool.query(updateQuery, [show_in_leaderboard || false, player_id]); const result = await pool.query(updateQuery, [show_in_leaderboard || false, player_id]);
if (result.rows.length === 0) { if (result.rows.length === 0) {
return res.status(404).json({ return res.status(404).json({
success: false, success: false,
message: 'Spieler nicht gefunden' message: 'Spieler nicht gefunden'
}); });
} }
res.json({ res.json({
success: true, success: true,
message: 'Einstellungen erfolgreich aktualisiert', message: 'Einstellungen erfolgreich aktualisiert',
data: result.rows[0] data: result.rows[0]
}); });
} catch (error) { } catch (error) {
console.error('Error updating player settings:', error); console.error('Error updating player settings:', error);
res.status(500).json({ res.status(500).json({
@@ -2959,14 +2959,14 @@ router.post('/v1/public/update-player-settings', async (req, res) => {
router.post('/v1/private/update-player-settings', requireApiKey, async (req, res) => { router.post('/v1/private/update-player-settings', requireApiKey, async (req, res) => {
try { try {
const { player_id, show_in_leaderboard } = req.body; const { player_id, show_in_leaderboard } = req.body;
if (!player_id) { if (!player_id) {
return res.status(400).json({ return res.status(400).json({
success: false, success: false,
message: 'Player ID ist erforderlich' message: 'Player ID ist erforderlich'
}); });
} }
// Update player settings // Update player settings
const updateQuery = ` const updateQuery = `
UPDATE players UPDATE players
@@ -2974,22 +2974,22 @@ router.post('/v1/private/update-player-settings', requireApiKey, async (req, res
WHERE id = $2 WHERE id = $2
RETURNING id, firstname, lastname, show_in_leaderboard RETURNING id, firstname, lastname, show_in_leaderboard
`; `;
const result = await pool.query(updateQuery, [show_in_leaderboard || false, player_id]); const result = await pool.query(updateQuery, [show_in_leaderboard || false, player_id]);
if (result.rows.length === 0) { if (result.rows.length === 0) {
return res.status(404).json({ return res.status(404).json({
success: false, success: false,
message: 'Spieler nicht gefunden' message: 'Spieler nicht gefunden'
}); });
} }
res.json({ res.json({
success: true, success: true,
message: 'Einstellungen erfolgreich aktualisiert', message: 'Einstellungen erfolgreich aktualisiert',
data: result.rows[0] data: result.rows[0]
}); });
} catch (error) { } catch (error) {
console.error('Error updating player settings:', error); console.error('Error updating player settings:', error);
res.status(500).json({ res.status(500).json({