import { useState, useEffect } from 'react'; import { getPaddleInstance } from '@/lib/paddle'; import type { Paddle } from '@paddle/paddle-js'; interface UsePaddleReturn { paddle: Paddle | null; isLoading: boolean; error: string | null; openCheckout: (planId: string) => Promise; } /** * Custom hook for Paddle integration * Handles Paddle initialization and checkout operations */ export function usePaddle(): UsePaddleReturn { const [paddle, setPaddle] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); // Initialize Paddle on mount useEffect(() => { let mounted = true; const initPaddle = async () => { try { setIsLoading(true); setError(null); const paddleInstance = await getPaddleInstance(); if (mounted) { if (paddleInstance) { setPaddle(paddleInstance); } else { setError('Failed to initialize Paddle'); } } } catch (err) { if (mounted) { setError(err instanceof Error ? err.message : 'Unknown error'); } } finally { if (mounted) { setIsLoading(false); } } }; initPaddle(); return () => { mounted = false; }; }, []); /** * Open Paddle checkout for a specific plan */ const openCheckout = async (planId: string) => { if (!paddle) { throw new Error('Paddle not initialized'); } try { // Call our API to handle the checkout const response = await fetch('/api/paddle', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ plan: planId }), }); if (!response.ok) { const errorText = await response.text(); throw new Error(errorText || 'Failed to create checkout'); } const result = await response.json(); if (!result.success) { throw new Error(result.message || 'Checkout failed'); } // For mock mode, we need to manually trigger checkout if (process.env.NEXT_PUBLIC_USE_MOCK_PADDLE === 'true') { console.log('🧪 [Hook] Mock mode detected, triggering checkout'); // Import paddle config to get price ID const { PADDLE_CONFIG } = await import('@/lib/paddle'); const priceId = PADDLE_CONFIG.priceIds[planId as keyof typeof PADDLE_CONFIG.priceIds]; console.log('🧪 [Hook] Using price ID:', priceId, 'for plan:', planId); console.log('🧪 [Hook] Paddle instance:', paddle); // Trigger mock checkout const checkoutData = { items: [{ priceId, quantity: 1 }], settings: { displayMode: 'overlay' as const, theme: 'light' as const, locale: 'en' as const, successUrl: `${window.location.origin}/dashboard?success=true` }, customData: { planId, userId: 'test_user', timestamp: new Date().toISOString() } }; console.log('🧪 [Hook] Opening checkout with data:', checkoutData); try { paddle.Checkout.open(checkoutData); console.log('🧪 [Hook] Checkout.open called successfully'); } catch (checkoutError) { console.error('🧪 [Hook] Checkout.open error:', checkoutError); } } // Checkout is opened inline by Paddle console.log('✅ Paddle checkout opened for plan:', planId); } catch (error) { console.error('❌ Checkout error:', error); throw error; } }; return { paddle, isLoading, error, openCheckout, }; }