feat(dashboard): new layout with sync button and top 5 most played

Remove the placeholder tiles and the settings tile, fix the mobile header width. iconUrl/formatPlaytime move to utils/games.js (599 min now shows 10h, not 10.0h), and the sync button logic to the useForceSync hook shared with the library.
This commit is contained in:
lobo committed 2026-09-24 09:49:06 +02:00
1 parent 84e31b23ea
commit 76a9ac3e6f
9 files changed
+216 -128

No files matched your search

+50
View File
@@ -0,0 +1,50 @@
import {useState} from 'react';
import {useNavigate} from 'react-router-dom';
import {useTranslation} from 'react-i18next';
const RELOAD_DELAY_MS = 4000;
/**
* Starts a library sync (POST /api/library/sync) and calls onStarted after a short delay,
* so the caller can reload once Steam data has arrived.
*/
export default function useForceSync(onStarted) {
const {t} = useTranslation();
const navigate = useNavigate();
const [busy, setBusy] = useState(false);
const [message, setMessage] = useState(null);
const trigger = async () => {
const token = localStorage.getItem('tbp_jwt');
if (!token) {
navigate('/login');
return;
}
setBusy(true);
setMessage(null);
try {
const response = await fetch(`${import.meta.env.VITE_CORE_API_URL}/api/library/sync`, {
method: 'POST',
headers: {'Authorization': `Bearer ${token}`},
});
if (response.status === 429) {
const json = await response.json().catch(() => ({}));
setMessage(t('LIBRARY.SYNC_COOLDOWN', {seconds: json.retryAfterSeconds ?? 60}));
return;
}
if (!response.ok) {
setMessage(t('LIBRARY.SYNC_FAILED'));
return;
}
setMessage(t('LIBRARY.SYNC_STARTED'));
setTimeout(onStarted, RELOAD_DELAY_MS);
} catch (err) {
console.error('sync trigger error:', err);
setMessage(t('INFO.ERROR.NETWORK_FAILURE'));
} finally {
setBusy(false);
}
};
return {trigger, busy, message};
}