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
+31 -1
View File
@@ -1,15 +1,20 @@
---
import Layout from "../../layouts/Layout.astro";
import ProductCard from "../../components/ProductCard.astro";
import HeartRating from "../../components/HeartRating.astro";
import { categories } from "../../data/categories";
import { products } from "../../data/products";
import { products, alleBewertungen, gesamtDurchschnitt } from "../../data/products";
import { useTranslations } from "../../i18n/ui";
import type { Locale } from "../../i18n/config";
const lang: Locale = "fr";
const t = useTranslations(lang);
const neuheiten = products.filter((p) => p.badges.includes("neu")).slice(0, 4);
const bestseller = products.filter((p) => p.badges.includes("bestseller")).slice(0, 4);
const sale = products.filter((p) => p.badges.includes("sale") || p.preisAlt).slice(0, 4);
const topBewertungen = alleBewertungen().slice(0, 3);
const bewertungSchnittGesamt = gesamtDurchschnitt();
---
<Layout title="Accueil" lang={lang} path="/">
<section class="hero">
@@ -84,6 +89,31 @@ const sale = products.filter((p) => p.badges.includes("sale") || p.preisAlt).sli
</section>
)}
{topBewertungen.length > 0 && bewertungSchnittGesamt !== null && (
<section class="section-tight">
<div class="container">
<span class="eyebrow">🩵 {t.reviews.heading}</span>
<h2>{t.reviews.heading}</h2>
<p class="lead">{t.reviews.lead}</p>
<div class="review-summary-row">
<HeartRating bewertung={bewertungSchnittGesamt} size={24} showValue={true} anzahlLabel={t.reviews.basedOn(alleBewertungen().length)} />
</div>
<div class="grid grid-3">
{topBewertungen.map((r) => (
<div class="card review-card">
<div class="review-card-head">
<span class="review-name">{r.name}</span>
<HeartRating bewertung={r.bewertung} size={14} />
</div>
{r.text && <p class="small">{r.text[lang]}</p>}
<a class="small" href={`/fr/produkt/${r.produktSlug}/`}>{t.reviews.toProduct} {r.produktName[lang]}</a>
</div>
))}
</div>
</div>
</section>
)}
<section class="section">
<div class="container grid grid-2 creator-section">
<div class="portrait-frame creator-photo">