diff --git a/public/js/players.js b/public/js/players.js index a240457..2aa59fd 100644 --- a/public/js/players.js +++ b/public/js/players.js @@ -135,10 +135,23 @@ async function clearCache() { } } -async function refreshPlayer(pdgaNumber) { +// Refreshes both the current rating and the prediction in one click. +// The single refresh button in the actions cell is wired to this wrapper +// (design has only one icon; we used to have two separate refresh buttons). +async function refreshPlayerData(pdgaNumber) { const icon = document.querySelector(`#row-${pdgaNumber} .cell-actions .refresh-icon`); if (icon) icon.classList.add('spinning'); + try { + await Promise.allSettled([ + refreshPlayer(pdgaNumber), + refreshRoundHistory(pdgaNumber) + ]); + } finally { + if (icon) icon.classList.remove('spinning'); + } +} +async function refreshPlayer(pdgaNumber) { try { const response = await fetch(`/api/refresh-player/${pdgaNumber}`, { method: 'POST' }); const data = await response.json(); @@ -172,15 +185,10 @@ async function refreshPlayer(pdgaNumber) { } catch (error) { console.error('Error refreshing player:', error); alert('Failed to refresh player data'); - } finally { - if (icon) icon.classList.remove('spinning'); } } async function refreshRoundHistory(pdgaNumber) { - const icon = document.querySelector(`#row-${pdgaNumber} .cell-actions .refresh-icon`); - if (icon) icon.classList.add('spinning'); - try { const response = await fetch(`/api/refresh-round-history/${pdgaNumber}`, { method: 'POST' }); const data = await response.json(); @@ -226,37 +234,10 @@ async function refreshRoundHistory(pdgaNumber) { } } } catch (error) { + // Rate-limited or scrape failure — common when refresh runs alongside the + // current-rating refresh. Log but don't alert; the user-facing surface is + // the spinner stopping (data may or may not have updated). console.error('Error refreshing round history:', error); - - let errorMessage = 'Failed to refresh prediction data'; - let errorDetails = ''; - - try { - const errorData = JSON.parse(error.message); - errorMessage = errorData.error || errorMessage; - - if (errorData.message) { - errorDetails = errorData.message; - } else { - errorDetails = errorData.details || ''; - if (errorData.suggestion) { - errorDetails += '\n\nSuggestion: ' + errorData.suggestion; - } - if (errorData.errorType) { - errorDetails += '\n\nError Type: ' + errorData.errorType; - } - if (errorData.timestamp) { - errorDetails += '\n\nTime: ' + new Date(errorData.timestamp).toLocaleString(); - } - } - } catch (parseError) { - errorDetails = error.message; - } - - const fullMessage = errorDetails ? errorMessage + '\n\n' + errorDetails : errorMessage; - alert(fullMessage); - } finally { - if (icon) icon.classList.remove('spinning'); } } diff --git a/views/partials/ratings-table.ejs b/views/partials/ratings-table.ejs index 0ebbacd..5fc0783 100644 --- a/views/partials/ratings-table.ejs +++ b/views/partials/ratings-table.ejs @@ -79,7 +79,7 @@ function renderSparkline(values) {