Simplify match history with filters and persistent pagination
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
export const matchPageSize = 25;
|
||||
export const matchSorts = ['started', 'round', 'duration', 'players'] as const;
|
||||
export type MatchSort = typeof matchSorts[number];
|
||||
export interface MatchHistoryQuery {
|
||||
game: string; map: string; q: string; days: number;
|
||||
status: '' | 'active' | 'completed' | 'interrupted';
|
||||
sort: MatchSort; direction: 'asc' | 'desc'; page: number;
|
||||
}
|
||||
export const matchQueryKeys = ['game', 'map', 'q', 'days', 'status', 'sort', 'direction', 'page'] as const;
|
||||
export function readMatchQuery(params: URLSearchParams): MatchHistoryQuery {
|
||||
const game = params.get('game') ?? '';
|
||||
const map = params.get('map') ?? '';
|
||||
const q = (params.get('q') ?? '').trim();
|
||||
const days = Number(params.get('days') || 0);
|
||||
const status = params.get('status') || '';
|
||||
const sort = params.get('sort') || 'started';
|
||||
const direction = params.get('direction') || 'desc';
|
||||
const page = Number(params.get('page') || 1);
|
||||
if (!['', 't5', 't6'].includes(game) || map.length > 1024 || q.length > 100
|
||||
|| ![0, 7, 30, 90].includes(days) || !['', 'active', 'completed', 'interrupted'].includes(status)
|
||||
|| !matchSorts.includes(sort as MatchSort) || !['asc', 'desc'].includes(direction)
|
||||
|| !Number.isSafeInteger(page) || page < 1 || page > 1000000) throw new Error('Invalid match history filters.');
|
||||
return { game, map, q, days, status: status as MatchHistoryQuery['status'], sort: sort as MatchSort, direction: direction as 'asc' | 'desc', page };
|
||||
}
|
||||
/** Namespaced filters also work inside an instance's Matches tab. */
|
||||
export function matchApiParams(url: URL): URLSearchParams {
|
||||
const params = new URLSearchParams();
|
||||
for (const key of matchQueryKeys) {
|
||||
const value = url.searchParams.get(`match${key[0].toUpperCase()}${key.slice(1)}`);
|
||||
if (value) params.set(key, value);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
export function matchHistoryHref(url: URL, changes: Partial<Record<keyof MatchHistoryQuery, string>>): string {
|
||||
const next = new URL(url);
|
||||
next.searchParams.delete('matches'); // Retire the former growing-list limit.
|
||||
next.searchParams.delete('matchPage');
|
||||
for (const [key, value] of Object.entries(changes)) {
|
||||
const name = `match${key[0].toUpperCase()}${key.slice(1)}`;
|
||||
if (value) next.searchParams.set(name, value); else next.searchParams.delete(name);
|
||||
}
|
||||
return next.pathname + next.search;
|
||||
}
|
||||
Reference in New Issue
Block a user