import {useEffect, useMemo, useState} from 'react'; import {Link, useNavigate, useParams} from 'react-router-dom'; import {useTranslation} from 'react-i18next'; import {formatPlaytime, iconUrl} from '../utils/games.js'; const formatUnlockedAt = (instant, locale) => { if (!instant) return ''; try { return new Date(instant).toLocaleDateString(locale, {year: 'numeric', month: 'short', day: 'numeric'}); } catch { return ''; } }; export default function GameDetail() { const {t, i18n} = useTranslation(); const {appid} = useParams(); const navigate = useNavigate(); const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; const token = localStorage.getItem('tbp_jwt'); if (!token) { navigate('/login'); return; } setIsLoading(true); setError(null); (async () => { try { const url = `${import.meta.env.VITE_CORE_API_URL}/api/library/games/${appid}`; const response = await fetch(url, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }, }); if (cancelled) return; if (response.status === 401) { localStorage.removeItem('tbp_jwt'); navigate('/login'); return; } if (response.status === 404) { setError(t('GAME_DETAIL.NOT_FOUND')); return; } if (!response.ok) { setError(t('GAME_DETAIL.ERROR_LOAD')); return; } const json = await response.json(); setData(json); } catch (err) { if (!cancelled) { console.error('GameDetail load error:', err); setError(t('INFO.ERROR.NETWORK_FAILURE')); } } finally { if (!cancelled) setIsLoading(false); } })(); return () => { cancelled = true; }; }, [appid, navigate, t]); const sortedAchievements = useMemo(() => { if (!data?.achievements) return []; return [...data.achievements].sort((a, b) => { if (a.unlocked !== b.unlocked) return a.unlocked ? -1 : 1; if (a.unlocked && b.unlocked) { return (b.unlockedAt ?? '').localeCompare(a.unlockedAt ?? ''); } return (a.displayName ?? a.apiName).localeCompare(b.displayName ?? b.apiName); }); }, [data]); return (
{t('GAME_DETAIL.PLAYTIME', {time: formatPlaytime(data.playtimeMinutes)})}