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]>
84 lines
3.0 KiB
TypeScript
84 lines
3.0 KiB
TypeScript
// Rein clientseitiges "Konto" (Phase 1, kein echtes Login/Backend) — genau wie der Warenkorb
|
|
// (siehe cart.ts) im localStorage gespeichert. Ermöglicht schon jetzt eine echte, durchgängige
|
|
// Demo: anmelden, Profil pflegen, Bestellungen bewerten, Kopfzeile reagiert überall darauf.
|
|
// TODO Phase 2: durch echtes Login (Cloudflare Worker + D1, siehe Tech-Stack-Entscheidung im
|
|
// Projekt-Vault) ersetzen — Struktur/Feldnamen bewusst schon so gewählt, dass sich eine echte
|
|
// Session später 1:1 einsetzen lässt, ohne Aufrufstellen in der ganzen Seite anpassen zu müssen.
|
|
|
|
export interface Account {
|
|
loggedIn: boolean;
|
|
username: string;
|
|
email: string;
|
|
/** Profilfoto als data:-URL (im Browser aus der hochgeladenen Datei erzeugt). */
|
|
photo: string;
|
|
/** "<bestellnummer>:<produkt-slug>"-Paare, zu denen schon eine Rezension abgegeben wurde. */
|
|
bewerteteBestellungen: string[];
|
|
}
|
|
|
|
const KEY = "vandiy_account_v1";
|
|
|
|
function leeresKonto(): Account {
|
|
return { loggedIn: false, username: "", email: "", photo: "", bewerteteBestellungen: [] };
|
|
}
|
|
|
|
export function getAccount(): Account {
|
|
if (typeof localStorage === "undefined") return leeresKonto();
|
|
try {
|
|
return { ...leeresKonto(), ...JSON.parse(localStorage.getItem(KEY) || "{}") };
|
|
} catch {
|
|
return leeresKonto();
|
|
}
|
|
}
|
|
|
|
function saveAccount(a: Account) {
|
|
localStorage.setItem(KEY, JSON.stringify(a));
|
|
window.dispatchEvent(new CustomEvent("account:changed", { detail: a }));
|
|
}
|
|
|
|
export function isLoggedIn(): boolean {
|
|
return getAccount().loggedIn;
|
|
}
|
|
|
|
/** Demo-Anmeldung: es gibt noch keine echte Passwortprüfung (Phase 2) — jede E-Mail meldet an,
|
|
* der Benutzername wird beim ersten Mal aus dem E-Mail-Namen abgeleitet, bleibt danach aber
|
|
* erhalten (spätere Logins überschreiben einen schon gewählten Benutzernamen nicht). */
|
|
export function login(email: string): Account {
|
|
const bestehend = getAccount();
|
|
const account: Account = {
|
|
...bestehend,
|
|
loggedIn: true,
|
|
email: email.trim(),
|
|
username: bestehend.username || email.split("@")[0] || "Kundin",
|
|
};
|
|
saveAccount(account);
|
|
return account;
|
|
}
|
|
|
|
export function logout() {
|
|
saveAccount({ ...getAccount(), loggedIn: false });
|
|
}
|
|
|
|
export function setUsername(username: string) {
|
|
saveAccount({ ...getAccount(), username: username.trim() });
|
|
}
|
|
|
|
export function setPhoto(dataUrl: string) {
|
|
saveAccount({ ...getAccount(), photo: dataUrl });
|
|
}
|
|
|
|
export function bestellSchluessel(bestellnummer: string, produktSlug: string): string {
|
|
return `${bestellnummer}:${produktSlug}`;
|
|
}
|
|
|
|
export function hatBestellungBewertet(bestellnummer: string, produktSlug: string): boolean {
|
|
return getAccount().bewerteteBestellungen.includes(bestellSchluessel(bestellnummer, produktSlug));
|
|
}
|
|
|
|
export function markiereBestellungBewertet(bestellnummer: string, produktSlug: string) {
|
|
const a = getAccount();
|
|
const schluessel = bestellSchluessel(bestellnummer, produktSlug);
|
|
if (!a.bewerteteBestellungen.includes(schluessel)) {
|
|
saveAccount({ ...a, bewerteteBestellungen: [...a.bewerteteBestellungen, schluessel] });
|
|
}
|
|
}
|