feat(backend): list popular finished games while games are live

GET /games/popular?kind=finished returns the most watched finished
games even when games are being played, so the web app can show live
and popular games together.
This commit is contained in:
Halit Aksoy 2026-10-16 09:31:44 +03:00
parent 8ad833cdbb
commit 193efd1458
3 changed files with 15 additions and 3 deletions

View File

@ -80,10 +80,11 @@ export class ExpressApp {
} }
})); }));
// Live games if any are being played, otherwise the most spectated finished games. // Live games if any are being played, otherwise the most spectated finished games. With kind=finished
// always the finished games, for clients that get live games over the WebSocket.
app.get("/games/popular", handleAsync(async (req, res) => { app.get("/games/popular", handleAsync(async (req, res) => {
const limit = parseLimit(req.query.limit, 5); const limit = parseLimit(req.query.limit, 5);
const live = liveGames.getTop(limit); const live = req.query.kind === "finished" ? [] : liveGames.getTop(limit);
if (live.length > 0) { if (live.length > 0) {
res.send({ kind: "live", games: live }); res.send({ kind: "live", games: live });
} else { } else {

View File

@ -138,6 +138,17 @@ describe("HTTP API", () => {
expect(body.games.map((g: any) => g.id)).toEqual([watched.id, quiet.id]); expect(body.games.map((g: any) => g.id)).toEqual([watched.id, quiet.id]);
expect(body.games[0]).not.toHaveProperty("moves"); expect(body.games[0]).not.toHaveProperty("moves");
}); });
it("lists finished games while games are live when asked for finished games", async () => {
const finished = await finishGame(CAROL, DAVE);
await flushPromises();
startGame();
expect((await get("/games/popular")).body.kind).toBe("live");
const { body } = await get("/games/popular?kind=finished");
expect(body.kind).toBe("finished");
expect(body.games.map((g: any) => g.id)).toEqual([finished.id]);
});
}); });
describe("GET /games/me/active", () => { describe("GET /games/me/active", () => {

View File

@ -4,7 +4,7 @@ Work through the tasks in order; each ends with its checks passing and a commit.
- [x] 1. **Core**: `ThemeManager` takes its themes; `PitViewModel.highlight` set by `PitAnimator`; `getSowingPath` - [x] 1. **Core**: `ThemeManager` takes its themes; `PitViewModel.highlight` set by `PitAnimator`; `getSowingPath`
with unit tests; new texts (en, tr). with unit tests; new texts (en, tr).
- [ ] 2. **Backend**: `GET /games/popular?kind=finished`; test. - [x] 2. **Backend**: `GET /games/popular?kind=finished`; test.
- [ ] 3. **Web app shell**: the three themes, font, base styles, `AppHeader` (logo, theme swatches, account menu, - [ ] 3. **Web app shell**: the three themes, font, base styles, `AppHeader` (logo, theme swatches, account menu,
action) on every page; restyle the lobby, privacy page, loading and connection panels. action) on every page; restyle the lobby, privacy page, loading and connection panels.
- [ ] 4. **Web app board**: `BoardView`, `PitView`, `StoreView`, stones, upright layout, highlights and move preview. - [ ] 4. **Web app board**: `BoardView`, `PitView`, `StoreView`, stones, upright layout, highlights and move preview.