feat: players page redesign — deltas, KPI tiles, sparklines, expanded row #9
+4
-1
@@ -1,10 +1,13 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { getTopbarLocals } = require('../services/topbar-service');
|
||||
const { getAllRatingsFromDB, computeKpis } = require('../services/player-service');
|
||||
|
||||
router.get('/', async (req, res) => {
|
||||
const topbar = await getTopbarLocals();
|
||||
res.render('index', { activePage: 'players', ...topbar });
|
||||
const players = await getAllRatingsFromDB();
|
||||
const kpis = computeKpis(players);
|
||||
res.render('index', { activePage: 'players', kpis, ...topbar });
|
||||
});
|
||||
|
||||
router.get('/courses', async (req, res) => {
|
||||
|
||||
@@ -292,10 +292,30 @@ async function refreshAllPlayersInDB(progressCallback = null) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregates KPI summary stats from an already-fetched player array.
|
||||
* All fields are derived from the player list — no extra DB queries.
|
||||
*/
|
||||
function computeKpis(players) {
|
||||
const active = players.filter(p => p.rating != null && p.rating > 0);
|
||||
const avg = active.length > 0
|
||||
? Math.round(active.reduce((sum, p) => sum + p.rating, 0) / active.length)
|
||||
: null;
|
||||
|
||||
return {
|
||||
tracked: players.length,
|
||||
active: active.length,
|
||||
avg,
|
||||
climbing: players.filter(p => p.ratingChange != null && p.ratingChange > 0).length,
|
||||
slipping: players.filter(p => p.ratingChange != null && p.ratingChange < 0).length
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getPlayerDataFromDB,
|
||||
scrapePDGARating,
|
||||
getPredictedRatingFromDB,
|
||||
getAllRatingsFromDB,
|
||||
refreshAllPlayersInDB
|
||||
refreshAllPlayersInDB,
|
||||
computeKpis
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user