Viel Push und achivements + AGB

This commit is contained in:
2025-09-16 23:41:34 +02:00
parent b2fc63e2d0
commit 5831d1bb91
8 changed files with 934 additions and 49 deletions

View File

@@ -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;
}