Neu: Kundenrezensionen mit Herzen in Lila-Babyblau, ueberall im Shop integriert

Neue HeartRating-Komponente (Herzen statt Sterne, Lila-Babyblau-Verlauf wie
der Rest der Markenoptik) + komplettes Rezensions-System:

- Produktkarten: Bewertungszeile (Herzen + Anzahl) unter dem Titel, nur wenn
  Bewertungen vorhanden sind.
- Produktseite: volle "Kundenrezensionen"-Sektion mit Durchschnitt und
  einzelnen Rezensionen (Name, Herzen, Datum, Text) bzw. "Noch keine
  Bewertungen"-Hinweis.
- Shop-Filter: neuer "Mindestbewertung"-Filter im Filter-Sidebar + neue
  Sortierung "Beste Bewertung".
- Startseite: "Was unsere Kund:innen sagen"-Sektion mit Gesamtbewertung und
  den 3 neuesten Rezensionen - erscheint automatisch, sobald die erste echte
  Bewertung existiert.
- Adminbereich: neues Feld "Bewertungen" pro Produkt (Name/Herzen/Text/Datum),
  mit deutlichem Hinweis, dass hier nur echte Kundenrueckmeldungen eingetragen
  werden duerfen - erfundene Bewertungen sind in Deutschland/der EU gesetzlich
  verboten (UWG). Deshalb bewusst OHNE Beispiel-Bewertungen im Code: alle
  Bereiche starten leer und blenden sich automatisch ein, sobald VanVan die
  erste echte Rezension eintraegt.

Mit temporaeren Testdaten end-to-end durchgetestet (Herzen-Darstellung,
Rezensions-Section, Filter, Startseiten-Sektion) und vor dem Commit wieder
aus den echten Produktdaten entfernt. Gilt fuer alle 4 Sprachen.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
qcigano
2026-08-03 03:15:00 +02:00
co-authored by Claude Sonnet 5
parent 1add9a42a1
commit b384938b92
18 changed files with 534 additions and 24 deletions
+7
View File
@@ -5,6 +5,8 @@ import { localePrefix } from "../i18n/config";
import { useTranslations } from "../i18n/ui";
import { formatPrice } from "../i18n/format";
import { effektiverPreis, rabattLabel, hatAktivenRabatt } from "../data/rabatt";
import { durchschnittsbewertung, anzahlBewertungen } from "../data/products";
import HeartRating from "./HeartRating.astro";
interface Props { product: Product; lang: Locale }
const { product, lang } = Astro.props;
@@ -12,6 +14,8 @@ const t = useTranslations(lang);
const finalPrice = effektiverPreis(product);
const discountBadge = rabattLabel(product);
const showOldAsPreis = !product.preisAlt && hatAktivenRabatt(product);
const bewertungSchnitt = durchschnittsbewertung(product);
const bewertungAnzahl = anzahlBewertungen(product);
const badgeLabel: Record<string, string> = {
neu: t.badge.neu,
@@ -55,6 +59,9 @@ const desc = product.beschreibung[lang];
</div>
</div>
<h3>{name}</h3>
{bewertungSchnitt !== null && (
<HeartRating bewertung={bewertungSchnitt} size={13} anzahlLabel={`(${bewertungAnzahl})`} />
)}
<p class="small">{desc.slice(0, 78)}{desc.length > 78 ? "…" : ""}</p>
<div class="price-row">
{product.preisAlt && <span class="price-old">{formatPrice(product.preisAlt, lang)}</span>}