@moontra/moonui-pro
Version:
Premium React components for MoonUI - Advanced UI library with 50+ pro components including performance, interactive, and gesture components
139 lines (116 loc) • 3.83 kB
text/typescript
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<void>;
}
/**
* Custom hook for Paddle integration
* Handles Paddle initialization and checkout operations
*/
export function usePaddle(): UsePaddleReturn {
const [paddle, setPaddle] = useState<Paddle | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(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,
};
}