From 340e22a8159a546005324d219a506d2f32c3edec Mon Sep 17 00:00:00 2001 From: Carsten Graf Date: Wed, 10 Sep 2025 19:40:57 +0200 Subject: [PATCH] Add real country flags to language selector - Replace emoji flags with SVG-based country flags - German flag: Black-Red-Gold (official colors) - USA flag: Red-White-Blue with stars - Dynamic flag switching on language change - Applied to both dashboard and leaderboard - Database achievements now support English translations - Extended achievements table with name_en and description_en columns - Updated API routes to return English translations - Simplified frontend translation system to use database translations --- public/css/dashboard.css | 84 ++++++-- public/css/leaderboard.css | 54 +++-- public/dashboard.html | 136 +++++++------ public/index.html | 4 +- public/js/dashboard.js | 389 ++++++++++++++++++++++++++++++++----- public/js/leaderboard.js | 19 ++ routes/api.js | 4 +- 7 files changed, 541 insertions(+), 149 deletions(-) diff --git a/public/css/dashboard.css b/public/css/dashboard.css index c7898db..b16a516 100644 --- a/public/css/dashboard.css +++ b/public/css/dashboard.css @@ -11,7 +11,7 @@ body { background: #0a0a0f; color: #ffffff; min-height: 100vh; - background-image: + background-image: radial-gradient(circle at 20% 80%, #1a1a2e 0%, transparent 50%), radial-gradient(circle at 80% 20%, #16213e 0%, transparent 50%), radial-gradient(circle at 40% 40%, #0f3460 0%, transparent 50%); @@ -24,6 +24,43 @@ body { min-height: 100vh; } +/* Language Selector */ +.language-selector { + position: fixed; + top: 2rem; + left: 2rem; + z-index: 1000; +} + +.language-selector select { + padding: 0.5rem 1rem; + background: rgba(15, 23, 42, 0.9); + border: 1px solid #334155; + border-radius: 0.5rem; + color: #ffffff; + font-size: 0.9rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + backdrop-filter: blur(10px); + padding-left: 2.5rem; + background-image: url('data:image/svg+xml,'); + background-repeat: no-repeat; + background-position: 0.5rem center; + background-size: 20px 15px; +} + +.language-selector select:hover { + border-color: #00d4ff; + box-shadow: 0 0 0 2px rgba(0, 212, 255, 0.1); +} + +.language-selector select:focus { + outline: none; + border-color: #00d4ff; + box-shadow: 0 0 0 3px rgba(0, 212, 255, 0.2); +} + .header-section { text-align: center; margin-bottom: 3rem; @@ -151,8 +188,13 @@ body { } @keyframes spin { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } } .user-info { @@ -893,8 +935,10 @@ body { /* Touch-friendly improvements for mobile */ @media (max-width: 768px) { .btn { - min-height: 44px; /* Apple's recommended minimum touch target */ - touch-action: manipulation; /* Prevents double-tap zoom */ + min-height: 44px; + /* Apple's recommended minimum touch target */ + touch-action: manipulation; + /* Prevents double-tap zoom */ } .card { @@ -930,7 +974,8 @@ body { /* Better spacing for mobile */ .header-section { margin-bottom: 2rem; - margin-top: 5rem; /* Account for fixed nav */ + margin-top: 5rem; + /* Account for fixed nav */ } /* Improve modal usability on mobile */ @@ -1019,7 +1064,7 @@ body { text-align: center; gap: 1.5rem; } - + .footer-links { flex-wrap: wrap; justify-content: center; @@ -1292,6 +1337,7 @@ body { transform: translateX(100%); opacity: 0; } + to { transform: translateX(0); opacity: 1; @@ -1340,33 +1386,33 @@ body { .achievements-header h2 { font-size: 2rem; } - + .achievement-stats { flex-direction: column; align-items: center; } - + .achievement-stat { width: 100%; max-width: 250px; } - + .category-tabs { flex-direction: column; align-items: center; } - + .category-tab { width: 100%; max-width: 200px; text-align: center; } - + .achievements-grid { grid-template-columns: 1fr; gap: 1rem; } - + .achievement-notification { top: 1rem; right: 1rem; @@ -1452,11 +1498,11 @@ body { border-radius: 50%; } -input:checked + .toggle-slider { +input:checked+.toggle-slider { background-color: #00d4ff; } -input:checked + .toggle-slider:before { +input:checked+.toggle-slider:before { transform: translateX(26px); } @@ -1482,17 +1528,17 @@ input:checked + .toggle-slider:before { align-items: flex-start; gap: 1rem; } - + .setting-control { margin-left: 0; align-self: flex-end; } - + .settings-actions { flex-direction: column; } - + .settings-actions .btn { width: 100%; } -} +} \ No newline at end of file diff --git a/public/css/leaderboard.css b/public/css/leaderboard.css index ea36c56..76f8ea4 100644 --- a/public/css/leaderboard.css +++ b/public/css/leaderboard.css @@ -11,7 +11,7 @@ body { background: #0a0a0f; color: #ffffff; min-height: 100vh; - background-image: + background-image: radial-gradient(circle at 20% 80%, #1a1a2e 0%, transparent 50%), radial-gradient(circle at 80% 20%, #16213e 0%, transparent 50%), radial-gradient(circle at 40% 40%, #0f3460 0%, transparent 50%); @@ -43,6 +43,11 @@ body { cursor: pointer; transition: all 0.2s ease; backdrop-filter: blur(10px); + padding-left: 2.5rem; + background-image: url('data:image/svg+xml,'); + background-repeat: no-repeat; + background-position: 0.5rem center; + background-size: 20px 15px; } .language-selector select:hover { @@ -177,13 +182,18 @@ body { left: -100%; width: 100%; height: 100%; - background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); animation: loading-sweep 1.5s infinite; } @keyframes loading-sweep { - 0% { left: -100%; } - 100% { left: 100%; } + 0% { + left: -100%; + } + + 100% { + left: 100%; + } } /* Horizontal Time Tabs */ @@ -524,9 +534,17 @@ body { } @keyframes pulse { - 0% { opacity: 1; } - 50% { opacity: 0.7; } - 100% { opacity: 1; } + 0% { + opacity: 1; + } + + 50% { + opacity: 0.7; + } + + 100% { + opacity: 1; + } } /* Notification Bubble Styles */ @@ -587,12 +605,19 @@ body { } @keyframes bounce { - 0%, 20%, 50%, 80%, 100% { + + 0%, + 20%, + 50%, + 80%, + 100% { transform: translateY(0); } + 40% { transform: translateY(-10px); } + 60% { transform: translateY(-5px); } @@ -603,6 +628,7 @@ body { opacity: 0; transform: translateX(-50%) translateY(-20px); } + to { opacity: 1; transform: translateX(-50%) translateY(0); @@ -614,6 +640,7 @@ body { opacity: 1; transform: translateX(-50%) translateY(0); } + to { opacity: 0; transform: translateX(-50%) translateY(-20px); @@ -649,7 +676,8 @@ body { .header-section { margin-bottom: 2rem; - margin-top: 5rem; /* Account for fixed buttons */ + margin-top: 5rem; + /* Account for fixed buttons */ } .dashboard-grid { @@ -789,7 +817,9 @@ body { display: none; } - .admin-login-btn, .dashboard-btn, .logout-btn { + .admin-login-btn, + .dashboard-btn, + .logout-btn { position: fixed; top: 1rem; right: 1rem; @@ -1088,10 +1118,10 @@ body { text-align: center; gap: 1.5rem; } - + .footer-links { flex-wrap: wrap; justify-content: center; gap: 1.5rem; } -} +} \ No newline at end of file diff --git a/public/dashboard.html b/public/dashboard.html index 2791969..5c0f7f1 100644 --- a/public/dashboard.html +++ b/public/dashboard.html @@ -70,83 +70,91 @@
+ +
+ +
+
-

DEIN DASHBOARD

-

Verwalte deine Läufe in der NINJACROSS ARENA

+

DEIN DASHBOARD

+

Verwalte deine Läufe in der NINJACROSS ARENA

-

Lade dein Dashboard...

+

Lade dein Dashboard...