From 10a150cb39e5174d60662009c7810b7e73590b2e Mon Sep 17 00:00:00 2001 From: Carsten Graf Date: Tue, 16 Sep 2025 01:31:22 +0200 Subject: [PATCH] Diverse Fixes nach refactoring --- public/css/dashboard.css | 81 ++++++++++++++++++++-- public/css/{leaderboard.css => index.css} | 64 +++++++++++++++++ public/dashboard.html | 1 + public/index.html | 4 +- public/js/dashboard.js | 9 ++- public/js/{leaderboard.js => index.js} | 0 public/pictures/icon-192.png | Bin 0 -> 5560 bytes routes/api.js | 11 +-- 8 files changed, 155 insertions(+), 15 deletions(-) rename public/css/{leaderboard.css => index.css} (93%) rename public/js/{leaderboard.js => index.js} (100%) create mode 100644 public/pictures/icon-192.png diff --git a/public/css/dashboard.css b/public/css/dashboard.css index 110b3d7..56b0f6b 100644 --- a/public/css/dashboard.css +++ b/public/css/dashboard.css @@ -105,24 +105,97 @@ body { display: inline-block; } +/* ============================================================================ + NAVIGATION BUTTONS - COMPLETE REDESIGN + ============================================================================ */ + +/* Base button styles */ +.btn { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1.5rem; + border: none; + border-radius: 0.5rem; + font-weight: 600; + font-size: 0.9rem; + text-decoration: none; + cursor: pointer; + transition: all 0.3s ease; + white-space: nowrap; +} + +/* Primary button (Dashboard) */ .btn-primary { - background: linear-gradient(135deg, #00d4ff, #0891b2); + background: #2563eb; color: white; } .btn-primary:hover { + background: #1d4ed8; transform: translateY(-2px); - box-shadow: 0 10px 25px rgba(0, 212, 255, 0.3); + box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4); } +/* Logout button */ .btn-logout { - background: linear-gradient(135deg, #dc3545, #c82333); + background: #dc2626; color: white; } .btn-logout:hover { + background: #b91c1c; transform: translateY(-2px); - box-shadow: 0 10px 25px rgba(220, 53, 69, 0.3); + box-shadow: 0 4px 12px rgba(220, 38, 38, 0.4); +} + +/* Mobile navigation container */ +.mobile-nav-buttons { + display: flex; + gap: 1rem; + align-items: center; + justify-content: flex-end; + margin: 1rem 0; + flex-wrap: wrap; + position: absolute; + top: 1rem; + right: 1rem; +} + +/* Login button */ +.admin-login-btn { + background: #f59e0b; + color: white; +} + +.admin-login-btn:hover { + background: #d97706; + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(245, 158, 11, 0.4); +} + +/* Dashboard button */ +.dashboard-btn { + background: #2563eb; + color: white; +} + +.dashboard-btn:hover { + background: #1d4ed8; + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4); +} + +/* Logout button */ +.logout-btn { + background: #dc2626; + color: white; +} + +.logout-btn:hover { + background: #b91c1c; + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(220, 38, 38, 0.4); } .dashboard-grid { diff --git a/public/css/leaderboard.css b/public/css/index.css similarity index 93% rename from public/css/leaderboard.css rename to public/css/index.css index 0f38426..05c5153 100644 --- a/public/css/leaderboard.css +++ b/public/css/index.css @@ -32,6 +32,70 @@ body { z-index: 1000; } +/* Mobile Navigation Buttons */ +.mobile-nav-buttons { + position: fixed; + top: 2rem; + right: 2rem; + display: flex; + gap: 1rem; + align-items: center; + z-index: 1000; +} + +.mobile-nav-buttons .admin-login-btn, +.mobile-nav-buttons .dashboard-btn, +.mobile-nav-buttons .logout-btn { + padding: 0.75rem 1.5rem; + border-radius: 0.5rem; + text-decoration: none; + font-weight: 600; + transition: all 0.3s ease; + border: none; + cursor: pointer; + display: inline-flex; + align-items: center; + gap: 0.5rem; + font-size: 0.9rem; +} + +.mobile-nav-buttons .admin-login-btn { + background: #f59e0b; + color: white; +} + +.mobile-nav-buttons .dashboard-btn { + background: #2563eb; + color: white; +} + +.mobile-nav-buttons .logout-btn { + background: #dc2626; + color: white; +} + +.mobile-nav-buttons .admin-login-btn:hover, +.mobile-nav-buttons .dashboard-btn:hover, +.mobile-nav-buttons .logout-btn:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); +} + +.mobile-nav-buttons .admin-login-btn:hover { + background: #d97706; + box-shadow: 0 4px 12px rgba(245, 158, 11, 0.4); +} + +.mobile-nav-buttons .dashboard-btn:hover { + background: #1d4ed8; + box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4); +} + +.mobile-nav-buttons .logout-btn:hover { + background: #b91c1c; + box-shadow: 0 4px 12px rgba(220, 38, 38, 0.4); +} + .language-selector select { padding: 0.5rem 1rem; background: rgba(15, 23, 42, 0.9); diff --git a/public/dashboard.html b/public/dashboard.html index 0e98516..4703ca7 100644 --- a/public/dashboard.html +++ b/public/dashboard.html @@ -6,6 +6,7 @@ SPEEDRUN ARENA - Admin Dashboard + diff --git a/public/index.html b/public/index.html index 3403b18..eb0c1e4 100644 --- a/public/index.html +++ b/public/index.html @@ -7,7 +7,7 @@ - + @@ -138,6 +138,6 @@ - + diff --git a/public/js/dashboard.js b/public/js/dashboard.js index 7e39f0a..512393f 100644 --- a/public/js/dashboard.js +++ b/public/js/dashboard.js @@ -34,7 +34,7 @@ async function initDashboard() { // User is authenticated, show dashboard if (session.user) { - console.log('User data:', session.user); + currentUser = session.user; displayUserInfo(session.user); } else { @@ -1041,6 +1041,8 @@ async function loadPlayerAchievements() { } const result = await response.json(); + + window.allAchievements = result.data; playerAchievements = result.data.filter(achievement => achievement.is_completed); @@ -1126,10 +1128,6 @@ function displayAchievements() { // Translate achievement const translatedAchievement = translateAchievement(achievement); - // Debug logging - if (achievement.name === 'Tageskönig') { - console.log('Tageskönig Debug:', { isCompleted, progress, earnedAt, completionCount }); - } let progressText = ''; if (isCompleted) { @@ -1155,6 +1153,7 @@ function displayAchievements() { const pointsText = currentLanguage === 'de' ? 'Punkte' : 'Points'; const totalPoints = completionCount > 0 ? achievement.points * completionCount : achievement.points; + return `
diff --git a/public/js/leaderboard.js b/public/js/index.js similarity index 100% rename from public/js/leaderboard.js rename to public/js/index.js diff --git a/public/pictures/icon-192.png b/public/pictures/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..556e396fccdd9c818d3d054549b4dfe282f6f0ef GIT binary patch literal 5560 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 { MAX(pa.earned_at) as earned_at, COUNT(pa.id) as completion_count FROM achievements a - LEFT JOIN player_achievements pa ON a.id = pa.achievement_id AND pa.player_id = $1 AND pa.is_completed = true + LEFT JOIN player_achievements pa ON a.id = pa.achievement_id AND pa.player_id = $1 WHERE a.is_active = true GROUP BY a.id, a.name, a.name_en, a.description, a.description_en, a.category, a.icon, a.points ORDER BY - is_completed DESC, + COALESCE(COUNT(pa.id) > 0, false) DESC, a.category, a.points DESC `, [playerId]); @@ -3549,8 +3549,11 @@ router.post('/achievements/check/:playerId', async (req, res) => { }); } - // Run achievement check - await pool.query('SELECT check_all_achievements($1)', [playerId]); + // Run achievement check using AchievementSystem + const AchievementSystem = require('../lib/achievementSystem'); + const achievementSystem = new AchievementSystem(); + await achievementSystem.loadAchievements(); + const newAchievementsFromCheck = await achievementSystem.checkAllAchievements(playerId); // Get newly earned achievements const newAchievements = await pool.query(`