feat(ui): make stat numbers clickable to open games
Build, Test & Push Frontend / quality-check (push) Successful in 28s
Build, Test & Push Frontend / docker (push) Successful in 26s

StatDrill context holds one dialog for a page. StatCount wraps a number:
total and status counts link to the library filter, other numbers open
StatGamesDialog. DrillRow and DrillButton support drill-down in tag bars
(genres, platforms, moods) and other stat displays. Dialog shows 40 games
per page with bottom-sheet layout on phones, handles pagination and errors
(403 not shared, 401 expired, 400 bad argument).
This commit is contained in:
lobo committed 2026-10-03 18:51:59 +02:00
1 parent ed5df8c40d
commit 777ba87fd6
31 files changed
+1026 -261

No files matched your search

+28
View File
@@ -90,6 +90,34 @@ describe('PointsPage', () => {
const bar = within(item).getByRole('progressbar');
expect(bar.getAttribute('aria-valuenow')).toBe('7');
expect(bar.getAttribute('aria-valuemax')).toBe('10');
expect(within(item).queryByRole('button', {name: 'POINTS.BUY'})).toBeNull();
});
it('opens the games behind a locked bar, and the history of a month', async () => {
const page = (appid) => json(200, {content: [{appid, name: `G${appid}`, status: 'FINISHED', at: '2026-09-01T10:00:00Z'}],
page: 0, size: 40, totalElements: 1, totalPages: 1, untracked: 3});
await renderPage({
'GET /api/rewards/progress/GAMES_FINISHED/games': page(1),
'GET /api/rewards/history/MONTH/2026-09/games': page(2),
});
const bar = screen.getByText('POINTS.ITEMS.BADGE_FINISH_10').closest('li');
fireEvent.click(within(bar).getByRole('button'));
expect(await screen.findByText('G1')).toBeTruthy();
expect(screen.getByText('STATS.FINISHED.BEFORE:3')).toBeTruthy();
fireEvent.keyDown(document.activeElement, {key: 'Escape'});
await waitFor(() => expect(screen.queryByText('G1')).toBeNull());
fireEvent.click(screen.getByRole('button', {name: '2026-09'}));
expect(await screen.findByText('G2')).toBeTruthy();
});
it('shows no button on a playtime-month bar', async () => {
await renderPage({'GET /api/rewards/wallet': json(200, wallet({
catalog: [{code: 'BADGE_MONTHS', slot: 'BADGE', price: 0, track: 'PLAY_MORE_MONTHS', target: 3}],
}))});
const item = screen.getByText('POINTS.ITEMS.BADGE_MONTHS').closest('li');
expect(within(item).queryByRole('button')).toBeNull();
});