feat: render sparklines + wire trend-chart pill toggle (#6)
This commit is contained in:
@@ -19,6 +19,15 @@
|
||||
<div style="display: flex; justify-content: flex-end; gap: 12px; margin-bottom: 16px;">
|
||||
<a href="#" onclick="clearCache(); return false;" style="color: var(--text-muted); font-size: 12px; text-decoration: none; opacity: 0.4;" title="Clear cache"><i class="fas fa-cog"></i></a>
|
||||
</div>
|
||||
<div class="table-toolbar">
|
||||
<button id="trendchart-toggle" class="pill-toggle" type="button" aria-pressed="false">
|
||||
<svg class="pill-icon" width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
||||
<polyline points="1,9 4,5 7,7 11,2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
<span class="pill-label">Trend chart</span>
|
||||
<span class="pill-dot"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="ratings-table" hx-get="/partials/ratings-table" hx-trigger="load"></div>
|
||||
`; %>
|
||||
|
||||
|
||||
@@ -1,3 +1,33 @@
|
||||
<%
|
||||
function renderSparkline(values) {
|
||||
if (!values || values.length < 2) return '';
|
||||
var w = 96, h = 28;
|
||||
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 + '" style="display:block;overflow:visible">' +
|
||||
'<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(--text-muted); padding: 40px 0;">No ratings found.</p>
|
||||
<% } else { %>
|
||||
@@ -20,6 +50,8 @@
|
||||
var deltaPredicted = player.deltaPredicted ?? null;
|
||||
var deltaPredictedPillText = deltaPredicted != null ? (deltaPredicted > 0 ? '+' + deltaPredicted : deltaPredicted.toString()) : null;
|
||||
var deltaPredictedPillClass = deltaPredicted > 0 ? 'up' : deltaPredicted < 0 ? 'down' : 'flat';
|
||||
|
||||
var sparklineSvg = renderSparkline(player.monthlyHistory || []);
|
||||
%>
|
||||
<tr id="row-<%= player.pdgaNumber %>" class="expandable-row" onclick="togglePlayerHistory(<%= player.pdgaNumber %>)">
|
||||
<td class="mobile-hide"><%= index + 1 %></td>
|
||||
@@ -36,6 +68,9 @@
|
||||
<% if (ratingChangePillText) { %>
|
||||
<span class="delta-pill <%= ratingChangePillClass %>"><%= ratingChangePillText %></span>
|
||||
<% } %>
|
||||
<% if (sparklineSvg) { %>
|
||||
<span class="sparkline"><%- sparklineSvg %></span>
|
||||
<% } %>
|
||||
<div class="std-dev-tooltip" id="tooltip-rating-<%= player.pdgaNumber %>"></div>
|
||||
</td>
|
||||
<td class="predicted-rating mobile-hide" id="predicted-<%= player.pdgaNumber %>">
|
||||
|
||||
Reference in New Issue
Block a user