'use client'; import { useRef, useState, useEffect } from 'react'; import { Link } from '@/i18n/navigation'; import Image from 'next/image'; import { motion, useInView, useScroll, useTransform } from 'framer-motion'; import { Ship, Shield, Zap, BarChart3, Package, Clock, CheckCircle2, ArrowRight, Search, Anchor, Container, FileText, LayoutDashboard, Bell, BookOpen, Users, Check, X, } from 'lucide-react'; import { useTranslations, useLocale } from 'next-intl'; import { useAuth } from '@/lib/context/auth-context'; import { LandingHeader, LandingFooter } from '@/components/layout'; function AnimatedCounter({ end, suffix = '', prefix = '', decimals = 0, isActive, duration = 2, }: { end: number; suffix?: string; prefix?: string; decimals?: number; isActive: boolean; duration?: number; }) { const [count, setCount] = useState(0); useEffect(() => { if (!isActive) return; let startTime: number | undefined; const animate = (timestamp: number) => { if (!startTime) startTime = timestamp; const progress = Math.min((timestamp - startTime) / (duration * 1000), 1); const eased = 1 - Math.pow(1 - progress, 3); setCount(eased * end); if (progress < 1) requestAnimationFrame(animate); else setCount(end); }; requestAnimationFrame(animate); }, [end, duration, isActive]); const display = decimals > 0 ? count.toFixed(decimals) : Math.floor(count).toString(); return ( <> {prefix} {display} {suffix} ); } export default function LandingPage() { const t = useTranslations('landing'); const tCommon = useTranslations('common'); const locale = useLocale(); const { user, isAuthenticated } = useAuth(); const heroRef = useRef(null); const featuresRef = useRef(null); const statsRef = useRef(null); const pricingRef = useRef(null); const testimonialsRef = useRef(null); const ctaRef = useRef(null); const howRef = useRef(null); const isHeroInView = useInView(heroRef, { once: true }); const isFeaturesInView = useInView(featuresRef, { once: true }); const isStatsInView = useInView(statsRef, { once: true, amount: 0.3 }); const isPricingInView = useInView(pricingRef, { once: true }); const isTestimonialsInView = useInView(testimonialsRef, { once: true }); const isCtaInView = useInView(ctaRef, { once: true }); const isHowInView = useInView(howRef, { once: true, amount: 0.2 }); const [billingYearly, setBillingYearly] = useState(false); const { scrollYProgress } = useScroll(); const backgroundY = useTransform(scrollYProgress, [0, 1], ['0%', '50%']); const features = [ { icon: BarChart3, title: t('features.dashboard.title'), description: t('features.dashboard.description'), color: 'from-blue-500 to-cyan-500', link: '/dashboard', }, { icon: Package, title: t('features.bookings.title'), description: t('features.bookings.description'), color: 'from-purple-500 to-pink-500', link: '/dashboard/bookings', }, { icon: FileText, title: t('features.documents.title'), description: t('features.documents.description'), color: 'from-orange-500 to-red-500', link: '/dashboard/documents', }, { icon: Search, title: t('features.tracking.title'), description: t('features.tracking.description'), color: 'from-green-500 to-emerald-500', link: '/dashboard/track-trace', }, { icon: BookOpen, title: t('features.wiki.title'), description: t('features.wiki.description'), color: 'from-yellow-500 to-orange-500', link: '/dashboard/wiki', }, { icon: Bell, title: t('features.notifications.title'), description: t('features.notifications.description'), color: 'from-indigo-500 to-purple-500', link: '/dashboard', }, ]; const stats = [ { end: 50, prefix: '', suffix: '+', decimals: 0, label: t('stats.carriers'), icon: Ship }, { end: 10, prefix: '', suffix: 'K+', decimals: 0, label: t('stats.ports'), icon: Anchor }, { end: 2, prefix: '<', suffix: 's', decimals: 0, label: t('stats.responseTime'), icon: Zap }, { end: 99.5, prefix: '', suffix: '%', decimals: 1, label: t('stats.availability'), icon: CheckCircle2, }, ]; const planFeaturesByKey: Record> = { bronze: [ { key: 'lclBooking', included: true }, { key: 'tracking', included: true }, { key: 'dashboard', included: false }, { key: 'wiki', included: false }, { key: 'userManagement', included: false }, { key: 'csvExport', included: false }, { key: 'apiAccess', included: false }, { key: 'kam', included: false }, ], silver: [ { key: 'lclBooking', included: true }, { key: 'tracking', included: true }, { key: 'dashboardAdvanced', included: true }, { key: 'wikiFull', included: true }, { key: 'userManagement', included: true }, { key: 'csvExport', included: true }, { key: 'apiAccess', included: false }, { key: 'kam', included: false }, ], gold: [ { key: 'lclBooking', included: true }, { key: 'tracking', included: true }, { key: 'dashboardAdvanced', included: true }, { key: 'wikiFull', included: true }, { key: 'userManagement', included: true }, { key: 'csvExport', included: true }, { key: 'apiFull', included: true }, { key: 'kam', included: false }, ], platinium: [ { key: 'lclBooking', included: true }, { key: 'tracking', included: true }, { key: 'dashboardAdvanced', included: true }, { key: 'wikiFull', included: true }, { key: 'userManagement', included: true }, { key: 'csvExport', included: true }, { key: 'apiFull', included: true }, { key: 'kamCustom', included: true }, ], }; const pricingPlans = [ { key: 'bronze', badge: null, monthlyPrice: 0, yearlyPrice: 0, yearlyMonthly: 0, commission: '5%', ctaLink: '/register', highlighted: false, accentColor: 'from-amber-600 to-yellow-500', textAccent: 'text-amber-700', badgeBg: 'bg-amber-100 text-amber-800', }, { key: 'silver', badge: 'popular', monthlyPrice: 249, yearlyPrice: 2739, yearlyMonthly: 228, commission: '3%', ctaLink: '/register', highlighted: true, accentColor: 'from-slate-400 to-slate-500', textAccent: 'text-slate-600', badgeBg: 'bg-slate-100 text-slate-700', }, { key: 'gold', badge: null, monthlyPrice: 899, yearlyPrice: 9889, yearlyMonthly: 824, commission: '2%', ctaLink: '/register', highlighted: false, accentColor: 'from-yellow-400 to-amber-400', textAccent: 'text-amber-600', badgeBg: 'bg-yellow-50 text-amber-700', }, { key: 'platinium', badge: 'custom', monthlyPrice: null, yearlyPrice: null, yearlyMonthly: null, commission: '1%', ctaLink: '/contact', highlighted: false, accentColor: 'from-brand-navy to-brand-turquoise', textAccent: 'text-brand-turquoise', badgeBg: 'bg-brand-navy/10 text-brand-navy', }, ] as const; const testimonials = (t.raw('testimonials.items') as Array<{ quote: string; author: string; role: string; company: string; }>) ?? []; const containerVariants = { hidden: { opacity: 0, y: 50 }, visible: { opacity: 1, y: 0, transition: { duration: 0.6, staggerChildren: 0.1, }, }, }; const itemVariants = { hidden: { opacity: 0, y: 20 }, visible: { opacity: 1, y: 0, transition: { duration: 0.5 }, }, }; const numberFormat = new Intl.NumberFormat(locale === 'fr' ? 'fr-FR' : 'en-US'); return (
{/* Hero Section */}
{/* Stats Section */}
{stats.map((stat, index) => { const IconComponent = stat.icon; return (
{stat.label}
); })}
{/* Features Section */}

{t('features.title')}

{t('features.subtitle')}

{features.map((feature, index) => { const IconComponent = feature.icon; return (

{feature.title}

{feature.description}

{tCommon('discover')}
); })}
{/* Partner Logos Section */}

{t('partners.title')}

{t('partners.subtitle')}

{[ 'ECU Line 2.png', 'ICL 1.png', 'NVO Consolidation 1.png', 'TCC LOG 1.png', 'VANGUARD 1.png', 'image 1.png', ].map((logo, index) => ( {`Partner ))}
{/* Pricing Section */}
{t('pricing.badge')}

{t('pricing.title')}

{t('pricing.subtitle')}

{t('pricing.monthly')} {t('pricing.yearly')} {billingYearly && ( {t('pricing.yearlySaving')} )} {pricingPlans.map(plan => { const planName = t(`pricing.plans.${plan.key}.name` as any); const planDescription = t(`pricing.plans.${plan.key}.description` as any); const planUsers = t(`pricing.plans.${plan.key}.users` as any); const planShipments = t(`pricing.plans.${plan.key}.shipments` as any); const planCta = t(`pricing.plans.${plan.key}.cta` as any); const planFeatures = planFeaturesByKey[plan.key] ?? []; return (
{plan.badge === 'popular' && (
{t('pricing.popularBadge')}
)} {plan.badge === 'custom' && (
{t('pricing.customBadge')}
)}
{planName}

{planDescription}

{plan.monthlyPrice === null ? (
{t('pricing.custom')}

{t('pricing.customSubtitle')}

) : plan.monthlyPrice === 0 ? (
{t('pricing.free')}

{t('pricing.freeSubtitle')}

) : (
{billingYearly ? plan.yearlyMonthly : plan.monthlyPrice}€ {t('pricing.perMonth')}
{billingYearly ? (

{t('pricing.billedYearly', { price: numberFormat.format(plan.yearlyPrice ?? 0), })}

) : (

{t('pricing.saveWithYearly')}

)}
)}
{planUsers}
{planShipments}
{t('pricing.commission', { rate: plan.commission })}
    {planFeatures.map((feature, featureIndex) => (
  • {feature.included ? ( ) : ( )} {t(`pricing.features.${feature.key}` as any)}
  • ))}
{planCta}
); })}

{t('pricing.noCommitment')}

{t('pricing.questions')}{' '} {t('pricing.contactSales')}

{/* How It Works Section */}

{t('howItWorks.title')}

{t('howItWorks.subtitle')}

{[ { stepKey: 'step1', step: '01', icon: Search }, { stepKey: 'step2', step: '02', icon: BarChart3 }, { stepKey: 'step3', step: '03', icon: CheckCircle2 }, { stepKey: 'step4', step: '04', icon: Container }, ].map((step, index) => { const IconComponent = step.icon; return (
{step.step}

{t(`howItWorks.${step.stepKey}.title` as any)}

{t(`howItWorks.${step.stepKey}.description` as any)}

); })}
{tCommon('tryNow')}

{t('howItWorks.ctaHint')}

{/* Testimonials Section */}

{t('testimonials.title')}

{t('testimonials.subtitle')}

{testimonials.map((testimonial, index) => (
{[...Array(5)].map((_, i) => ( ))}

"{testimonial.quote}"

{testimonial.author}
{testimonial.role} - {testimonial.company}
))}
{/* CTA Section */}

{t('cta.title')}

{t('cta.subtitle')}

{isAuthenticated && user ? ( {t('cta.ctaAuthenticated')} ) : ( <> {t('cta.ctaRegister')} {t('cta.ctaLogin')} )}
{t('cta.features.noCard')}
{t('cta.features.quickSetup')}
{t('cta.features.secure')}
); }