'use client'; import React, { useState, useMemo } from 'react'; import PageLayout from '../components/PageLayout'; import { useRouter } from 'next/navigation'; import { useActiveCoffees } from './hooks/getActiveCoffees'; import { useShippingFees } from './hooks/useShippingFees'; import AboHeroHeader from './components/AboHeroHeader'; import AboStepper from './components/AboStepper'; import CoffeeSelectionGrid from './components/CoffeeSelectionGrid'; import SelectionSummaryCard from './components/SelectionSummaryCard'; import SubscribeGuard from './components/SubscribeGuard'; import { COFFEE_SELECTIONS_STORAGE_KEY, COFFEE_SELECTIONS_UNIT, COFFEE_SELECTIONS_UNIT_STORAGE_KEY, getOrderPackError, getRemainingMinPacks, MAX_ABO_PACKS, packsToCapsules, } from './lib/orderRules'; import { useTranslation } from '../i18n/useTranslation'; export default function CoffeeAbonnementPage() { return ( ); } function CoffeeAbonnementPageContent() { const { t } = useTranslation(); const [selections, setSelections] = useState>({}); const router = useRouter(); // Fetch active coffees from the backend const { coffees, loading, error } = useActiveCoffees(); // Shipping fees (threshold-based) const { resolveShippingFee, loading: shippingLoading, error: shippingError } = useShippingFees(); const selectedEntries = useMemo( () => Object.entries(selections).map(([id, qty]) => { const coffee = coffees.find((c) => c.id === id); if (!coffee) return null; return { coffee, quantity: qty }; }).filter(Boolean) as { coffee: ReturnType['coffees'][number]; quantity: number }[], [selections, coffees] ); const totalPrice = useMemo( () => selectedEntries.reduce( (sum, entry) => sum + entry.quantity * entry.coffee.pricePer10, 0 ), [selectedEntries] ); const totalPacks = useMemo( () => selectedEntries.reduce((sum, entry) => sum + entry.quantity, 0), [selectedEntries] ); const totalCapsules = useMemo(() => packsToCapsules(totalPacks), [totalPacks]); const selectedShippingFee = resolveShippingFee(totalCapsules); const isFreeShippingSelected = Number(selectedShippingFee) === 0; const orderPackError = getOrderPackError(totalPacks); const remainingMinPacks = getRemainingMinPacks(totalPacks); const totalNetWithShipping = useMemo( () => totalPrice + (Number.isFinite(selectedShippingFee) ? selectedShippingFee : 0), [totalPrice, selectedShippingFee] ); const canProceed = selectedEntries.length > 0 && !orderPackError; const proceedToSummary = () => { if (!canProceed) return; try { sessionStorage.setItem(COFFEE_SELECTIONS_STORAGE_KEY, JSON.stringify(selections)); sessionStorage.setItem(COFFEE_SELECTIONS_UNIT_STORAGE_KEY, COFFEE_SELECTIONS_UNIT); } catch {} router.push('/coffee-abonnements/summary'); }; const setQuantity = (id: string, nextValue: number) => { setSelections((prev) => { const normalized = Math.max(0, Math.floor(Number(nextValue) || 0)); const current = prev[id] || 0; const otherTotal = Object.entries(prev).reduce((sum, [key, qty]) => key === id ? sum : sum + qty, 0); const maxForCoffee = Math.max(0, MAX_ABO_PACKS - otherTotal); const bounded = Math.min(normalized, maxForCoffee); if (bounded <= 0) { if (!(id in prev)) return prev; const next = { ...prev }; delete next[id]; return next; } if (bounded === current) return prev; return { ...prev, [id]: bounded }; }); }; const adjustQuantity = (id: string, delta: number) => { const current = selections[id] || 0; setQuantity(id, current + delta); }; return (
); }