'use client'; import React, { useState, useEffect } from 'react'; import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card'; import { Button } from '@/components/ui/Button'; import { Badge } from '@/components/ui/Badge'; import { showToast } from '@/components/ui/Toast'; import { useRouter } from 'next/navigation'; import { BillingToggle } from '@/components/ui/BillingToggle'; import { ObfuscatedMailto } from '@/components/ui/ObfuscatedMailto'; export default function PricingPage() { const router = useRouter(); const [loading, setLoading] = useState(null); const [currentPlan, setCurrentPlan] = useState('FREE'); const [currentInterval, setCurrentInterval] = useState<'month' | 'year' | null>(null); const [billingPeriod, setBillingPeriod] = useState<'month' | 'year'>('month'); useEffect(() => { // Fetch current user plan const fetchUserPlan = async () => { try { const response = await fetch('/api/user/plan'); if (response.ok) { const data = await response.json(); setCurrentPlan(data.plan || 'FREE'); setCurrentInterval(data.interval || null); } } catch (error) { console.error('Error fetching user plan:', error); } }; fetchUserPlan(); }, []); const handleUpgrade = async (plan: 'PRO' | 'BUSINESS') => { setLoading(plan); try { const response = await fetch('/api/stripe/create-checkout-session', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ plan, billingInterval: billingPeriod === 'month' ? 'month' : 'year', }), }); if (!response.ok) { throw new Error('Failed to create checkout session'); } const { url } = await response.json(); window.location.href = url; } catch (error) { console.error('Error creating checkout session:', error); showToast('Failed to start checkout. Please try again.', 'error'); setLoading(null); } }; const handleDowngrade = async () => { // Show confirmation dialog const confirmed = window.confirm( 'Are you sure you want to downgrade to the Free plan? Your subscription will be canceled immediately and you will lose access to premium features.' ); if (!confirmed) { return; } setLoading('FREE'); try { const response = await fetch('/api/stripe/cancel-subscription', { method: 'POST', headers: { 'Content-Type': 'application/json', }, }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || 'Failed to cancel subscription'); } showToast('Successfully downgraded to Free plan', 'success'); // Refresh to update the plan setTimeout(() => { window.location.reload(); }, 1500); } catch (error: any) { console.error('Error canceling subscription:', error); showToast(error.message || 'Failed to downgrade. Please try again.', 'error'); setLoading(null); } }; // Helper function to check if this is the user's exact current plan (plan + interval) const isCurrentPlanWithInterval = (planType: string, interval: 'month' | 'year') => { return currentPlan === planType && currentInterval === interval; }; // Helper function to check if user has this plan but different interval const hasPlanDifferentInterval = (planType: string) => { return currentPlan === planType && currentInterval && currentInterval !== billingPeriod; }; const selectedInterval = billingPeriod === 'month' ? 'month' : 'year'; const plans = [ { key: 'free', name: 'Free', price: '€0', period: 'forever', showDiscount: false, features: [ '3 active dynamic QR codes (8 types available)', 'Unlimited static QR codes', 'Basic scan tracking', 'Standard QR design templates', 'Download as SVG/PNG', ], buttonText: currentPlan === 'FREE' ? 'Current Plan' : 'Downgrade to Free', buttonVariant: 'outline' as const, disabled: currentPlan === 'FREE', popular: false, onDowngrade: handleDowngrade, }, { key: 'pro', name: 'Pro', price: billingPeriod === 'month' ? '€9' : '€90', period: billingPeriod === 'month' ? 'per month' : 'per year', showDiscount: billingPeriod === 'year', features: [ '50 dynamic QR codes', 'Unlimited static QR codes', 'Advanced analytics (scans, devices, locations)', 'Custom branding (colors & logos)', ], buttonText: isCurrentPlanWithInterval('PRO', selectedInterval) ? 'Current Plan' : hasPlanDifferentInterval('PRO') ? `Switch to ${billingPeriod === 'month' ? 'Monthly' : 'Yearly'}` : 'Upgrade to Pro', buttonVariant: 'primary' as const, disabled: isCurrentPlanWithInterval('PRO', selectedInterval), popular: true, onUpgrade: () => handleUpgrade('PRO'), }, { key: 'business', name: 'Business', price: billingPeriod === 'month' ? '€29' : '€290', period: billingPeriod === 'month' ? 'per month' : 'per year', showDiscount: billingPeriod === 'year', features: [ '500 dynamic QR codes', 'Unlimited static QR codes', 'Everything from Pro', 'Bulk QR Creation (up to 1,000)', 'Priority email support', 'Advanced tracking & insights', ], buttonText: isCurrentPlanWithInterval('BUSINESS', selectedInterval) ? 'Current Plan' : hasPlanDifferentInterval('BUSINESS') ? `Switch to ${billingPeriod === 'month' ? 'Monthly' : 'Yearly'}` : 'Upgrade to Business', buttonVariant: 'primary' as const, disabled: isCurrentPlanWithInterval('BUSINESS', selectedInterval), popular: false, onUpgrade: () => handleUpgrade('BUSINESS'), }, ]; return (

Choose Your Plan

Select the perfect plan for your QR code needs

{plans.map((plan) => ( {plan.popular && (
Most Popular
)} {plan.name}
{plan.price} {plan.period}
{plan.showDiscount && ( Save 16% )}
    {plan.features.map((feature: string, index: number) => (
  • {feature}
  • ))}
))}

All plans include unlimited static QR codes and basic customization.

Need help choosing? Contact our team

); }