- Produktdetailseite: dezenter Hinweis direkt bei der Kaufentscheidung, dass beim Checkout eine persoenliche Geschenknachricht hinterlegt werden kann (Feature existierte bereits, war aber nur im Checkout-Formular selbst sichtbar — zu spaet, um Mengen-/Produktwahl noch zu beeinflussen) - Produktdetailseite (Honig): kontextuelle Links zu passenden Honigwissen-Artikeln (Kristallisation immer, Fruehtracht/Sommertracht wenn aus Harvest.type erkennbar) direkt bei den Produktdetails statt einer isolierten, von der Kaufseite aus unverlinkten Wissenssektion - Suche (Shop-Uebersicht + Live-Suchvorschlaege) gleicht jetzt deutsche Umlaute/scharfes S gegen ihre ASCII-Transliteration ab (z.B. "Bluete" findet "Bluete"-Produkte, "kraeftig" findet "kräftig") — vorher lieferte eine Suche in der jeweils anderen Schreibweise keine Treffer, obwohl der Katalog durchgaengig echte Umlaute verwendet; Logik in neuer, reiner lib/search-match.ts mit eigenen Tests ausgelagert - Bewusst NICHT angefasst: Newsletter-Rabattanreiz (fehlt, aber Prozentsatz/ Mechanik ist eine Owner-Entscheidung) und Trust-Badges am Kaufabschluss (bereits vorhanden auf Produktseite/Warenkorb/Checkout) Verifikation: pnpm exec tsc --noEmit clean, pnpm test 151/151 (15 Dateien, +9 neue Tests fuer search-match), pnpm build erfolgreich.
30 lines
1.2 KiB
TypeScript
30 lines
1.2 KiB
TypeScript
/**
|
|
* Normalisiert deutsche Umlaute/scharfes S fuer die Produktsuche: "ü", "ö",
|
|
* "ä" und "ß" werden auf ihre gaengige ASCII-Transliteration ("ue", "oe",
|
|
* "ae", "ss") abgebildet. Ohne das liefert eine Suche nach "Bluete" keine
|
|
* Treffer fuer "Blüte" und umgekehrt — viele Kundinnen und Kunden tippen aus
|
|
* Gewohnheit oder auf einer nicht-deutschen Tastatur die ASCII-Schreibweise,
|
|
* waehrend Produktnamen/-tags im Katalog durchgaengig echte Umlaute nutzen
|
|
* (z.B. "Frühtracht", "kräftig", "Altenmünster").
|
|
*/
|
|
export function normalizeSearchText(value: string): string {
|
|
return value
|
|
.toLowerCase()
|
|
.replace(/ä/g, "ae")
|
|
.replace(/ö/g, "oe")
|
|
.replace(/ü/g, "ue")
|
|
.replace(/ß/g, "ss");
|
|
}
|
|
|
|
/**
|
|
* Mehrwortige Teilstring-Suche: jedes Wort aus `query` muss irgendwo in
|
|
* `haystack` vorkommen (Reihenfolge egal), umlaut-unabhaengig in beide
|
|
* Richtungen (echter Umlaut <-> ASCII-Transliteration).
|
|
*/
|
|
export function matchesSearchQuery(haystack: string, query: string): boolean {
|
|
const words = normalizeSearchText(query).split(/\s+/).filter(Boolean);
|
|
if (words.length === 0) return true;
|
|
const normalizedHaystack = normalizeSearchText(haystack);
|
|
return words.every((word) => normalizedHaystack.includes(word));
|
|
}
|