80 lines
2.6 KiB
TypeScript
80 lines
2.6 KiB
TypeScript
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;
|
|
}
|