/** * Anzeigehilfen fuer Google-Rezensionen. Reine Funktionen ohne * Seiteneffekte, damit sie ohne Netzwerk testbar sind. */ /** Ab dieser Laenge wird eine Rezension zunaechst gekuerzt angezeigt. */ export const REVIEW_CLAMP_CHARS = 320; /** Initialen statt Profilbild: bis zu zwei Buchstaben aus dem Anzeigenamen. */ export function initialsOf(name: string): string { const letters = name .trim() .split(/\s+/) .map((part) => Array.from(part.replace(/[^\p{L}\p{N}]/gu, ""))[0] ?? "") .filter(Boolean); if (letters.length === 0) return "?"; const pick = letters.length === 1 ? [letters[0]] : [letters[0], letters[letters.length - 1]]; return pick.join("").toLocaleUpperCase("de-DE"); } /** "4,8" – Durchschnitt mit einer Nachkommastelle im deutschen Format. */ export function formatRating(rating: number): string { return rating.toLocaleString("de-DE", { minimumFractionDigits: 1, maximumFractionDigits: 1 }); } /** Zugaenglicher Text fuer eine Sternebewertung, z. B. "4 von 5 Sternen". */ export function starsLabel(rating: number): string { const value = Number.isInteger(rating) ? String(rating) : formatRating(rating); return `${value} von 5 Sternen`; } /** "1 Rezension" bzw. "12 Rezensionen". */ export function reviewCountLabel(count: number): string { return `${count.toLocaleString("de-DE")} ${count === 1 ? "Rezension" : "Rezensionen"}`; } export function needsClamp(text: string): boolean { return text.length > REVIEW_CLAMP_CHARS; }