141 lines
5.4 KiB
TypeScript
141 lines
5.4 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState } from 'react';
|
|
import { motion } from 'framer-motion';
|
|
import Link from 'next/link';
|
|
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card';
|
|
import { Button } from '@/components/ui/Button';
|
|
import { Badge } from '@/components/ui/Badge';
|
|
import { BillingToggle } from '@/components/ui/BillingToggle';
|
|
|
|
interface PricingProps {
|
|
t: any; // i18n translation function
|
|
}
|
|
|
|
export const Pricing: React.FC<PricingProps> = ({ t }) => {
|
|
const [billingPeriod, setBillingPeriod] = useState<'month' | 'year'>('month');
|
|
|
|
const plans = [
|
|
{
|
|
key: 'free',
|
|
popular: false,
|
|
},
|
|
{
|
|
key: 'pro',
|
|
popular: true,
|
|
},
|
|
{
|
|
key: 'business',
|
|
popular: false,
|
|
},
|
|
];
|
|
|
|
return (
|
|
<section id="pricing" className="py-16">
|
|
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl">
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.5 }}
|
|
className="text-center mb-12"
|
|
>
|
|
<h2 className="text-3xl lg:text-4xl font-bold text-gray-900 mb-4">
|
|
{t.pricing.title}
|
|
</h2>
|
|
<p className="text-xl text-gray-600">
|
|
{t.pricing.subtitle}
|
|
</p>
|
|
</motion.div>
|
|
|
|
<div className="flex justify-center mb-8">
|
|
<BillingToggle value={billingPeriod} onChange={setBillingPeriod} />
|
|
</div>
|
|
|
|
<div className="grid md:grid-cols-3 gap-8 max-w-5xl mx-auto">
|
|
{plans.map((plan, index) => (
|
|
<motion.div
|
|
key={plan.key}
|
|
initial={{ opacity: 0, y: 20 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.5, delay: index * 0.1 }}
|
|
className="h-full"
|
|
>
|
|
<Card
|
|
className={`h-full flex flex-col ${plan.popular
|
|
? 'border-primary-500 shadow-xl relative scale-105 z-10'
|
|
: 'border-gray-200 hover:border-gray-300 hover:shadow-lg transition-all'
|
|
}`}
|
|
>
|
|
{plan.popular && (
|
|
<div className="absolute -top-4 left-1/2 transform -translate-x-1/2 w-full text-center">
|
|
<Badge variant="info" className="px-4 py-1.5 shadow-sm">
|
|
{t.pricing[plan.key].badge}
|
|
</Badge>
|
|
</div>
|
|
)}
|
|
|
|
<CardHeader className="text-center pb-8">
|
|
<CardTitle className="text-2xl mb-4">
|
|
{t.pricing[plan.key].title}
|
|
</CardTitle>
|
|
<div className="flex flex-col items-center">
|
|
<div className="flex items-baseline justify-center">
|
|
<span className="text-4xl font-bold">
|
|
{plan.key === 'free'
|
|
? t.pricing[plan.key].price
|
|
: billingPeriod === 'month'
|
|
? t.pricing[plan.key].price
|
|
: plan.key === 'pro'
|
|
? '€90'
|
|
: '€290'}
|
|
</span>
|
|
<span className="text-gray-600 ml-2">
|
|
{plan.key === 'free'
|
|
? t.pricing[plan.key].period
|
|
: billingPeriod === 'month'
|
|
? t.pricing[plan.key].period
|
|
: 'per year'}
|
|
</span>
|
|
</div>
|
|
{billingPeriod === 'year' && plan.key !== 'free' && (
|
|
<Badge variant="success" className="mt-2">
|
|
Save 16%
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
</CardHeader>
|
|
|
|
<CardContent className="space-y-8 flex-1 flex flex-col">
|
|
<ul className="space-y-3 flex-1">
|
|
{t.pricing[plan.key].features.map((feature: string, index: number) => (
|
|
<li key={index} className="flex items-start space-x-3">
|
|
<svg className="w-5 h-5 text-success-500 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
|
</svg>
|
|
<span className="text-gray-700">{feature}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
|
|
<div className="mt-8 pt-8 border-t border-gray-100">
|
|
<Link href="/signup">
|
|
<Button
|
|
variant={plan.popular ? 'primary' : 'outline'}
|
|
className="w-full"
|
|
size="lg"
|
|
>
|
|
Get Started
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}; |