import React, { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Check, X, Zap, Crown, Rocket, ShieldCheck, ArrowLeft, Sparkles, Loader2, Star } from 'lucide-react'; import { useAuth } from 'react-oidc-context'; interface UpgradePageProps { onBack?: () => void; } type BillingCycle = 'monthly' | 'yearly'; export const UpgradePage: React.FC = ({ onBack }) => { const auth = useAuth(); const [billingCycle, setBillingCycle] = useState('yearly'); const [isLoading, setIsLoading] = useState(false); const [statusLoading, setStatusLoading] = useState(true); const [hasAccess, setHasAccess] = useState(false); const [error, setError] = useState(null); useEffect(() => { checkStatus(); }, []); const checkStatus = async () => { try { const token = auth.user?.access_token; if (!token) return; const backendUrl = import.meta.env.VITE_BACKEND_URL || 'http://localhost:3001'; const response = await fetch(`${backendUrl}/api/payments/status`, { headers: { 'Authorization': `Bearer ${token}` } }); if (response.ok) { const data = await response.json(); setHasAccess(data.hasAccess); } } catch (err) { console.error('Failed to check status:', err); } finally { setStatusLoading(false); } }; const handleCheckout = async () => { try { setIsLoading(true); setError(null); const token = auth.user?.access_token; if (!token) { auth.signinRedirect(); return; } const backendUrl = import.meta.env.VITE_BACKEND_URL || 'http://localhost:3001'; const response = await fetch(`${backendUrl}/api/payments/checkout`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ planType: billingCycle, successUrl: `${window.location.origin}/payment/success`, cancelUrl: `${window.location.origin}/payment/cancel` }) }); if (!response.ok) { throw new Error('Failed to initiate checkout'); } const { url } = await response.json(); window.location.href = url; } catch (err) { setError('Something went wrong. Please try again.'); setIsLoading(false); } }; const containerVariants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.1 } } }; const itemVariants = { hidden: { y: 20, opacity: 0 }, visible: { y: 0, opacity: 1, transition: { type: 'spring', bounce: 0.4 } } }; if (statusLoading) { return (
); } if (hasAccess) { return (

You're a Pro!

You have unlocked unlimited power. Enjoy your premium features!

); } return (
{onBack && ( )}

Unlock Unlimited Power

Supercharge your quizzes with AI magic. Create more, play more, win more.

Starter

For casual players

$0 /forever
Most Popular

Pro Gamer

For serious hosts

${billingCycle === 'monthly' ? '5' : '4.17'} /mo
{billingCycle === 'yearly' && (

Billed $50 yearly (save $10)

)}
{error && (

{error}

)}
Secure payment via Stripe Cancel anytime 7-day money-back guarantee
); }; const FeatureItem: React.FC<{ text: string; included: boolean; dark?: boolean }> = ({ text, included, dark }) => (
  • {included ? : }
    {text}
  • );