pricign tbale udpated
This commit is contained in:
@@ -5,20 +5,20 @@
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Check } from 'lucide-react';
|
||||
import Button from '../button/Button';
|
||||
import Badge from '../badge/Badge';
|
||||
|
||||
export interface PricingPlan {
|
||||
id: number;
|
||||
name: string;
|
||||
monthlyPrice: number;
|
||||
price: number;
|
||||
originalPrice?: number;
|
||||
period: string;
|
||||
description: string;
|
||||
features: string[];
|
||||
buttonText: string;
|
||||
highlighted?: boolean;
|
||||
disabled?: boolean;
|
||||
annualDiscountPercent?: number;
|
||||
// Plan limits
|
||||
max_sites?: number;
|
||||
max_users?: number;
|
||||
@@ -44,7 +44,8 @@ export function PricingTable({ variant = '1', title, plans, showToggle = false,
|
||||
|
||||
const getPrice = (plan: PricingPlan) => {
|
||||
if (billingPeriod === 'annual') {
|
||||
return (plan.monthlyPrice * 12 * 0.8).toFixed(0); // 20% discount for annual
|
||||
const discount = plan.annualDiscountPercent || 20;
|
||||
return (plan.monthlyPrice * 12 * (100 - discount) / 100).toFixed(0);
|
||||
}
|
||||
return plan.monthlyPrice.toFixed(0);
|
||||
};
|
||||
@@ -63,30 +64,34 @@ export function PricingTable({ variant = '1', title, plans, showToggle = false,
|
||||
|
||||
{showToggle && (
|
||||
<div className="flex justify-center mb-8">
|
||||
<div className="inline-flex items-center gap-3 p-1 bg-gray-100 dark:bg-gray-800 rounded-lg">
|
||||
<button
|
||||
onClick={() => setBillingPeriod('monthly')}
|
||||
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
|
||||
billingPeriod === 'monthly'
|
||||
? 'bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm'
|
||||
: 'text-gray-600 dark:text-gray-400'
|
||||
}`}
|
||||
>
|
||||
Monthly
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setBillingPeriod('annual')}
|
||||
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
|
||||
billingPeriod === 'annual'
|
||||
? 'bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm'
|
||||
: 'text-gray-600 dark:text-gray-400'
|
||||
}`}
|
||||
>
|
||||
Annual
|
||||
<Badge className="ml-2 text-xs" color="success">
|
||||
Save 20%
|
||||
</Badge>
|
||||
</button>
|
||||
<div className="inline-flex items-center gap-3">
|
||||
<div className="inline-flex items-center gap-3 p-1 bg-gray-100 dark:bg-gray-800 rounded-lg">
|
||||
<button
|
||||
onClick={() => setBillingPeriod('monthly')}
|
||||
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
|
||||
billingPeriod === 'monthly'
|
||||
? 'bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm'
|
||||
: 'text-gray-600 dark:text-gray-400'
|
||||
}`}
|
||||
>
|
||||
Monthly
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setBillingPeriod('annual')}
|
||||
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
|
||||
billingPeriod === 'annual'
|
||||
? 'bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm'
|
||||
: 'text-gray-600 dark:text-gray-400'
|
||||
}`}
|
||||
>
|
||||
Annually
|
||||
</button>
|
||||
</div>
|
||||
{billingPeriod === 'annual' && (
|
||||
<span className="badge-success">
|
||||
Save {Math.round(plans[0]?.annualDiscountPercent || 20)}%
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -97,15 +102,15 @@ export function PricingTable({ variant = '1', title, plans, showToggle = false,
|
||||
key={plan.id}
|
||||
className={`relative rounded-lg border ${
|
||||
plan.highlighted
|
||||
? 'border-primary shadow-lg ring-2 ring-primary ring-opacity-50'
|
||||
? 'pricing-card-featured border-gray-700 shadow-lg ring-2 ring-gray-700'
|
||||
: 'border-gray-200 dark:border-gray-700'
|
||||
} bg-white dark:bg-gray-800 p-6 flex flex-col`}
|
||||
} ${plan.highlighted ? '' : 'bg-white dark:bg-gray-800'} p-6 flex flex-col`}
|
||||
>
|
||||
{plan.highlighted && (
|
||||
<div className="absolute -top-4 left-1/2 transform -translate-x-1/2">
|
||||
<Badge color="primary" className="px-3 py-1">
|
||||
<span className="badge-primary px-3 py-1 inline-block">
|
||||
Popular
|
||||
</Badge>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -115,15 +120,20 @@ export function PricingTable({ variant = '1', title, plans, showToggle = false,
|
||||
</div>
|
||||
|
||||
<div className="mb-6">
|
||||
<div className="flex items-baseline gap-1">
|
||||
<span className="text-4xl font-bold text-gray-900 dark:text-white">
|
||||
<div className="flex items-baseline gap-2">
|
||||
<span className={`text-4xl font-bold ${plan.highlighted ? 'text-white' : 'text-gray-900 dark:text-white'} price-text`}>
|
||||
${getPrice(plan)}
|
||||
</span>
|
||||
<span className="text-gray-600 dark:text-gray-400">{getPeriod()}</span>
|
||||
<span className={plan.highlighted ? 'text-gray-300' : 'text-gray-600 dark:text-gray-400'}>{getPeriod()}</span>
|
||||
{plan.originalPrice && billingPeriod === 'monthly' && (
|
||||
<span className="text-lg line-through text-gray-400">
|
||||
${plan.originalPrice.toFixed(2)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{billingPeriod === 'annual' && plan.monthlyPrice > 0 && (
|
||||
<p className="text-sm text-gray-500 mt-1">
|
||||
Billed ${(plan.monthlyPrice * 12 * 0.8).toFixed(0)}/year
|
||||
Billed ${(plan.monthlyPrice * 12 * (100 - (plan.annualDiscountPercent || 20)) / 100).toFixed(0)}/year
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
@@ -192,14 +202,13 @@ export function PricingTable({ variant = '1', title, plans, showToggle = false,
|
||||
)}
|
||||
</ul>
|
||||
|
||||
<Button
|
||||
variant={plan.highlighted ? 'primary' : 'outline'}
|
||||
className="w-full"
|
||||
<button
|
||||
className={plan.highlighted ? 'btn-primary' : 'btn-outline'}
|
||||
onClick={() => onPlanSelect?.(plan)}
|
||||
disabled={plan.disabled}
|
||||
>
|
||||
{plan.buttonText}
|
||||
</Button>
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user