e3352d7e32
- Posts.categories is now hasMany — blog list/detail/live-preview render a comma-joined list instead of a single category. - Checkout's "Abweichende Lieferadresse" gains optional Firma + Kontakt- E-Mail/Telefon fields (handed to the shipping carrier, not used for customer communication). - Customer profile can now store its own shipping address (mirroring Customers.ts's new "Lieferadresse" tab), prefilling the checkout override instead of always starting blank. - Product-level optional SKU (previously only on variants) snapshots onto each order item and shows up on invoices (visual + EN16931 XML), the confirmation email, and the account order detail page.
76 lines
2.5 KiB
TypeScript
76 lines
2.5 KiB
TypeScript
"use client";
|
|
|
|
// Survives navigating away from /checkout and back (e.g. to double-check
|
|
// something in /cart) — same localStorage approach as lib/cart.ts/
|
|
// lib/discount.ts, but plain read/write functions rather than
|
|
// useSyncExternalStore: CheckoutContent is this draft's only reader, so
|
|
// there's no cross-component subscription to keep in sync the way the cart
|
|
// needs (Navbar + CartContent + CheckoutContent all read it at once).
|
|
// Deliberately excludes `password` — that field stays a plain uncontrolled
|
|
// input, never persisted.
|
|
const DRAFT_KEY = "ep_checkout_draft";
|
|
|
|
export type CheckoutDraft = {
|
|
firstName: string;
|
|
lastName: string;
|
|
email: string;
|
|
// Optional B2B fields — see CheckoutContent.tsx's own comment on why
|
|
// they sit here (right next to the Rechnungsadresse fields, not a
|
|
// separate persisted concept).
|
|
companyName: string;
|
|
vatId: string;
|
|
// Rechnungsadresse is always a plain street address now — no
|
|
// deliveryMethod/packstationNumber/postNumber here, only on the
|
|
// shipping* override fields below (see CheckoutContent.tsx).
|
|
street: string;
|
|
zip: string;
|
|
city: string;
|
|
country: string;
|
|
hasDifferentShippingAddress: boolean;
|
|
shippingFirstName: string;
|
|
shippingLastName: string;
|
|
shippingDeliveryMethod: "address" | "packstation";
|
|
shippingStreet: string;
|
|
shippingPackstationNumber: string;
|
|
shippingPostNumber: string;
|
|
shippingZip: string;
|
|
shippingCity: string;
|
|
shippingCountry: string;
|
|
shippingCompanyName: string;
|
|
shippingContactEmail: string;
|
|
shippingContactPhone: string;
|
|
newsletterOptIn: boolean;
|
|
shippingMethodId: number | null;
|
|
paymentMethodId: number | null;
|
|
};
|
|
|
|
export function readCheckoutDraft(): Partial<CheckoutDraft> | null {
|
|
if (typeof window === "undefined") return null;
|
|
try {
|
|
const raw = window.localStorage.getItem(DRAFT_KEY);
|
|
return raw ? JSON.parse(raw) : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function writeCheckoutDraft(draft: CheckoutDraft) {
|
|
try {
|
|
window.localStorage.setItem(DRAFT_KEY, JSON.stringify(draft));
|
|
} catch {
|
|
// localStorage unavailable (private browsing etc.) — the draft just
|
|
// doesn't persist this time, same best-effort fallback as
|
|
// lib/order.ts's sessionStorage write.
|
|
}
|
|
}
|
|
|
|
// Called once an order actually completes (handleSubmit) — a leftover
|
|
// draft from a finished purchase would otherwise pre-fill the next one.
|
|
export function clearCheckoutDraft() {
|
|
try {
|
|
window.localStorage.removeItem(DRAFT_KEY);
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|