/** * Die Filter einer Suche, als Adressparameter und als Objekt. * * Ohne Abhängigkeiten: die Suchseite baut damit ihre Adresse, und gespeicherte * Ansichten sind nichts anderes als eine solche Adresse. Dass beides dieselbe * Darstellung benutzt, ist der Punkt — eine Ansicht ist ein Lesezeichen. */ /** Die Arten, über die einzeln gesucht werden kann. */ export const SEARCH_KINDS = ['case', 'document', 'personnel'] as const export type SearchKind = (typeof SEARCH_KINDS)[number] /** * Was in der Adresse stehen kann. `all` ist der Auslieferungszustand: wer * einen Namen eintippt, will wissen, wo er überhaupt vorkommt, und nicht * zuerst entscheiden, wonach er sucht. Die einzelnen Arten bleiben als Filter. */ export const SEARCH_SCOPES = ['all', ...SEARCH_KINDS] as const export type SearchScope = (typeof SEARCH_SCOPES)[number] export type SearchFilters = { q: string kind: SearchScope status?: string templateKey?: string classification?: number /** Nur Akten, an denen der Suchende beteiligt ist. */ mine?: boolean /** Wiedervorlage bis einschliesslich diesem Tag. */ dueBefore?: string /** Seit diesem Zeitpunkt geändert, ISO. */ changedSince?: string /** Seit diesem Zeitpunkt **nicht** geändert, ISO. */ idleSince?: string cursor?: string } export function parseFilters(params: URLSearchParams | Record): SearchFilters { const get = (name: string): string | undefined => { const wert = params instanceof URLSearchParams ? params.get(name) : params[name] return wert && wert.length > 0 ? wert : undefined } const kind = get('kind') const stufe = get('classification') return { q: (get('q') ?? '').slice(0, 200), kind: (SEARCH_SCOPES as readonly string[]).includes(kind ?? '') ? (kind as SearchScope) : 'all', status: get('status'), templateKey: get('templateKey'), classification: stufe !== undefined && /^[0-5]$/.test(stufe) ? Number(stufe) : undefined, mine: get('mine') === '1', dueBefore: get('dueBefore'), changedSince: get('changedSince'), idleSince: get('idleSince'), cursor: get('cursor'), } } /** Zurück in eine Adresse. Leere Filter fallen weg, damit sie kurz bleibt. */ export function toSearchParams(filters: Partial): string { const params = new URLSearchParams() for (const [name, wert] of Object.entries(filters)) { if (wert === undefined || wert === '' || wert === false) continue params.set(name, wert === true ? '1' : String(wert)) } return params.toString() }