import {useState} from 'react'; import {useNavigate} from 'react-router-dom'; import {useTranslation} from 'react-i18next'; import {toast} from 'sonner'; import {Hand, Loader2, Trash2} from 'lucide-react'; import {Button} from '@/components/ui/button'; import {Card} from '@/components/ui/card'; import {Input} from '@/components/ui/input'; import {Label} from '@/components/ui/label'; import {hoursToMinutes, removeGame, restoreGame, toHours, updateManualGame} from '../utils/manualGames.js'; import {MAX_PLATFORM_LENGTH} from '../utils/limits.js'; import useUnsavedChanges, {discardChanges} from '../hooks/useUnsavedChanges.js'; const UNDO_MS = 8000; /** * Platform and hours of a game added by hand, and removing it. Steam games get both from the sync. * * @param onSaved gets the saved platform and playtimeMinutes */ export default function ManualGameCard({game, onSaved}) { const {t} = useTranslation(); const navigate = useNavigate(); const [platform, setPlatform] = useState(game.platform ?? ''); const [hours, setHours] = useState(toHours(game.playtimeMinutes)); const [busy, setBusy] = useState(false); const [confirmRemove, setConfirmRemove] = useState(false); // PlayStation owns the playtime of its rows: Core ignores a value sent for one. const psn = game.source === 'PSN'; const playtimeMinutes = psn ? game.playtimeMinutes : hoursToMinutes(hours); const dirty = platform.trim() !== (game.platform ?? '') || playtimeMinutes !== game.playtimeMinutes; useUnsavedChanges(dirty); const run = async (request, onOk) => { setBusy(true); try { const response = await request(); if (response.status === 401) return; if (!response.ok) { toast.error(t('BACKLOG.SAVE_FAILED')); return; } onOk(); } catch (err) { console.error('manual game error:', err); toast.error(t('INFO.ERROR.NETWORK_FAILURE')); } finally { setBusy(false); } }; const save = () => run(() => updateManualGame(game.appid, {platform: platform.trim(), playtimeMinutes}), () => { onSaved({platform: platform.trim(), playtimeMinutes}); toast.success(t('BACKLOG.SAVED')); }); const undoRemove = () => run(() => restoreGame(game.appid), () => { toast.success(t('REMOVED_GAMES.RESTORED')); navigate(`/library/${game.appid}`); }); const remove = () => run(() => removeGame(game.appid), () => { toast.success(t('MANUAL_GAME.REMOVED'), { duration: UNDO_MS, action: {label: t('MANUAL_GAME.UNDO'), onClick: undoRemove}, }); // The game is gone, so are its unsaved edits on this page. discardChanges(); navigate('/library', {replace: true}); }); return (

{t('MANUAL_GAME.TITLE')}

{!psn &&

{t('MANUAL_GAME.HINT')}

}
setPlatform(e.target.value)}/>
{!psn && (
setHours(e.target.value)}/>
)}
{confirmRemove ? (
{t('MANUAL_GAME.REMOVE_CONFIRM')}
) : ( )}
); }