Files
ToBePlayed-Frontend/src/utils/backlog.js
T
lobo f71e8f7aff
Build, Test & Push Frontend / quality-check (push) Successful in 25s
Build, Test & Push Frontend / docker (push) Successful in 23s
feat(library): add game links, auditor queue, audit log and filter
LinkGameDialog (user request or auditor link), EditionsCard on the
details page, LinkQueuePage and AuditLogPage for auditors with paging,
hideDuplicates filter and editions badge in the library, audit menu
entries, de/en texts.
2026-10-02 09:10:56 +02:00

71 lines
2.7 KiB
JavaScript

import {apiFetch} from './api.js';
import {GAME_STATUSES} from './limits.js';
// Radix Select has no empty value, so "no priority" needs its own value in the form.
export const NO_PRIORITY = 'NONE';
export const parseStatus = (value) => (GAME_STATUSES.includes(value) ? value : null);
export const toBacklogRequest = ({status, rating, notes, priority}) => ({
status,
rating: rating || null,
notes: notes?.trim() ? notes : null,
priority: priority === NO_PRIORITY ? null : priority,
});
/**
* The fields of `form` that differ from `saved`, in request form: what saveBacklogEntry sends.
*/
export const changedFields = (saved, form) => {
const before = toBacklogRequest(saved);
return Object.fromEntries(Object.entries(toBacklogRequest(form)).filter(([field, value]) => value !== before[field]));
};
/**
* PATCH /api/library/games/{appid}/backlog with only the changed fields, so an older tab keeps the newer ones; null
* clears a field. Answers the whole entry. The caller handles the response status.
*
* @param changes see changedFields
*/
export const saveBacklogEntry = (appid, changes) =>
apiFetch(`${import.meta.env.VITE_CORE_API_URL}/api/library/games/${appid}/backlog`, {
method: 'PATCH',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(changes),
});
/**
* PUT /api/library/games/{appid}/status. The caller handles the response status.
*/
export const saveGameStatus = (appid, status) =>
apiFetch(`${import.meta.env.VITE_CORE_API_URL}/api/library/games/${appid}/status`, {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({status}),
});
/**
* PUT /api/library/games/{appid}/finished-hint: "Not yet" on the finished hint. Answers 204.
*
* @param dismissed the hint type the user answered, ENDING or PLAYTIME
*/
export const dismissFinishedHint = (appid, dismissed) =>
apiFetch(`${import.meta.env.VITE_CORE_API_URL}/api/library/games/${appid}/finished-hint`, {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({dismissed}),
});
export const libraryQuery = ({page, size, sort, status, q, maxMinutes, hidden, hideDuplicates}) => {
const params = new URLSearchParams({page: String(page), size: String(size), sort});
if (hidden) params.set('hidden', 'true');
if (hideDuplicates) params.set('hideDuplicates', 'true');
if (status) params.set('status', status);
if (q?.trim()) params.set('q', q.trim());
if (maxMinutes) params.set('maxMinutes', String(maxMinutes));
return params.toString();
};
export const backlogShare = (summary) =>
summary?.total ? Math.round(((summary.byStatus?.BACKLOG ?? 0) / summary.total) * 100) : 0;