import {useCallback, useEffect, useRef, useState} from 'react'; import {useTranslation} from 'react-i18next'; import {Button} from '@/components/ui/button'; import {Dialog, DialogContent, DialogDescription, DialogTitle} from '@/components/ui/dialog'; import {Skeleton} from '@/components/ui/skeleton'; import GameRow from './GameRow.jsx'; import ComingBadge from '../ComingBadge.jsx'; import GameStatusBadge from '../GameStatusBadge.jsx'; import {formatDate} from '../../utils/format.js'; import {formatPlaytime} from '../../utils/games.js'; import {fetchStatGames} from '../../utils/statGames.js'; const ERRORS = {403: 'STATS.DRILL.NOT_SHARED', 401: 'STATS.DRILL.EXPIRED'}; /** * The games behind one number, 40 per page. * * @param request `{title, source, ticket, linked, params}` or null (closed) */ export default function StatGamesDialog({request, onClose, onCloseAutoFocus}) { const {t, i18n} = useTranslation(); const [state, setState] = useState({games: [], page: 0, totalPages: 0, total: 0, untracked: 0}); const [status, setStatus] = useState('loading'); const openRequest = useRef(null); const load = useCallback(async (page, current) => { setStatus('loading'); const {ok, status: code, data} = await fetchStatGames(request.source, {...request.params, page}, request.ticket); if (openRequest.current !== request) return; if (!ok) { setStatus(code); return; } setState({ games: [...current, ...data.content], page, totalPages: data.totalPages, total: data.totalElements, untracked: data.untracked ?? 0, }); setStatus('ok'); }, [request]); useEffect(() => { openRequest.current = request; if (!request) return; setState({games: [], page: 0, totalPages: 0, total: 0, untracked: 0}); load(0, []); }, [request, load]); const value = (game) => { if (request.source === 'community') { return `${t('STATS.DRILL.IN_LIBRARIES', {count: game.libraries})} · ${formatPlaytime(game.minutes)}`; } const moved = game.fromStatus || game.toStatus; return ( <> {!moved && game.status && } {moved && ( {game.fromStatus ? t(`BACKLOG.STATUS.${game.fromStatus}`) : t('STATS.DRILL.NEW_IN_LIBRARY')} {' → '}{game.toStatus ? t(`BACKLOG.STATUS.${game.toStatus}`) : '–'} )} {game.at ? formatDate(game.at, i18n.language, {dateStyle: 'medium'}) : formatPlaytime(game.minutes ?? game.playtimeMinutes ?? 0)} > ); }; const failed = typeof status === 'number'; return ( !open && onClose()}> {request?.title} {status === 'ok' ? t('STATS.DRILL.GAMES', {count: state.total}) : ' '} {request && ( {state.games.map((game, index) => ( ))} )} {status === 'loading' && } {status === 'ok' && state.games.length === 0 && ( {t('STATS.DRILL.EMPTY')} )} {status === 'ok' && state.untracked > 0 && ( {t('STATS.FINISHED.BEFORE', {count: state.untracked})} )} {failed && ( {t(ERRORS[status] ?? 'STATS.DRILL.ERROR')} {status === 401 ? globalThis.location.reload()}> {t('STATS.DRILL.RELOAD')} : status !== 403 && ( load(state.page + (state.games.length > 0 ? 1 : 0), state.games)}> {t('DASHBOARD.RETRY')} )} )} {status === 'ok' && state.page + 1 < state.totalPages && ( load(state.page + 1, state.games)}> {t('STATS.DRILL.LOAD_MORE')} )} ); }
{t('STATS.DRILL.EMPTY')}
{t('STATS.FINISHED.BEFORE', {count: state.untracked})}
{t(ERRORS[status] ?? 'STATS.DRILL.ERROR')}