import {useEffect, useState} from 'react'; import {useTranslation} from 'react-i18next'; import {Dialog, DialogContent, DialogDescription, DialogTitle} from '@/components/ui/dialog'; import {Skeleton} from '@/components/ui/skeleton'; import GameRow from './stats/GameRow.jsx'; import {formatPlaytime} from '../utils/games.js'; import {fetchSyncChanges, groupByKind} from '../utils/syncChanges.js'; /** * The changes of the last sync, grouped by kind. Loads the result again when it opens: the achievements of a sync * arrive after its games. */ export default function SyncChangesDialog({onClose}) { const {t} = useTranslation(); const [changes, setChanges] = useState(null); const [failed, setFailed] = useState(false); useEffect(() => { let current = true; fetchSyncChanges() .then((body) => { if (!current) return; if (body) setChanges(body.changes ?? []); else setFailed(true); }) .catch(() => current && setFailed(true)); return () => { current = false; }; }, []); const value = (change) => { switch (change.kind) { case 'PLAYTIME': return `+${formatPlaytime(change.amount)}`; case 'ACHIEVEMENTS': return `+${change.amount}`; case 'STATUS': return `${t(`BACKLOG.STATUS.${change.fromStatus}`)} → ${t(`BACKLOG.STATUS.${change.toStatus}`)}`; default: return null; } }; return ( !open && onClose()}> {t('SYNC_CHANGES.TITLE')} {t('SYNC_CHANGES.TITLE')} {changes === null && !failed && } {failed &&

{t('SYNC_CHANGES.ERROR')}

} {changes && changes.length === 0 &&

{t('SYNC_CHANGES.EMPTY')}

} {changes && groupByKind(changes).map(({kind, changes: rows}) => (

{t(`SYNC_CHANGES.HEADING.${kind}`)}

    {rows.map((change, index) => (
  • ))}
))}
); }