Public Access
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.
This commit is contained in:
1 parent
f1a6bc0443
commit
9adc606c57
5 files changed
+44
-6
No files matched your search
@@ -40,7 +40,7 @@ export default function CurrentlyPlayingCard({games, syncing, wide}) {
|
||||
<FitText text={g.name ?? `App ${g.appid}`}/>
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground tabular-nums">
|
||||
{formatPlaytime(g.playtimeMinutes)}
|
||||
{formatPlaytime(g.totalPlaytimeMinutes ?? g.playtimeMinutes)}
|
||||
</div>
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
@@ -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(<MemoryRouter><CurrentlyPlayingCard games={[{appid: 620, name: 'Portal 2', playtimeMinutes: 100,
|
||||
totalPlaytimeMinutes: 600, status: 'PLAYING'}]}/></MemoryRouter>);
|
||||
|
||||
expect(screen.getByText('10h')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -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 (
|
||||
<Card className="gap-0 py-0">
|
||||
<div className="flex flex-wrap items-center justify-between gap-x-3 px-5 py-4 border-b">
|
||||
@@ -62,12 +64,12 @@ export default function MostPlayedCard({games, syncing, equipped, chart = 'LIST'
|
||||
<div className="mt-2 h-1.5 rounded-full bg-muted">
|
||||
<div
|
||||
className="h-full rounded-full bg-primary"
|
||||
style={{width: `${Math.max(2, (g.playtimeMinutes / maxMinutes) * 100)}%`}}
|
||||
style={{width: `${Math.max(2, (total(g) / maxMinutes) * 100)}%`}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span className="w-12 sm:w-14 text-right text-sm font-medium text-muted-foreground tabular-nums">
|
||||
{formatPlaytime(g.playtimeMinutes)}
|
||||
{formatPlaytime(total(g))}
|
||||
</span>
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
@@ -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(<MemoryRouter><MostPlayedCard games={[{appid: 620, name: 'Portal 2', playtimeMinutes: 100,
|
||||
totalPlaytimeMinutes: 600, status: 'PLAYING'}]}/></MemoryRouter>);
|
||||
|
||||
expect(screen.getByText('10h')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user