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}

+
+
+ +
+
+ + + +
+
+ +
+
+

{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)} +
  • + ))} +
+ +
+ {t.accountDash.orderTotal}: {formatPrice(b.summe, 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} +
+ {t.account.previewLink} +
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; ---
-
+
VanVan i ihrer Werkstatt mit ihre sÀlber ghÀklete Plushies {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}

+
+
+ +
+
+ + + +
+
+ +
+
+

{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)} +
  • + ))} +
+ +
+ {t.accountDash.orderTotal}: {formatPrice(b.summe, 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; ---
-
+
VanVan in her workshop with her handmade crochet plushies {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}

+
+
+ +
+
+ + + +
+
+ +
+
+

{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)} +
  • + ))} +
+ +
+ {t.accountDash.orderTotal}: {formatPrice(b.summe, 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; ---
-
+
VanVan dans son atelier avec ses peluches au crochet faites main {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}

+
+
+ +
+
+ + + +
+
+ +
+
+

{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)} +
  • + ))} +
+ +
+ {t.accountDash.orderTotal}: {formatPrice(b.summe, 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; ---
-
+
VanVan in ihrer Werkstatt mit selbstgehÀkelten Plushies {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. */