Files
ToBePlayed-Frontend/src/utils/syncChanges.js
T
lobo bbc707de87
Build, Test & Push Frontend / quality-check (push) Successful in 40s
Build, Test & Push Frontend / docker (push) Successful in 23s
feat(sync): add Set to 100% button for all-unlocked games
The sync details show a Set to 100% button for ALL_UNLOCKED games.
The button uses the existing status PUT, checks points, and reloads
the Dashboard. Refs #21
2026-10-11 16:22:49 +02:00

55 lines
2.3 KiB
JavaScript

import {apiFetch} from './api.js';
const CORE = () => import.meta.env.VITE_CORE_API_URL;
// The order of the groups in the details.
const KINDS = ['ALL_UNLOCKED', 'ADDED', 'REMOVED', 'PLAYTIME', 'ACHIEVEMENTS', 'STATUS'];
/**
* `{syncedAt, startedBy, seen, importedGames, changes: [{kind, appid, name, imageUrl, amount, fromStatus, toStatus}]}`,
* or null when the user has no result (204) or the answer is not 200. PLAYTIME: amount in minutes, ACHIEVEMENTS:
* amount is the number of new unlocks. ALL_UNLOCKED: the sync unlocked the last
* achievement; gone once the game is COMPLETED.
*/
export async function fetchSyncChanges() {
const response = await apiFetch(`${CORE()}/api/library/sync-changes`);
return response.status === 200 ? response.json() : null;
}
/**
* The result with this `syncedAt` stays seen on every device. A newer result is not touched.
*/
export const markSyncChangesSeen = (syncedAt) =>
apiFetch(`${CORE()}/api/library/sync-changes/seen`, {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({syncedAt}),
});
/**
* What the dashboard shows of a result: null (nothing), `{mode: 'nothing'}` for a manual sync that changed nothing, or
* `{mode: 'changes', imported, added, removed, minutes, achievements, moves}`. A result the user saw, and an empty
* result of an automatic or a visit sync, show nothing.
*/
export function bannerOf(result) {
if (!result || result.seen) return null;
const changes = result.changes ?? [];
const imported = result.importedGames ?? 0;
if (changes.length === 0 && imported === 0) {
return result.startedBy === 'MANUAL' ? {mode: 'nothing'} : null;
}
const of = (kind) => changes.filter((change) => change.kind === kind);
const sum = (kind) => of(kind).reduce((total, change) => total + (change.amount ?? 0), 0);
return {
mode: 'changes', imported, added: of('ADDED').length, removed: of('REMOVED').length,
minutes: sum('PLAYTIME'), achievements: sum('ACHIEVEMENTS'), moves: of('STATUS').length,
};
}
/**
* `[{kind, changes}]` for the kinds that have changes, in the order of KINDS.
*/
export const groupByKind = (changes) => KINDS
.map((kind) => ({kind, changes: changes.filter((change) => change.kind === kind)}))
.filter((group) => group.changes.length > 0);