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 ? : status !== 403 && ( )}
)} {status === 'ok' && state.page + 1 < state.totalPages && ( )}
); }