feat: power play indicator with live countdown clock
Shows a red pill below the team rows when a PP is active, displaying the team on the power play and a ticking countdown. PP clock always resyncs from the API (no local anchoring) since 2-minute penalties are short enough that accuracy matters throughout. Removed the old inline PP text from team rows. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -73,6 +73,7 @@ function renderLiveGame(game) {
|
||||
</div>
|
||||
${teamRow(game, 'Away', 'live')}
|
||||
${teamRow(game, 'Home', 'live')}
|
||||
${ppIndicator(game)}
|
||||
${hype}
|
||||
</div>`;
|
||||
}
|
||||
@@ -112,12 +113,10 @@ function teamRow(game, side, state) {
|
||||
const logo = game[`${side} Logo`];
|
||||
const score = game[`${side} Score`];
|
||||
const sog = game[`${side} Shots`];
|
||||
const pp = game[`${side} Power Play`];
|
||||
const record = game[`${side} Record`];
|
||||
|
||||
const sogHtml = (state === 'live' || state === 'final') && sog !== undefined
|
||||
? `<span class="team-sog">${sog} SOG</span>` : '';
|
||||
const ppHtml = pp ? `<span class="team-pp">${pp}</span>` : '';
|
||||
|
||||
const right = state === 'pre'
|
||||
? `<span class="team-record">${record}</span>`
|
||||
@@ -128,12 +127,31 @@ function teamRow(game, side, state) {
|
||||
<img src="${logo}" alt="${name} logo" class="team-logo">
|
||||
<div class="team-meta">
|
||||
<span class="team-name">${name}</span>
|
||||
${sogHtml}${ppHtml}
|
||||
${sogHtml}
|
||||
</div>
|
||||
${right}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function ppIndicator(game) {
|
||||
const awayPP = game['Away Power Play'];
|
||||
const homePP = game['Home Power Play'];
|
||||
const pp = awayPP || homePP;
|
||||
if (!pp) return '';
|
||||
|
||||
const team = awayPP ? game['Away Team'] : game['Home Team'];
|
||||
const timeStr = pp.replace('PP ', '');
|
||||
const seconds = timeToSeconds(timeStr);
|
||||
const attrs = `data-seconds="${seconds}" data-received-at="${Date.now()}" data-pp-clock`;
|
||||
|
||||
return `
|
||||
<div class="pp-indicator">
|
||||
<span class="pp-label">PP</span>
|
||||
<span class="pp-team">${team}</span>
|
||||
<span class="pp-clock" ${attrs}>${timeStr}</span>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// ── Gauge ────────────────────────────────────────────
|
||||
|
||||
function updateGauges() {
|
||||
@@ -166,7 +184,7 @@ function secondsToTime(s) {
|
||||
function snapshotClocks(grid) {
|
||||
const snapshot = new Map();
|
||||
grid.querySelectorAll('[data-game-key]').forEach(card => {
|
||||
const badge = card.querySelector('[data-seconds][data-received-at]');
|
||||
const badge = card.querySelector('[data-seconds][data-received-at]:not([data-pp-clock])');
|
||||
if (!badge) return;
|
||||
const seconds = parseInt(badge.dataset.seconds, 10);
|
||||
const receivedAt = parseInt(badge.dataset.receivedAt, 10);
|
||||
@@ -181,7 +199,7 @@ function restoreClocks(grid, snapshot) {
|
||||
grid.querySelectorAll('[data-game-key]').forEach(card => {
|
||||
const prior = snapshot.get(card.dataset.gameKey);
|
||||
if (!prior) return;
|
||||
const badge = card.querySelector('[data-seconds][data-received-at]');
|
||||
const badge = card.querySelector('[data-seconds][data-received-at]:not([data-pp-clock])');
|
||||
if (!badge) return;
|
||||
// Only restore if we're outside the final sync window
|
||||
if (prior.current > CLOCK_SYNC_THRESHOLD) {
|
||||
|
||||
Reference in New Issue
Block a user