Skip to content

Commit 8f90fca

Browse files
committed
change how leaderboards are loaded
1 parent 0be4a7b commit 8f90fca

1 file changed

Lines changed: 103 additions & 40 deletions

File tree

public_html/rpcn-game.php

Lines changed: 103 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ function rpcn_build_svg(array $data, string $gradId): string
104104
return $out;
105105
}
106106

107-
// Pre-compute all chart ranges
107+
// Pre-compute all chart ranges
108108
$chartPeriodsMeta = ['48h' => '48H', '1w' => '1W', '1m' => '1M', '3m' => '3M', '6m' => '6M', '1y' => '1Y'];
109109
$chartSvgs = [];
110110
foreach ($chartPeriodsMeta as $key => $label) {
@@ -114,19 +114,10 @@ function rpcn_build_svg(array $data, string $gradId): string
114114
$chartSvgs[$key] = rpcn_build_svg($filtered, 'rpcn-grad-' . $key);
115115
}
116116

117-
// Pre-render leaderboard boards server-side
118-
$boardContents = [];
119-
$autoShowBoard = null;
120-
if ($hasLeaderboard && !empty($boards)) {
121-
foreach ($boards as $boardId => $boardName) {
122-
ob_start();
123-
$rpcn_game->handle_ajax($commId, (string)$boardId);
124-
$boardContents[(int)$boardId] = ob_get_clean();
125-
}
126-
if (count($boards) === 1) {
127-
$autoShowBoard = (int)array_key_first($boards);
128-
}
129-
}
117+
// Leaderboard boards
118+
$autoShowBoard = ($hasLeaderboard && !empty($boards) && count($boards) === 1)
119+
? (int)array_key_first($boards)
120+
: null;
130121
?>
131122
<!DOCTYPE html>
132123
<html lang="en">
@@ -468,13 +459,8 @@ function rpcn_build_svg(array $data, string $gradId): string
468459
transform: translateY(-1px);
469460
}
470461

471-
/* Board selection & views */
472-
#rpcn-board-selection { display: none; }
473-
.rpcn-board-view { display: none; }
474-
#board-list:checked ~ #rpcn-board-selection { display: block; }
475-
<?php foreach (array_keys($boardContents) as $bid): ?>
476-
#board-<?= (int)$bid ?>:checked ~ #board-view-<?= (int)$bid ?> { display: block; }
477-
<?php endforeach; ?>
462+
/* Board selection & view panes */
463+
#rpcn-board-view { display: none; }
478464

479465
.rpcn-btn-back-lb {
480466
display: inline-flex;
@@ -540,6 +526,28 @@ function rpcn_build_svg(array $data, string $gradId): string
540526
}
541527
.rpcn-no-scores { color: var(--rpcn-subtle); padding: 20px 0; text-align: center; font-style: italic; }
542528

529+
/* Loading spinner */
530+
.rpcn-lb-loading {
531+
display: flex;
532+
align-items: center;
533+
justify-content: center;
534+
gap: 10px;
535+
padding: 50px 0;
536+
color: var(--rpcn-muted);
537+
font-size: .88rem;
538+
}
539+
.rpcn-lb-loading::before {
540+
content: '';
541+
width: 18px;
542+
height: 18px;
543+
border: 2px solid var(--rpcn-border);
544+
border-top: 2px solid var(--rpcn-accent);
545+
border-radius: 50%;
546+
animation: rpcn-spin .7s linear infinite;
547+
flex-shrink: 0;
548+
}
549+
@keyframes rpcn-spin { to { transform: rotate(360deg); } }
550+
543551
@media (max-width: 640px) {
544552
.rpcn-game { flex-direction: column; }
545553
.rpcn-game-icon,
@@ -559,8 +567,8 @@ function rpcn_build_svg(array $data, string $gradId): string
559567
<!-- Game header -->
560568
<div class="rpcn-game">
561569
<div class="rpcn-game-icon-wrap">
562-
<img src="<?= htmlspecialchars($gameIcon) ?>"
563-
alt="Game Icon"
570+
<img src="<?= htmlspecialchars($gameIcon) ?>"
571+
alt="Game Icon"
564572
class="rpcn-game-icon"
565573
onerror="this.src='/cdn/rpcn/icon0/default.png'">
566574
</div>
@@ -637,43 +645,98 @@ class="rpcn-game-icon"
637645

638646
</div><!-- /#panel-charts -->
639647

640-
<!-- Leaderboards tab -->
641-
<?php if ($hasLeaderboard && !empty($boardContents)): ?>
648+
<!-- Leaderboards tab -->
649+
<?php if ($hasLeaderboard && !empty($boards)): ?>
642650
<div id="panel-lb" class="rpcn-tab-panel">
643651

644-
<input type="radio" name="rpcn-board" id="board-list" class="rpcn-sr"
645-
<?= $autoShowBoard === null ? 'checked' : '' ?>>
646-
<?php foreach (array_keys($boardContents) as $bid): ?>
647-
<input type="radio" name="rpcn-board" id="board-<?= (int)$bid ?>" class="rpcn-sr"
648-
<?= $autoShowBoard === (int)$bid ? 'checked' : '' ?>>
649-
<?php endforeach; ?>
650-
651652
<!-- Board selection grid -->
652653
<div id="rpcn-board-selection">
654+
<?php if (count($boards) > 1): ?>
653655
<p class="rpcn-lb-section-title">Choose Scoreboard</p>
656+
<?php endif; ?>
654657
<div class="rpcn-board-grid">
655658
<?php foreach ($boards as $boardId => $boardName): ?>
656-
<label for="board-<?= (int)$boardId ?>" class="rpcn-board-btn">
659+
<button class="rpcn-board-btn"
660+
data-board-id="<?= (int)$boardId ?>"
661+
data-board-name="<?= htmlspecialchars($boardName) ?>">
657662
<?= htmlspecialchars($boardName) ?>
658-
</label>
663+
</button>
659664
<?php endforeach; ?>
660665
</div>
661666
</div>
662667

663-
<?php foreach ($boardContents as $bid => $content): ?>
664-
<div id="board-view-<?= (int)$bid ?>" class="rpcn-board-view">
665-
<?php if ($autoShowBoard === null): ?>
666-
<label for="board-list" class="rpcn-btn-back-lb">Back to boards</label>
668+
<!-- Board content pane (shown after a board is selected) -->
669+
<div id="rpcn-board-view">
670+
<?php if (count($boards) > 1): ?>
671+
<button class="rpcn-btn-back-lb" id="rpcn-back-lb">&#8592; Back to boards</button>
667672
<?php endif; ?>
668-
<?= $content ?>
673+
<div id="rpcn-board-content"></div>
669674
</div>
670-
<?php endforeach; ?>
671675

672676
</div><!-- /#panel-lb -->
673677
<?php endif; ?>
674678

675679
</div><!-- /.rpcn-tab-panels -->
676680

677681
</div><!-- /.rpcn-page-wrap -->
682+
<script>
683+
(function () {
684+
const commId = <?= json_encode($commId) ?>;
685+
const autoBoard = <?= json_encode($autoShowBoard) ?>;
686+
const multiBoard = <?= json_encode(count($boards) > 1) ?>;
687+
688+
const selection = document.getElementById('rpcn-board-selection');
689+
const view = document.getElementById('rpcn-board-view');
690+
const content = document.getElementById('rpcn-board-content');
691+
const backBtn = document.getElementById('rpcn-back-lb');
692+
693+
if (!selection || !view || !content) return;
694+
695+
function loadBoard(boardId) {
696+
selection.style.display = 'none';
697+
view.style.display = 'block';
698+
content.innerHTML = '<div class="rpcn-lb-loading">Loading scores</div>';
699+
700+
fetch('rpcn-game.php?comm_id=' + encodeURIComponent(commId) + '&ajax=1&board_id=' + encodeURIComponent(boardId))
701+
.then(function (r) {
702+
if (!r.ok) throw new Error('HTTP ' + r.status);
703+
return r.text();
704+
})
705+
.then(function (html) {
706+
content.innerHTML = html;
707+
})
708+
.catch(function () {
709+
content.innerHTML = "<p class='rpcn-error'>Failed to load scores. Please try again.</p>";
710+
});
711+
}
712+
713+
document.querySelectorAll('.rpcn-board-btn').forEach(function (btn) {
714+
btn.addEventListener('click', function () {
715+
loadBoard(btn.dataset.boardId);
716+
});
717+
});
718+
719+
// Back button
720+
if (backBtn) {
721+
backBtn.addEventListener('click', function () {
722+
view.style.display = 'none';
723+
content.innerHTML = '';
724+
selection.style.display = 'block';
725+
});
726+
}
727+
728+
// Autoload when there is only one board
729+
if (autoBoard !== null) {
730+
// Trigger when user switches to the Leaderboards tab
731+
var tabLb = document.getElementById('tab-lb');
732+
if (tabLb) {
733+
var loaded = false;
734+
tabLb.addEventListener('change', function () {
735+
if (!loaded) { loaded = true; loadBoard(autoBoard); }
736+
});
737+
}
738+
}
739+
})();
740+
</script>
678741
</body>
679742
</html>

0 commit comments

Comments
 (0)