"use client";
import { AlertCircle } from "lucide-react";
import { Alert, AlertDescription, Badge, Button } from "../../../../../shadcnui";
import { SectionHeader } from "../../../../../components/typography";
import { formatCurrency } from "../../../components/utils/currency";
import { StripePriceInterface } from "../../../stripe-price/data/stripe-price.interface";
import { ProrationPreviewInterface } from "../../../stripe-invoice/data/stripe-invoice.interface";
import { PromotionCodeValidationResult } from "../../../stripe-promotion-code";
import { PromoCodeInput } from "../../../stripe-promotion-code/components/PromoCodeInput";
import { StripeSubscriptionInterface } from "../../data";
type WizardStepReviewProps = {
selectedPrice: StripePriceInterface | null;
subscription?: StripeSubscriptionInterface;
prorationPreview: ProrationPreviewInterface | null;
hasPaymentMethod: boolean;
error: string | null;
isProcessing: boolean;
onBack: () => void;
onAddPaymentMethod: () => void;
onConfirm: () => void;
// Promotion code props
promotionCode: PromotionCodeValidationResult | null;
isValidatingPromoCode: boolean;
promoCodeError: string | null;
onApplyPromoCode: (code: string) => void;
onRemovePromoCode: () => void;
// Trial upgrade flag
isTrialUpgrade: boolean;
};
export function WizardStepReview({
selectedPrice,
subscription,
prorationPreview,
hasPaymentMethod,
error,
isProcessing,
onBack,
onAddPaymentMethod,
onConfirm,
promotionCode,
isValidatingPromoCode,
promoCodeError,
onApplyPromoCode,
onRemovePromoCode,
isTrialUpgrade,
}: WizardStepReviewProps) {
if (!selectedPrice) {
return (
No plan selected. Please go back and select a plan.
);
}
const isChangingPlan = subscription && subscription.price?.id !== selectedPrice.id;
const formatInterval = (price: StripePriceInterface) => {
if (price.priceType === "one_time") return "one-time";
const interval = price.recurring?.interval || "month";
return interval === "year" ? "yearly" : "monthly";
};
// Calculate discounted price if promotion code is applied
const calculateDiscountedPrice = (): number | null => {
if (!promotionCode?.valid || !selectedPrice.unitAmount) return null;
const originalPrice = selectedPrice.unitAmount;
if (promotionCode.discountType === "percent_off" && promotionCode.discountValue) {
return originalPrice * (1 - promotionCode.discountValue / 100);
}
if (promotionCode.discountType === "amount_off" && promotionCode.discountValue) {
// amount_off is in cents, same as unitAmount
return Math.max(0, originalPrice - promotionCode.discountValue);
}
return null;
};
const discountedPrice = calculateDiscountedPrice();
// Calculate discounted immediate charge for proration preview
const calculateDiscountedImmediateCharge = (): number | null => {
if (!promotionCode?.valid || !prorationPreview?.immediateCharge) return null;
const originalCharge = prorationPreview.immediateCharge;
if (promotionCode.discountType === "percent_off" && promotionCode.discountValue) {
return originalCharge * (1 - promotionCode.discountValue / 100);
}
if (promotionCode.discountType === "amount_off" && promotionCode.discountValue) {
return Math.max(0, originalCharge - promotionCode.discountValue);
}
return null;
};
const discountedImmediateCharge = calculateDiscountedImmediateCharge();
// Format the discount description
const getDiscountDescription = (): string | null => {
if (!promotionCode?.valid) return null;
if (promotionCode.discountType === "percent_off" && promotionCode.discountValue) {
return `${promotionCode.discountValue}% off`;
}
if (promotionCode.discountType === "amount_off" && promotionCode.discountValue) {
return `${formatCurrency(promotionCode.discountValue, promotionCode.currency || selectedPrice.currency)} off`;
}
return null;
};
const discountDescription = getDiscountDescription();
return (
{/* Selected Plan Summary */}
Selected Plan
{selectedPrice.product?.name}
{selectedPrice.nickname &&
{selectedPrice.nickname}
}
{discountedPrice !== null ? (
<>
{formatCurrency(selectedPrice.unitAmount || 0, selectedPrice.currency)}
{formatCurrency(discountedPrice, selectedPrice.currency)}
{discountDescription &&
{discountDescription} }
>
) : (
{formatCurrency(selectedPrice.unitAmount || 0, selectedPrice.currency)}
)}
{formatInterval(selectedPrice)}
{/* Proration Preview (for plan changes) */}
{isChangingPlan && prorationPreview && (
{isTrialUpgrade ? "Trial Upgrade" : "Proration Summary"}
{isTrialUpgrade
? "Your trial will end immediately and you will be charged the full price."
: "Your next charge will be adjusted to account for the plan change."}
{isTrialUpgrade ? "Amount to charge now:" : "Amount due now:"}
{discountedImmediateCharge !== null ? (
<>
{formatCurrency(prorationPreview.immediateCharge, prorationPreview.currency)}
{formatCurrency(discountedImmediateCharge, prorationPreview.currency)}
>
) : (
formatCurrency(prorationPreview.immediateCharge, prorationPreview.currency)
)}
)}
{/* Promotion Code */}
{/* Payment Method Status */}
Payment Method
{hasPaymentMethod ? "A payment method is on file" : "No payment method on file"}
{!hasPaymentMethod && (
Add Payment Method
)}
{/* Error Display */}
{error && (
{error}
)}
{/* Action Buttons */}
Back
{isProcessing
? "Processing..."
: hasPaymentMethod
? isChangingPlan
? "Confirm Plan Change"
: "Subscribe Now"
: "Add Payment Method"}
);
}