From 9adc606c57903c9246145337596c84f98605e2cf Mon Sep 17 00:00:00 2001 From: lobo Date: Fri, 9 Oct 2026 14:35:07 +0200 Subject: [PATCH] feat(library): show set total playtime on dashboard cards Most played and currently playing cards show the total playtime of the game set. Use the own minutes when the API sends no total. --- README.md | 2 +- src/components/CurrentlyPlayingCard.jsx | 2 +- src/components/CurrentlyPlayingCard.test.jsx | 18 ++++++++++++++++++ src/components/MostPlayedCard.jsx | 10 ++++++---- src/components/MostPlayedCard.test.jsx | 18 ++++++++++++++++++ 5 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 src/components/CurrentlyPlayingCard.test.jsx create mode 100644 src/components/MostPlayedCard.test.jsx diff --git a/README.md b/README.md index 2c22059..97a7c24 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ To Be Played is split into three repositories: - **Detail per platform**: the details page of a game with several platforms (or a PlayStation title on a Steam game) shows `PlatformsCard` above the editions: one row per platform with playtime, last played and the achievement or trophy progress of that platform, a total row, and a link to the edition whose page lists the achievements. The hero - playtime and the library card show the set total (`totalPlaytimeMinutes`); sorting and the stats stay per edition. + playtime and the library card show the set total (`totalPlaytimeMinutes`); sorting, stats, dashboard cards and the public profile use the set total (Core V45); per row stay the playtime history, rewards and the played / never started counts. - **Add a game by name** for games outside Steam (PlayStation, Switch, Xbox, physical): search IGDB, pick a hit, a platform and optional hours. Works without a Steam ID. Games already in ToBePlayed come first. Check several hits to add them at once through the import review. diff --git a/src/components/CurrentlyPlayingCard.jsx b/src/components/CurrentlyPlayingCard.jsx index 7716535..4a3a4b7 100644 --- a/src/components/CurrentlyPlayingCard.jsx +++ b/src/components/CurrentlyPlayingCard.jsx @@ -40,7 +40,7 @@ export default function CurrentlyPlayingCard({games, syncing, wide}) {
- {formatPlaytime(g.playtimeMinutes)} + {formatPlaytime(g.totalPlaytimeMinutes ?? g.playtimeMinutes)}
diff --git a/src/components/CurrentlyPlayingCard.test.jsx b/src/components/CurrentlyPlayingCard.test.jsx new file mode 100644 index 0000000..154c3a5 --- /dev/null +++ b/src/components/CurrentlyPlayingCard.test.jsx @@ -0,0 +1,18 @@ +// @vitest-environment jsdom +import {afterEach, describe, expect, it, vi} from 'vitest'; +import {cleanup, render, screen} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; +import CurrentlyPlayingCard from './CurrentlyPlayingCard.jsx'; + +vi.mock('react-i18next', () => import('../test/i18n-mock.js')); + +describe('CurrentlyPlayingCard', () => { + afterEach(cleanup); + + it('shows the set total of a game, not the minutes of its own row', () => { + render(); + + expect(screen.getByText('10h')).toBeTruthy(); + }); +}); diff --git a/src/components/MostPlayedCard.jsx b/src/components/MostPlayedCard.jsx index 42efb37..3387841 100644 --- a/src/components/MostPlayedCard.jsx +++ b/src/components/MostPlayedCard.jsx @@ -12,15 +12,17 @@ import {formatPlaytime} from '../utils/games.js'; import {coverEffect} from '../utils/rewards.js'; import {playChart} from '../utils/statCharts.js'; +const total = (g) => g.totalPlaytimeMinutes ?? g.playtimeMinutes; + /** * @param chart LIST, BARS, PIE or DONUT * @param onChart `(form)`: shows the picker */ export default function MostPlayedCard({games, syncing, equipped, chart = 'LIST', onChart}) { const {t} = useTranslation(); - const mapped = games.map((g) => ({appid: g.appid, name: g.name, minutes: g.playtimeMinutes})); + const mapped = games.map((g) => ({appid: g.appid, name: g.name, minutes: total(g)})); const form = playChart(chart, mapped); - const maxMinutes = games[0]?.playtimeMinutes || 1; + const maxMinutes = mapped[0]?.minutes || 1; return (
@@ -62,12 +64,12 @@ export default function MostPlayedCard({games, syncing, equipped, chart = 'LIST'
- {formatPlaytime(g.playtimeMinutes)} + {formatPlaytime(total(g))} diff --git a/src/components/MostPlayedCard.test.jsx b/src/components/MostPlayedCard.test.jsx new file mode 100644 index 0000000..5ac94f4 --- /dev/null +++ b/src/components/MostPlayedCard.test.jsx @@ -0,0 +1,18 @@ +// @vitest-environment jsdom +import {afterEach, describe, expect, it, vi} from 'vitest'; +import {cleanup, render, screen} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; +import MostPlayedCard from './MostPlayedCard.jsx'; + +vi.mock('react-i18next', () => import('../test/i18n-mock.js')); + +describe('MostPlayedCard', () => { + afterEach(cleanup); + + it('shows the set total of a game, not the minutes of its own row', () => { + render(); + + expect(screen.getByText('10h')).toBeTruthy(); + }); +});