Kundenrezensionen jetzt vollständig durch Kund:innen selbst, nicht mehr über Admin
Bisher musste VanVan Bewertungen manuell im CMS eintragen. Jetzt können angemeldete Kund:innen Rezensionen direkt auf der Produktseite abgeben (inkl. Herzen-Sternebewertung und Text). Die Durchschnittsbewertung wird automatisch berechnet und überall live eingebunden: Produktkarten (shop-weit), Produktdetailseite, Shop-Filter/Sortierung nach Bewertung und die Kundenstimmen-Sektion auf der Startseite. Neu dazu: ein Kontobereich fürs Login (Demo-Login per E-Mail), Profilfoto- Upload, wählbarer Benutzername, und ein Header-Kontomenü, das nur bei Anmeldung erscheint. Jede Bestellung im Konto-Dashboard hat einen "Rezension schreiben"-Link, der direkt zur Produktseite führt und dort per Bestellnummer verknüpft wird; im Profil ist dann sofort sichtbar, welche Bestellungen schon bewertet wurden. Technisch als reines Frontend/localStorage-System umgesetzt (kein Backend in dieser Phase), analog zum bestehenden Warenkorb-Muster. Admin-CMS-Feld für manuelle Bewertungen entfernt, da Rezensionen jetzt ausschließlich von Kund:innen kommen (auch aus rechtlichen Gründen: keine Fake-Bewertungen). Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
d27a858d8f
commit
6f10e41386
+56
-20
@@ -8,6 +8,7 @@ import type { Locale } from "./config";
|
||||
export const ui = {
|
||||
de: {
|
||||
nav: { shop: "Shop", sale: "Sale", creative: "Über die Kreative", faq: "FAQ", contact: "Kontakt", account: "Mein Konto", login: "Anmelden" },
|
||||
accountMenu: { myAccount: "Mein Konto", logout: "Abmelden" },
|
||||
topbar: "Versandkostenfrei ab 75 € innerhalb DE/AT/CH/LU",
|
||||
footer: {
|
||||
tagline: "Handgemacht mit Liebe – Kreativität zum Verschenken und Selbstbehalten.",
|
||||
@@ -38,6 +39,10 @@ export const ui = {
|
||||
photoNote: "echte Fotos ergänzt VanVan später",
|
||||
reviewsTitle: "Kundenrezensionen", noReviews: "Noch keine Bewertungen für dieses Produkt — sei die/der Erste!",
|
||||
reviewCount: (n: number) => `${n} Bewertung${n === 1 ? "" : "en"}`,
|
||||
writeReviewTitle: "🩵 Deine Rezension", yourRating: "Deine Bewertung", yourReview: "Was hat dir gefallen? (optional)",
|
||||
yourName: "Dein Name", submitReview: "Rezension veröffentlichen", reviewSaved: "Danke für deine Rezension! ✓",
|
||||
reviewNeedsRating: "Bitte wähle 1–5 Herzen aus.", reviewFromOrder: (nr: string) => `Du bewertest deine Bestellung ${nr}.`,
|
||||
loginHintReview: "Angemeldet als", notLoggedInReview: "Du bist nicht angemeldet — deine Rezension wird mit dem eingegebenen Namen veröffentlicht.",
|
||||
},
|
||||
shop: {
|
||||
title: "Alle Produkte", lead: "Stöbere durch alle handgemachten Stücke – filtere und sortiere nach deinen Wünschen.",
|
||||
@@ -198,15 +203,16 @@ export const ui = {
|
||||
},
|
||||
account: {
|
||||
eyebrow: "Mein Konto", title: "Anmelden oder als Gast bestellen",
|
||||
todoNote: "Phase 1 – reine Oberfläche ohne echtes Login/Registrierung. Bestellhistorie, Sendungsverfolgung, Wunschliste und \"Zuletzt angesehen\" folgen in Phase 2 mit echter Datenbank-Anbindung.",
|
||||
loginTitle: "Anmelden", email: "E-Mail", password: "Passwort", loginButton: "Anmelden (folgt in Phase 2)", forgotPassword: "Passwort vergessen?",
|
||||
todoNote: "Phase 1 – Demo-Anmeldung ohne echte Passwortprüfung: Jede E-Mail-Adresse funktioniert, das Passwort-Feld ist reine Vorschau. Die Bestellungen im Konto sind Beispieldaten. Eine echte Anmeldung mit Datenbank kommt in Phase 2.",
|
||||
loginTitle: "Anmelden", email: "E-Mail", password: "Passwort", loginButton: "Anmelden", forgotPassword: "Passwort vergessen?",
|
||||
newTitle: "Neu hier?", newText: "Lege ein Konto an, um Bestellhistorie, Wunschliste und Sendungsverfolgung an einem Ort zu haben – oder bestelle einfach als Gast, ganz ohne Konto.",
|
||||
guestButton: "Als Gast weiter einkaufen",
|
||||
previewLink: "👁️ Vorschau: So sieht der Bereich für angemeldete Kund:innen aus",
|
||||
loginError: "Bitte gib eine E-Mail-Adresse ein.",
|
||||
},
|
||||
accountDash: {
|
||||
eyebrow: "Mein Konto", greeting: "Hallo Marie 🩵", lead: "Schön, dass du wieder da bist. Hier findest du alle deine Bestellungen, deine Wunschliste und deine Daten auf einen Blick.",
|
||||
previewNote: "VORSCHAU-ANSICHT (Phase 1): So sieht der persönliche Bereich aus, sobald ein:e Kund:in angemeldet ist. Die hier gezeigten Bestellungen und Daten sind reine Beispieldaten zur Gestaltung — es gibt noch kein echtes Login und keine echte Datenbank. Beides kommt in Phase 2 (Cloudflare Worker + D1), danach zeigt diese Seite die echten Daten der jeweils angemeldeten Person.",
|
||||
eyebrow: "Mein Konto", greeting: (name: string) => `Hallo ${name} 🩵`, lead: "Schön, dass du wieder da bist. Hier findest du alle deine Bestellungen, deine Wunschliste und deine Daten auf einen Blick.",
|
||||
previewNote: "Phase 1: Deine Anmeldung, dein Profil und deine Rezensionen werden schon jetzt echt auf diesem Gerät gespeichert. Nur die Bestellungen unten sind Beispieldaten zur Gestaltung — echte Bestellungen kommen in Phase 2 mit Zahlungsanbindung und Datenbank (Cloudflare Worker + D1).",
|
||||
notLoggedIn: "Du bist nicht angemeldet — du wirst zur Anmeldung weitergeleitet …",
|
||||
logout: "Abmelden",
|
||||
statOrders: "Bestellungen", statWishlist: "Wunschliste", statOpen: "Offene Sendungen",
|
||||
ordersTitle: "📦 Meine Bestellungen",
|
||||
@@ -216,10 +222,14 @@ export const ui = {
|
||||
wishlistTitle: "🩵 Meine Wunschliste", wishlistEmpty: "Deine Wunschliste ist noch leer — stöbere im Shop und speichere deine Lieblingsstücke mit dem Herz-Symbol.",
|
||||
recentTitle: "🕘 Zuletzt angesehen",
|
||||
profileTitle: "👤 Meine Daten", profileName: "Name", profileEmail: "E-Mail", profileAddress: "Lieferadresse", profileEdit: "Daten bearbeiten",
|
||||
reviewBtn: "🩵 Rezension schreiben", reviewedBadge: "✓ Bewertet",
|
||||
usernameLabel: "Benutzername", usernameSave: "Speichern", usernameSaved: "Gespeichert ✓",
|
||||
photoLabel: "Profilfoto", photoChange: "Foto ändern", photoRemove: "Entfernen",
|
||||
},
|
||||
},
|
||||
en: {
|
||||
nav: { shop: "Shop", sale: "Sale", creative: "About the Maker", faq: "FAQ", contact: "Contact", account: "My Account", login: "Sign in" },
|
||||
accountMenu: { myAccount: "My Account", logout: "Sign out" },
|
||||
topbar: "Free shipping from €75 within DE/AT/CH/LU",
|
||||
footer: {
|
||||
tagline: "Handmade with love – creativity to gift and to keep.",
|
||||
@@ -250,6 +260,10 @@ export const ui = {
|
||||
photoNote: "real photos will be added by VanVan later",
|
||||
reviewsTitle: "Customer reviews", noReviews: "No reviews yet for this product — be the first!",
|
||||
reviewCount: (n: number) => `${n} review${n === 1 ? "" : "s"}`,
|
||||
writeReviewTitle: "🩵 Your review", yourRating: "Your rating", yourReview: "What did you like? (optional)",
|
||||
yourName: "Your name", submitReview: "Publish review", reviewSaved: "Thanks for your review! ✓",
|
||||
reviewNeedsRating: "Please choose 1–5 hearts.", reviewFromOrder: (nr: string) => `You're reviewing your order ${nr}.`,
|
||||
loginHintReview: "Signed in as", notLoggedInReview: "You're not signed in — your review will be published under the name you enter.",
|
||||
},
|
||||
shop: {
|
||||
title: "All products", lead: "Browse all handmade pieces – filter and sort to your liking.",
|
||||
@@ -410,15 +424,16 @@ export const ui = {
|
||||
},
|
||||
account: {
|
||||
eyebrow: "My Account", title: "Sign in or check out as a guest",
|
||||
todoNote: "Phase 1 – interface only, no real login/registration yet. Order history, tracking, wishlist and \"recently viewed\" follow in Phase 2 with a real database connection.",
|
||||
loginTitle: "Sign in", email: "Email", password: "Password", loginButton: "Sign in (coming in Phase 2)", forgotPassword: "Forgot password?",
|
||||
todoNote: "Phase 1 – demo sign-in without real password checking: any email address works, the password field is a preview only. Orders shown in the account are example data. A real login with a database is coming in Phase 2.",
|
||||
loginTitle: "Sign in", email: "Email", password: "Password", loginButton: "Sign in", forgotPassword: "Forgot password?",
|
||||
newTitle: "New here?", newText: "Create an account to keep order history, wishlist and tracking in one place – or simply check out as a guest, no account needed.",
|
||||
guestButton: "Continue shopping as guest",
|
||||
previewLink: "👁️ Preview: what signed-in customers see",
|
||||
loginError: "Please enter an email address.",
|
||||
},
|
||||
accountDash: {
|
||||
eyebrow: "My Account", greeting: "Hello Marie 🩵", lead: "Good to see you again. Here you'll find all your orders, your wishlist and your details at a glance.",
|
||||
previewNote: "PREVIEW (Phase 1): This is what the personal area looks like once a customer is signed in. The orders and details shown here are example data for design purposes only — there is no real login or database yet. Both are coming in Phase 2 (Cloudflare Worker + D1), after which this page will show the signed-in person's real data.",
|
||||
eyebrow: "My Account", greeting: (name: string) => `Hello ${name} 🩵`, lead: "Good to see you again. Here you'll find all your orders, your wishlist and your details at a glance.",
|
||||
previewNote: "Phase 1: your sign-in, your profile and your reviews are already genuinely saved on this device. Only the orders below are example data for design purposes — real orders arrive in Phase 2 with payment integration and a database (Cloudflare Worker + D1).",
|
||||
notLoggedIn: "You're not signed in — redirecting you to sign in …",
|
||||
logout: "Sign out",
|
||||
statOrders: "Orders", statWishlist: "Wishlist", statOpen: "Open shipments",
|
||||
ordersTitle: "📦 My orders",
|
||||
@@ -428,10 +443,14 @@ export const ui = {
|
||||
wishlistTitle: "🩵 My wishlist", wishlistEmpty: "Your wishlist is still empty — browse the shop and save your favourites with the heart icon.",
|
||||
recentTitle: "🕘 Recently viewed",
|
||||
profileTitle: "👤 My details", profileName: "Name", profileEmail: "Email", profileAddress: "Delivery address", profileEdit: "Edit details",
|
||||
reviewBtn: "🩵 Write a review", reviewedBadge: "✓ Reviewed",
|
||||
usernameLabel: "Username", usernameSave: "Save", usernameSaved: "Saved ✓",
|
||||
photoLabel: "Profile photo", photoChange: "Change photo", photoRemove: "Remove",
|
||||
},
|
||||
},
|
||||
ch: {
|
||||
nav: { shop: "Shop", sale: "Aktion", creative: "Über d'Kreativi", faq: "FAQ", contact: "Kontakt", account: "Mis Konto", login: "Aamälde" },
|
||||
accountMenu: { myAccount: "Mis Konto", logout: "Abmälde" },
|
||||
topbar: "Gratisversand ab 75 € innerhalb DE/AT/CH/LU",
|
||||
footer: {
|
||||
tagline: "Vo Hang gmacht mit Härz – Sächeli zum Verschänke und Sälber Bhalte.",
|
||||
@@ -462,6 +481,10 @@ export const ui = {
|
||||
photoNote: "echti Fotis macht VanVan später drby",
|
||||
reviewsTitle: "Kundebewärtige", noReviews: "No kei Bewärtige für das Produkt — sei du dr Erschti!",
|
||||
reviewCount: (n: number) => `${n} Bewärtig${n === 1 ? "" : "e"}`,
|
||||
writeReviewTitle: "🩵 Dini Bewärtig", yourRating: "Dini Bewärtig", yourReview: "Was hat dir gfalle? (optional)",
|
||||
yourName: "Din Name", submitReview: "Bewärtig veröffentliche", reviewSaved: "Danke für dini Bewärtig! ✓",
|
||||
reviewNeedsRating: "Bitte wähl 1–5 Herzli us.", reviewFromOrder: (nr: string) => `Du bewärtisch dini Bstellig ${nr}.`,
|
||||
loginHintReview: "Aagmäldet als", notLoggedInReview: "Du bisch nid aagmäldet — dini Bewärtig wird mit em iigäbene Name veröffentlicht.",
|
||||
},
|
||||
shop: {
|
||||
title: "Alli Produkt", lead: "Lueg dr alli vo Hang gmachte Sächeli a – filtere und sortiere, wie's dir passt.",
|
||||
@@ -622,15 +645,16 @@ export const ui = {
|
||||
},
|
||||
account: {
|
||||
eyebrow: "Mis Konto", title: "Aamälde oder als Gast bstelle",
|
||||
todoNote: "Phase 1 – nume d'Oberflächi ohni echts Login/Registrierig. Bstellhistorie, Sändigsverfolgig, Wunschlischte und \"Zletscht aagluegt\" chöme i Phase 2.",
|
||||
loginTitle: "Aamälde", email: "E-Mail", password: "Passwort", loginButton: "Aamälde (chunnt i Phase 2)", forgotPassword: "Passwort vergässe?",
|
||||
todoNote: "Phase 1 – Demo-Aamäldig ohni echti Passwortprüefig: jedi E-Mail-Adrässe funktioniert, s'Passwort-Fäld isch nume Vorschau. D'Bstellige im Konto sind Bispieldate. E echti Aamäldig mit Datebank chunnt i Phase 2.",
|
||||
loginTitle: "Aamälde", email: "E-Mail", password: "Passwort", loginButton: "Aamälde", forgotPassword: "Passwort vergässe?",
|
||||
newTitle: "Neu da?", newText: "Leg es Konto a, für Bstellhistorie, Wunschlischte und Sändigsverfolgig a einem Ort z'ha – oder bstell eifach als Gast, ganz ohni Konto.",
|
||||
guestButton: "Als Gast wyter yichaufe",
|
||||
previewLink: "👁️ Vorschau: so gseht dr Bereich für aagmäldeti Kund:inne us",
|
||||
loginError: "Bitte gib e E-Mail-Adrässe i.",
|
||||
},
|
||||
accountDash: {
|
||||
eyebrow: "Mis Konto", greeting: "Hoi Marie 🩵", lead: "Schön, bisch wieder da. Da findsch alli dini Bstellige, dini Wunschlischte und dini Date uf ein Blick.",
|
||||
previewNote: "VORSCHAU (Phase 1): So gseht dr persönlich Bereich us, sobald öpper aagmäldet isch. D'Bstellige und Date wo da zeigt werde, sind reini Bispieldate für d'Gstaltig — es git no kei echts Login und kei echti Datebank. Beides chunnt i Phase 2 (Cloudflare Worker + D1), denn zeigt die Syte d'echte Date vo dr aagmäldete Person.",
|
||||
eyebrow: "Mis Konto", greeting: (name: string) => `Hoi ${name} 🩵`, lead: "Schön, bisch wieder da. Da findsch alli dini Bstellige, dini Wunschlischte und dini Date uf ein Blick.",
|
||||
previewNote: "Phase 1: dini Aamäldig, dis Profil und dini Bewärtige werde scho jetzt echt uf däm Gerät gspeicheret. Nume d'Bstellige unde sind Bispieldate für d'Gstaltig — echti Bstellige chöme i Phase 2 mit Zahligsaabindig und Datebank (Cloudflare Worker + D1).",
|
||||
notLoggedIn: "Du bisch nid aagmäldet — du wirsch zur Aamäldig wytergleitet …",
|
||||
logout: "Abmälde",
|
||||
statOrders: "Bstellige", statWishlist: "Wunschlischte", statOpen: "Offni Sändige",
|
||||
ordersTitle: "📦 Mini Bstellige",
|
||||
@@ -640,10 +664,14 @@ export const ui = {
|
||||
wishlistTitle: "🩵 Mini Wunschlischte", wishlistEmpty: "Dini Wunschlischte isch no leer — lueg im Shop verbi und spicher dini Lieblingssächeli mit em Härz-Symbol.",
|
||||
recentTitle: "🕘 Zletscht aagluegt",
|
||||
profileTitle: "👤 Mini Date", profileName: "Name", profileEmail: "E-Mail", profileAddress: "Lieferadrässe", profileEdit: "Date bearbeite",
|
||||
reviewBtn: "🩵 Bewärtig schrybe", reviewedBadge: "✓ Bewärtet",
|
||||
usernameLabel: "Benutzername", usernameSave: "Spichere", usernameSaved: "Gspicheret ✓",
|
||||
photoLabel: "Profilfoto", photoChange: "Foto ändere", photoRemove: "Entferne",
|
||||
},
|
||||
},
|
||||
fr: {
|
||||
nav: { shop: "Boutique", sale: "Soldes", creative: "À propos de la créatrice", faq: "FAQ", contact: "Contact", account: "Mon compte", login: "Se connecter" },
|
||||
accountMenu: { myAccount: "Mon compte", logout: "Se déconnecter" },
|
||||
topbar: "Livraison gratuite dès 75 € en DE/AT/CH/LU",
|
||||
footer: {
|
||||
tagline: "Fait main avec amour – de la créativité à offrir ou à garder.",
|
||||
@@ -674,6 +702,10 @@ export const ui = {
|
||||
photoNote: "VanVan ajoutera de vraies photos plus tard",
|
||||
reviewsTitle: "Avis clients", noReviews: "Pas encore d'avis pour ce produit — soyez le/la premier(ère) !",
|
||||
reviewCount: (n: number) => `${n} avis`,
|
||||
writeReviewTitle: "🩵 Votre avis", yourRating: "Votre note", yourReview: "Qu'avez-vous aimé ? (facultatif)",
|
||||
yourName: "Votre nom", submitReview: "Publier l'avis", reviewSaved: "Merci pour votre avis ! ✓",
|
||||
reviewNeedsRating: "Merci de choisir 1 à 5 cœurs.", reviewFromOrder: (nr: string) => `Vous évaluez votre commande ${nr}.`,
|
||||
loginHintReview: "Connecté(e) en tant que", notLoggedInReview: "Vous n'êtes pas connecté(e) — votre avis sera publié sous le nom que vous indiquez.",
|
||||
},
|
||||
shop: {
|
||||
title: "Tous les produits", lead: "Parcourez toutes les pièces faites main – filtrez et triez selon vos envies.",
|
||||
@@ -834,15 +866,16 @@ export const ui = {
|
||||
},
|
||||
account: {
|
||||
eyebrow: "Mon compte", title: "Se connecter ou commander en tant qu'invité",
|
||||
todoNote: "Phase 1 – interface uniquement, pas encore de vraie connexion/inscription. L'historique des commandes, le suivi, la liste de souhaits et \"vu récemment\" suivront en phase 2.",
|
||||
loginTitle: "Se connecter", email: "E-mail", password: "Mot de passe", loginButton: "Se connecter (disponible en phase 2)", forgotPassword: "Mot de passe oublié ?",
|
||||
todoNote: "Phase 1 – connexion de démonstration sans vérification réelle du mot de passe : n'importe quelle adresse e-mail fonctionne, le champ mot de passe n'est qu'un aperçu. Les commandes affichées dans le compte sont des exemples. Une vraie connexion avec base de données arrivera en phase 2.",
|
||||
loginTitle: "Se connecter", email: "E-mail", password: "Mot de passe", loginButton: "Se connecter", forgotPassword: "Mot de passe oublié ?",
|
||||
newTitle: "Nouveau ici ?", newText: "Créez un compte pour retrouver l'historique des commandes, la liste de souhaits et le suivi au même endroit – ou commandez simplement en tant qu'invité, sans compte.",
|
||||
guestButton: "Continuer mes achats en tant qu'invité",
|
||||
previewLink: "👁️ Aperçu : l'espace vu par les client(e)s connecté(e)s",
|
||||
loginError: "Veuillez saisir une adresse e-mail.",
|
||||
},
|
||||
accountDash: {
|
||||
eyebrow: "Mon compte", greeting: "Bonjour Marie 🩵", lead: "Ravie de vous revoir. Retrouvez ici toutes vos commandes, votre liste de souhaits et vos données en un coup d'œil.",
|
||||
previewNote: "APERÇU (phase 1) : voici à quoi ressemble l'espace personnel une fois le/la client(e) connecté(e). Les commandes et données affichées ici sont des exemples destinés à la conception — il n'existe encore ni connexion réelle ni base de données. Les deux arriveront en phase 2 (Cloudflare Worker + D1) ; cette page affichera alors les données réelles de la personne connectée.",
|
||||
eyebrow: "Mon compte", greeting: (name: string) => `Bonjour ${name} 🩵`, lead: "Ravie de vous revoir. Retrouvez ici toutes vos commandes, votre liste de souhaits et vos données en un coup d'œil.",
|
||||
previewNote: "Phase 1 : votre connexion, votre profil et vos avis sont déjà réellement enregistrés sur cet appareil. Seules les commandes ci-dessous sont des exemples destinés à la conception — les vraies commandes arriveront en phase 2 avec le paiement et une base de données (Cloudflare Worker + D1).",
|
||||
notLoggedIn: "Vous n'êtes pas connecté(e) — redirection vers la connexion …",
|
||||
logout: "Se déconnecter",
|
||||
statOrders: "Commandes", statWishlist: "Liste de souhaits", statOpen: "Envois en cours",
|
||||
ordersTitle: "📦 Mes commandes",
|
||||
@@ -852,6 +885,9 @@ export const ui = {
|
||||
wishlistTitle: "🩵 Ma liste de souhaits", wishlistEmpty: "Votre liste de souhaits est encore vide — parcourez la boutique et enregistrez vos coups de cœur avec l'icône en forme de cœur.",
|
||||
recentTitle: "🕘 Vus récemment",
|
||||
profileTitle: "👤 Mes données", profileName: "Nom", profileEmail: "E-mail", profileAddress: "Adresse de livraison", profileEdit: "Modifier mes données",
|
||||
reviewBtn: "🩵 Écrire un avis", reviewedBadge: "✓ Avis publié",
|
||||
usernameLabel: "Nom d'utilisateur", usernameSave: "Enregistrer", usernameSaved: "Enregistré ✓",
|
||||
photoLabel: "Photo de profil", photoChange: "Changer la photo", photoRemove: "Supprimer",
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
Reference in New Issue
Block a user