diff --git a/public/css/mobile.css b/public/css/mobile.css index ccc5c87..41ab2e9 100644 --- a/public/css/mobile.css +++ b/public/css/mobile.css @@ -342,6 +342,27 @@ transform: rotate(180deg); } + /* Refresh button: hidden by default, revealed only when the card is open. + Larger than the desktop icon to give a comfortable touch target (≥44px). */ + .m-card__head .m-refresh-icon { + display: none; + } + + .m-card.is-open .m-card__head .m-refresh-icon { + display: grid; + width: 44px; + height: 44px; + margin-left: 0; + font-size: 15px; + opacity: 0.7; + flex-shrink: 0; + } + + .m-card.is-open .m-card__head .m-refresh-icon:active { + opacity: 1; + color: var(--accent); + } + .m-card__body { display: grid; grid-template-columns: minmax(0, 1fr) auto; diff --git a/public/js/players.js b/public/js/players.js index 7334ee4..ffd4024 100644 --- a/public/js/players.js +++ b/public/js/players.js @@ -131,10 +131,16 @@ async function clearCache() { // Refreshes both the current rating and the prediction in one click, then // re-swaps the table so every derived value (deltas, pills, sparkline) reflects // the new state. Cheaper than fine-grained DOM updates and guaranteed consistent -// because the server renders the truth. +// because the server renders the truth. The mobile cards partial is included +// inside ratings-table, so swapping #ratings-table re-renders both views at once. async function refreshPlayerData(pdgaNumber) { - const icon = document.querySelector(`#row-${pdgaNumber} .cell-actions .refresh-icon`); - if (icon) icon.classList.add('spinning'); + // The desktop row exists in the DOM even on mobile (hidden via CSS), so spin + // both possible icons; only the one visible in the active viewport is seen. + const icons = [ + document.querySelector(`#row-${pdgaNumber} .cell-actions .refresh-icon`), + document.querySelector(`#m-card-${pdgaNumber} .m-refresh-icon`) + ].filter(Boolean); + icons.forEach(icon => icon.classList.add('spinning')); try { await Promise.allSettled([ fetch(`/api/refresh-player/${pdgaNumber}`, { method: 'POST' }), @@ -144,7 +150,7 @@ async function refreshPlayerData(pdgaNumber) { } catch (error) { console.error('Error refreshing player data:', error); } finally { - if (icon) icon.classList.remove('spinning'); + icons.forEach(icon => icon.classList.remove('spinning')); } } diff --git a/views/partials/ratings-cards.ejs b/views/partials/ratings-cards.ejs index 009de31..eec74ad 100644 --- a/views/partials/ratings-cards.ejs +++ b/views/partials/ratings-cards.ejs @@ -65,6 +65,11 @@ function renderSparkline(values, opts) { <%= player.name %> #<%= player.pdgaNumber %> +