wuavy/comp-shell-tracker
0
1<!DOCTYPE html>2<html lang="en">3<head>4 <meta charset="UTF-8">5 <meta name="viewport" content="width=device-width, initial-scale=1.0">6 <title>Shell Tracker</title>7 <script src="https://cdn.tailwindcss.com"></script>8 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">9 <style>10 body {11 background: linear-gradient(135deg, #000033 0%, #0a0a2a 100%);12 min-height: 100vh;13 font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;14 }15 16 .leaderboard-box {17 background: linear-gradient(135deg, #1a237e 0%, #0d47a1 100%);18 box-shadow: 0 15px 30px rgba(13, 71, 161, 0.2);19 border-radius: 12px;20 transform: perspective(1000px) rotateX(5deg);21 transition: all 0.3s ease;22 }23 24 .leaderboard-box:hover {25 transform: perspective(1000px) rotateX(0deg);26 box-shadow: 0 20px 40px rgba(13, 71, 161, 0.3);27 }28 29 .leaderboard-header {30 border-bottom: 2px solid rgba(255, 255, 255, 0.1);31 text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);32 }33 34 .leaderboard-row {35 transition: all 0.2s ease;36 border-bottom: 1px solid rgba(255, 255, 255, 0.05);37 display: grid;38 grid-template-columns: 80px 2fr 1fr 1fr 1fr 80px;39 align-items: center;40 }41 42 .leaderboard-row:hover {43 background-color: rgba(255, 255, 255, 0.05);44 transform: translateX(5px);45 }46 47 .rank-1 {48 background: linear-gradient(90deg, rgba(255,215,0,0.15) 0%, rgba(255,215,0,0) 100%);49 }50 51 .rank-2 {52 background: linear-gradient(90deg, rgba(192,192,192,0.15) 0%, rgba(192,192,192,0) 100%);53 }54 55 .rank-3 {56 background: linear-gradient(90deg, rgba(205,127,50,0.15) 0%, rgba(205,127,50,0) 100%);57 }58 59 .pulse {60 animation: pulse 2s infinite;61 }62 63 @keyframes pulse {64 0% {65 box-shadow: 0 0 0 0 rgba(25, 118, 210, 0.5);66 }67 70% {68 box-shadow: 0 0 0 10px rgba(25, 118, 210, 0);69 }70 100% {71 box-shadow: 0 0 0 0 rgba(25, 118, 210, 0);72 }73 }74 75 .btn-primary {76 background: linear-gradient(135deg, #1565c0 0%, #0d47a1 100%);77 transition: all 0.3s ease;78 }79 80 .btn-primary:hover {81 transform: translateY(-2px);82 box-shadow: 0 5px 15px rgba(21, 101, 192, 0.3);83 }84 85 .btn-discord {86 background: linear-gradient(135deg, #7289da 0%, #5865a8 100%);87 transition: all 0.3s ease;88 }89 90 .btn-discord:hover {91 transform: translateY(-2px);92 box-shadow: 0 5px 15px rgba(114, 137, 218, 0.3);93 }94 95 .btn-edit {96 background: linear-gradient(135deg, #4CAF50 0%, #2E7D32 100%);97 transition: all 0.3s ease;98 }99 100 .btn-edit:hover {101 transform: translateY(-2px);102 box-shadow: 0 5px 15px rgba(76, 175, 80, 0.3);103 }104 105 .btn-remove {106 background: linear-gradient(135deg, #f44336 0%, #c62828 100%);107 transition: all 0.3s ease;108 }109 110 .btn-remove:hover {111 transform: translateY(-2px);112 box-shadow: 0 5px 15px rgba(244, 67, 54, 0.3);113 }114 115 .search-bar {116 background: rgba(255, 255, 255, 0.1);117 border: 1px solid rgba(255, 255, 255, 0.2);118 transition: all 0.3s ease;119 }120 121 .search-bar:focus {122 background: rgba(255, 255, 255, 0.15);123 box-shadow: 0 0 0 3px rgba(66, 165, 245, 0.3);124 }125 126 .modal-overlay {127 position: fixed;128 top: 0;129 left: 0;130 right: 0;131 bottom: 0;132 background-color: rgba(0, 0, 0, 0.7);133 display: flex;134 justify-content: center;135 align-items: center;136 z-index: 1000;137 }138 139 .modal-content {140 background: linear-gradient(135deg, #1a237e 0%, #0d47a1 100%);141 padding: 1.5rem;142 border-radius: 12px;143 max-width: 400px;144 width: 90%;145 box-shadow: 0 15px 30px rgba(13, 71, 161, 0.4);146 text-align: center;147 }148 149 .modal-close {150 position: absolute;151 top: 10px;152 right: 10px;153 background: none;154 border: none;155 color: white;156 font-size: 1.5rem;157 cursor: pointer;158 }159 160 .form-group {161 margin-bottom: 0.75rem;162 text-align: left;163 }164 165 .form-label {166 display: block;167 margin-bottom: 0.25rem;168 color: #90CAF9;169 font-weight: 500;170 font-size: 0.875rem;171 }172 173 .form-input {174 width: 100%;175 padding: 0.5rem;176 border-radius: 6px;177 border: 1px solid rgba(255, 255, 255, 0.2);178 background: rgba(255, 255, 255, 0.1);179 color: white;180 transition: all 0.3s ease;181 font-size: 0.875rem;182 }183 184 .form-input:focus {185 outline: none;186 background: rgba(255, 255, 255, 0.15);187 border-color: #42A5F5;188 box-shadow: 0 0 0 2px rgba(66, 165, 245, 0.2);189 }190 191 .staff-password {192 background: rgba(255, 0, 0, 0.1);193 border: 1px solid rgba(255, 0, 0, 0.3);194 margin-top: 1rem;195 padding: 0.75rem;196 border-radius: 6px;197 }198 199 .staff-label {200 color: #FF5252;201 font-weight: 600;202 font-size: 0.875rem;203 }204 205 .error-message {206 color: #FF5252;207 font-size: 0.75rem;208 margin-top: 0.25rem;209 display: none;210 }211 212 .hidden-row {213 display: none;214 }215 216 .header-row {217 display: grid;218 grid-template-columns: 80px 2fr 1fr 1fr 1fr 80px;219 align-items: center;220 padding: 0.75rem 1.5rem;221 font-weight: 600;222 text-transform: uppercase;223 font-size: 0.75rem;224 color: rgba(200, 200, 255, 0.8);225 border-bottom: 1px solid rgba(255, 255, 255, 0.1);226 }227 228 .password-modal {229 background: linear-gradient(135deg, #1a237e 0%, #0d47a1 100%);230 padding: 1.5rem;231 border-radius: 12px;232 max-width: 350px;233 width: 90%;234 box-shadow: 0 15px 30px rgba(13, 71, 161, 0.4);235 text-align: center;236 }237 238 .password-input {239 width: 100%;240 padding: 0.75rem;241 margin: 1rem 0;242 border-radius: 6px;243 border: 1px solid rgba(255, 255, 255, 0.2);244 background: rgba(255, 255, 255, 0.1);245 color: white;246 font-size: 1rem;247 }248 249 .password-error {250 color: #FF5252;251 font-size: 0.875rem;252 margin-top: 0.5rem;253 display: none;254 }255 </style>256</head>257<body class="flex items-center justify-center p-4">258 <div class="leaderboard-box w-full max-w-5xl overflow-hidden">259 <div class="leaderboard-header p-6 bg-gradient-to-r from-blue-900 to-blue-800">260 <div class="flex items-center justify-between">261 <h1 class="text-3xl font-bold text-white flex items-center">262 <i class="fas fa-shell mr-3 text-blue-300"></i>263 Shell Tracker264 </h1>265 <div class="flex space-x-4">266 <button id="editBtn" class="btn-edit px-4 py-2 text-white rounded-lg font-semibold flex items-center">267 <i class="fas fa-key mr-2"></i> Edit268 </button>269 <button id="registerBtn" class="btn-primary px-4 py-2 text-white rounded-lg font-semibold flex items-center">270 <i class="fas fa-user-plus mr-2"></i> Register Now271 </button>272 <a href="https://discord.gg/DXDMurpuCW" target="_blank" class="btn-discord px-4 py-2 text-white rounded-lg font-semibold flex items-center">273 <i class="fab fa-discord mr-2"></i> Join Discord274 </a>275 </div>276 </div>277 278 <div class="mt-4 relative">279 <input type="text" 280 id="searchInput"281 placeholder="Search players..." 282 class="search-bar w-full px-4 py-3 rounded-lg text-white placeholder-blue-200 focus:outline-none">283 <i class="fas fa-search absolute right-4 top-3.5 text-blue-200"></i>284 </div>285 </div>286 287 <div class="bg-blue-900 bg-opacity-20">288 <div class="header-row">289 <div>Rank</div>290 <div>Player</div>291 <div>PR</div>292 <div>Region</div>293 <div>Device</div>294 <div>Actions</div>295 </div>296 297 <div id="leaderboardContent" class="divide-y divide-blue-800 divide-opacity-50">298 <!-- Empty state -->299 <div class="py-12 text-center">300 <i class="fas fa-user-slash text-4xl text-blue-400 opacity-50 mb-4"></i>301 <h3 class="text-xl text-blue-200 font-medium">No players found</h3>302 <p class="text-blue-300 mt-2">Start tracking players by registering above</p>303 </div>304 </div>305 </div>306 307 <div class="p-4 bg-blue-900 bg-opacity-30 flex justify-between items-center">308 <div class="text-blue-200 text-sm">309 Showing <span id="showingFrom" class="font-bold">0</span>-<span id="showingTo" class="font-bold">0</span> of <span id="totalPlayers" class="font-bold">0</span> players310 </div>311 <div class="flex space-x-2">312 <button class="px-3 py-1 bg-blue-800 bg-opacity-50 text-blue-200 rounded hover:bg-blue-700 transition" disabled>313 <i class="fas fa-chevron-left"></i>314 </button>315 <button class="px-3 py-1 bg-blue-700 text-white rounded font-bold">316 1317 </button>318 <button class="px-3 py-1 bg-blue-800 bg-opacity-50 text-blue-200 rounded hover:bg-blue-700 transition" disabled>319 <i class="fas fa-chevron-right"></i>320 </button>321 </div>322 </div>323 </div>324 325 <!-- Coming Soon Modal -->326 <div id="comingSoonModal" class="modal-overlay hidden">327 <div class="modal-content relative">328 <button class="modal-close">×</button>329 <i class="fas fa-clock text-5xl text-blue-300 mb-4"></i>330 <h2 class="text-2xl font-bold text-white mb-2">Coming Soon!</h2>331 <p class="text-blue-200 mb-6">The registration feature will be available shortly. Stay tuned for updates!</p>332 <button class="btn-primary px-6 py-2 text-white rounded-lg font-semibold">333 Got it!334 </button>335 </div>336 </div>337 338 <!-- Edit Modal -->339 <div id="editModal" class="modal-overlay hidden">340 <div class="modal-content relative">341 <button class="modal-close">×</button>342 <i class="fas fa-user-edit text-4xl text-blue-300 mb-3"></i>343 <h2 class="text-xl font-bold text-white mb-3">Edit Player</h2>344 345 <form id="editForm">346 <div class="form-group">347 <label for="playerName" class="form-label">Player Name</label>348 <input type="text" id="playerName" class="form-input" required>349 <div id="nameError" class="error-message">Please enter a player name</div>350 </div>351 352 <div class="form-group">353 <label for="profilePic" class="form-label">Profile Picture URL</label>354 <input type="url" id="profilePic" class="form-input" required>355 <div id="picError" class="error-message">Please enter a valid URL</div>356 </div>357 358 <div class="form-group">359 <label for="playerPR" class="form-label">Player PR</label>360 <input type="number" id="playerPR" class="form-input" required>361 <div id="prError" class="error-message">Please enter a valid PR</div>362 </div>363 364 <div class="form-group">365 <label for="playerRank" class="form-label">Rank</label>366 <input type="number" id="playerRank" class="form-input" required>367 <div id="rankError" class="error-message">Please enter a valid rank</div>368 </div>369 370 <div class="form-group">371 <label for="playerRegion" class="form-label">Region</label>372 <select id="playerRegion" class="form-input" required>373 <option value="">Select Region</option>374 <option value="NA">North America</option>375 <option value="EU">Europe</option>376 <option value="AS">Asia</option>377 <option value="SA">South America</option>378 <option value="OC">Oceania</option>379 </select>380 <div id="regionError" class="error-message">Please select a region</div>381 </div>382 383 <div class="form-group">384 <label for="playerDevice" class="form-label">Device</label>385 <select id="playerDevice" class="form-input" required>386 <option value="">Select Device</option>387 <option value="Mobile">Mobile</option>388 <option value="PC">PC</option>389 <option value="Console">Console</option>390 </select>391 <div id="deviceError" class="error-message">Please select a device</div>392 </div>393 394 <div class="staff-password">395 <label for="staffPassword" class="staff-label">Password (Staff Only)</label>396 <input type="password" id="staffPassword" class="form-input mt-2" required>397 <div id="passwordError" class="error-message">Incorrect password</div>398 </div>399 400 <button type="submit" class="btn-primary px-6 py-2 text-white rounded-lg font-semibold mt-4 w-full">401 <i class="fas fa-check mr-2"></i> Finish402 </button>403 </form>404 </div>405 </div>406 407 <!-- Remove Password Modal -->408 <div id="removePasswordModal" class="modal-overlay hidden">409 <div class="password-modal relative">410 <button class="modal-close">×</button>411 <i class="fas fa-lock text-4xl text-blue-300 mb-3"></i>412 <h2 class="text-xl font-bold text-white mb-2">Confirm Removal</h2>413 <p class="text-blue-200 mb-4">Enter password to remove this player:</p>414 <input type="password" id="removePassword" class="password-input" placeholder="Enter password">415 <div id="removePasswordError" class="password-error">Incorrect password</div>416 <div class="flex space-x-4 mt-4">417 <button id="cancelRemove" class="px-4 py-2 bg-gray-600 text-white rounded-lg font-semibold flex-1">418 Cancel419 </button>420 <button id="confirmRemove" class="px-4 py-2 btn-remove text-white rounded-lg font-semibold flex-1">421 <i class="fas fa-trash-alt mr-2"></i> Remove422 </button>423 </div>424 </div>425 </div>426 427 <script>428 document.addEventListener('DOMContentLoaded', function() {429 const searchInput = document.getElementById('searchInput');430 const registerBtn = document.getElementById('registerBtn');431 const editBtn = document.getElementById('editBtn');432 const comingSoonModal = document.getElementById('comingSoonModal');433 const editModal = document.getElementById('editModal');434 const removePasswordModal = document.getElementById('removePasswordModal');435 const closeModals = document.querySelectorAll('.modal-close');436 const gotItBtn = document.querySelector('.comingSoonModal button');437 const editForm = document.getElementById('editForm');438 const leaderboardContent = document.getElementById('leaderboardContent');439 const showingFrom = document.getElementById('showingFrom');440 const showingTo = document.getElementById('showingTo');441 const totalPlayers = document.getElementById('totalPlayers');442 const cancelRemove = document.getElementById('cancelRemove');443 const confirmRemove = document.getElementById('confirmRemove');444 const removePassword = document.getElementById('removePassword');445 const removePasswordError = document.getElementById('removePasswordError');446 447 let players = [];448 let playerToRemove = null;449 450 // Search functionality451 searchInput.addEventListener('input', function() {452 const searchTerm = this.value.toLowerCase();453 const rows = leaderboardContent.querySelectorAll('.leaderboard-row');454 455 let visibleCount = 0;456 457 rows.forEach(row => {458 const playerName = row.querySelector('div:nth-child(2) span').textContent.toLowerCase();459 if (playerName.includes(searchTerm)) {460 row.classList.remove('hidden-row');461 visibleCount++;462 } else {463 row.classList.add('hidden-row');464 }465 });466 467 updateShowingCount(visibleCount);468 });469 470 // Register button opens modal471 registerBtn.addEventListener('click', function() {472 comingSoonModal.classList.remove('hidden');473 });474 475 // Edit button opens modal476 editBtn.addEventListener('click', function() {477 editModal.classList.remove('hidden');478 });479 480 // Close modals481 closeModals.forEach(btn => {482 btn.addEventListener('click', function() {483 comingSoonModal.classList.add('hidden');484 editModal.classList.add('hidden');485 removePasswordModal.classList.add('hidden');486 });487 });488 489 // Close modals when clicking outside490 [comingSoonModal, editModal, removePasswordModal].forEach(modal => {491 modal.addEventListener('click', function(e) {492 if (e.target === modal) {493 modal.classList.add('hidden');494 }495 });496 });497 498 // Cancel remove499 cancelRemove.addEventListener('click', function() {500 removePasswordModal.classList.add('hidden');501 playerToRemove = null;502 removePassword.value = '';503 removePasswordError.style.display = 'none';504 });505 506 // Confirm remove507 confirmRemove.addEventListener('click', function() {508 if (removePassword.value === "Sub2beargm!") {509 // Remove the player510 removePlayer(playerToRemove);511 removePasswordModal.classList.add('hidden');512 removePassword.value = '';513 removePasswordError.style.display = 'none';514 } else {515 removePasswordError.style.display = 'block';516 }517 });518 519 // Edit form submission520 editForm.addEventListener('submit', function(e) {521 e.preventDefault();522 523 // Reset error messages524 document.querySelectorAll('.error-message').forEach(el => {525 el.style.display = 'none';526 });527 528 // Validate form529 let isValid = true;530 const playerName = document.getElementById('playerName').value;531 const profilePic = document.getElementById('profilePic').value;532 const playerPR = document.getElementById('playerPR').value;533 const playerRank = document.getElementById('playerRank').value;534 const playerRegion = document.getElementById('playerRegion').value;535 const playerDevice = document.getElementById('playerDevice').value;536 const staffPassword = document.getElementById('staffPassword').value;537 538 if (!playerName) {539 document.getElementById('nameError').style.display = 'block';540 isValid = false;541 }542 543 if (!profilePic) {544 document.getElementById('picError').style.display = 'block';545 isValid = false;546 }547 548 if (!playerPR) {549 document.getElementById('prError').style.display = 'block';550 isValid = false;551 }552 553 if (!playerRank) {554 document.getElementById('rankError').style.display = 'block';555 isValid = false;556 }557 558 if (!playerRegion) {559 document.getElementById('regionError').style.display = 'block';560 isValid = false;561 }562 563 if (!playerDevice) {564 document.getElementById('deviceError').style.display = 'block';565 isValid = false;566 }567 568 // Check password569 if (staffPassword !== "Sub2beargm!") {570 document.getElementById('passwordError').style.display = 'block';571 isValid = false;572 }573 574 if (isValid) {575 // Add player to players array576 const newPlayer = {577 name: playerName,578 pic: profilePic,579 pr: playerPR,580 rank: playerRank,581 region: playerRegion,582 device: playerDevice583 };584 585 players.push(newPlayer);586 587 // Update leaderboard588 updateLeaderboard();589 590 // Close modal591 editModal.classList.add('hidden');592 593 // Reset form594 editForm.reset();595 }596 });597 598 function updateLeaderboard() {599 // Remove empty state if it exists600 if (leaderboardContent.querySelector('.py-12')) {601 leaderboardContent.innerHTML = '';602 }603 604 // Clear current leaderboard605 leaderboardContent.innerHTML = '';606 607 // Sort players by rank608 players.sort((a, b) => a.rank - b.rank);609 610 // Add players to leaderboard611 players.forEach(player => {612 const row = document.createElement('div');613 row.className = `leaderboard-row px-6 py-4 rank-${player.rank}`;614 615 row.innerHTML = `616 <div class="font-bold text-white">${player.rank}</div>617 <div class="flex items-center">618 <img src="${player.pic}" alt="${player.name}" class="w-10 h-10 rounded-full mr-3 object-cover">619 <span class="text-white font-medium">${player.name}</span>620 </div>621 <div class="text-blue-200">${player.pr} PR</div>622 <div class="text-blue-200">${player.region}</div>623 <div class="text-blue-200">${player.device}</div>624 <div class="flex justify-end">625 <button class="btn-remove px-3 py-1 text-white rounded text-sm flex items-center remove-btn" data-player="${player.name}">626 <i class="fas fa-trash-alt mr-1"></i> Remove627 </button>628 </div>629 `;630 631 // Add to leaderboard632 leaderboardContent.appendChild(row);633 });634 635 // Add event listeners to remove buttons636 document.querySelectorAll('.remove-btn').forEach(btn => {637 btn.addEventListener('click', function() {638 playerToRemove = this.getAttribute('data-player');639 removePasswordModal.classList.remove('hidden');640 });641 });642 643 // Update showing count644 updateShowingCount(players.length);645 }646 647 function removePlayer(playerName) {648 // Remove player from array649 players = players.filter(player => player.name !== playerName);650 651 // Update leaderboard652 updateLeaderboard();653 654 // If no players left, show empty state655 if (players.length === 0) {656 leaderboardContent.innerHTML = `657 <div class="py-12 text-center">658 <i class="fas fa-user-slash text-4xl text-blue-400 opacity-50 mb-4"></i>659 <h3 class="text-xl text-blue-200 font-medium">No players found</h3>660 <p class="text-blue-300 mt-2">Start tracking players by registering above</p>661 </div>662 `;663 664 updateShowingCount(0);665 }666 }667 668 function updateShowingCount(count) {669 showingFrom.textContent = count > 0 ? '1' : '0';670 showingTo.textContent = count;671 totalPlayers.textContent = count;672 }673 });674 </script>675</body>676</html>