Files
pdga-rating/views/partials/ratings-cards.ejs
T
Samuel Enocsson 5791d8e34f refactor: move std-dev info to accordion, remove tooltip (#19)
- Add "Round spread" row (±stdDev, range lo–hi) to desktop accordion
  (player-history.ejs) and mobile card expanded section (ratings-cards.ejs)
- Remove .std-dev-tooltip div and .std-dev-inline span from table partial
- Remove stdDevTooltipText, updateStdDevInline, initRatingsTooltips helpers
  and all call sites from players.js
- Remove .std-dev-tooltip and .std-dev-inline CSS rules; drop cursor:help
  from .rating-value
2026-05-25 07:54:46 +02:00

129 lines
6.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<%
// Mobile sparkline helper — parametrised, used only in this partial
function renderSparkline(values, opts) {
opts = opts || {};
var w = opts.w || 70;
var h = opts.h || 26;
if (!values || values.length < 2) return '';
var min = Math.min.apply(null, values);
var max = Math.max.apply(null, values);
var range = max - min || 1;
var xStep = w / (values.length - 1);
var pts = values.map(function(v, i) {
return {
x: (i * xStep).toFixed(1),
y: (((max - v) / range) * (h - 4) + 2).toFixed(1)
};
});
var linePath = pts.map(function(p, i) {
return (i === 0 ? 'M' : 'L') + ' ' + p.x + ' ' + p.y;
}).join(' ');
var last = pts[pts.length - 1];
var areaPath = linePath + ' L ' + last.x + ' ' + h + ' L 0 ' + h + ' Z';
return '<svg width="' + w + '" height="' + h + '" viewBox="0 0 ' + w + ' ' + h + '" class="m-chart-spark" aria-hidden="true">' +
'<path d="' + areaPath + '" style="fill:var(--accent);fill-opacity:0.10"/>' +
'<path d="' + linePath + '" style="stroke:var(--accent);stroke-width:1.5;fill:none;stroke-linejoin:round;stroke-linecap:round"/>' +
'<circle cx="' + last.x + '" cy="' + last.y + '" r="2.5" style="fill:var(--accent)"/>' +
'</svg>';
}
%>
<% if (ratings.length === 0) { %>
<p style="text-align: center; color: var(--ink-3); padding: 40px 0;">No players tracked yet.</p>
<% } else { %>
<div class="mobile-section-head">
<span class="kicker">TRACKED PLAYERS &middot; <%= ratings.length %></span>
<button id="trendchart-toggle-mobile" class="pill-button" type="button" aria-pressed="false">Trend chart</button>
</div>
<div class="mobile-list">
<% ratings.forEach(function(player, index) {
var sparkSvg = renderSparkline(player.monthlyHistory || [], { w: 70, h: 26 });
var isFirst = index === 0;
var rank = index + 1;
var ratingIsNull = (player.rating == null);
var ratingCls = ratingIsNull ? 'flat' : (player.ratingChange > 0 ? 'up' : player.ratingChange < 0 ? 'down' : 'flat');
var ratingGlyph = (ratingIsNull || player.ratingChange === 0) ? '' : (player.ratingChange > 0 ? '▲' : '▼');
var ratingNum = ratingIsNull ? '—' : (player.ratingChange > 0 ? '+' + player.ratingChange : String(player.ratingChange));
var predIsNull = (player.predictedRating == null);
var predCls = predIsNull ? 'flat' : (player.deltaPredicted > 0 ? 'up' : player.deltaPredicted < 0 ? 'down' : 'flat');
var predGlyph = (predIsNull || player.deltaPredicted === 0) ? '' : (player.deltaPredicted > 0 ? '▲' : '▼');
var predNum = predIsNull ? '—' : (player.deltaPredicted > 0 ? '+' + player.deltaPredicted : String(player.deltaPredicted));
%>
<div class="m-card" id="m-card-<%= player.pdgaNumber %>"
tabindex="0" role="button" aria-expanded="false" aria-label="Expand player details"
onclick="toggleMobilePlayerCard(<%= player.pdgaNumber %>)"
onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();toggleMobilePlayerCard(<%= player.pdgaNumber %>);}">
<div class="m-card__head">
<div class="m-rank-chip<%= isFirst ? ' m-rank-chip--first' : '' %>"><%= rank %></div>
<div class="m-card__name-stack">
<span class="m-player-name"><%= player.name %></span>
<span class="m-pdga-num">#<%= player.pdgaNumber %></span>
</div>
<span class="m-chevron">&#9660;</span>
</div>
<div class="m-card__body">
<div class="m-card__stats">
<div class="m-stat-row">
<span class="m-stat-label">RATING</span>
<span class="m-num"><%= player.rating || '—' %></span>
<span class="delta-pill <%= ratingCls %>"><span class="delta-glyph"><%= ratingGlyph %></span><span class="delta-num"><%= ratingNum %></span></span>
</div>
<div class="m-stat-row">
<span class="m-stat-label">PREDICTED</span>
<span class="m-num m-num--predicted"><%= player.predictedRating || '—' %></span>
<span class="delta-pill <%= predCls %> delta-predicted-pill"><span class="delta-glyph"><%= predGlyph %></span><span class="delta-num"><%= predNum %></span></span>
</div>
</div>
<% if (sparkSvg) { %>
<div class="m-card__sparkline"><span class="sparkline"><%- sparkSvg %></span></div>
<% } %>
</div>
<div class="m-card__expand">
<% if (player.ratingHistory && player.ratingHistory.length > 0) { %>
<div class="player-chart m-chart"
data-variant="mobile"
data-history="<%= JSON.stringify(player.ratingHistory) %>">
</div>
<% } %>
<dl class="m-detail-grid">
<div>
<dt>Current rating</dt>
<dd><%= player.rating || '—' %></dd>
</div>
<div>
<dt>Last month</dt>
<dd><%= player.lastMonthRating || '—' %></dd>
</div>
<div>
<dt>Change vs last month</dt>
<dd><span class="delta-pill <%= ratingCls %>"><span class="delta-glyph"><%= ratingGlyph %></span><span class="delta-num"><%= ratingNum %></span></span></dd>
</div>
<div>
<dt>Predicted next update</dt>
<dd><%= player.predictedRating || '—' %></dd>
</div>
<div>
<dt>Gap to predicted</dt>
<dd><span class="delta-pill <%= predCls %> delta-predicted-pill"><span class="delta-glyph"><%= predGlyph %></span><span class="delta-num"><%= predNum %></span></span></dd>
</div>
<% if (player.stdDev != null && player.rating) { %>
<div>
<dt>Round spread</dt>
<dd>±<%= player.stdDev %> (range <%= player.rating - player.stdDev %><%= player.rating + player.stdDev %>)</dd>
</div>
<% } %>
</dl>
</div>
</div>
<% }); %>
</div>
<% } %>