Files
vans-diy-bastelbedarf/src/scripts/account.ts
T
qciganoandClaude Sonnet 5 6f10e41386 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]>
2026-08-03 04:17:04 +02:00

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] });
}
}