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 useSessionExpired from '../hooks/useSessionExpired.js'; import {hoursToMinutes, removeGame, updateManualGame} from '../utils/manualGames.js'; // Two decimals: then hoursToMinutes gives back the same minute, so an unchanged form is not dirty. const toHours = (minutes) => (minutes > 0 ? String(Math.round((minutes / 60) * 100) / 100) : ''); /** * 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 expireSession = useSessionExpired(); const [platform, setPlatform] = useState(game.platform ?? ''); const [hours, setHours] = useState(toHours(game.playtimeMinutes)); const [busy, setBusy] = useState(false); const [confirmRemove, setConfirmRemove] = useState(false); const playtimeMinutes = hoursToMinutes(hours); const dirty = platform.trim() !== (game.platform ?? '') || playtimeMinutes !== game.playtimeMinutes; const run = async (request, onOk) => { setBusy(true); try { const response = await request(); if (response.status === 401) { expireSession(); 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 remove = () => run(() => removeGame(game.appid), () => { toast.success(t('MANUAL_GAME.REMOVED')); navigate('/library', {replace: true}); }); return (

{t('MANUAL_GAME.TITLE')}

{t('MANUAL_GAME.HINT')}

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