feat: add monthlyHistory[] per player via getMonthlyHistory + bulk fetch (#6)

Add getMonthlyHistory() to models/player for single-player use and
getAllMonthlyHistoriesFromDB() for bulk fetches (one query, grouped in
memory). Wire monthlyHistory into all player objects returned by
getPlayerDataFromDB and getAllRatingsFromDB. Bulk path pre-fetches in
one query to avoid N extra per-player queries.
This commit is contained in:
Samuel Enocsson
2026-05-21 13:41:20 +02:00
parent 19756b80e5
commit 3dcd3131a0
5 changed files with 161 additions and 42 deletions
+41
View File
@@ -551,3 +551,44 @@ a:hover {
padding: 8px 6px;
}
}
/* ── Delta Pills ──────────────────────────────── */
.delta-pill {
display: inline-flex;
align-items: center;
padding: 2px 8px;
border-radius: 999px;
font-family: var(--font-mono);
font-feature-settings: "tnum", "zero";
font-size: 11px;
font-weight: 500;
margin-top: 4px;
}
.delta-pill.up {
background: var(--up-soft);
color: var(--up);
}
.delta-pill.down {
background: var(--down-soft);
color: var(--down);
}
.delta-pill.flat {
background: oklch(0.95 0.004 260);
color: var(--ink-3);
}
/* ── Table Header Hints ───────────────────────── */
.th-hint {
display: block;
font-size: 9.5px;
font-weight: 400;
text-transform: none;
letter-spacing: 0;
color: var(--ink-3);
margin-top: 2px;
}
+7 -13
View File
@@ -96,16 +96,10 @@ async function refreshPlayer(pdgaNumber) {
if (data.success) {
const row = document.getElementById(`row-${pdgaNumber}`);
const ratingCell = row.querySelector('.rating');
const ratingChangeCell = row.querySelector('.rating-change');
const nameLink = row.querySelector('.player-name a');
nameLink.textContent = data.player.name;
const ratingChangeText = data.player.ratingChange ?
(data.player.ratingChange > 0 ? `+${data.player.ratingChange}` : data.player.ratingChange.toString()) : 'N/A';
const ratingChangeClass = data.player.ratingChange > 0 ? 'positive' :
data.player.ratingChange < 0 ? 'negative' : 'neutral';
const ratingValue = ratingCell.querySelector('.rating-value');
if (ratingValue) {
ratingValue.textContent = data.player.rating || 'N/A';
@@ -122,13 +116,13 @@ async function refreshPlayer(pdgaNumber) {
}
}
if (ratingChangeCell) ratingChangeCell.textContent = ratingChangeText;
if (ratingChangeCell) ratingChangeCell.className = `rating-change ${ratingChangeClass} mobile-hide`;
const mobileChange = ratingCell.querySelector('.mobile-only.rating-change');
if (mobileChange) {
mobileChange.textContent = ratingChangeText;
mobileChange.className = `mobile-only rating-change ${ratingChangeClass}`;
const deltaMonthPill = ratingCell.querySelector('.delta-pill');
if (deltaMonthPill && data.player.ratingChange != null) {
const pillChange = data.player.ratingChange;
const pillText = pillChange > 0 ? `+${pillChange}` : pillChange.toString();
const pillClass = pillChange > 0 ? 'up' : pillChange < 0 ? 'down' : 'flat';
deltaMonthPill.textContent = pillText;
deltaMonthPill.className = `delta-pill ${pillClass}`;
}
}
} catch (error) {