A few weeks ago I wrote about keeping the league table readable when the signal at the ground disappears. The fixtures list had the same problem, plus one of its own: people only ever want the next game, and they want it before they scroll. The list I was copying the layout from is the one on https://baduzah-celtics.co.za/, where upcoming matches and finished ones sit in the same feed, so I had to split them myself.
The data is an array of matches with an ISO kick-off time, home and away names, and a score that is null until the game is played. Around thirty rows for a season. Small enough that I never bothered with IndexedDB.
Splitting past and upcoming
My first attempt compared kick-off strings to new Date().toISOString(). It mostly worked, which is the worst kind of working. A match that kicked off at 15:00 dropped into "played" at 15:00 exactly, while the score was still null for another two hours, and the top of the page showed nothing at all during the game.
Now a match counts as upcoming until it has a score or is more than three hours past kick-off:
const THREE_HOURS = 3 * 60 * 60 * 1000;
function isUpcoming(match, now = Date.now()) {
if (match.score !== null) return false;
return new Date(match.kickoff).getTime() + THREE_HOURS > now;
}
const upcoming = matches.filter(m => isUpcoming(m))
.sort((a, b) => new Date(a.kickoff) - new Date(b.kickoff));
const next = upcoming[0];
next gets its own card above the list, with the date written out in words. Everything else renders below in the usual rows.
The cache bit
Same pattern as the table: fetch with a four second timeout, save the raw JSON to localStorage with a timestamp, fall back to the saved copy when the request fails. Two changes this time.
I save the fetch time and the server's own updated field separately. They differ more than you would think, because the feed itself is sometimes a day behind, and showing only my fetch time made stale data look fresh.
And I recompute isUpcoming on render, not on fetch. If the phone loaded the list at noon and you open it again at six, the noon copy still knows the afternoon game is finished, even without a connection. That one took me an embarrassingly long time to notice, because I was always testing at my desk with wifi.
Still not sure what to do about postponed games. The feed keeps the old date and adds nothing, so for now they just sit in "upcoming" with a date in the past until somebody fixes the data.
Top comments (0)