feat: Wabenhain Honig-Shop Anwendung
Vollstaendige Next.js/Prisma-E-Commerce-Anwendung fuer eine Imkerei: Shop, Warenkorb, Stripe-Checkout, Kundenkonto mit 2FA, Admin-Bereich (Produkte, Ernten, Chargen, Bestellungen, Gutscheine, admin-editierbare Website-Inhalte), i18n (DE/EN), Rate-Limiting/CSP/Audit-Log-Haertung, PostgreSQL- und MySQL-Unterstuetzung ueber austauschbare Prisma- Treiber-Adapter, Unit-/Komponenten-/E2E-Tests.
This commit is contained in:
1 parent
5c76fcc266
commit
c7927f2883
240 files changed
+26096
-137
No files matched your search
@@ -0,0 +1,50 @@
|
||||
export interface ShippingTierLike {
|
||||
minQuantity: number;
|
||||
maxQuantity: number | null;
|
||||
priceCents: number;
|
||||
}
|
||||
|
||||
// Greift nur, wenn im Admin-Bereich (noch) keine Staffeln gepflegt sind —
|
||||
// verhindert einen kaputten Checkout statt einer korrekten Preisauskunft.
|
||||
export const FALLBACK_SHIPPING_CENTS = 490;
|
||||
|
||||
/**
|
||||
* Reine Zuordnungsfunktion ohne Datenbankzugriff — bewusst getrennt von
|
||||
* shipping.ts, damit sowohl der serverseitige Checkout (lib/shipping.ts) als
|
||||
* auch die client-seitige Warenkorb-Live-Vorschau (warenkorb-content.tsx)
|
||||
* exakt dieselbe Staffel-Logik verwenden, ohne Prisma ins Client-Bundle zu
|
||||
* ziehen.
|
||||
*/
|
||||
export function resolveShippingCostCents(tiers: ShippingTierLike[], totalQuantity: number): number {
|
||||
if (totalQuantity <= 0) return 0;
|
||||
if (tiers.length === 0) return FALLBACK_SHIPPING_CENTS;
|
||||
|
||||
const sorted = [...tiers].sort((a, b) => a.minQuantity - b.minQuantity);
|
||||
const matching = sorted.find(
|
||||
(tier) => totalQuantity >= tier.minQuantity && (tier.maxQuantity === null || totalQuantity <= tier.maxQuantity)
|
||||
);
|
||||
// Menge liegt oberhalb aller gepflegten Staffeln (z.B. nur bis 19 Stueck
|
||||
// definiert) — die teuerste/oberste Staffel greift, statt die Bestellung
|
||||
// mangels passendem Tarif abzulehnen.
|
||||
return matching ? matching.priceCents : sorted[sorted.length - 1].priceCents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Naechste (teurere) Staffel oberhalb der aktuellen Menge — fuer eine ehrliche
|
||||
* Transparenz-Anzeige im Warenkorb ("noch X Stueck bis zur naechsten Stufe").
|
||||
* Anders als ein "kostenloser Versand ab X"-Hinweis wird hier bewusst NICHT
|
||||
* suggeriert, dass mehr kaufen guenstiger wird — die Staffeln steigen mit der
|
||||
* Menge, siehe FALLBACK_SHIPPING_CENTS-Kommentar oben.
|
||||
*/
|
||||
export function getNextShippingTier(
|
||||
tiers: ShippingTierLike[],
|
||||
totalQuantity: number
|
||||
): { unitsUntilNext: number; priceCents: number } | null {
|
||||
if (tiers.length === 0 || totalQuantity <= 0) return null;
|
||||
|
||||
const sorted = [...tiers].sort((a, b) => a.minQuantity - b.minQuantity);
|
||||
const next = sorted.find((tier) => tier.minQuantity > totalQuantity);
|
||||
if (!next) return null;
|
||||
|
||||
return { unitsUntilNext: next.minQuantity - totalQuantity, priceCents: next.priceCents };
|
||||
}
|
||||
Reference in new issue
Block a user