xpeditis2.0/apps/frontend/app/pricing/page.tsx
2026-03-18 15:11:09 +01:00

308 lines
11 KiB
TypeScript

'use client';
import React, { useState } from 'react';
import Link from 'next/link';
import Image from 'next/image';
import { Check, X, ArrowRight, Shield } from 'lucide-react';
type BillingInterval = 'monthly' | 'yearly';
const PLANS = [
{
name: 'Bronze',
key: 'BRONZE' as const,
monthlyPrice: 0,
yearlyPrice: 0,
description: 'Pour démarrer et tester la plateforme',
maxUsers: 1,
maxShipments: '12/an',
commission: '5%',
support: 'Aucun',
badge: null,
features: [
{ name: 'Recherche de tarifs', included: true },
{ name: 'Réservations', included: true },
{ name: 'Tableau de bord', included: false },
{ name: 'Wiki Maritime', included: false },
{ name: 'Gestion des utilisateurs', included: false },
{ name: 'Import CSV', included: false },
{ name: 'Accès API', included: false },
{ name: 'Interface personnalisée', included: false },
{ name: 'KAM dédié', included: false },
],
cta: 'Commencer gratuitement',
ctaStyle: 'bg-gray-900 text-white hover:bg-gray-800',
popular: false,
},
{
name: 'Silver',
key: 'SILVER' as const,
monthlyPrice: 249,
yearlyPrice: 2739,
description: 'Pour les équipes en croissance',
maxUsers: 5,
maxShipments: 'Illimitées',
commission: '3%',
support: 'Email',
badge: 'silver' as const,
features: [
{ name: 'Recherche de tarifs', included: true },
{ name: 'Réservations', included: true },
{ name: 'Tableau de bord', included: true },
{ name: 'Wiki Maritime', included: true },
{ name: 'Gestion des utilisateurs', included: true },
{ name: 'Import CSV', included: true },
{ name: 'Accès API', included: false },
{ name: 'Interface personnalisée', included: false },
{ name: 'KAM dédié', included: false },
],
cta: 'Choisir Silver',
ctaStyle: 'bg-brand-turquoise text-white hover:opacity-90',
popular: true,
},
{
name: 'Gold',
key: 'GOLD' as const,
monthlyPrice: 899,
yearlyPrice: 9889,
description: 'Pour les entreprises établies',
maxUsers: 20,
maxShipments: 'Illimitées',
commission: '2%',
support: 'Direct',
badge: 'gold' as const,
features: [
{ name: 'Recherche de tarifs', included: true },
{ name: 'Réservations', included: true },
{ name: 'Tableau de bord', included: true },
{ name: 'Wiki Maritime', included: true },
{ name: 'Gestion des utilisateurs', included: true },
{ name: 'Import CSV', included: true },
{ name: 'Accès API', included: true },
{ name: 'Interface personnalisée', included: false },
{ name: 'KAM dédié', included: false },
],
cta: 'Choisir Gold',
ctaStyle: 'bg-yellow-500 text-white hover:bg-yellow-600',
popular: false,
},
{
name: 'Platinium',
key: 'PLATINIUM' as const,
monthlyPrice: -1,
yearlyPrice: -1,
description: 'Solutions sur mesure',
maxUsers: 'Illimité',
maxShipments: 'Illimitées',
commission: '1%',
support: 'KAM dédié',
badge: 'platinium' as const,
features: [
{ name: 'Recherche de tarifs', included: true },
{ name: 'Réservations', included: true },
{ name: 'Tableau de bord', included: true },
{ name: 'Wiki Maritime', included: true },
{ name: 'Gestion des utilisateurs', included: true },
{ name: 'Import CSV', included: true },
{ name: 'Accès API', included: true },
{ name: 'Interface personnalisée', included: true },
{ name: 'KAM dédié', included: true },
],
cta: 'Nous contacter',
ctaStyle: 'bg-purple-600 text-white hover:bg-purple-700',
popular: false,
},
];
function formatPrice(amount: number): string {
return new Intl.NumberFormat('fr-FR', {
style: 'currency',
currency: 'EUR',
minimumFractionDigits: 0,
maximumFractionDigits: 0,
}).format(amount);
}
export default function PricingPage() {
const [billing, setBilling] = useState<BillingInterval>('monthly');
return (
<div className="min-h-screen bg-white">
{/* Header */}
<header className="border-b">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex items-center justify-between">
<Link href="/">
<Image
src="/assets/logos/logo-black.svg"
alt="Xpeditis"
width={40}
height={48}
priority
/>
</Link>
<div className="flex items-center gap-4">
<Link href="/login" className="text-sm text-gray-600 hover:text-gray-900">
Connexion
</Link>
<Link
href="/register"
className="text-sm bg-brand-turquoise text-white px-4 py-2 rounded-lg hover:opacity-90"
>
Inscription
</Link>
</div>
</div>
</header>
{/* Hero */}
<section className="py-16 text-center">
<h1 className="text-4xl font-bold text-gray-900 mb-4">
Des tarifs simples et transparents
</h1>
<p className="text-lg text-gray-600 max-w-2xl mx-auto mb-8">
Choisissez la formule adaptée à votre activité de transport maritime.
Commencez gratuitement, évoluez selon vos besoins.
</p>
{/* Billing toggle */}
<div className="flex items-center justify-center gap-4 mb-12">
<span className={`text-sm font-medium ${billing === 'monthly' ? 'text-gray-900' : 'text-gray-500'}`}>
Mensuel
</span>
<button
onClick={() => setBilling(billing === 'monthly' ? 'yearly' : 'monthly')}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
billing === 'yearly' ? 'bg-brand-turquoise' : 'bg-gray-300'
}`}
>
<span
className={`inline-block h-4 w-4 rounded-full bg-white transition-transform ${
billing === 'yearly' ? 'translate-x-6' : 'translate-x-1'
}`}
/>
</button>
<span className={`text-sm font-medium ${billing === 'yearly' ? 'text-gray-900' : 'text-gray-500'}`}>
Annuel
</span>
{billing === 'yearly' && (
<span className="text-xs bg-green-100 text-green-800 px-2 py-1 rounded-full font-medium">
-1 mois offert
</span>
)}
</div>
</section>
{/* Plans grid */}
<section className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-20">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{PLANS.map((plan) => (
<div
key={plan.key}
className={`relative rounded-2xl border-2 p-6 flex flex-col ${
plan.popular
? 'border-brand-turquoise shadow-lg shadow-brand-turquoise/10'
: 'border-gray-200'
}`}
>
{plan.popular && (
<div className="absolute -top-3 left-1/2 -translate-x-1/2">
<span className="bg-brand-turquoise text-white text-xs font-semibold px-3 py-1 rounded-full">
Populaire
</span>
</div>
)}
{/* Plan name & badge */}
<div className="flex items-center gap-2 mb-2">
<h3 className="text-xl font-bold text-gray-900">{plan.name}</h3>
{plan.badge && (
<Shield className={`w-5 h-5 ${
plan.badge === 'silver' ? 'text-slate-500' :
plan.badge === 'gold' ? 'text-yellow-500' :
'text-purple-500'
}`} />
)}
</div>
<p className="text-sm text-gray-500 mb-4">{plan.description}</p>
{/* Price */}
<div className="mb-6">
{plan.monthlyPrice === -1 ? (
<p className="text-3xl font-bold text-gray-900">Sur devis</p>
) : plan.monthlyPrice === 0 ? (
<p className="text-3xl font-bold text-gray-900">Gratuit</p>
) : (
<>
<p className="text-3xl font-bold text-gray-900">
{billing === 'monthly'
? formatPrice(plan.monthlyPrice)
: formatPrice(Math.round(plan.yearlyPrice / 12))}
<span className="text-base font-normal text-gray-500">/mois</span>
</p>
{billing === 'yearly' && (
<p className="text-sm text-gray-500 mt-1">
{formatPrice(plan.yearlyPrice)}/an (11 mois)
</p>
)}
</>
)}
</div>
{/* Quick stats */}
<div className="space-y-2 mb-6 text-sm">
<div className="flex justify-between">
<span className="text-gray-500">Utilisateurs</span>
<span className="font-medium">{plan.maxUsers}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-500">Expéditions</span>
<span className="font-medium">{plan.maxShipments}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-500">Commission</span>
<span className="font-medium">{plan.commission}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-500">Support</span>
<span className="font-medium">{plan.support}</span>
</div>
</div>
{/* Features */}
<div className="flex-1 space-y-2 mb-6">
{plan.features.map((feature) => (
<div key={feature.name} className="flex items-center gap-2 text-sm">
{feature.included ? (
<Check className="w-4 h-4 text-green-500 flex-shrink-0" />
) : (
<X className="w-4 h-4 text-gray-300 flex-shrink-0" />
)}
<span className={feature.included ? 'text-gray-700' : 'text-gray-400'}>
{feature.name}
</span>
</div>
))}
</div>
{/* CTA */}
<Link
href={plan.key === 'PLATINIUM' ? '/contact' : '/register'}
className={`block text-center py-3 px-4 rounded-lg text-sm font-semibold transition-all ${plan.ctaStyle}`}
>
{plan.cta}
<ArrowRight className="inline-block w-4 h-4 ml-1" />
</Link>
</div>
))}
</div>
</section>
{/* Footer */}
<footer className="border-t py-8 text-center text-sm text-gray-500">
<p>Tous les prix sont en euros HT. Facturation annuelle = 11 mois.</p>
</footer>
</div>
);
}