Files
EvoFirewall/apps/web/src/lib/search-params.ts
T

53 lines
1.8 KiB
TypeScript

import type { Filter } from '@/components/reui/filters'
/**
* Сериализация состояния страниц (таб/поиск/фильтры) в URL search-параметры:
* tab — id вкладки, q — строка поиска, f — JSON-массив фильтров.
* Пустые значения не пишутся в URL (deep-link остаётся чистым).
*/
export function filtersToSearch(filters: Filter[]): string | undefined {
if (filters.length === 0) return undefined
try {
return JSON.stringify(filters)
} catch {
return undefined
}
}
export function searchToFilters(raw: unknown): Filter[] {
if (typeof raw !== 'string' || raw.length === 0) return []
try {
const parsed: unknown = JSON.parse(raw)
if (!Array.isArray(parsed)) return []
return parsed.filter(
(x): x is Filter =>
typeof x === 'object' &&
x !== null &&
typeof (x as Filter).field === 'string' &&
typeof (x as Filter).operator === 'string' &&
Array.isArray((x as Filter).values),
)
} catch {
return []
}
}
/** Строка поиска: undefined при пустой, чтобы не писать пустой q в URL. */
export function searchToQ(raw: unknown): string | undefined {
return typeof raw === 'string' && raw.length > 0 ? raw : undefined
}
/** Вкладка: валидируется по списку допустимых id. */
export function searchToTab(
raw: unknown,
allowed: readonly string[],
): string | undefined {
return typeof raw === 'string' && allowed.includes(raw) ? raw : undefined
}
/** Флаг из search-параметра: только `true` пишется в URL. */
export function searchToFlag(raw: unknown): boolean | undefined {
return raw === true || raw === '1' ? true : undefined
}