import { useEffect, useState } from 'react'; import { motion } from 'framer-motion'; import { getOrderDetails } from '../api/checkoutClient'; import { OrderDetailsResponse } from '../types'; import { CarbonImpactComparison } from '../components/CarbonImpactComparison'; import { useCalculatorState } from '../hooks/useCalculatorState'; interface CheckoutSuccessProps { onNavigateHome: () => void; onNavigateCalculator: () => void; } // Map backend status to user-friendly labels const getStatusDisplay = (status: string): { label: string; className: string } => { switch (status) { case 'paid': case 'fulfilled': return { label: 'Confirmed', className: 'bg-green-100 text-green-700' }; case 'pending': return { label: 'Processing', className: 'bg-yellow-100 text-yellow-700' }; default: return { label: status.toUpperCase(), className: 'bg-slate-100 text-slate-700' }; } }; // Format currency with commas const formatCurrency = (amount: number): string => { return amount.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); }; export default function CheckoutSuccess({ onNavigateHome, onNavigateCalculator }: CheckoutSuccessProps) { const [orderDetails, setOrderDetails] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const { clearState } = useCalculatorState(); // Clear calculator state on successful payment (per user preference) useEffect(() => { if (orderDetails && (orderDetails.order.status === 'paid' || orderDetails.order.status === 'fulfilled')) { clearState(); } }, [orderDetails, clearState]); useEffect(() => { const fetchOrderDetails = async () => { // Get session ID from URL const params = new URLSearchParams(window.location.search); const sessionId = params.get('session_id'); if (!sessionId) { setError('No session ID found in URL'); setLoading(false); return; } try { const details = await getOrderDetails(sessionId); setOrderDetails(details); } catch (err) { setError('Failed to load order details'); console.error(err); } finally { setLoading(false); } }; fetchOrderDetails(); }, []); if (loading) { return (

Loading your order details...

); } if (error || !orderDetails) { return (
⚠️

Order Not Found

{error || 'Unable to retrieve order details'}

); } const { order, session } = orderDetails; const totalAmount = order.totalAmount / 100; // Convert cents to dollars const baseAmount = order.baseAmount / 100; const processingFee = order.processingFee / 100; // Use Stripe payment status if available (more accurate for just-completed payments) // Otherwise fall back to order status const effectiveStatus = session.paymentStatus === 'paid' ? 'paid' : order.status; const statusDisplay = getStatusDisplay(effectiveStatus); return ( <> {/* Print-specific styles */}
{/* Receipt Container */}
{/* Header with Logo */} Puffin Offset

Order Confirmed

Thank you for your carbon offset purchase

{/* Success Badge */}
{/* Order Details Section */}

Order Summary

{/* Carbon Offset - Highlighted */}
Carbon Offset

{order.tons} tons CO₂

{/* Portfolio */}
Portfolio #{order.portfolioId}
{/* Pricing Breakdown */}
Offset Cost ${formatCurrency(baseAmount)}
Processing Fee (3%) ${formatCurrency(processingFee)}
Total Paid ${formatCurrency(totalAmount)}
{/* Order Metadata */}
Order ID

{order.id}

Status

{statusDisplay.label}

{session.customerEmail && (
Email

{session.customerEmail}

)}
Date

{new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}

{/* Impact Comparisons */}
{/* Action Buttons */} {/* Confirmation Email Notice */} {session.customerEmail && (

Confirmation email sent to {session.customerEmail}

)} {/* Footer */}

Thank you for making a positive impact on our planet

Questions? Contact us at support@puffinoffset.com

); }