fix: address code review for visual layer + topbar (#4)
This commit is contained in:
@@ -72,6 +72,9 @@
|
||||
--shadow-overlay: 0 20px 60px rgba(15, 23, 42, 0.15), 0 4px 12px rgba(15, 23, 42, 0.08);
|
||||
|
||||
--transition: 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
/* Topbar dimensions (used by sticky thead) */
|
||||
--topbar-height: 64px;
|
||||
}
|
||||
|
||||
/* ── Reset & Base ─────────────────────────────── */
|
||||
@@ -279,6 +282,7 @@ body {
|
||||
}
|
||||
|
||||
@media (max-width: 880px) {
|
||||
:root { --topbar-height: 56px; }
|
||||
.topbar__inner { padding: 10px 16px; gap: 10px; }
|
||||
.topbar__meta-item, .topbar__divider { display: none; }
|
||||
.topbar__refresh-label { display: none; }
|
||||
@@ -322,7 +326,7 @@ table {
|
||||
|
||||
thead {
|
||||
position: sticky;
|
||||
top: 56px;
|
||||
top: var(--topbar-height);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
@@ -547,7 +551,7 @@ a:hover {
|
||||
}
|
||||
|
||||
thead {
|
||||
top: 56px;
|
||||
top: var(--topbar-height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ app.set('view engine', 'ejs');
|
||||
app.set('views', path.join(__dirname, 'views/pages'));
|
||||
app.use(express.static('public'));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
|
||||
app.use(playerRoutes);
|
||||
app.use(courseRoutes);
|
||||
|
||||
@@ -185,15 +185,17 @@ function savePredictedRatingToDB(pdgaNumber, predictedRating, stdDev = null) {
|
||||
});
|
||||
}
|
||||
|
||||
function getLastRefresh(callback) {
|
||||
function getLastRefresh() {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.get(
|
||||
'SELECT MAX(last_updated) AS lastRefresh FROM players',
|
||||
[],
|
||||
(err, row) => {
|
||||
if (err) return callback(err);
|
||||
callback(null, row ? row.lastRefresh : null);
|
||||
if (err) reject(err);
|
||||
else resolve(row ? row.lastRefresh : null);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -12,21 +12,26 @@ const logger = require('../logger');
|
||||
|
||||
let refreshInProgress = false;
|
||||
|
||||
router.post('/api/refresh-all', async (req, res) => {
|
||||
router.post('/api/refresh-all', async (req, res, next) => {
|
||||
if (refreshInProgress) {
|
||||
logger.info('refresh-all already in progress, rejecting');
|
||||
return res.status(409).json({ error: 'Refresh already in progress' });
|
||||
}
|
||||
refreshInProgress = true;
|
||||
try {
|
||||
try {
|
||||
await refreshAllPlayersInDB();
|
||||
} catch (err) {
|
||||
logger.error({ err }, 'refresh-all failed');
|
||||
}
|
||||
const page = req.body?.page === 'courses' ? 'courses' : 'players';
|
||||
const locals = await getTopbarLocals();
|
||||
res.render('../partials/topbar', { activePage: page, ...locals });
|
||||
} catch (err) {
|
||||
next(err);
|
||||
} finally {
|
||||
refreshInProgress = false;
|
||||
}
|
||||
const locals = await getTopbarLocals();
|
||||
res.render('../partials/topbar', { activePage: req.query.page || 'players', ...locals });
|
||||
});
|
||||
|
||||
router.get('/partials/ratings-table', async (req, res) => {
|
||||
|
||||
@@ -32,9 +32,7 @@ function computeNextUpdate(now = new Date()) {
|
||||
|
||||
async function getTopbarLocals() {
|
||||
try {
|
||||
const lastIso = await new Promise((resolve, reject) => {
|
||||
getLastRefresh((err, val) => (err ? reject(err) : resolve(val)));
|
||||
});
|
||||
const lastIso = await getLastRefresh();
|
||||
return { lastRefresh: formatRelative(lastIso), nextUpdate: computeNextUpdate() };
|
||||
} catch (err) {
|
||||
logger.warn({ err }, 'topbar locals fallback');
|
||||
@@ -42,4 +40,4 @@ async function getTopbarLocals() {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getTopbarLocals, formatRelative, computeNextUpdate };
|
||||
module.exports = { getTopbarLocals };
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
<%- include('../partials/layout', {
|
||||
title: 'PDGA Courses - Sweden',
|
||||
heading: 'PDGA Courses - Sweden',
|
||||
activePage: 'courses',
|
||||
cssFiles: ['courses.css'],
|
||||
jsFiles: ['courses.js'],
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
|
||||
<%- include('../partials/layout', {
|
||||
title: 'PDGA Ratings',
|
||||
heading: 'PDGA Player Ratings',
|
||||
activePage: 'players',
|
||||
cssFiles: ['players.css'],
|
||||
jsFiles: ['tooltips.js', 'chart.js', 'progress.js', 'players.js'],
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
class="topbar__refresh"
|
||||
type="button"
|
||||
hx-post="/api/refresh-all"
|
||||
hx-vals='{"page": "<%= activePage %>"}'
|
||||
hx-target="#topbar"
|
||||
hx-swap="outerHTML"
|
||||
hx-disabled-elt="this"
|
||||
|
||||
Reference in New Issue
Block a user