Add DHL checkout integrations (autocomplete, postnummer, return label)
Wires the new backend DHL endpoints into checkout: an address-autocomplete dropdown on the street fields, live Postnummer validation for Packstation delivery, and a return-label download link on the order-detail page. Proxied through Next.js API routes since DHL credentials are tenant- specific and CheckoutContent is a Client Component. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -200,6 +200,10 @@ export type Product = {
|
||||
spotlightHeadline: string | null;
|
||||
spotlightText: string | null;
|
||||
spotlightImage: string | null;
|
||||
// Per-product opt-in for a wishlist heart on the homepage spotlight —
|
||||
// independent of (in addition to) the global wishlistEnabled toggle,
|
||||
// which still gates the feature site-wide regardless of this flag.
|
||||
spotlightShowWishlist: boolean;
|
||||
// Plain booleans, not the raw stock/threshold numbers — the public API
|
||||
// has no reason to leak exact stock counts, callers only ever need
|
||||
// "can this be bought right now". `outOfStock` on the product itself
|
||||
@@ -249,6 +253,7 @@ type PayloadProduct = {
|
||||
spotlightHeadline: string | null;
|
||||
spotlightText: string | null;
|
||||
spotlightImage: { url: string } | number | null;
|
||||
spotlightShowWishlist: boolean;
|
||||
trackInventory: boolean;
|
||||
stock: number | null;
|
||||
allowBackorder: boolean;
|
||||
@@ -312,6 +317,7 @@ export function mapPayloadProduct(product: PayloadProduct): Product {
|
||||
spotlightText: product.spotlightText || null,
|
||||
spotlightImage:
|
||||
typeof product.spotlightImage === "object" && product.spotlightImage ? product.spotlightImage.url : null,
|
||||
spotlightShowWishlist: product.spotlightShowWishlist,
|
||||
outOfStock: isOutOfStock(product.trackInventory, product.stock, product.allowBackorder),
|
||||
lowStock: isLowStock(product.trackInventory, product.stock, product.lowStockThreshold),
|
||||
maxQty: maxPurchasableQty(product.trackInventory, product.stock, product.allowBackorder),
|
||||
@@ -392,6 +398,21 @@ export async function getProductImagesByIds(ids: number[]): Promise<Map<number,
|
||||
return map;
|
||||
}
|
||||
|
||||
// Resolves a bare media id to its download URL — used by
|
||||
// /konto/bestellungen/[orderNumber] for order.dhlReturnLabelMedia, which
|
||||
// stays a raw id on the order fetch itself (that fetch is deliberately
|
||||
// depth=0, see getCustomerOrderDetail's own comment) rather than bumping
|
||||
// that fetch's depth just for this one occasional field. `no-store`, not
|
||||
// ISR-cached like getProductImagesByIds — a return label is a one-off,
|
||||
// account-specific document, not shared/reusable content worth caching.
|
||||
export async function getMediaUrlById(id: number): Promise<{ url: string; filename: string } | null> {
|
||||
const res = await fetch(`${PAYLOAD_URL}/api/media/${id}`, { cache: "no-store" });
|
||||
if (!res.ok) return null;
|
||||
const data: { url?: string; filename?: string } = await res.json();
|
||||
if (!data.url) return null;
|
||||
return { url: data.url, filename: data.filename ?? "download.pdf" };
|
||||
}
|
||||
|
||||
// Derived from getProducts() (same 60s-ISR-cached fetch every other
|
||||
// discovery surface already uses) instead of its own separate Payload
|
||||
// query — also what lets the auto-spotlight rule below just be a plain
|
||||
|
||||
Reference in New Issue
Block a user