diff --git a/src/i18n/ui.ts b/src/i18n/ui.ts
index 7ae75ca..a7ed19d 100644
--- a/src/i18n/ui.ts
+++ b/src/i18n/ui.ts
@@ -202,6 +202,20 @@ export const ui = {
loginTitle: "Anmelden", email: "E-Mail", password: "Passwort", loginButton: "Anmelden (folgt in Phase 2)", 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",
+ },
+ 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.",
+ logout: "Abmelden",
+ statOrders: "Bestellungen", statWishlist: "Wunschliste", statOpen: "Offene Sendungen",
+ ordersTitle: "đŠ Meine Bestellungen",
+ orderNo: "Bestellung", orderDate: "Bestellt am", orderTotal: "Gesamt", orderItems: "Artikel",
+ trackingLabel: "Sendungsverfolgung", trackingBtn: "Sendung verfolgen â", invoiceBtn: "Rechnung (PDF)", reorderBtn: "Nochmal bestellen",
+ statusBezahlt: "Bezahlt", statusBearbeitung: "In Bearbeitung", statusVersandVorbereitet: "Versand vorbereitet", statusVersendet: "Versendet", statusAbgeschlossen: "Abgeschlossen",
+ 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",
},
},
en: {
@@ -400,6 +414,20 @@ export const ui = {
loginTitle: "Sign in", email: "Email", password: "Password", loginButton: "Sign in (coming in Phase 2)", 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",
+ },
+ 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.",
+ logout: "Sign out",
+ statOrders: "Orders", statWishlist: "Wishlist", statOpen: "Open shipments",
+ ordersTitle: "đŠ My orders",
+ orderNo: "Order", orderDate: "Ordered on", orderTotal: "Total", orderItems: "Items",
+ trackingLabel: "Tracking", trackingBtn: "Track shipment â", invoiceBtn: "Invoice (PDF)", reorderBtn: "Order again",
+ statusBezahlt: "Paid", statusBearbeitung: "In progress", statusVersandVorbereitet: "Preparing shipment", statusVersendet: "Shipped", statusAbgeschlossen: "Completed",
+ 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",
},
},
ch: {
@@ -598,6 +626,20 @@ export const ui = {
loginTitle: "AamÀlde", email: "E-Mail", password: "Passwort", loginButton: "AamÀlde (chunnt i Phase 2)", 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",
+ },
+ 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.",
+ logout: "AbmÀlde",
+ statOrders: "Bstellige", statWishlist: "Wunschlischte", statOpen: "Offni SĂ€ndige",
+ ordersTitle: "đŠ Mini Bstellige",
+ orderNo: "Bstellig", orderDate: "Bstellt am", orderTotal: "Total", orderItems: "Artikel",
+ trackingLabel: "SĂ€ndigsverfolgig", trackingBtn: "SĂ€ndig verfolge â", invoiceBtn: "RĂ€chnig (PDF)", reorderBtn: "Nomal bstelle",
+ statusBezahlt: "Zahlt", statusBearbeitung: "I dr Bearbeitig", statusVersandVorbereitet: "Versand vorbereitet", statusVersendet: "Verschickt", statusAbgeschlossen: "Abgschlosse",
+ 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",
},
},
fr: {
@@ -796,6 +838,20 @@ export const ui = {
loginTitle: "Se connecter", email: "E-mail", password: "Mot de passe", loginButton: "Se connecter (disponible en phase 2)", 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",
+ },
+ 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.",
+ logout: "Se déconnecter",
+ statOrders: "Commandes", statWishlist: "Liste de souhaits", statOpen: "Envois en cours",
+ ordersTitle: "đŠ Mes commandes",
+ orderNo: "Commande", orderDate: "Commandé le", orderTotal: "Total", orderItems: "Articles",
+ trackingLabel: "Suivi", trackingBtn: "Suivre l'envoi â", invoiceBtn: "Facture (PDF)", reorderBtn: "Commander Ă nouveau",
+ statusBezahlt: "Payée", statusBearbeitung: "En préparation", statusVersandVorbereitet: "Envoi en préparation", statusVersendet: "Expédiée", statusAbgeschlossen: "Terminée",
+ 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",
},
},
} as const;
diff --git a/src/pages/ch/konto/angemeldet.astro b/src/pages/ch/konto/angemeldet.astro
new file mode 100644
index 0000000..a420e11
--- /dev/null
+++ b/src/pages/ch/konto/angemeldet.astro
@@ -0,0 +1,160 @@
+---
+import Layout from "../../../layouts/Layout.astro";
+import ProductCard from "../../../components/ProductCard.astro";
+import { products } from "../../../data/products";
+import type { Locale } from "../../../i18n/config";
+import { useTranslations } from "../../../i18n/ui";
+import { formatPrice } from "../../../i18n/format";
+
+const lang: Locale = "ch";
+const t = useTranslations(lang);
+
+// VORSCHAU-SEITE (Phase 1): So sieht der persönliche Bereich aus, sobald jemand angemeldet ist.
+// Es gibt noch kein echtes Login und keine Datenbank â die Bestellungen unten sind reine
+// Beispieldaten, damit Aufbau, Status-Anzeige und Bedienung schon jetzt beurteilt und
+// weiterentwickelt werden können. In Phase 2 (Cloudflare Worker + D1) werden sie durch die
+// echten Daten der angemeldeten Person ersetzt; Layout und Texte bleiben dann bestehen.
+const beispielBestellungen = [
+ {
+ nummer: "VDB-2026-0184",
+ datum: "28.07.2026",
+ status: "versendet" as const,
+ summe: 47.5,
+ tracking: "00340434161094015791",
+ artikel: [
+ { name: "\"HasiDog\" im blauen Overall", menge: 1, preis: 25 },
+ { name: "Perlenarmband âHimmelblau\"", menge: 1, preis: 14.5 },
+ ],
+ },
+ {
+ nummer: "VDB-2026-0157",
+ datum: "12.07.2026",
+ status: "abgeschlossen" as const,
+ summe: 22,
+ tracking: null,
+ artikel: [{ name: "Ergonomisches HĂ€kelnadel-Set (9-teilig)", menge: 1, preis: 22 }],
+ },
+];
+
+const statusLabel = {
+ bezahlt: t.accountDash.statusBezahlt,
+ bearbeitung: t.accountDash.statusBearbeitung,
+ versandVorbereitet: t.accountDash.statusVersandVorbereitet,
+ versendet: t.accountDash.statusVersendet,
+ abgeschlossen: t.accountDash.statusAbgeschlossen,
+} as const;
+
+// "Zuletzt angesehen" zeigt in dieser Vorschau einfach die ersten echten Produkte aus dem Shop â
+// in Phase 2 kommt hier die tatsÀchliche Verlaufs-Historie der angemeldeten Person hin.
+const zuletztAngesehen = products.slice(0, 3);
+const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versendet").length;
+---
+
+
+
+
{t.accountDash.previewNote}
+
+
+
+
+
+
+
+
+
+ {beispielBestellungen.length}
+ {t.accountDash.statOrders}
+
+
+ 0
+ {t.accountDash.statWishlist}
+
+
+ {offeneSendungen}
+ {t.accountDash.statOpen}
+
+
+
+
+
+
+
+
{t.accountDash.ordersTitle}
+
+ {beispielBestellungen.map((b) => (
+
+
+
+ {t.accountDash.orderNo} {b.nummer}
+ {t.accountDash.orderDate} {b.datum}
+
+
{statusLabel[b.status]}
+
+
+
+ {b.artikel.map((a) => (
+ -
+ {a.menge}Ă {a.name}
+ {formatPrice(a.preis * a.menge, lang)}
+
+ ))}
+
+
+
+ {b.tracking && (
+
{t.accountDash.trackingLabel}: {b.tracking}
+ )}
+
+ ))}
+
+
+
+
+
+
+
{t.accountDash.wishlistTitle}
+
+
{t.accountDash.wishlistEmpty}
+
+
+
+
+ {zuletztAngesehen.length > 0 && (
+
+
+
{t.accountDash.recentTitle}
+
{zuletztAngesehen.map((p) =>
)}
+
+
+ )}
+
+
+
+
{t.accountDash.profileTitle}
+
+
+
+ | {t.accountDash.profileName} | Marie Beispiel |
+ | {t.accountDash.profileEmail} | marie@beispiel.de |
+ | {t.accountDash.profileAddress} | MusterstraĂe 1 10115 Berlin Deutschland |
+
+
+
{t.accountDash.profileEdit}
+
+
+
+
diff --git a/src/pages/ch/konto/index.astro b/src/pages/ch/konto/index.astro
index c2f88cd..3105f1c 100644
--- a/src/pages/ch/konto/index.astro
+++ b/src/pages/ch/konto/index.astro
@@ -31,5 +31,8 @@ const t = useTranslations(lang);
{t.account.guestButton}
+
diff --git a/src/pages/ch/ueber-die-kreative/index.astro b/src/pages/ch/ueber-die-kreative/index.astro
index ff7db87..0da477c 100644
--- a/src/pages/ch/ueber-die-kreative/index.astro
+++ b/src/pages/ch/ueber-die-kreative/index.astro
@@ -5,32 +5,40 @@ import { useTranslations } from "../../../i18n/ui";
const lang: Locale = "ch";
const t = useTranslations(lang);
+
+// Der erste Story-Abschnitt steht direkt neben dem Foto von VanVan statt darunter als eigener
+// Block. Alle weiteren Abschnitte bleiben wie bisher darunter.
+const [ersteStory, ...weitereStories] = t.about.story;
---
-
+
{t.common.handmadeBadge}
-
+
{t.about.eyebrow}
{t.about.title}
{t.about.lead}
+
{ersteStory.title}
+ {ersteStory.paragraphs.map((p) =>
{p}
)}
-
-
- {t.about.story.map((s) => (
-
-
{s.title}
- {s.paragraphs.map((p) =>
{p}
)}
-
- ))}
-
-
+ {weitereStories.length > 0 && (
+
+
+ {weitereStories.map((s) => (
+
+
{s.title}
+ {s.paragraphs.map((p) =>
{p}
)}
+
+ ))}
+
+
+ )}
diff --git a/src/pages/en/konto/angemeldet.astro b/src/pages/en/konto/angemeldet.astro
new file mode 100644
index 0000000..6f79a8b
--- /dev/null
+++ b/src/pages/en/konto/angemeldet.astro
@@ -0,0 +1,160 @@
+---
+import Layout from "../../../layouts/Layout.astro";
+import ProductCard from "../../../components/ProductCard.astro";
+import { products } from "../../../data/products";
+import type { Locale } from "../../../i18n/config";
+import { useTranslations } from "../../../i18n/ui";
+import { formatPrice } from "../../../i18n/format";
+
+const lang: Locale = "en";
+const t = useTranslations(lang);
+
+// VORSCHAU-SEITE (Phase 1): So sieht der persönliche Bereich aus, sobald jemand angemeldet ist.
+// Es gibt noch kein echtes Login und keine Datenbank â die Bestellungen unten sind reine
+// Beispieldaten, damit Aufbau, Status-Anzeige und Bedienung schon jetzt beurteilt und
+// weiterentwickelt werden können. In Phase 2 (Cloudflare Worker + D1) werden sie durch die
+// echten Daten der angemeldeten Person ersetzt; Layout und Texte bleiben dann bestehen.
+const beispielBestellungen = [
+ {
+ nummer: "VDB-2026-0184",
+ datum: "28.07.2026",
+ status: "versendet" as const,
+ summe: 47.5,
+ tracking: "00340434161094015791",
+ artikel: [
+ { name: "\"HasiDog\" im blauen Overall", menge: 1, preis: 25 },
+ { name: "Perlenarmband âHimmelblau\"", menge: 1, preis: 14.5 },
+ ],
+ },
+ {
+ nummer: "VDB-2026-0157",
+ datum: "12.07.2026",
+ status: "abgeschlossen" as const,
+ summe: 22,
+ tracking: null,
+ artikel: [{ name: "Ergonomisches HĂ€kelnadel-Set (9-teilig)", menge: 1, preis: 22 }],
+ },
+];
+
+const statusLabel = {
+ bezahlt: t.accountDash.statusBezahlt,
+ bearbeitung: t.accountDash.statusBearbeitung,
+ versandVorbereitet: t.accountDash.statusVersandVorbereitet,
+ versendet: t.accountDash.statusVersendet,
+ abgeschlossen: t.accountDash.statusAbgeschlossen,
+} as const;
+
+// "Zuletzt angesehen" zeigt in dieser Vorschau einfach die ersten echten Produkte aus dem Shop â
+// in Phase 2 kommt hier die tatsÀchliche Verlaufs-Historie der angemeldeten Person hin.
+const zuletztAngesehen = products.slice(0, 3);
+const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versendet").length;
+---
+
+
+
+
{t.accountDash.previewNote}
+
+
+
+
+
+
+
+
+
+ {beispielBestellungen.length}
+ {t.accountDash.statOrders}
+
+
+ 0
+ {t.accountDash.statWishlist}
+
+
+ {offeneSendungen}
+ {t.accountDash.statOpen}
+
+
+
+
+
+
+
+
{t.accountDash.ordersTitle}
+
+ {beispielBestellungen.map((b) => (
+
+
+
+ {t.accountDash.orderNo} {b.nummer}
+ {t.accountDash.orderDate} {b.datum}
+
+
{statusLabel[b.status]}
+
+
+
+ {b.artikel.map((a) => (
+ -
+ {a.menge}Ă {a.name}
+ {formatPrice(a.preis * a.menge, lang)}
+
+ ))}
+
+
+
+ {b.tracking && (
+
{t.accountDash.trackingLabel}: {b.tracking}
+ )}
+
+ ))}
+
+
+
+
+
+
+
{t.accountDash.wishlistTitle}
+
+
{t.accountDash.wishlistEmpty}
+
+
+
+
+ {zuletztAngesehen.length > 0 && (
+
+
+
{t.accountDash.recentTitle}
+
{zuletztAngesehen.map((p) =>
)}
+
+
+ )}
+
+
+
+
{t.accountDash.profileTitle}
+
+
+
+ | {t.accountDash.profileName} | Marie Beispiel |
+ | {t.accountDash.profileEmail} | marie@beispiel.de |
+ | {t.accountDash.profileAddress} | MusterstraĂe 1 10115 Berlin Deutschland |
+
+
+
{t.accountDash.profileEdit}
+
+
+
+
diff --git a/src/pages/en/konto/index.astro b/src/pages/en/konto/index.astro
index b30afab..d137c92 100644
--- a/src/pages/en/konto/index.astro
+++ b/src/pages/en/konto/index.astro
@@ -31,5 +31,8 @@ const t = useTranslations(lang);
{t.account.guestButton}
+
diff --git a/src/pages/en/ueber-die-kreative/index.astro b/src/pages/en/ueber-die-kreative/index.astro
index 361ab05..549bc28 100644
--- a/src/pages/en/ueber-die-kreative/index.astro
+++ b/src/pages/en/ueber-die-kreative/index.astro
@@ -5,32 +5,40 @@ import { useTranslations } from "../../../i18n/ui";
const lang: Locale = "en";
const t = useTranslations(lang);
+
+// Der erste Story-Abschnitt steht direkt neben dem Foto von VanVan statt darunter als eigener
+// Block. Alle weiteren Abschnitte bleiben wie bisher darunter.
+const [ersteStory, ...weitereStories] = t.about.story;
---
-
+
{t.common.handmadeBadge}
-
+
{t.about.eyebrow}
{t.about.title}
{t.about.lead}
+
{ersteStory.title}
+ {ersteStory.paragraphs.map((p) =>
{p}
)}
-
-
- {t.about.story.map((s) => (
-
-
{s.title}
- {s.paragraphs.map((p) =>
{p}
)}
-
- ))}
-
-
+ {weitereStories.length > 0 && (
+
+
+ {weitereStories.map((s) => (
+
+
{s.title}
+ {s.paragraphs.map((p) =>
{p}
)}
+
+ ))}
+
+
+ )}
diff --git a/src/pages/fr/konto/angemeldet.astro b/src/pages/fr/konto/angemeldet.astro
new file mode 100644
index 0000000..ddce105
--- /dev/null
+++ b/src/pages/fr/konto/angemeldet.astro
@@ -0,0 +1,160 @@
+---
+import Layout from "../../../layouts/Layout.astro";
+import ProductCard from "../../../components/ProductCard.astro";
+import { products } from "../../../data/products";
+import type { Locale } from "../../../i18n/config";
+import { useTranslations } from "../../../i18n/ui";
+import { formatPrice } from "../../../i18n/format";
+
+const lang: Locale = "fr";
+const t = useTranslations(lang);
+
+// VORSCHAU-SEITE (Phase 1): So sieht der persönliche Bereich aus, sobald jemand angemeldet ist.
+// Es gibt noch kein echtes Login und keine Datenbank â die Bestellungen unten sind reine
+// Beispieldaten, damit Aufbau, Status-Anzeige und Bedienung schon jetzt beurteilt und
+// weiterentwickelt werden können. In Phase 2 (Cloudflare Worker + D1) werden sie durch die
+// echten Daten der angemeldeten Person ersetzt; Layout und Texte bleiben dann bestehen.
+const beispielBestellungen = [
+ {
+ nummer: "VDB-2026-0184",
+ datum: "28.07.2026",
+ status: "versendet" as const,
+ summe: 47.5,
+ tracking: "00340434161094015791",
+ artikel: [
+ { name: "\"HasiDog\" im blauen Overall", menge: 1, preis: 25 },
+ { name: "Perlenarmband âHimmelblau\"", menge: 1, preis: 14.5 },
+ ],
+ },
+ {
+ nummer: "VDB-2026-0157",
+ datum: "12.07.2026",
+ status: "abgeschlossen" as const,
+ summe: 22,
+ tracking: null,
+ artikel: [{ name: "Ergonomisches HĂ€kelnadel-Set (9-teilig)", menge: 1, preis: 22 }],
+ },
+];
+
+const statusLabel = {
+ bezahlt: t.accountDash.statusBezahlt,
+ bearbeitung: t.accountDash.statusBearbeitung,
+ versandVorbereitet: t.accountDash.statusVersandVorbereitet,
+ versendet: t.accountDash.statusVersendet,
+ abgeschlossen: t.accountDash.statusAbgeschlossen,
+} as const;
+
+// "Zuletzt angesehen" zeigt in dieser Vorschau einfach die ersten echten Produkte aus dem Shop â
+// in Phase 2 kommt hier die tatsÀchliche Verlaufs-Historie der angemeldeten Person hin.
+const zuletztAngesehen = products.slice(0, 3);
+const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versendet").length;
+---
+
+
+
+
{t.accountDash.previewNote}
+
+
+
+
+
+
+
+
+
+ {beispielBestellungen.length}
+ {t.accountDash.statOrders}
+
+
+ 0
+ {t.accountDash.statWishlist}
+
+
+ {offeneSendungen}
+ {t.accountDash.statOpen}
+
+
+
+
+
+
+
+
{t.accountDash.ordersTitle}
+
+ {beispielBestellungen.map((b) => (
+
+
+
+ {t.accountDash.orderNo} {b.nummer}
+ {t.accountDash.orderDate} {b.datum}
+
+
{statusLabel[b.status]}
+
+
+
+ {b.artikel.map((a) => (
+ -
+ {a.menge}Ă {a.name}
+ {formatPrice(a.preis * a.menge, lang)}
+
+ ))}
+
+
+
+ {b.tracking && (
+
{t.accountDash.trackingLabel}: {b.tracking}
+ )}
+
+ ))}
+
+
+
+
+
+
+
{t.accountDash.wishlistTitle}
+
+
{t.accountDash.wishlistEmpty}
+
+
+
+
+ {zuletztAngesehen.length > 0 && (
+
+
+
{t.accountDash.recentTitle}
+
{zuletztAngesehen.map((p) =>
)}
+
+
+ )}
+
+
+
+
{t.accountDash.profileTitle}
+
+
+
+ | {t.accountDash.profileName} | Marie Beispiel |
+ | {t.accountDash.profileEmail} | marie@beispiel.de |
+ | {t.accountDash.profileAddress} | MusterstraĂe 1 10115 Berlin Deutschland |
+
+
+
{t.accountDash.profileEdit}
+
+
+
+
diff --git a/src/pages/fr/konto/index.astro b/src/pages/fr/konto/index.astro
index 0c1dbe7..d22d208 100644
--- a/src/pages/fr/konto/index.astro
+++ b/src/pages/fr/konto/index.astro
@@ -31,5 +31,8 @@ const t = useTranslations(lang);
{t.account.guestButton}
+
diff --git a/src/pages/fr/ueber-die-kreative/index.astro b/src/pages/fr/ueber-die-kreative/index.astro
index 837593f..45ae115 100644
--- a/src/pages/fr/ueber-die-kreative/index.astro
+++ b/src/pages/fr/ueber-die-kreative/index.astro
@@ -5,32 +5,40 @@ import { useTranslations } from "../../../i18n/ui";
const lang: Locale = "fr";
const t = useTranslations(lang);
+
+// Der erste Story-Abschnitt steht direkt neben dem Foto von VanVan statt darunter als eigener
+// Block. Alle weiteren Abschnitte bleiben wie bisher darunter.
+const [ersteStory, ...weitereStories] = t.about.story;
---
-
+
{t.common.handmadeBadge}
-
+
{t.about.eyebrow}
{t.about.title}
{t.about.lead}
+
{ersteStory.title}
+ {ersteStory.paragraphs.map((p) =>
{p}
)}
-
-
- {t.about.story.map((s) => (
-
-
{s.title}
- {s.paragraphs.map((p) =>
{p}
)}
-
- ))}
-
-
+ {weitereStories.length > 0 && (
+
+
+ {weitereStories.map((s) => (
+
+
{s.title}
+ {s.paragraphs.map((p) =>
{p}
)}
+
+ ))}
+
+
+ )}
diff --git a/src/pages/konto/angemeldet.astro b/src/pages/konto/angemeldet.astro
new file mode 100644
index 0000000..30f1d40
--- /dev/null
+++ b/src/pages/konto/angemeldet.astro
@@ -0,0 +1,160 @@
+---
+import Layout from "../../layouts/Layout.astro";
+import ProductCard from "../../components/ProductCard.astro";
+import { products } from "../../data/products";
+import type { Locale } from "../../i18n/config";
+import { useTranslations } from "../../i18n/ui";
+import { formatPrice } from "../../i18n/format";
+
+const lang: Locale = "de";
+const t = useTranslations(lang);
+
+// VORSCHAU-SEITE (Phase 1): So sieht der persönliche Bereich aus, sobald jemand angemeldet ist.
+// Es gibt noch kein echtes Login und keine Datenbank â die Bestellungen unten sind reine
+// Beispieldaten, damit Aufbau, Status-Anzeige und Bedienung schon jetzt beurteilt und
+// weiterentwickelt werden können. In Phase 2 (Cloudflare Worker + D1) werden sie durch die
+// echten Daten der angemeldeten Person ersetzt; Layout und Texte bleiben dann bestehen.
+const beispielBestellungen = [
+ {
+ nummer: "VDB-2026-0184",
+ datum: "28.07.2026",
+ status: "versendet" as const,
+ summe: 47.5,
+ tracking: "00340434161094015791",
+ artikel: [
+ { name: "\"HasiDog\" im blauen Overall", menge: 1, preis: 25 },
+ { name: "Perlenarmband âHimmelblau\"", menge: 1, preis: 14.5 },
+ ],
+ },
+ {
+ nummer: "VDB-2026-0157",
+ datum: "12.07.2026",
+ status: "abgeschlossen" as const,
+ summe: 22,
+ tracking: null,
+ artikel: [{ name: "Ergonomisches HĂ€kelnadel-Set (9-teilig)", menge: 1, preis: 22 }],
+ },
+];
+
+const statusLabel = {
+ bezahlt: t.accountDash.statusBezahlt,
+ bearbeitung: t.accountDash.statusBearbeitung,
+ versandVorbereitet: t.accountDash.statusVersandVorbereitet,
+ versendet: t.accountDash.statusVersendet,
+ abgeschlossen: t.accountDash.statusAbgeschlossen,
+} as const;
+
+// "Zuletzt angesehen" zeigt in dieser Vorschau einfach die ersten echten Produkte aus dem Shop â
+// in Phase 2 kommt hier die tatsÀchliche Verlaufs-Historie der angemeldeten Person hin.
+const zuletztAngesehen = products.slice(0, 3);
+const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versendet").length;
+---
+
+
+
+
{t.accountDash.previewNote}
+
+
+
+
+
+
+
+
+
+ {beispielBestellungen.length}
+ {t.accountDash.statOrders}
+
+
+ 0
+ {t.accountDash.statWishlist}
+
+
+ {offeneSendungen}
+ {t.accountDash.statOpen}
+
+
+
+
+
+
+
+
{t.accountDash.ordersTitle}
+
+ {beispielBestellungen.map((b) => (
+
+
+
+ {t.accountDash.orderNo} {b.nummer}
+ {t.accountDash.orderDate} {b.datum}
+
+
{statusLabel[b.status]}
+
+
+
+ {b.artikel.map((a) => (
+ -
+ {a.menge}Ă {a.name}
+ {formatPrice(a.preis * a.menge, lang)}
+
+ ))}
+
+
+
+ {b.tracking && (
+
{t.accountDash.trackingLabel}: {b.tracking}
+ )}
+
+ ))}
+
+
+
+
+
+
+
{t.accountDash.wishlistTitle}
+
+
{t.accountDash.wishlistEmpty}
+
+
+
+
+ {zuletztAngesehen.length > 0 && (
+
+
+
{t.accountDash.recentTitle}
+
{zuletztAngesehen.map((p) =>
)}
+
+
+ )}
+
+
+
+
{t.accountDash.profileTitle}
+
+
+
+ | {t.accountDash.profileName} | Marie Beispiel |
+ | {t.accountDash.profileEmail} | marie@beispiel.de |
+ | {t.accountDash.profileAddress} | MusterstraĂe 1 10115 Berlin Deutschland |
+
+
+
{t.accountDash.profileEdit}
+
+
+
+
diff --git a/src/pages/konto/index.astro b/src/pages/konto/index.astro
index 2c717a3..0946630 100644
--- a/src/pages/konto/index.astro
+++ b/src/pages/konto/index.astro
@@ -31,5 +31,10 @@ const t = useTranslations(lang);
{t.account.guestButton}
+ {/* Direkter Weg zur Vorschau des eingeloggten Kundenbereichs â solange es noch kein echtes
+ Login gibt (Phase 2), wÀre diese Ansicht sonst gar nicht erreichbar. */}
+
diff --git a/src/pages/ueber-die-kreative/index.astro b/src/pages/ueber-die-kreative/index.astro
index 1f10379..17ec1a8 100644
--- a/src/pages/ueber-die-kreative/index.astro
+++ b/src/pages/ueber-die-kreative/index.astro
@@ -5,32 +5,41 @@ import { useTranslations } from "../../i18n/ui";
const lang: Locale = "de";
const t = useTranslations(lang);
+
+// Der erste Story-Abschnitt ("Meine Reise begann mit einer einzigen Masche") steht direkt neben
+// dem Foto von VanVan, statt darunter als eigener Block â so liest man ihre Geschichte sofort
+// gemeinsam mit ihrem Bild. Alle weiteren Abschnitte bleiben wie bisher darunter.
+const [ersteStory, ...weitereStories] = t.about.story;
---
-
+
{t.common.handmadeBadge}
-
+
{t.about.eyebrow}
{t.about.title}
{t.about.lead}
+
{ersteStory.title}
+ {ersteStory.paragraphs.map((p) =>
{p}
)}
-
-
- {t.about.story.map((s) => (
-
-
{s.title}
- {s.paragraphs.map((p) =>
{p}
)}
-
- ))}
-
-
+ {weitereStories.length > 0 && (
+
+
+ {weitereStories.map((s) => (
+
+
{s.title}
+ {s.paragraphs.map((p) =>
{p}
)}
+
+ ))}
+
+
+ )}
diff --git a/src/styles/global.css b/src/styles/global.css
index b9622fe..66b8ca9 100644
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -679,6 +679,29 @@ a:focus-visible, button:focus-visible {
border-radius: var(--radius-s);
}
+/* "Ăber die Kreative": VanVans Geschichte steht direkt NEBEN ihrem Foto (statt darunter als
+ eigener Block). Weil die Textspalte dadurch deutlich höher wird als das Foto, wird hier oben
+ ausgerichtet statt gestreckt â sonst wĂŒrde die Fotokarte mit viel leerem Raum mitwachsen.
+ Das Foto bleibt beim Lesen sichtbar (sticky), solange genug Platz da ist. */
+/* NUR im zweispaltigen Layout (ab 901px): oben ausrichten statt strecken + Foto bleibt beim
+ Lesen sichtbar. Bewusst NICHT global gesetzt â unterhalb von 900px stehen Foto und Text
+ ohnehin untereinander, und dort fĂŒhrt `align-items: start` zu einem echten Fehler: die
+ Grid-Zeile wird dann anhand des geschÀtzten Bild-SeitenverhÀltnisses berechnet und fÀllt
+ ~100px zu niedrig aus, wodurch das Foto in den Text darunter hineinragt (gemessen: 80px
+ Ăberlappung). Mit dem Standardverhalten (stretch) tritt das nicht auf. */
+@media (min-width: 901px) {
+ .intro-story { align-items: start; }
+ .intro-story .portrait-frame.portrait { position: sticky; top: 6.5rem; }
+}
+/* text-wrap: balance verteilt die Zeilen der Ăberschrift gleichmĂ€Ăig â sonst rutscht bei
+ breiten Fenstern nur das đ©” allein in eine eigene Zeile. */
+.intro-story-text h1 { margin-bottom: 0.6rem; text-wrap: balance; }
+.intro-story-text h2 {
+ margin-top: 2rem;
+ font-size: clamp(1.4rem, 2.4vw, 1.8rem);
+}
+.intro-story-text p { max-width: 60ch; }
+
/* Wechselt innerhalb einer Tier-Familie ab: Foto links/rechts, Text jeweils gegenĂŒber â sorgt
fĂŒr optische Abwechslung, sobald mehrere Varianten einer Serie eigene Seiten bekommen. */
.intro-reverse .portrait-frame.portrait { order: 2; }
@@ -1074,16 +1097,15 @@ a:focus-visible, button:focus-visible {
color: var(--c-accent);
margin: 2.2rem 0 0;
}
+/* Das Kategorie-Emoji steht frei neben der Ăberschrift â vorher saĂ es in einem farbigen
+ Kreis, der auf Wunsch entfernt wurde (der Kreis hat das Emoji eher eingesperrt als
+ hervorgehoben und passte nicht zum ruhigen Rest der Seite). */
.kategorie-section-label .label-icon {
display: inline-flex;
align-items: center;
justify-content: center;
- width: 1.9rem;
- height: 1.9rem;
- border-radius: 50%;
- font-size: 1rem;
- background: linear-gradient(135deg, var(--c-accent), var(--c-purple-glow) 45%, var(--c-sale) 100%);
- color: #08181c;
+ font-size: 1.35rem;
+ line-height: 1;
}
.kategorie-section-label-rule {
height: 2px;
@@ -1126,6 +1148,44 @@ a:focus-visible, button:focus-visible {
.thumb.product-photo:hover { box-shadow: 0 0 0 3px rgba(10, 9, 16, 0.6), 0 0 0 4px var(--c-accent); }
.badge-row { display: flex; gap: 0.5rem; margin-bottom: 0.8rem; flex-wrap: wrap; }
+/* Persönlicher Kundenbereich (/konto/angemeldet/) â Ansicht fĂŒr angemeldete Kund:innen mit
+ Bestellhistorie, Sendungsverfolgung, Wunschliste und Profildaten. Nutzt durchgehend die
+ bestehende Karten-/Badge-Optik der Seite, damit sich nichts fremd anfĂŒhlt. */
+.account-head {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ gap: 1.5rem;
+ flex-wrap: wrap;
+}
+.account-head h1 { margin: 0.2rem 0 0.5rem; }
+.account-head .lead { margin: 0; max-width: 52ch; }
+.account-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-top: 1.2rem; }
+.account-stat { text-align: center; display: flex; flex-direction: column; gap: 0.25rem; padding: 1.2rem 1rem; }
+.account-stat-value { font-family: var(--font-head); font-size: 1.9rem; font-weight: 700; color: var(--c-accent); line-height: 1; }
+@media (max-width: 620px) { .account-stats { grid-template-columns: 1fr; } }
+
+.order-list { display: flex; flex-direction: column; gap: 1.1rem; }
+.order-card { display: flex; flex-direction: column; gap: 0.9rem; }
+.order-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
+.order-no { display: block; font-weight: 700; font-size: 1.02rem; }
+.order-meta { color: var(--c-text-muted); }
+/* Bestellstatus in den Farben der jeweiligen Phase (siehe Pflichtenheft Punkt 12): unterwegs =
+ Akzentfarbe, abgeschlossen = ruhiges GrĂŒn, in Arbeit = neutral. */
+.order-status-versendet { background: color-mix(in srgb, var(--c-accent) 34%, transparent); border-color: color-mix(in srgb, var(--c-accent) 55%, transparent); }
+.order-status-abgeschlossen { background: rgba(126, 200, 160, 0.28); border-color: rgba(126, 200, 160, 0.5); color: #cfeee0; }
+.order-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
+.order-items li { display: flex; justify-content: space-between; gap: 1rem; font-size: 0.95rem; color: var(--c-text-muted); }
+.order-item-price { color: var(--c-text); white-space: nowrap; }
+.order-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; border-top: 1px dashed rgba(244, 241, 247, 0.14); padding-top: 0.9rem; }
+.order-total { font-size: 1.05rem; }
+.order-total strong { color: var(--c-accent); }
+.order-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
+.order-tracking-no { margin: 0; color: var(--c-text-muted); }
+.order-tracking-no code { font-size: 0.9em; letter-spacing: 0.02em; }
+.profile-card { display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; }
+.profile-card .specs { margin-top: 0; width: 100%; }
+
/* Kundenrezensionen â Herzen in Lila-Babyblau statt Sterne (siehe HeartRating.astro), damit
Bewertungen sich erkennbar in die restliche Seite einfĂŒgen statt wie ein fremdes Bewertungs-
Widget zu wirken. */