fix
This commit is contained in:
parent
301409624b
commit
10b45599ae
@ -27,14 +27,15 @@ export default function OrganizationSettingsPage() {
|
|||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const [activeTab, setActiveTab] = useState<TabType>('information');
|
const [activeTab, setActiveTab] = useState<TabType>('information');
|
||||||
|
|
||||||
// Auto-switch to subscription tab if coming back from Stripe
|
// Auto-switch to subscription tab if coming back from Stripe (only for ADMIN/MANAGER)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const isSuccess = searchParams.get('success') === 'true';
|
const isSuccess = searchParams.get('success') === 'true';
|
||||||
const isCanceled = searchParams.get('canceled') === 'true';
|
const isCanceled = searchParams.get('canceled') === 'true';
|
||||||
if (isSuccess || isCanceled) {
|
const canAccessBilling = user?.role === 'ADMIN' || user?.role === 'MANAGER';
|
||||||
|
if ((isSuccess || isCanceled) && canAccessBilling) {
|
||||||
setActiveTab('subscription');
|
setActiveTab('subscription');
|
||||||
}
|
}
|
||||||
}, [searchParams]);
|
}, [searchParams, user?.role]);
|
||||||
const [organization, setOrganization] = useState<OrganizationResponse | null>(null);
|
const [organization, setOrganization] = useState<OrganizationResponse | null>(null);
|
||||||
const [formData, setFormData] = useState<OrganizationForm>({
|
const [formData, setFormData] = useState<OrganizationForm>({
|
||||||
name: '',
|
name: '',
|
||||||
@ -165,6 +166,9 @@ export default function OrganizationSettingsPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if user can view subscription and licenses (only ADMIN and MANAGER)
|
||||||
|
const canViewBilling = user?.role === 'ADMIN' || user?.role === 'MANAGER';
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
id: 'information' as TabType,
|
id: 'information' as TabType,
|
||||||
@ -185,24 +189,27 @@ export default function OrganizationSettingsPage() {
|
|||||||
</svg>
|
</svg>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
// Only show subscription and licenses tabs for ADMIN and MANAGER roles
|
||||||
id: 'subscription' as TabType,
|
...(canViewBilling ? [
|
||||||
label: 'Abonnement',
|
{
|
||||||
icon: (
|
id: 'subscription' as TabType,
|
||||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
label: 'Abonnement',
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
|
icon: (
|
||||||
</svg>
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
),
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
|
||||||
},
|
</svg>
|
||||||
{
|
),
|
||||||
id: 'licenses' as TabType,
|
},
|
||||||
label: 'Licences',
|
{
|
||||||
icon: (
|
id: 'licenses' as TabType,
|
||||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
label: 'Licences',
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
|
icon: (
|
||||||
</svg>
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
),
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||||
},
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
] : []),
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -432,9 +439,9 @@ export default function OrganizationSettingsPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activeTab === 'subscription' && <SubscriptionTab />}
|
{activeTab === 'subscription' && canViewBilling && <SubscriptionTab />}
|
||||||
|
|
||||||
{activeTab === 'licenses' && <LicensesTab />}
|
{activeTab === 'licenses' && canViewBilling && <LicensesTab />}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Actions (only for information and address tabs) */}
|
{/* Actions (only for information and address tabs) */}
|
||||||
|
|||||||
@ -22,6 +22,12 @@ import {
|
|||||||
Container,
|
Container,
|
||||||
FileText,
|
FileText,
|
||||||
LayoutDashboard,
|
LayoutDashboard,
|
||||||
|
Bell,
|
||||||
|
BookOpen,
|
||||||
|
Users,
|
||||||
|
Building2,
|
||||||
|
Check,
|
||||||
|
X,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { useAuth } from '@/lib/context/auth-context';
|
import { useAuth } from '@/lib/context/auth-context';
|
||||||
|
|
||||||
@ -50,6 +56,7 @@ export default function LandingPage() {
|
|||||||
const featuresRef = useRef(null);
|
const featuresRef = useRef(null);
|
||||||
const statsRef = useRef(null);
|
const statsRef = useRef(null);
|
||||||
const toolsRef = useRef(null);
|
const toolsRef = useRef(null);
|
||||||
|
const pricingRef = useRef(null);
|
||||||
const testimonialsRef = useRef(null);
|
const testimonialsRef = useRef(null);
|
||||||
const ctaRef = useRef(null);
|
const ctaRef = useRef(null);
|
||||||
|
|
||||||
@ -57,6 +64,7 @@ export default function LandingPage() {
|
|||||||
const isFeaturesInView = useInView(featuresRef, { once: true });
|
const isFeaturesInView = useInView(featuresRef, { once: true });
|
||||||
const isStatsInView = useInView(statsRef, { once: true });
|
const isStatsInView = useInView(statsRef, { once: true });
|
||||||
const isToolsInView = useInView(toolsRef, { once: true });
|
const isToolsInView = useInView(toolsRef, { once: true });
|
||||||
|
const isPricingInView = useInView(pricingRef, { once: true });
|
||||||
const isTestimonialsInView = useInView(testimonialsRef, { once: true });
|
const isTestimonialsInView = useInView(testimonialsRef, { once: true });
|
||||||
const isCtaInView = useInView(ctaRef, { once: true });
|
const isCtaInView = useInView(ctaRef, { once: true });
|
||||||
|
|
||||||
@ -72,84 +80,90 @@ export default function LandingPage() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const features = [
|
const features = [
|
||||||
{
|
|
||||||
icon: Search,
|
|
||||||
title: 'Recherche Intelligente',
|
|
||||||
description:
|
|
||||||
'Comparez instantanément les tarifs de plus de 50 compagnies maritimes en temps réel.',
|
|
||||||
color: 'from-blue-500 to-cyan-500',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: Zap,
|
|
||||||
title: 'Réservation Rapide',
|
|
||||||
description: 'Réservez vos containers LCL/FCL en quelques clics avec confirmation immédiate.',
|
|
||||||
color: 'from-purple-500 to-pink-500',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
icon: BarChart3,
|
icon: BarChart3,
|
||||||
title: 'Tableau de Bord',
|
title: 'Dashboard Analytics',
|
||||||
description: 'Suivez tous vos envois en temps réel avec des KPIs détaillés et des analytics.',
|
description:
|
||||||
|
'Suivez tous vos KPIs en temps réel : bookings, volumes, revenus et alertes personnalisées.',
|
||||||
|
color: 'from-blue-500 to-cyan-500',
|
||||||
|
link: '/dashboard',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Package,
|
||||||
|
title: 'Gestion des Bookings',
|
||||||
|
description: 'Créez, gérez et suivez vos réservations maritimes LCL/FCL avec un historique complet.',
|
||||||
|
color: 'from-purple-500 to-pink-500',
|
||||||
|
link: '/dashboard/bookings',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: FileText,
|
||||||
|
title: 'Documents Maritimes',
|
||||||
|
description: 'Centralisez tous vos documents : B/L, factures, certificats et documents douaniers.',
|
||||||
color: 'from-orange-500 to-red-500',
|
color: 'from-orange-500 to-red-500',
|
||||||
|
link: '/dashboard/documents',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: Globe,
|
icon: Search,
|
||||||
title: '10 000+ Ports',
|
title: 'Track & Trace',
|
||||||
description:
|
description:
|
||||||
'Accédez à un réseau mondial de ports avec des données actualisées quotidiennement.',
|
'Suivez vos conteneurs en temps réel auprès de 10+ transporteurs majeurs (Maersk, MSC, CMA CGM...).',
|
||||||
color: 'from-green-500 to-emerald-500',
|
color: 'from-green-500 to-emerald-500',
|
||||||
|
link: '/dashboard/track-trace',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: TrendingUp,
|
icon: BookOpen,
|
||||||
title: 'Meilleurs Prix',
|
title: 'Wiki Maritime',
|
||||||
description:
|
description:
|
||||||
'Optimisation automatique des tarifs pour vous garantir les prix les plus compétitifs.',
|
'Base de connaissances complète : Incoterms, documents, procédures douanières et plus encore.',
|
||||||
color: 'from-yellow-500 to-orange-500',
|
color: 'from-yellow-500 to-orange-500',
|
||||||
|
link: '/dashboard/wiki',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: Shield,
|
icon: Bell,
|
||||||
title: 'Sécurisé',
|
title: 'Notifications Temps Réel',
|
||||||
description:
|
description:
|
||||||
'Plateforme conforme aux standards internationaux avec chiffrement de bout en bout.',
|
'Restez informé avec des alertes instantanées sur vos bookings, documents et mises à jour.',
|
||||||
color: 'from-indigo-500 to-purple-500',
|
color: 'from-indigo-500 to-purple-500',
|
||||||
|
link: '/dashboard',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const tools = [
|
const tools = [
|
||||||
{
|
{
|
||||||
icon: Calculator,
|
icon: LayoutDashboard,
|
||||||
title: 'Calculateur de Fret',
|
title: 'Dashboard',
|
||||||
description: 'Estimez vos coûts de transport en temps réel',
|
description: 'Vue d\'ensemble de votre activité maritime',
|
||||||
link: '/tools/calculator',
|
link: '/dashboard',
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: MapPin,
|
|
||||||
title: 'Distance & Temps',
|
|
||||||
description: 'Calculez la distance et le temps entre ports',
|
|
||||||
link: '/tools/distance',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: Package,
|
icon: Package,
|
||||||
title: 'Optimiseur de Chargement',
|
title: 'Mes Bookings',
|
||||||
description: "Maximisez l'utilisation de vos containers",
|
description: 'Gérez toutes vos réservations en un seul endroit',
|
||||||
link: '/tools/load-optimizer',
|
link: '/dashboard/bookings',
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: Ship,
|
|
||||||
title: 'Suivi en Temps Réel',
|
|
||||||
description: 'Trackez vos envois partout dans le monde',
|
|
||||||
link: '/tracking',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: FileText,
|
icon: FileText,
|
||||||
title: 'Documents Maritimes',
|
title: 'Documents',
|
||||||
description: 'Générez automatiquement vos documents',
|
description: 'Accédez à tous vos documents maritimes',
|
||||||
link: '/tools/documents',
|
link: '/dashboard/documents',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: TrendingUp,
|
icon: Search,
|
||||||
title: 'Index des Tarifs',
|
title: 'Track & Trace',
|
||||||
description: 'Suivez les tendances du marché maritime',
|
description: 'Suivez vos conteneurs en temps réel',
|
||||||
link: '/tools/freight-index',
|
link: '/dashboard/track-trace',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: BookOpen,
|
||||||
|
title: 'Wiki Maritime',
|
||||||
|
description: 'Base de connaissances du fret maritime',
|
||||||
|
link: '/dashboard/wiki',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Users,
|
||||||
|
title: 'Mon Profil',
|
||||||
|
description: 'Gérez vos informations personnelles',
|
||||||
|
link: '/dashboard/profile',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -160,6 +174,63 @@ export default function LandingPage() {
|
|||||||
{ value: '99.5%', label: 'Disponibilité', icon: CheckCircle2 },
|
{ value: '99.5%', label: 'Disponibilité', icon: CheckCircle2 },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const pricingPlans = [
|
||||||
|
{
|
||||||
|
name: 'Starter',
|
||||||
|
price: 'Gratuit',
|
||||||
|
period: '',
|
||||||
|
description: 'Idéal pour découvrir la plateforme',
|
||||||
|
features: [
|
||||||
|
{ text: 'Jusqu\'à 5 bookings/mois', included: true },
|
||||||
|
{ text: 'Track & Trace illimité', included: true },
|
||||||
|
{ text: 'Wiki maritime complet', included: true },
|
||||||
|
{ text: 'Dashboard basique', included: true },
|
||||||
|
{ text: 'Support par email', included: true },
|
||||||
|
{ text: 'Gestion des documents', included: false },
|
||||||
|
{ text: 'Notifications temps réel', included: false },
|
||||||
|
{ text: 'API access', included: false },
|
||||||
|
],
|
||||||
|
cta: 'Commencer gratuitement',
|
||||||
|
highlighted: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Professional',
|
||||||
|
price: '99€',
|
||||||
|
period: '/mois',
|
||||||
|
description: 'Pour les transitaires en croissance',
|
||||||
|
features: [
|
||||||
|
{ text: 'Bookings illimités', included: true },
|
||||||
|
{ text: 'Track & Trace illimité', included: true },
|
||||||
|
{ text: 'Wiki maritime complet', included: true },
|
||||||
|
{ text: 'Dashboard avancé + KPIs', included: true },
|
||||||
|
{ text: 'Support prioritaire', included: true },
|
||||||
|
{ text: 'Gestion des documents', included: true },
|
||||||
|
{ text: 'Notifications temps réel', included: true },
|
||||||
|
{ text: 'API access', included: false },
|
||||||
|
],
|
||||||
|
cta: 'Essai gratuit 14 jours',
|
||||||
|
highlighted: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Enterprise',
|
||||||
|
price: 'Sur mesure',
|
||||||
|
period: '',
|
||||||
|
description: 'Pour les grandes entreprises',
|
||||||
|
features: [
|
||||||
|
{ text: 'Tout Professional +', included: true },
|
||||||
|
{ text: 'API access complet', included: true },
|
||||||
|
{ text: 'Intégrations personnalisées', included: true },
|
||||||
|
{ text: 'Account manager dédié', included: true },
|
||||||
|
{ text: 'SLA garanti 99.9%', included: true },
|
||||||
|
{ text: 'Formation sur site', included: true },
|
||||||
|
{ text: 'Multi-organisations', included: true },
|
||||||
|
{ text: 'Audit & conformité', included: true },
|
||||||
|
],
|
||||||
|
cta: 'Contactez-nous',
|
||||||
|
highlighted: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const testimonials = [
|
const testimonials = [
|
||||||
{
|
{
|
||||||
quote:
|
quote:
|
||||||
@ -474,15 +545,23 @@ export default function LandingPage() {
|
|||||||
key={index}
|
key={index}
|
||||||
variants={itemVariants}
|
variants={itemVariants}
|
||||||
whileHover={{ scale: 1.05, y: -10 }}
|
whileHover={{ scale: 1.05, y: -10 }}
|
||||||
className="group bg-white p-8 rounded-2xl shadow-lg hover:shadow-2xl transition-all border border-gray-100 cursor-pointer"
|
|
||||||
>
|
>
|
||||||
<div
|
<Link
|
||||||
className={`w-14 h-14 rounded-xl bg-gradient-to-br ${feature.color} flex items-center justify-center mb-4 group-hover:scale-110 transition-transform`}
|
href={feature.link}
|
||||||
|
className="group block bg-white p-8 rounded-2xl shadow-lg hover:shadow-2xl transition-all border border-gray-100"
|
||||||
>
|
>
|
||||||
<IconComponent className="w-7 h-7 text-white" />
|
<div
|
||||||
</div>
|
className={`w-14 h-14 rounded-xl bg-gradient-to-br ${feature.color} flex items-center justify-center mb-4 group-hover:scale-110 transition-transform`}
|
||||||
<h3 className="text-2xl font-bold text-brand-navy mb-3">{feature.title}</h3>
|
>
|
||||||
<p className="text-gray-600 leading-relaxed">{feature.description}</p>
|
<IconComponent className="w-7 h-7 text-white" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-2xl font-bold text-brand-navy mb-3 group-hover:text-brand-turquoise transition-colors">{feature.title}</h3>
|
||||||
|
<p className="text-gray-600 leading-relaxed">{feature.description}</p>
|
||||||
|
<div className="mt-4 flex items-center text-brand-turquoise font-medium opacity-0 group-hover:opacity-100 transition-opacity">
|
||||||
|
<span>Découvrir</span>
|
||||||
|
<ArrowRight className="w-4 h-4 ml-2 group-hover:translate-x-1 transition-transform" />
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@ -603,6 +682,103 @@ export default function LandingPage() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{/* Pricing Section */}
|
||||||
|
<section
|
||||||
|
ref={pricingRef}
|
||||||
|
id="pricing"
|
||||||
|
className="py-20 lg:py-32 bg-gradient-to-br from-gray-50 to-white"
|
||||||
|
>
|
||||||
|
<div className="max-w-7xl mx-auto px-6 lg:px-8">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 30 }}
|
||||||
|
animate={isPricingInView ? { opacity: 1, y: 0 } : {}}
|
||||||
|
transition={{ duration: 0.8 }}
|
||||||
|
className="text-center mb-16"
|
||||||
|
>
|
||||||
|
<h2 className="text-4xl lg:text-5xl font-bold text-brand-navy mb-4">
|
||||||
|
Tarifs simples et transparents
|
||||||
|
</h2>
|
||||||
|
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
|
||||||
|
Choisissez le plan adapté à vos besoins. Évoluez à tout moment.
|
||||||
|
</p>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
variants={containerVariants}
|
||||||
|
initial="hidden"
|
||||||
|
animate={isPricingInView ? 'visible' : 'hidden'}
|
||||||
|
className="grid grid-cols-1 md:grid-cols-3 gap-8"
|
||||||
|
>
|
||||||
|
{pricingPlans.map((plan, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={index}
|
||||||
|
variants={itemVariants}
|
||||||
|
whileHover={{ y: -10 }}
|
||||||
|
className={`relative bg-white rounded-2xl shadow-lg border-2 transition-all ${
|
||||||
|
plan.highlighted
|
||||||
|
? 'border-brand-turquoise shadow-2xl scale-105'
|
||||||
|
: 'border-gray-200 hover:border-brand-turquoise/50'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{plan.highlighted && (
|
||||||
|
<div className="absolute -top-4 left-1/2 transform -translate-x-1/2">
|
||||||
|
<span className="bg-brand-turquoise text-white text-sm font-bold px-4 py-1 rounded-full">
|
||||||
|
Populaire
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="p-8">
|
||||||
|
<h3 className="text-2xl font-bold text-brand-navy mb-2">{plan.name}</h3>
|
||||||
|
<p className="text-gray-600 mb-6">{plan.description}</p>
|
||||||
|
<div className="mb-6">
|
||||||
|
<span className="text-5xl font-bold text-brand-navy">{plan.price}</span>
|
||||||
|
<span className="text-gray-500">{plan.period}</span>
|
||||||
|
</div>
|
||||||
|
<ul className="space-y-3 mb-8">
|
||||||
|
{plan.features.map((feature, featureIndex) => (
|
||||||
|
<li key={featureIndex} className="flex items-center">
|
||||||
|
{feature.included ? (
|
||||||
|
<Check className="w-5 h-5 text-brand-green mr-3 flex-shrink-0" />
|
||||||
|
) : (
|
||||||
|
<X className="w-5 h-5 text-gray-300 mr-3 flex-shrink-0" />
|
||||||
|
)}
|
||||||
|
<span className={feature.included ? 'text-gray-700' : 'text-gray-400'}>
|
||||||
|
{feature.text}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<Link
|
||||||
|
href={plan.name === 'Enterprise' ? '/contact' : '/register'}
|
||||||
|
className={`block w-full text-center py-3 px-6 rounded-lg font-semibold transition-all ${
|
||||||
|
plan.highlighted
|
||||||
|
? 'bg-brand-turquoise text-white hover:bg-brand-turquoise/90 shadow-lg hover:shadow-xl'
|
||||||
|
: 'bg-gray-100 text-brand-navy hover:bg-gray-200'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{plan.cta}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={isPricingInView ? { opacity: 1, y: 0 } : {}}
|
||||||
|
transition={{ duration: 0.8, delay: 0.4 }}
|
||||||
|
className="mt-12 text-center"
|
||||||
|
>
|
||||||
|
<p className="text-gray-600">
|
||||||
|
Tous les plans incluent un essai gratuit de 14 jours. Aucune carte bancaire requise.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-gray-500 mt-2">
|
||||||
|
Des questions ? <Link href="/contact" className="text-brand-turquoise hover:underline">Contactez notre équipe commerciale</Link>
|
||||||
|
</p>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
{/* How It Works Section */}
|
{/* How It Works Section */}
|
||||||
<section className="py-20 lg:py-32 bg-gradient-to-br from-brand-navy to-brand-navy/95 relative overflow-hidden">
|
<section className="py-20 lg:py-32 bg-gradient-to-br from-brand-navy to-brand-navy/95 relative overflow-hidden">
|
||||||
<div className="absolute inset-0 opacity-10">
|
<div className="absolute inset-0 opacity-10">
|
||||||
|
|||||||
@ -274,9 +274,6 @@ export default function SubscriptionTab() {
|
|||||||
: `Plus que ${subscription.availableLicenses} licence${subscription.availableLicenses === 1 ? '' : 's'} disponible${subscription.availableLicenses === 1 ? '' : 's'}.`}
|
: `Plus que ${subscription.availableLicenses} licence${subscription.availableLicenses === 1 ? '' : 's'} disponible${subscription.availableLicenses === 1 ? '' : 's'}.`}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<p className="mt-2 text-xs text-gray-400">
|
|
||||||
Les administrateurs (ADMIN) ont des licences illimitées et ne sont pas comptés.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Billing Period */}
|
{/* Billing Period */}
|
||||||
@ -416,28 +413,6 @@ export default function SubscriptionTab() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Info about webhooks in development */}
|
|
||||||
{process.env.NODE_ENV === 'development' && (
|
|
||||||
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
|
||||||
<div className="flex">
|
|
||||||
<div className="flex-shrink-0">
|
|
||||||
<svg className="h-5 w-5 text-yellow-400" viewBox="0 0 20 20" fill="currentColor">
|
|
||||||
<path fillRule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clipRule="evenodd" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div className="ml-3">
|
|
||||||
<h3 className="text-sm font-medium text-yellow-800">Mode développement</h3>
|
|
||||||
<div className="mt-2 text-sm text-yellow-700">
|
|
||||||
<p>
|
|
||||||
Pour que les webhooks Stripe fonctionnent en local, exécutez :{' '}
|
|
||||||
<code className="bg-yellow-100 px-1 rounded">stripe listen --forward-to localhost:4000/api/v1/subscriptions/webhook</code>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user