'use client'; import { useEffect, useState } from 'react'; import { useSearchParams, useRouter } from 'next/navigation'; import { useQueryClient } from '@tanstack/react-query'; import { API_BASE } from '@/lib/config'; import { CheckCircle2, XCircle, RefreshCw } from 'lucide-react'; import { useI18n } from '@/lib/i18n'; /** * /checkout/success * Stripe redirects here after a successful payment. * We call /api/v1/auth/checkout/sync to update the user plan in DB, * then redirect to /dashboard/profile?tab=subscription. */ export default function CheckoutSuccessPage() { const searchParams = useSearchParams(); const router = useRouter(); const sessionId = searchParams.get('session_id'); const queryClient = useQueryClient(); const { t } = useI18n(); const [status, setStatus] = useState<'syncing' | 'ok' | 'error'>('syncing'); const [message, setMessage] = useState(''); useEffect(() => { if (!sessionId) { // No session_id — just redirect to profile router.replace('/dashboard/profile?tab=subscription'); return; } const token = localStorage.getItem('token'); if (!token) { router.replace('/auth/login'); return; } // Sync the checkout session to update plan in DB fetch(`${API_BASE}/api/v1/auth/checkout/sync?session_id=${sessionId}`, { headers: { Authorization: `Bearer ${token}` }, }) .then(async (res) => { let data: any = {}; try { data = await res.json(); } catch { /* ignore */ } if (res.ok) { setStatus('ok'); setMessage( data.data?.plan ? t('checkout.planActivated', { plan: data.data.plan }) : t('checkout.subscriptionActivated') ); queryClient.invalidateQueries({ queryKey: ['user', 'me'] }); // Redirect after 2s setTimeout(() => router.replace('/dashboard/profile?tab=subscription'), 2000); } else { setStatus('error'); setMessage(data.message ?? data.error ?? t('checkout.syncError')); setTimeout(() => router.replace('/dashboard/profile?tab=subscription'), 3000); } }) .catch(() => { setStatus('error'); setMessage(t('checkout.networkError')); setTimeout(() => router.replace('/dashboard/profile?tab=subscription'), 3000); }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [sessionId]); return (
{status === 'syncing' && ( <>

{t('checkout.activating')}

{t('checkout.activatingDesc')}

)} {status === 'ok' && ( <>

{t('checkout.paymentConfirmed')}

{message}

{t('checkout.redirectingToProfile')}

)} {status === 'error' && ( <>

{t('checkout.paymentReceived')}

{message}

{t('checkout.redirecting')}

)}
); }