From 837f4401070d754bfc7a4c2eb239e6e7e245bf5d Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Thu, 26 Mar 2026 21:25:51 +0100 Subject: [PATCH] feat: add plan summary component for checkout page --- components/checkout/PlanSummary.tsx | 125 ++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 components/checkout/PlanSummary.tsx diff --git a/components/checkout/PlanSummary.tsx b/components/checkout/PlanSummary.tsx new file mode 100644 index 0000000..7a6eab7 --- /dev/null +++ b/components/checkout/PlanSummary.tsx @@ -0,0 +1,125 @@ +'use client' + +import { useState } from 'react' +import { useRouter, useSearchParams } from 'next/navigation' +import { Check } from '@phosphor-icons/react' +import { + TRAFFIC_TIERS, + getSitesLimitForPlan, + getMaxRetentionMonthsForPlan, + PLAN_PRICES, +} from '@/lib/plans' + +interface PlanSummaryProps { + plan: string + interval: string + limit: number +} + +export default function PlanSummary({ plan, interval, limit }: PlanSummaryProps) { + const router = useRouter() + const searchParams = useSearchParams() + const [currentInterval, setCurrentInterval] = useState(interval) + + const monthlyCents = PLAN_PRICES[plan]?.[limit] || 0 + const isYearly = currentInterval === 'year' + const displayPrice = isYearly ? (monthlyCents * 11) / 100 : monthlyCents / 100 + const monthlyEquivalent = isYearly ? displayPrice / 12 : displayPrice + + const tierLabel = + TRAFFIC_TIERS.find((t) => t.value === limit)?.label || + `${(limit / 1000).toFixed(0)}k` + const sitesLimit = getSitesLimitForPlan(plan) + const retentionMonths = getMaxRetentionMonthsForPlan(plan) + const retentionLabel = + retentionMonths >= 12 + ? `${retentionMonths / 12} year${retentionMonths > 12 ? 's' : ''}` + : `${retentionMonths} months` + + const handleIntervalToggle = (newInterval: string) => { + setCurrentInterval(newInterval) + const params = new URLSearchParams(searchParams.toString()) + params.set('interval', newInterval) + router.replace(`/checkout?${params.toString()}`, { scroll: false }) + } + + const features = [ + `${tierLabel} pageviews/mo`, + `${sitesLimit} site${sitesLimit && sitesLimit > 1 ? 's' : ''}`, + `${retentionLabel} data retention`, + 'Unlimited team members', + 'Custom events & goals', + 'Funnels & user journeys', + ] + + return ( +
+ {/* Plan header */} +
+

{plan}

+ + 30-day trial + +
+ + {/* Price display */} +
+
+ + €{isYearly ? monthlyEquivalent.toFixed(2) : displayPrice.toFixed(0)} + + /mo +
+ {isYearly && ( +
+ + €{displayPrice.toFixed(2)} billed yearly + + + Save 1 month + +
+ )} +
+ + {/* Interval toggle */} +
+ + +
+ + {/* Divider */} +
+ + {/* Features list */} +
    + {features.map((feature) => ( +
  • + + {feature} +
  • + ))} +
+
+ ) +}