'use client' import { Suspense, useEffect, useState } from 'react' import { useRouter, useSearchParams } from 'next/navigation' import Image from 'next/image' import Link from 'next/link' import { motion } from 'framer-motion' import { useAuth } from '@/lib/auth/context' import { useSubscription } from '@/lib/swr/dashboard' import { getSubscription } from '@/lib/api/billing' import { PLAN_PRICES, TRAFFIC_TIERS } from '@/lib/plans' import PlanSummary from '@/components/checkout/PlanSummary' import PaymentForm from '@/components/checkout/PaymentForm' import pulseLogo from '@/public/pulse_logo_no_margins.png' // --------------------------------------------------------------------------- // Validation helpers // --------------------------------------------------------------------------- const VALID_PLANS = new Set(Object.keys(PLAN_PRICES)) const VALID_INTERVALS = new Set(['month', 'year']) const VALID_LIMITS = new Set(TRAFFIC_TIERS.map((t) => t.value)) function isValidCheckoutParams(plan: string | null, interval: string | null, limit: string | null) { if (!plan || !interval || !limit) return false const limitNum = Number(limit) if (!VALID_PLANS.has(plan)) return false if (!VALID_INTERVALS.has(interval)) return false if (!VALID_LIMITS.has(limitNum)) return false if (!PLAN_PRICES[plan]?.[limitNum]) return false return true } // --------------------------------------------------------------------------- // Success polling component (post-3DS return) // --------------------------------------------------------------------------- function CheckoutSuccess() { const router = useRouter() const [ready, setReady] = useState(false) const [timedOut, setTimedOut] = useState(false) useEffect(() => { let cancelled = false const timeout = setTimeout(() => setTimedOut(true), 30000) const poll = async () => { for (let i = 0; i < 15; i++) { if (cancelled) return try { const data = await getSubscription() if (data.subscription_status === 'active' || data.subscription_status === 'trialing') { setReady(true) clearTimeout(timeout) setTimeout(() => router.push('/'), 2000) return } } catch { // ignore — keep polling } await new Promise((r) => setTimeout(r, 2000)) } setTimedOut(true) } poll() return () => { cancelled = true clearTimeout(timeout) } }, [router]) return (
Redirecting to dashboard...
> ) : timedOut ? ( <>Your payment was received. It may take a moment to activate.
Go to dashboard > ) : ( <>This usually takes a few seconds.
> )}