Viel Push und achivements + AGB
This commit is contained in:
@@ -400,7 +400,7 @@ function filterData() {
|
||||
displayAchievements();
|
||||
} else {
|
||||
currentPlayers = filteredData;
|
||||
displayPlayers();
|
||||
displayPlayersWithAchievements();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -427,7 +427,7 @@ function refreshData() {
|
||||
if (currentAchievementMode === 'achievements') {
|
||||
loadAchievements();
|
||||
} else {
|
||||
loadPlayers();
|
||||
loadPlayersWithAchievements();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1372,7 +1372,7 @@ async function toggleAchievementMode() {
|
||||
currentAchievementMode = 'players';
|
||||
document.getElementById('dataTitle').textContent = '👥 Spieler-Achievements';
|
||||
document.getElementById('searchInput').placeholder = 'Spieler durchsuchen...';
|
||||
await loadPlayers();
|
||||
await loadPlayersWithAchievements();
|
||||
} else {
|
||||
currentAchievementMode = 'achievements';
|
||||
document.getElementById('dataTitle').textContent = '🏆 Achievement-Verwaltung';
|
||||
@@ -1382,7 +1382,7 @@ async function toggleAchievementMode() {
|
||||
}
|
||||
|
||||
// Load all players with achievement statistics
|
||||
async function loadPlayers() {
|
||||
async function loadPlayersWithAchievements() {
|
||||
try {
|
||||
const response = await fetch('/api/v1/admin/achievements/players');
|
||||
const result = await response.json();
|
||||
@@ -1390,7 +1390,7 @@ async function loadPlayers() {
|
||||
if (result.success) {
|
||||
currentPlayers = result.data;
|
||||
currentData = result.data; // Set for filtering
|
||||
displayPlayers();
|
||||
displayPlayersWithAchievements();
|
||||
} else {
|
||||
showError('Fehler beim Laden der Spieler: ' + result.message);
|
||||
}
|
||||
@@ -1401,7 +1401,7 @@ async function loadPlayers() {
|
||||
}
|
||||
|
||||
// Display players in table
|
||||
function displayPlayers() {
|
||||
function displayPlayersWithAchievements() {
|
||||
const content = document.getElementById('dataContent');
|
||||
|
||||
if (currentPlayers.length === 0) {
|
||||
|
||||
@@ -618,6 +618,7 @@ async function createRfidPlayerRecord() {
|
||||
const firstname = document.getElementById('playerFirstname').value.trim();
|
||||
const lastname = document.getElementById('playerLastname').value.trim();
|
||||
const birthdate = document.getElementById('playerBirthdate').value;
|
||||
const agbAccepted = document.getElementById('agbAccepted').checked;
|
||||
|
||||
// Validation
|
||||
if (!rawUid) {
|
||||
@@ -652,6 +653,14 @@ async function createRfidPlayerRecord() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!agbAccepted) {
|
||||
const agbErrorMsg = currentLanguage === 'de' ?
|
||||
'Bitte stimme den Allgemeinen Geschäftsbedingungen zu' :
|
||||
'Please accept the Terms of Service';
|
||||
showMessage('rfidMessage', agbErrorMsg, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Format the UID to match database format
|
||||
const formattedUid = formatRfidUid(rawUid);
|
||||
@@ -672,7 +681,8 @@ async function createRfidPlayerRecord() {
|
||||
firstname: firstname,
|
||||
lastname: lastname,
|
||||
birthdate: birthdate,
|
||||
supabase_user_id: currentUser?.id || null
|
||||
supabase_user_id: currentUser?.id || null,
|
||||
agb_accepted: agbAccepted
|
||||
})
|
||||
});
|
||||
|
||||
@@ -689,6 +699,7 @@ async function createRfidPlayerRecord() {
|
||||
document.getElementById('playerFirstname').value = '';
|
||||
document.getElementById('playerLastname').value = '';
|
||||
document.getElementById('playerBirthdate').value = '';
|
||||
document.getElementById('agbAccepted').checked = false;
|
||||
|
||||
// Hide create player section since user is now linked
|
||||
const createPlayerSection = document.getElementById('createPlayerSection');
|
||||
@@ -1139,7 +1150,7 @@ let currentAchievementCategory = 'all';
|
||||
|
||||
// Load achievements for the current player
|
||||
async function loadPlayerAchievements() {
|
||||
if (!currentPlayerId) {
|
||||
if (!currentPlayerId || currentPlayerId === 'undefined' || currentPlayerId === 'null') {
|
||||
showAchievementsNotAvailable();
|
||||
return;
|
||||
}
|
||||
@@ -1372,7 +1383,7 @@ function showStatistics() {
|
||||
|
||||
async function loadAnalyticsData() {
|
||||
try {
|
||||
if (!currentPlayerId) {
|
||||
if (!currentPlayerId || currentPlayerId === 'undefined' || currentPlayerId === 'null') {
|
||||
console.error('No player ID available - user not linked');
|
||||
// Show fallback data when user is not linked
|
||||
displayAnalyticsFallback();
|
||||
@@ -1400,7 +1411,7 @@ async function loadAnalyticsData() {
|
||||
|
||||
async function loadStatisticsData() {
|
||||
try {
|
||||
if (!currentPlayerId) {
|
||||
if (!currentPlayerId || currentPlayerId === 'undefined' || currentPlayerId === 'null') {
|
||||
console.error('No player ID available - user not linked');
|
||||
// Show fallback data when user is not linked
|
||||
displayStatisticsFallback();
|
||||
@@ -1682,7 +1693,7 @@ function showAchievementsNotAvailable() {
|
||||
|
||||
// Check achievements for current player
|
||||
async function checkPlayerAchievements() {
|
||||
if (!currentPlayerId) return;
|
||||
if (!currentPlayerId || currentPlayerId === 'undefined' || currentPlayerId === 'null') return;
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/achievements/check/${currentPlayerId}?t=${Date.now()}`, {
|
||||
@@ -1738,8 +1749,13 @@ function showAchievementNotification(newAchievements) {
|
||||
|
||||
// Initialize achievements when player is loaded
|
||||
function initializeAchievements(playerId) {
|
||||
currentPlayerId = playerId;
|
||||
loadPlayerAchievements();
|
||||
if (playerId && playerId !== 'undefined' && playerId !== 'null') {
|
||||
currentPlayerId = playerId;
|
||||
loadPlayerAchievements();
|
||||
} else {
|
||||
console.warn('Invalid player ID provided to initializeAchievements:', playerId);
|
||||
currentPlayerId = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert VAPID key from base64url to Uint8Array
|
||||
@@ -1764,6 +1780,16 @@ function urlBase64ToUint8Array(base64String) {
|
||||
// Web Notification Functions
|
||||
function showWebNotification(title, message, icon = '🏆') {
|
||||
if ('Notification' in window && Notification.permission === 'granted') {
|
||||
// Log notification details to console
|
||||
console.log('🔔 Web Notification sent:', {
|
||||
title: title,
|
||||
message: message,
|
||||
icon: icon,
|
||||
playerId: currentPlayerId || 'unknown',
|
||||
pushPlayerId: localStorage.getItem('pushPlayerId') || 'unknown',
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
const notification = new Notification(title, {
|
||||
body: message,
|
||||
icon: '/pictures/icon-192.png',
|
||||
@@ -1809,7 +1835,7 @@ async function checkBestTimeNotifications() {
|
||||
const { daily, weekly, monthly } = result.data;
|
||||
|
||||
// Check if current player has best times
|
||||
if (currentPlayerId) {
|
||||
if (currentPlayerId && currentPlayerId !== 'undefined' && currentPlayerId !== 'null') {
|
||||
const now = new Date();
|
||||
const isEvening = now.getHours() >= 19;
|
||||
|
||||
@@ -1910,30 +1936,87 @@ async function checkBestTimeNotifications() {
|
||||
// Check for new achievements and show notifications
|
||||
async function checkAchievementNotifications() {
|
||||
try {
|
||||
if (!currentPlayerId) return;
|
||||
|
||||
console.log('🔍 checkAchievementNotifications() called');
|
||||
|
||||
// Check if push notifications are enabled
|
||||
const pushPlayerId = localStorage.getItem('pushPlayerId');
|
||||
if (!pushPlayerId) {
|
||||
console.log('🔕 Push notifications disabled, skipping achievement check');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🔍 Push notifications enabled for player:', pushPlayerId);
|
||||
|
||||
const response = await fetch(`/api/achievements/player/${currentPlayerId}?t=${Date.now()}`);
|
||||
// Use pushPlayerId for notifications instead of currentPlayerId
|
||||
if (!pushPlayerId || pushPlayerId === 'undefined' || pushPlayerId === 'null') return;
|
||||
|
||||
const response = await fetch(`/api/achievements/player/${pushPlayerId}?t=${Date.now()}`);
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success && result.data) {
|
||||
const newAchievements = result.data.filter(achievement => {
|
||||
// Check if achievement was earned in the last 5 minutes
|
||||
const earnedAt = new Date(achievement.earned_at);
|
||||
const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
|
||||
return earnedAt > fiveMinutesAgo;
|
||||
console.log('🔍 Checking achievements for notifications:', {
|
||||
totalAchievements: result.data.length,
|
||||
playerId: pushPlayerId
|
||||
});
|
||||
|
||||
const newAchievements = result.data.filter(achievement => {
|
||||
// Only check completed achievements
|
||||
if (!achievement.is_completed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if achievement was earned in the last 10 minutes (extended window)
|
||||
const earnedAt = achievement.earned_at ? new Date(achievement.earned_at) : null;
|
||||
const tenMinutesAgo = new Date(Date.now() - 10 * 60 * 1000);
|
||||
|
||||
// If no earned_at date, check if it was completed recently by checking completion_count
|
||||
if (!earnedAt) {
|
||||
// Send to server console
|
||||
fetch('/api/v1/public/log', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
level: 'info',
|
||||
message: `🔍 Achievement completed but no earned_at: ${achievement.name} (completion_count: ${achievement.completion_count})`,
|
||||
playerId: pushPlayerId
|
||||
})
|
||||
}).catch(() => {}); // Ignore errors
|
||||
|
||||
// For achievements without earned_at, assume they are new if completion_count is 1
|
||||
// This is a fallback for recently completed achievements
|
||||
return achievement.completion_count === 1;
|
||||
}
|
||||
|
||||
const isNew = earnedAt > tenMinutesAgo;
|
||||
|
||||
// Send detailed info to server console
|
||||
fetch('/api/v1/public/log', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
level: 'info',
|
||||
message: `🔍 Achievement check: ${achievement.name} - earned_at: ${earnedAt.toISOString()}, isNew: ${isNew}, completed: ${achievement.is_completed}`,
|
||||
playerId: pushPlayerId
|
||||
})
|
||||
}).catch(() => {}); // Ignore errors
|
||||
|
||||
return isNew;
|
||||
});
|
||||
|
||||
console.log('🔍 New achievements found:', newAchievements.length);
|
||||
|
||||
if (newAchievements.length > 0) {
|
||||
for (const achievement of newAchievements) {
|
||||
// Check if notification was already sent for this achievement
|
||||
const achievementCheck = await fetch(`/api/v1/public/notification-sent/${currentPlayerId}/achievement?achievementId=${achievement.achievement_id}&locationId=${achievement.location_id || ''}`);
|
||||
const achievementId = achievement.id || achievement.achievement_id;
|
||||
const locationId = achievement.location_id || '';
|
||||
|
||||
if (!achievementId) {
|
||||
console.warn('Achievement ID is missing for achievement:', achievement);
|
||||
continue;
|
||||
}
|
||||
|
||||
const achievementCheck = await fetch(`/api/v1/public/notification-sent/${pushPlayerId}/achievement?achievementId=${achievementId}&locationId=${locationId}`);
|
||||
const achievementResult = await achievementCheck.json();
|
||||
|
||||
if (!achievementResult.wasSent) {
|
||||
@@ -1949,10 +2032,10 @@ async function checkAchievementNotifications() {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
playerId: currentPlayerId,
|
||||
playerId: pushPlayerId,
|
||||
notificationType: 'achievement',
|
||||
achievementId: achievement.achievement_id,
|
||||
locationId: achievement.location_id || null
|
||||
achievementId: achievementId,
|
||||
locationId: locationId || null
|
||||
})
|
||||
});
|
||||
console.log(`🏆 Achievement notification sent: ${achievement.name}`);
|
||||
@@ -2015,7 +2098,7 @@ function updateLeaderboardSetting() {
|
||||
|
||||
async function saveSettings() {
|
||||
try {
|
||||
if (!currentPlayerId) {
|
||||
if (!currentPlayerId || currentPlayerId === 'undefined' || currentPlayerId === 'null') {
|
||||
console.error('No player ID available');
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user