import {useEffect, useRef, useState} from 'react'; import {useTranslation} from 'react-i18next'; import usePointsCheck from '../hooks/usePointsCheck.js'; import {formatDate, formatDay} from '../utils/format.js'; import {STATUS_NOT_REACHED} from '../utils/rewards.js'; const WAITING = {NO_PROOF: 'POINTS.GAME.WAITING', NO_PLAY_AFTER_START: 'POINTS.GAME.WAITING_START'}; // The rest of an early finish waits for Steam play, with or without playtime on record. const WAITING_TOPUP = ['NO_PROOF', 'NO_PLAYTIME']; const waitingKey = (kind, reason) => (kind === 'FINISHED_TOPUP' ? WAITING_TOPUP.includes(reason) && 'POINTS.GAME.WAITING_TOPUP' : WAITING[reason]); /** * What the game earned: one line per paid row and one per kind that is missing, with the reason from Core. Loading it * settles the points; a status change after the first load also shows the points toast. `refreshes` loads it again * after the Steam refresh of the game page, which may have stored an unlock that settles points. */ export default function GamePointsLine({game, refreshes = 0}) { const {t, i18n} = useTranslation(); const check = usePointsCheck(); const [points, setPoints] = useState(null); const lastStatus = useRef(null); useEffect(() => { const changed = lastStatus.current !== null && lastStatus.current !== game.status; lastStatus.current = game.status; let stale = false; check(game.appid, {status: game.status, tell: changed}).then((data) => { if (!stale && data) setPoints(data); }); return () => { stale = true; }; }, [check, game.appid, game.status, refreshes]); if (!points) return null; const earlySinceText = points.earlySince && formatDay(points.earlySince, i18n.language, {dateStyle: 'medium'}); const kindText = (kind) => t(`POINTS.KINDS.${kind}`); const lines = [ ...points.paid.map((row) => t('POINTS.GAME.PAID', { kind: kindText(row.kind), points: row.points, date: formatDate(row.paidAt, i18n.language, {dateStyle: 'medium'}), }) + (row.appid === game.appid ? '' : ` ${t('POINTS.GAME.OTHER_EDITION')}`)), ...Object.entries(points.missing).filter(([, reason]) => !STATUS_NOT_REACHED.includes(reason)).map(([kind, reason]) => ( waitingKey(kind, reason) ? t(waitingKey(kind, reason)) : t('POINTS.GAME.NONE', {kind: kindText(kind), reason: t(`POINTS.REASONS.${reason}`, {date: earlySinceText})}))), ]; return lines.map((line, i) =>
{line}
); }