dev #21

Merged
Seazn merged 35 commits from dev into main 2026-05-21 17:34:44 +00:00
Showing only changes of commit 93886751a3 - Show all commits

View File

@ -1,4 +1,5 @@
import type { CoffeeItem } from '../hooks/getActiveCoffees';
import { MAX_ABO_PACKS, MIN_ABO_PACKS, packsToCapsules } from '../lib/orderRules';
type SelectedEntry = {
coffee: CoffeeItem;
@ -12,9 +13,9 @@ type Props = {
selectedShippingFee: number;
totalNetWithShipping: number;
totalCapsules: number;
packsSelected: number;
selectedPlanCapsules: number;
requiredPacks: number;
totalPacks: number;
orderPackError: string | null;
remainingMinPacks: number;
canProceed: boolean;
onProceed: () => void;
title: string;
@ -29,9 +30,9 @@ export default function SelectionSummaryCard({
selectedShippingFee,
totalNetWithShipping,
totalCapsules,
packsSelected,
selectedPlanCapsules,
requiredPacks,
totalPacks,
orderPackError,
remainingMinPacks,
canProceed,
onProceed,
title,
@ -49,10 +50,10 @@ export default function SelectionSummaryCard({
<div className="flex flex-col">
<span className="font-medium text-slate-800">{entry.coffee.name}</span>
<span className="text-xs text-slate-500">
{entry.quantity} pcs <span className="inline-flex items-center font-semibold text-slate-900">EUR {entry.coffee.pricePer10}/10</span>
{entry.quantity} packs ({packsToCapsules(entry.quantity)} capsules) <span className="inline-flex items-center font-semibold text-slate-900">EUR {entry.coffee.pricePer10.toFixed(2)}/pack</span>
</span>
</div>
<div className="text-right font-semibold text-slate-800">EUR {((entry.quantity / 10) * entry.coffee.pricePer10).toFixed(2)}</div>
<div className="text-right font-semibold text-slate-800">EUR {(entry.quantity * entry.coffee.pricePer10).toFixed(2)}</div>
</div>
))}
@ -68,11 +69,21 @@ export default function SelectionSummaryCard({
<span className="text-lg font-extrabold tracking-tight text-slate-900">EUR {totalNetWithShipping.toFixed(2)}</span>
</div>
<div className="text-xs text-slate-700">
Selected: {totalCapsules} capsules ({packsSelected} packs of 10). Target: {selectedPlanCapsules} capsules ({requiredPacks} packs).
{packsSelected !== requiredPacks && (
<span className="ml-2 inline-flex items-center rounded-md bg-rose-50 text-rose-700 px-2 py-1 border border-rose-200">
{packsSelected < requiredPacks ? `${requiredPacks - packsSelected} packs missing.` : `${packsSelected - requiredPacks} packs too many.`}
<div className="space-y-2 text-xs text-slate-700">
<div>
<span className="font-semibold">{totalPacks.toLocaleString('en-US')}</span> packs selected.
<div className="text-slate-500">{totalCapsules.toLocaleString('en-US')} capsules total · minimum {MIN_ABO_PACKS} packs · maximum {MAX_ABO_PACKS.toLocaleString('en-US')} packs</div>
</div>
{orderPackError ? (
<span className="inline-flex items-center rounded-md bg-rose-50 text-rose-700 px-2 py-1 border border-rose-200">
{remainingMinPacks > 0
? `${remainingMinPacks} more pack${remainingMinPacks === 1 ? '' : 's'} needed to reach the minimum order.`
: orderPackError}
</span>
) : (
<span className="inline-flex items-center rounded-md bg-emerald-50 text-emerald-700 px-2 py-1 border border-emerald-200">
Selection is within the allowed order range.
</span>
)}
</div>
@ -101,7 +112,9 @@ export default function SelectionSummaryCard({
{!canProceed && (
<p className="text-xs text-slate-600">
You can continue once exactly {selectedPlanCapsules} capsules ({requiredPacks} packs) are selected.
{remainingMinPacks > 0
? `You can continue once at least ${MIN_ABO_PACKS} packs are selected.`
: `Please reduce the order to ${MAX_ABO_PACKS.toLocaleString('en-US')} packs or fewer.`}
</p>
)}
</section>