// Wie aus einer Eingabe Suchmuster werden. // // Getrennt von der Seite, weil hier die Entscheidungen stecken, die man // prüfen können muss: was als Wort zählt, was am Wortanfang treffen muss und // was von LIKE als Text und nicht als Platzhalter gelesen wird. // // Die Bedeutung selbst — „trifft am Wortanfang" — liegt im SQL der Seite: // verglichen wird gegen Vorname, Nachname und Position zusammengesetzt, mit // Trennzeichen als Wortgrenze. /** * Die Zeichen, die im Namen als Wortgrenze zählen. * * Sie stehen hier und nicht in der Seite, weil **beide Seiten des Vergleichs** * sie brauchen: das Feld wird per `translate` an diesen Zeichen in Leerzeichen * zerlegt, und die Eingabe muss genauso zerlegt werden. Vorher tat es nur das * Feld — wer „Müller-Weiß" mit Bindestrich suchte, erzeugte das Muster * `müller-weiß%`, während im Heuhaufen „müller weiß" stand. Null Treffer, * obwohl die Person da ist; ohne Bindestrich fand man sie. Gemeldet im Test * vom 29.09. (C.08). */ export const TRENNZEICHEN = "-/:.,"; /** Für `translate(…, TRENNZEICHEN, TRENNZEICHEN_ERSATZ)`: gleich lang, nur Leerzeichen. */ export const TRENNZEICHEN_ERSATZ = " ".repeat(TRENNZEICHEN.length); const WORTGRENZE = new RegExp(`[\\s${TRENNZEICHEN.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&")}]+`); /** Nur Ziffern? Dann ist es eine Personalnummer und kein Name. */ export function istPersonalnummer(term: string): boolean { return /^\d+$/.test(term.trim()); } /** * Je Suchwort zwei LIKE-Muster: „am Anfang" und „nach einem Leerzeichen". * Zusammen ergeben sie „am Anfang eines Wortes". * * Ein Wort als Teilzeichenkette zu suchen wäre einfacher und war die erste * Fassung — bei „Winkler H" traf das „H" dann auf Thomas, Katharina und * CNC-Dreher:in, also auf alle. Je kürzer die Eingabe, desto unbrauchbarer * das Ergebnis, und ein Anfangsbuchstabe ist die kürzeste sinnvolle Eingabe. */ export function suchMuster(term: string): string[][] { return term .trim() // An denselben Zeichen zerlegt wie das Feld, gegen das verglichen wird: // „Müller-Weiß" wird zu zwei Wörtern, die beide am Wortanfang treffen // müssen — genau wie „Müller Weiß". .split(WORTGRENZE) .filter(Boolean) .map((wort) => { // Die Platzhalter von LIKE entschärfen: wer „50 %" tippt, sucht Text. const klein = wort.toLowerCase().replace(/[\\%_]/g, (z) => `\\${z}`); return [`${klein}%`, `% ${klein}%`]; }); }