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

+13 -2
View File
@@ -2,6 +2,7 @@ import {useEffect, useState} from 'react';
import {useTranslation} from 'react-i18next';
import {Card} from '@/components/ui/card';
import {useDrillTarget} from './stats/StatDrill.jsx';
function useCountUp(target, durationMs = 1600) {
const [value, setValue] = useState(0);
@@ -25,10 +26,14 @@ function useCountUp(target, durationMs = 1600) {
return value;
}
export default function StatCard({label, value, icon: Icon, suffix}) {
/**
* @param drill `{params}` of StatCount: the card is a button that opens the games behind the number
*/
export default function StatCard({label, value, icon: Icon, suffix, drill}) {
const {i18n} = useTranslation();
const animated = useCountUp(value);
return (
const target = useDrillTarget({title: label, ...drill});
const card = (
<Card className="gap-3 p-5">
{Icon && (
<span className="flex size-9 items-center justify-center rounded-lg bg-primary/10 text-primary">
@@ -41,4 +46,10 @@ export default function StatCard({label, value, icon: Icon, suffix}) {
<div className="text-sm text-muted-foreground">{label}</div>
</Card>
);
return target ? (
<button type="button" onClick={target.onClick}
className="block w-full rounded-xl text-left transition-colors hover:text-primary focus-visible:ring-2 focus-visible:ring-ring">
{card}
</button>
) : card;
}