This commit is contained in:
David 2026-01-26 00:08:04 +01:00
parent 10b45599ae
commit a200987288
16 changed files with 4691 additions and 622 deletions

View File

@ -0,0 +1,476 @@
'use client';
import { useRef } from 'react';
import Link from 'next/link';
import { motion, useInView } from 'framer-motion';
import {
Ship,
Target,
Eye,
Heart,
Users,
TrendingUp,
Linkedin,
Calendar,
ArrowRight,
} from 'lucide-react';
import { LandingHeader, LandingFooter } from '@/components/layout';
export default function AboutPage() {
const heroRef = useRef(null);
const missionRef = useRef(null);
const valuesRef = useRef(null);
const teamRef = useRef(null);
const timelineRef = useRef(null);
const statsRef = useRef(null);
const isHeroInView = useInView(heroRef, { once: true });
const isMissionInView = useInView(missionRef, { once: true });
const isValuesInView = useInView(valuesRef, { once: true });
const isTeamInView = useInView(teamRef, { once: true });
const isTimelineInView = useInView(timelineRef, { once: true });
const isStatsInView = useInView(statsRef, { once: true });
const values = [
{
icon: Target,
title: 'Excellence',
description:
'Nous visons l\'excellence dans chaque aspect de notre plateforme, en offrant une expérience utilisateur de premier ordre.',
color: 'from-blue-500 to-cyan-500',
},
{
icon: Heart,
title: 'Transparence',
description:
'Nous croyons en une communication ouverte et honnête avec nos clients, partenaires et employés.',
color: 'from-pink-500 to-rose-500',
},
{
icon: Users,
title: 'Collaboration',
description:
'Le succès se construit ensemble. Nous travaillons main dans la main avec nos clients pour atteindre leurs objectifs.',
color: 'from-purple-500 to-indigo-500',
},
{
icon: TrendingUp,
title: 'Innovation',
description:
'Nous repoussons constamment les limites de la technologie pour révolutionner le fret maritime.',
color: 'from-orange-500 to-amber-500',
},
];
const team = [
{
name: 'Jean-Pierre Durand',
role: 'CEO & Co-fondateur',
bio: 'Ex-directeur chez Maersk, 20 ans d\'expérience dans le shipping',
image: '/assets/images/team/ceo.jpg',
linkedin: '#',
},
{
name: 'Marie Lefebvre',
role: 'CTO & Co-fondatrice',
bio: 'Ex-Google, experte en plateformes B2B et systèmes distribués',
image: '/assets/images/team/cto.jpg',
linkedin: '#',
},
{
name: 'Thomas Martin',
role: 'COO',
bio: 'Ex-CMA CGM, spécialiste des opérations maritimes internationales',
image: '/assets/images/team/coo.jpg',
linkedin: '#',
},
{
name: 'Sophie Bernard',
role: 'VP Sales',
bio: '15 ans d\'expérience commerciale dans le secteur logistique',
image: '/assets/images/team/vp-sales.jpg',
linkedin: '#',
},
{
name: 'Alexandre Petit',
role: 'VP Engineering',
bio: 'Ex-Uber Freight, expert en systèmes de réservation temps réel',
image: '/assets/images/team/vp-eng.jpg',
linkedin: '#',
},
{
name: 'Claire Moreau',
role: 'VP Product',
bio: 'Ex-Flexport, passionnée par l\'UX et l\'innovation produit',
image: '/assets/images/team/vp-product.jpg',
linkedin: '#',
},
];
const timeline = [
{
year: '2021',
title: 'Fondation',
description: 'Création de Xpeditis avec une vision claire : simplifier le fret maritime pour tous.',
},
{
year: '2022',
title: 'Première version',
description: 'Lancement de la plateforme beta avec 10 compagnies maritimes partenaires.',
},
{
year: '2023',
title: 'Série A',
description: 'Levée de fonds de 15M€ pour accélérer notre expansion européenne.',
},
{
year: '2024',
title: 'Expansion',
description: '50+ compagnies maritimes, présence dans 15 pays européens.',
},
{
year: '2025',
title: 'Leader européen',
description: 'Plateforme #1 du fret maritime B2B en Europe avec 500+ clients actifs.',
},
];
const stats = [
{ value: '500+', label: 'Clients actifs' },
{ value: '50+', label: 'Compagnies maritimes' },
{ value: '15', label: 'Pays couverts' },
{ value: '100K+', label: 'Réservations/an' },
];
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 },
},
};
return (
<div className="min-h-screen bg-white">
<LandingHeader activePage="about" />
{/* Hero Section */}
<section ref={heroRef} className="relative pt-32 pb-20 bg-gradient-to-br from-brand-navy to-brand-navy/95 overflow-hidden">
<div className="absolute inset-0 opacity-10">
<div className="absolute top-20 left-20 w-96 h-96 bg-brand-turquoise rounded-full blur-3xl" />
<div className="absolute bottom-20 right-20 w-96 h-96 bg-brand-green rounded-full blur-3xl" />
</div>
<div className="relative z-10 max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center"
>
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={isHeroInView ? { scale: 1, opacity: 1 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="inline-flex items-center space-x-2 bg-white/10 backdrop-blur-sm px-4 py-2 rounded-full mb-8 border border-white/20"
>
<Ship className="w-5 h-5 text-brand-turquoise" />
<span className="text-white/90 text-sm font-medium">Notre histoire</span>
</motion.div>
<h1 className="text-4xl lg:text-6xl font-bold text-white mb-6 leading-tight">
Révolutionner le fret maritime,
<br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-brand-turquoise to-brand-green">
une réservation à la fois
</span>
</h1>
<p className="text-xl text-white/80 mb-10 max-w-3xl mx-auto leading-relaxed">
Fondée en 2021, Xpeditis est née d'une vision simple : rendre le fret maritime aussi simple
qu'une réservation de vol. Nous connectons les transitaires du monde entier avec les plus
grandes compagnies maritimes.
</p>
</motion.div>
</div>
{/* Wave */}
<div className="absolute bottom-0 left-0 right-0">
<svg className="w-full h-16" viewBox="0 0 1440 60" preserveAspectRatio="none">
<path
d="M0,30 C240,50 480,10 720,30 C960,50 1200,10 1440,30 L1440,60 L0,60 Z"
fill="white"
/>
</svg>
</div>
</section>
{/* Mission & Vision Section */}
<section ref={missionRef} className="py-20">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
variants={containerVariants}
initial="hidden"
animate={isMissionInView ? 'visible' : 'hidden'}
className="grid grid-cols-1 lg:grid-cols-2 gap-12"
>
<motion.div
variants={itemVariants}
className="bg-gradient-to-br from-brand-turquoise/10 to-brand-turquoise/5 p-10 rounded-3xl border border-brand-turquoise/20"
>
<div className="w-16 h-16 bg-brand-turquoise rounded-2xl flex items-center justify-center mb-6">
<Target className="w-8 h-8 text-white" />
</div>
<h2 className="text-3xl font-bold text-brand-navy mb-4">Notre Mission</h2>
<p className="text-gray-600 text-lg leading-relaxed">
Démocratiser l'accès au fret maritime en offrant une plateforme technologique de pointe
qui simplifie la recherche, la comparaison et la réservation de transport maritime pour
tous les professionnels de la logistique.
</p>
</motion.div>
<motion.div
variants={itemVariants}
className="bg-gradient-to-br from-brand-green/10 to-brand-green/5 p-10 rounded-3xl border border-brand-green/20"
>
<div className="w-16 h-16 bg-brand-green rounded-2xl flex items-center justify-center mb-6">
<Eye className="w-8 h-8 text-white" />
</div>
<h2 className="text-3xl font-bold text-brand-navy mb-4">Notre Vision</h2>
<p className="text-gray-600 text-lg leading-relaxed">
Devenir la référence mondiale du fret maritime digital, en connectant chaque transitaire
à chaque compagnie maritime, partout dans le monde, avec la transparence et l'efficacité
que mérite le commerce international.
</p>
</motion.div>
</motion.div>
</div>
</section>
{/* Stats Section */}
<section ref={statsRef} className="py-16 bg-gray-50">
<motion.div
variants={containerVariants}
initial="hidden"
animate={isStatsInView ? 'visible' : 'hidden'}
className="max-w-7xl mx-auto px-6 lg:px-8"
>
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8">
{stats.map((stat, index) => (
<motion.div
key={index}
variants={itemVariants}
className="text-center"
>
<motion.div
initial={{ scale: 0 }}
animate={isStatsInView ? { scale: 1 } : {}}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="text-5xl lg:text-6xl font-bold text-brand-turquoise mb-2"
>
{stat.value}
</motion.div>
<div className="text-gray-600 font-medium">{stat.label}</div>
</motion.div>
))}
</div>
</motion.div>
</section>
{/* Values Section */}
<section ref={valuesRef} className="py-20">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isValuesInView ? { 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">Nos Valeurs</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Les principes qui guident chacune de nos décisions
</p>
</motion.div>
<motion.div
variants={containerVariants}
initial="hidden"
animate={isValuesInView ? 'visible' : 'hidden'}
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8"
>
{values.map((value, index) => {
const IconComponent = value.icon;
return (
<motion.div
key={index}
variants={itemVariants}
whileHover={{ y: -10 }}
className="bg-white p-8 rounded-2xl shadow-lg border border-gray-100 hover:shadow-xl transition-all"
>
<div
className={`w-14 h-14 rounded-xl bg-gradient-to-br ${value.color} flex items-center justify-center mb-4`}
>
<IconComponent className="w-7 h-7 text-white" />
</div>
<h3 className="text-xl font-bold text-brand-navy mb-3">{value.title}</h3>
<p className="text-gray-600">{value.description}</p>
</motion.div>
);
})}
</motion.div>
</div>
</section>
{/* Timeline Section */}
<section ref={timelineRef} className="py-20 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={isTimelineInView ? { 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">Notre Parcours</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
De la startup au leader européen du fret maritime digital
</p>
</motion.div>
<div className="relative">
{/* Timeline line */}
<div className="hidden lg:block absolute left-1/2 transform -translate-x-1/2 w-1 h-full bg-brand-turquoise/20" />
<div className="space-y-12">
{timeline.map((item, index) => (
<motion.div
key={index}
initial={{ opacity: 0, x: index % 2 === 0 ? -50 : 50 }}
animate={isTimelineInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.6, delay: index * 0.1 }}
className={`flex items-center ${index % 2 === 0 ? 'lg:flex-row' : 'lg:flex-row-reverse'}`}
>
<div className={`flex-1 ${index % 2 === 0 ? 'lg:pr-12 lg:text-right' : 'lg:pl-12'}`}>
<div className="bg-white p-6 rounded-2xl shadow-lg border border-gray-100 inline-block">
<div className="flex items-center space-x-3 mb-3">
<Calendar className="w-5 h-5 text-brand-turquoise" />
<span className="text-2xl font-bold text-brand-turquoise">{item.year}</span>
</div>
<h3 className="text-xl font-bold text-brand-navy mb-2">{item.title}</h3>
<p className="text-gray-600">{item.description}</p>
</div>
</div>
<div className="hidden lg:flex items-center justify-center">
<div className="w-6 h-6 bg-brand-turquoise rounded-full border-4 border-white shadow-lg" />
</div>
<div className="hidden lg:block flex-1" />
</motion.div>
))}
</div>
</div>
</div>
</section>
{/* Team Section */}
<section ref={teamRef} className="py-20">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isTeamInView ? { 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">Notre Équipe</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Des experts passionnés par le maritime et la technologie
</p>
</motion.div>
<motion.div
variants={containerVariants}
initial="hidden"
animate={isTeamInView ? 'visible' : 'hidden'}
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"
>
{team.map((member, index) => (
<motion.div
key={index}
variants={itemVariants}
whileHover={{ y: -10 }}
className="bg-white rounded-2xl shadow-lg border border-gray-100 overflow-hidden group"
>
<div className="aspect-[4/3] bg-gradient-to-br from-brand-navy to-brand-navy/80 flex items-center justify-center relative overflow-hidden">
<div className="w-24 h-24 bg-white/20 rounded-full flex items-center justify-center">
<Users className="w-12 h-12 text-white/80" />
</div>
<div className="absolute inset-0 bg-brand-turquoise/80 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
<a
href={member.linkedin}
className="w-12 h-12 bg-white rounded-full flex items-center justify-center hover:scale-110 transition-transform"
>
<Linkedin className="w-6 h-6 text-brand-navy" />
</a>
</div>
</div>
<div className="p-6">
<h3 className="text-xl font-bold text-brand-navy mb-1">{member.name}</h3>
<p className="text-brand-turquoise font-medium mb-3">{member.role}</p>
<p className="text-gray-600 text-sm">{member.bio}</p>
</div>
</motion.div>
))}
</motion.div>
</div>
</section>
{/* CTA Section */}
<section className="py-20 bg-gradient-to-br from-brand-navy to-brand-navy/95">
<div className="max-w-4xl mx-auto px-6 lg:px-8 text-center">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
>
<h2 className="text-4xl lg:text-5xl font-bold text-white mb-6">
Rejoignez l'aventure Xpeditis
</h2>
<p className="text-xl text-white/80 mb-10">
Que vous soyez transitaire à la recherche d'une solution moderne ou talent souhaitant
rejoindre une équipe passionnée, nous avons hâte de vous rencontrer.
</p>
<div className="flex flex-col sm:flex-row items-center justify-center space-y-4 sm:space-y-0 sm:space-x-6">
<Link
href="/register"
className="group px-8 py-4 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-all hover:shadow-2xl font-semibold text-lg flex items-center space-x-2"
>
<span>Créer un compte</span>
<ArrowRight className="w-5 h-5 group-hover:translate-x-1 transition-transform" />
</Link>
<Link
href="/careers"
className="px-8 py-4 bg-white text-brand-navy rounded-lg hover:bg-gray-100 transition-all font-semibold text-lg"
>
Voir les offres d'emploi
</Link>
</div>
</motion.div>
</div>
</section>
<LandingFooter />
</div>
);
}

View File

@ -0,0 +1,473 @@
'use client';
import { useState, useRef } from 'react';
import Link from 'next/link';
import { motion, useInView } from 'framer-motion';
import {
Ship,
BookOpen,
Calendar,
Clock,
User,
ArrowRight,
Search,
TrendingUp,
Globe,
FileText,
Anchor,
} from 'lucide-react';
import { LandingHeader, LandingFooter } from '@/components/layout';
export default function BlogPage() {
const [selectedCategory, setSelectedCategory] = useState('all');
const [searchQuery, setSearchQuery] = useState('');
const heroRef = useRef(null);
const articlesRef = useRef(null);
const categoriesRef = useRef(null);
const isHeroInView = useInView(heroRef, { once: true });
const isArticlesInView = useInView(articlesRef, { once: true });
const isCategoriesInView = useInView(categoriesRef, { once: true });
const categories = [
{ value: 'all', label: 'Tous les articles', icon: BookOpen },
{ value: 'industry', label: 'Industrie maritime', icon: Ship },
{ value: 'technology', label: 'Technologie', icon: TrendingUp },
{ value: 'guides', label: 'Guides pratiques', icon: FileText },
{ value: 'news', label: 'Actualités', icon: Globe },
];
const featuredArticle = {
id: 1,
title: 'L\'avenir du fret maritime : comment l\'IA transforme la logistique',
excerpt:
'Découvrez comment l\'intelligence artificielle révolutionne la gestion des expéditions maritimes et optimise les chaînes d\'approvisionnement mondiales.',
category: 'technology',
author: 'Marie Lefebvre',
authorRole: 'CTO',
date: '15 janvier 2025',
readTime: '8 min',
image: '/assets/images/blog/featured.jpg',
tags: ['IA', 'Innovation', 'Logistique'],
};
const articles = [
{
id: 2,
title: 'Guide complet des Incoterms 2020 pour le transport maritime',
excerpt:
'Tout ce que vous devez savoir sur les règles Incoterms et leur application dans le fret maritime international.',
category: 'guides',
author: 'Thomas Martin',
date: '10 janvier 2025',
readTime: '12 min',
image: '/assets/images/blog/incoterms.jpg',
tags: ['Incoterms', 'Guide', 'Commerce international'],
},
{
id: 3,
title: 'Comment optimiser vos coûts de transport maritime en 2025',
excerpt:
'Stratégies et conseils pratiques pour réduire vos dépenses logistiques sans compromettre la qualité de service.',
category: 'guides',
author: 'Sophie Bernard',
date: '8 janvier 2025',
readTime: '6 min',
image: '/assets/images/blog/costs.jpg',
tags: ['Optimisation', 'Coûts', 'Stratégie'],
},
{
id: 4,
title: 'Les plus grands ports européens : classement 2025',
excerpt:
'Analyse des performances des principaux ports européens et tendances du trafic conteneurisé.',
category: 'industry',
author: 'Jean-Pierre Durand',
date: '5 janvier 2025',
readTime: '10 min',
image: '/assets/images/blog/ports.jpg',
tags: ['Ports', 'Europe', 'Statistiques'],
},
{
id: 5,
title: 'Xpeditis lève 15M€ pour accélérer son expansion',
excerpt:
'Notre série A nous permet de renforcer notre équipe et d\'étendre notre présence en Europe.',
category: 'news',
author: 'Jean-Pierre Durand',
date: '3 janvier 2025',
readTime: '4 min',
image: '/assets/images/blog/funding.jpg',
tags: ['Financement', 'Croissance', 'Xpeditis'],
},
{
id: 6,
title: 'Décarbonation du transport maritime : où en sommes-nous ?',
excerpt:
'État des lieux des initiatives environnementales dans le secteur maritime et perspectives pour 2030.',
category: 'industry',
author: 'Claire Moreau',
date: '28 décembre 2024',
readTime: '9 min',
image: '/assets/images/blog/green.jpg',
tags: ['Environnement', 'Décarbonation', 'Durabilité'],
},
{
id: 7,
title: 'APIs et intégrations : comment connecter votre TMS à Xpeditis',
excerpt:
'Guide technique pour intégrer notre plateforme avec vos systèmes de gestion existants.',
category: 'technology',
author: 'Alexandre Petit',
date: '22 décembre 2024',
readTime: '15 min',
image: '/assets/images/blog/api.jpg',
tags: ['API', 'Intégration', 'Technique'],
},
{
id: 8,
title: 'Les documents essentiels pour l\'export maritime',
excerpt:
'Check-list complète des documents requis pour vos expéditions maritimes internationales.',
category: 'guides',
author: 'Thomas Martin',
date: '18 décembre 2024',
readTime: '7 min',
image: '/assets/images/blog/documents.jpg',
tags: ['Documents', 'Export', 'Douane'],
},
];
const filteredArticles = articles.filter((article) => {
const categoryMatch = selectedCategory === 'all' || article.category === selectedCategory;
const searchMatch =
searchQuery === '' ||
article.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
article.excerpt.toLowerCase().includes(searchQuery.toLowerCase());
return categoryMatch && searchMatch;
});
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 },
},
};
return (
<div className="min-h-screen bg-white">
<LandingHeader activePage="blog" />
{/* Hero Section */}
<section ref={heroRef} className="relative pt-32 pb-20 bg-gradient-to-br from-brand-navy to-brand-navy/95 overflow-hidden">
<div className="absolute inset-0 opacity-10">
<div className="absolute top-20 left-20 w-96 h-96 bg-brand-turquoise rounded-full blur-3xl" />
<div className="absolute bottom-20 right-20 w-96 h-96 bg-brand-green rounded-full blur-3xl" />
</div>
<div className="relative z-10 max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center"
>
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={isHeroInView ? { scale: 1, opacity: 1 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="inline-flex items-center space-x-2 bg-white/10 backdrop-blur-sm px-4 py-2 rounded-full mb-8 border border-white/20"
>
<BookOpen className="w-5 h-5 text-brand-turquoise" />
<span className="text-white/90 text-sm font-medium">Blog Xpeditis</span>
</motion.div>
<h1 className="text-4xl lg:text-6xl font-bold text-white mb-6 leading-tight">
Actualités & Insights
<br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-brand-turquoise to-brand-green">
du fret maritime
</span>
</h1>
<p className="text-xl text-white/80 mb-10 max-w-3xl mx-auto leading-relaxed">
Restez informé des dernières tendances du transport maritime, découvrez nos guides
pratiques et suivez l'actualité de Xpeditis.
</p>
{/* Search Bar */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, delay: 0.4 }}
className="max-w-xl mx-auto"
>
<div className="relative">
<Search className="absolute left-4 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
type="text"
placeholder="Rechercher un article..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full pl-12 pr-4 py-4 rounded-xl bg-white text-gray-900 placeholder-gray-400 focus:ring-2 focus:ring-brand-turquoise focus:outline-none"
/>
</div>
</motion.div>
</motion.div>
</div>
{/* Wave */}
<div className="absolute bottom-0 left-0 right-0">
<svg className="w-full h-16" viewBox="0 0 1440 60" preserveAspectRatio="none">
<path
d="M0,30 C240,50 480,10 720,30 C960,50 1200,10 1440,30 L1440,60 L0,60 Z"
fill="white"
/>
</svg>
</div>
</section>
{/* Categories */}
<section ref={categoriesRef} className="py-8 border-b border-gray-200">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={isCategoriesInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6 }}
className="max-w-7xl mx-auto px-6 lg:px-8"
>
<div className="flex flex-wrap items-center justify-center gap-4">
{categories.map((category) => {
const IconComponent = category.icon;
const isActive = selectedCategory === category.value;
return (
<button
key={category.value}
onClick={() => setSelectedCategory(category.value)}
className={`flex items-center space-x-2 px-4 py-2 rounded-full transition-all ${
isActive
? 'bg-brand-turquoise text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
}`}
>
<IconComponent className="w-4 h-4" />
<span className="font-medium">{category.label}</span>
</button>
);
})}
</div>
</motion.div>
</section>
{/* Featured Article */}
<section className="py-16">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
>
<Link href={`/blog/${featuredArticle.id}`}>
<div className="relative bg-gradient-to-br from-brand-navy to-brand-navy/90 rounded-3xl overflow-hidden group cursor-pointer">
<div className="absolute inset-0 bg-gradient-to-r from-brand-navy via-brand-navy/80 to-transparent z-10" />
<div className="absolute right-0 top-0 bottom-0 w-1/2 bg-brand-turquoise/20 flex items-center justify-center">
<Anchor className="w-48 h-48 text-white/10" />
</div>
<div className="relative z-20 p-8 lg:p-12">
<div className="max-w-2xl">
<div className="flex items-center space-x-2 mb-4">
<span className="px-3 py-1 bg-brand-turquoise text-white text-sm font-medium rounded-full">
À la une
</span>
<span className="px-3 py-1 bg-white/20 text-white text-sm font-medium rounded-full">
{categories.find((c) => c.value === featuredArticle.category)?.label}
</span>
</div>
<h2 className="text-3xl lg:text-4xl font-bold text-white mb-4 group-hover:text-brand-turquoise transition-colors">
{featuredArticle.title}
</h2>
<p className="text-lg text-white/80 mb-6">{featuredArticle.excerpt}</p>
<div className="flex items-center space-x-6 text-white/60 text-sm">
<div className="flex items-center space-x-2">
<User className="w-4 h-4" />
<span>{featuredArticle.author}</span>
</div>
<div className="flex items-center space-x-2">
<Calendar className="w-4 h-4" />
<span>{featuredArticle.date}</span>
</div>
<div className="flex items-center space-x-2">
<Clock className="w-4 h-4" />
<span>{featuredArticle.readTime}</span>
</div>
</div>
<div className="flex items-center space-x-2 mt-6 text-brand-turquoise font-medium opacity-0 group-hover:opacity-100 transition-opacity">
<span>Lire l'article</span>
<ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
</div>
</div>
</div>
</div>
</Link>
</motion.div>
</div>
</section>
{/* Articles Grid */}
<section ref={articlesRef} className="py-16 bg-gray-50">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isArticlesInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="flex items-center justify-between mb-12"
>
<h2 className="text-3xl font-bold text-brand-navy">Tous les articles</h2>
<span className="text-gray-500">{filteredArticles.length} articles</span>
</motion.div>
{filteredArticles.length === 0 ? (
<div className="text-center py-12">
<Search className="w-16 h-16 text-gray-300 mx-auto mb-4" />
<h3 className="text-xl font-medium text-gray-600">Aucun article trouvé</h3>
<p className="text-gray-500">Essayez de modifier vos filtres ou votre recherche</p>
</div>
) : (
<motion.div
variants={containerVariants}
initial="hidden"
animate={isArticlesInView ? 'visible' : 'hidden'}
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"
>
{filteredArticles.map((article) => (
<motion.div key={article.id} variants={itemVariants}>
<Link href={`/blog/${article.id}`}>
<div className="bg-white rounded-2xl shadow-lg overflow-hidden group hover:shadow-xl transition-all h-full flex flex-col">
<div className="aspect-video bg-gradient-to-br from-brand-navy/10 to-brand-turquoise/10 flex items-center justify-center relative">
<Ship className="w-16 h-16 text-brand-navy/20" />
<div className="absolute top-4 left-4">
<span className="px-3 py-1 bg-white/90 text-brand-navy text-xs font-medium rounded-full">
{categories.find((c) => c.value === article.category)?.label}
</span>
</div>
</div>
<div className="p-6 flex-1 flex flex-col">
<h3 className="text-xl font-bold text-brand-navy mb-3 group-hover:text-brand-turquoise transition-colors line-clamp-2">
{article.title}
</h3>
<p className="text-gray-600 mb-4 line-clamp-2 flex-1">{article.excerpt}</p>
<div className="flex flex-wrap gap-2 mb-4">
{article.tags.map((tag) => (
<span
key={tag}
className="px-2 py-1 bg-gray-100 text-gray-600 text-xs rounded-full"
>
{tag}
</span>
))}
</div>
<div className="flex items-center justify-between text-sm text-gray-500 pt-4 border-t border-gray-100">
<div className="flex items-center space-x-2">
<div className="w-8 h-8 bg-brand-turquoise/10 rounded-full flex items-center justify-center">
<User className="w-4 h-4 text-brand-turquoise" />
</div>
<span>{article.author}</span>
</div>
<div className="flex items-center space-x-4">
<span>{article.date}</span>
<span className="flex items-center space-x-1">
<Clock className="w-4 h-4" />
<span>{article.readTime}</span>
</span>
</div>
</div>
</div>
</div>
</Link>
</motion.div>
))}
</motion.div>
)}
{/* Load More */}
{filteredArticles.length > 0 && (
<motion.div
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: 0.2 }}
className="text-center mt-12"
>
<button className="px-8 py-4 bg-white border-2 border-brand-turquoise text-brand-turquoise rounded-lg hover:bg-brand-turquoise hover:text-white transition-all font-semibold">
Charger plus d'articles
</button>
</motion.div>
)}
</div>
</section>
{/* Newsletter Section */}
<section className="py-20 bg-gradient-to-br from-brand-navy to-brand-navy/95">
<div className="max-w-4xl mx-auto px-6 lg:px-8 text-center">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
>
<h2 className="text-4xl font-bold text-white mb-6">
Restez informé
</h2>
<p className="text-xl text-white/80 mb-10">
Abonnez-vous à notre newsletter pour recevoir les derniers articles et actualités
du fret maritime directement dans votre boîte mail.
</p>
<form className="flex flex-col sm:flex-row items-center justify-center space-y-4 sm:space-y-0 sm:space-x-4">
<input
type="email"
placeholder="votre@email.com"
className="w-full sm:w-96 px-6 py-4 rounded-lg bg-white text-gray-900 placeholder-gray-400 focus:ring-2 focus:ring-brand-turquoise focus:outline-none"
/>
<button
type="submit"
className="w-full sm:w-auto px-8 py-4 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-all font-semibold flex items-center justify-center space-x-2"
>
<span>S'abonner</span>
<ArrowRight className="w-5 h-5" />
</button>
</form>
<p className="text-white/50 text-sm mt-4">
En vous inscrivant, vous acceptez notre politique de confidentialité. Désabonnement possible à tout moment.
</p>
</motion.div>
</div>
</section>
<LandingFooter />
</div>
);
}

View File

@ -0,0 +1,621 @@
'use client';
import { useState, useRef } from 'react';
import Link from 'next/link';
import { motion, useInView, AnimatePresence } from 'framer-motion';
import {
Briefcase,
MapPin,
Clock,
Users,
Heart,
Zap,
Coffee,
GraduationCap,
Plane,
Building2,
ChevronDown,
ChevronRight,
ArrowRight,
Search,
Code,
LineChart,
Headphones,
Megaphone,
} from 'lucide-react';
import { LandingHeader, LandingFooter } from '@/components/layout';
export default function CareersPage() {
const [selectedDepartment, setSelectedDepartment] = useState('all');
const [selectedLocation, setSelectedLocation] = useState('all');
const [expandedJob, setExpandedJob] = useState<number | null>(null);
const heroRef = useRef(null);
const benefitsRef = useRef(null);
const jobsRef = useRef(null);
const cultureRef = useRef(null);
const isHeroInView = useInView(heroRef, { once: true });
const isBenefitsInView = useInView(benefitsRef, { once: true });
const isJobsInView = useInView(jobsRef, { once: true });
const isCultureInView = useInView(cultureRef, { once: true });
const benefits = [
{
icon: Heart,
title: 'Mutuelle Premium',
description: 'Couverture santé complète pour vous et votre famille',
},
{
icon: Plane,
title: 'Télétravail Flexible',
description: 'Travaillez d\'où vous voulez, jusqu\'à 3 jours par semaine',
},
{
icon: Coffee,
title: 'Bien-être au Travail',
description: 'Salle de sport, fruits frais, et événements d\'équipe',
},
{
icon: GraduationCap,
title: 'Formation Continue',
description: '2 000€/an de budget formation et conférences',
},
{
icon: Users,
title: 'Équipe Internationale',
description: 'Travaillez avec des talents de 15 nationalités',
},
{
icon: Zap,
title: 'Stock Options',
description: 'Participez à la croissance de l\'entreprise',
},
];
const jobs = [
{
id: 1,
title: 'Senior Frontend Engineer',
department: 'Engineering',
location: 'Paris',
type: 'CDI',
remote: true,
salary: '65K - 85K €',
description: 'Rejoignez notre équipe frontend pour développer la prochaine génération de notre plateforme.',
requirements: [
'5+ ans d\'expérience en développement frontend',
'Maîtrise de React, TypeScript et Next.js',
'Expérience avec les design systems',
'Capacité à mentorer des développeurs juniors',
],
icon: Code,
},
{
id: 2,
title: 'Backend Engineer (Node.js)',
department: 'Engineering',
location: 'Paris',
type: 'CDI',
remote: true,
salary: '55K - 75K €',
description: 'Construisez des APIs scalables pour connecter les transitaires aux compagnies maritimes.',
requirements: [
'3+ ans d\'expérience en Node.js/NestJS',
'Maîtrise de PostgreSQL et Redis',
'Connaissance des architectures microservices',
'Expérience avec Docker et Kubernetes appréciée',
],
icon: Code,
},
{
id: 3,
title: 'Product Manager',
department: 'Product',
location: 'Paris',
type: 'CDI',
remote: true,
salary: '60K - 80K €',
description: 'Définissez la vision produit et priorisez les fonctionnalités avec notre équipe.',
requirements: [
'4+ ans d\'expérience en product management B2B',
'Expérience dans la logistique ou le shipping appréciée',
'Capacité à analyser les données et définir les KPIs',
'Excellentes compétences en communication',
],
icon: LineChart,
},
{
id: 4,
title: 'Account Executive',
department: 'Sales',
location: 'Rotterdam',
type: 'CDI',
remote: false,
salary: '50K - 70K € + variable',
description: 'Développez notre portefeuille clients aux Pays-Bas et en Belgique.',
requirements: [
'3+ ans d\'expérience en vente B2B',
'Connaissance du secteur maritime/logistique',
'Maîtrise du néerlandais et de l\'anglais',
'Capacité à gérer des cycles de vente longs',
],
icon: Megaphone,
},
{
id: 5,
title: 'Customer Success Manager',
department: 'Customer Success',
location: 'Paris',
type: 'CDI',
remote: true,
salary: '45K - 60K €',
description: 'Accompagnez nos clients dans l\'utilisation de la plateforme et maximisez leur satisfaction.',
requirements: [
'2+ ans d\'expérience en customer success',
'Expérience avec les outils CRM (HubSpot, Salesforce)',
'Excellent relationnel et sens du service',
'Capacité à former et accompagner les utilisateurs',
],
icon: Headphones,
},
{
id: 6,
title: 'Data Analyst',
department: 'Data',
location: 'Hambourg',
type: 'CDI',
remote: true,
salary: '50K - 65K €',
description: 'Analysez les données de shipping pour optimiser notre plateforme et nos processus.',
requirements: [
'3+ ans d\'expérience en data analysis',
'Maîtrise de SQL, Python et des outils BI',
'Expérience avec le shipping/logistics appréciée',
'Capacité à communiquer les insights aux équipes',
],
icon: LineChart,
},
];
const departments = [
{ value: 'all', label: 'Tous les départements' },
{ value: 'Engineering', label: 'Engineering' },
{ value: 'Product', label: 'Product' },
{ value: 'Sales', label: 'Sales' },
{ value: 'Customer Success', label: 'Customer Success' },
{ value: 'Data', label: 'Data' },
];
const locations = [
{ value: 'all', label: 'Toutes les villes' },
{ value: 'Paris', label: 'Paris' },
{ value: 'Rotterdam', label: 'Rotterdam' },
{ value: 'Hambourg', label: 'Hambourg' },
];
const filteredJobs = jobs.filter((job) => {
const departmentMatch = selectedDepartment === 'all' || job.department === selectedDepartment;
const locationMatch = selectedLocation === 'all' || job.location === selectedLocation;
return departmentMatch && locationMatch;
});
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 },
},
};
return (
<div className="min-h-screen bg-white">
<LandingHeader activePage="careers" />
{/* Hero Section */}
<section ref={heroRef} className="relative pt-32 pb-20 bg-gradient-to-br from-brand-navy to-brand-navy/95 overflow-hidden">
<div className="absolute inset-0 opacity-10">
<div className="absolute top-20 left-20 w-96 h-96 bg-brand-turquoise rounded-full blur-3xl" />
<div className="absolute bottom-20 right-20 w-96 h-96 bg-brand-green rounded-full blur-3xl" />
</div>
<div className="relative z-10 max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center"
>
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={isHeroInView ? { scale: 1, opacity: 1 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="inline-flex items-center space-x-2 bg-white/10 backdrop-blur-sm px-4 py-2 rounded-full mb-8 border border-white/20"
>
<Briefcase className="w-5 h-5 text-brand-turquoise" />
<span className="text-white/90 text-sm font-medium">Rejoignez-nous</span>
</motion.div>
<h1 className="text-4xl lg:text-6xl font-bold text-white mb-6 leading-tight">
Construisons ensemble
<br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-brand-turquoise to-brand-green">
le futur du maritime
</span>
</h1>
<p className="text-xl text-white/80 mb-10 max-w-3xl mx-auto leading-relaxed">
Rejoignez une équipe passionnée qui révolutionne le fret maritime. Des défis stimulants,
une culture bienveillante et des opportunités de croissance uniques vous attendent.
</p>
<div className="flex flex-col sm:flex-row items-center justify-center space-y-4 sm:space-y-0 sm:space-x-6">
<a
href="#jobs"
className="group px-8 py-4 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-all hover:shadow-2xl font-semibold text-lg flex items-center space-x-2"
>
<span>Voir les offres</span>
<ArrowRight className="w-5 h-5 group-hover:translate-x-1 transition-transform" />
</a>
<Link
href="/about"
className="px-8 py-4 bg-white text-brand-navy rounded-lg hover:bg-gray-100 transition-all font-semibold text-lg"
>
En savoir plus
</Link>
</div>
</motion.div>
</div>
{/* Wave */}
<div className="absolute bottom-0 left-0 right-0">
<svg className="w-full h-16" viewBox="0 0 1440 60" preserveAspectRatio="none">
<path
d="M0,30 C240,50 480,10 720,30 C960,50 1200,10 1440,30 L1440,60 L0,60 Z"
fill="white"
/>
</svg>
</div>
</section>
{/* Stats Section */}
<section className="py-16 bg-gray-50">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8">
{[
{ value: '50+', label: 'Employés' },
{ value: '15', label: 'Nationalités' },
{ value: '3', label: 'Bureaux en Europe' },
{ value: '40%', label: 'Femmes dans la tech' },
].map((stat, index) => (
<motion.div
key={index}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="text-center"
>
<div className="text-5xl font-bold text-brand-turquoise mb-2">{stat.value}</div>
<div className="text-gray-600 font-medium">{stat.label}</div>
</motion.div>
))}
</div>
</div>
</section>
{/* Benefits Section */}
<section ref={benefitsRef} className="py-20">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isBenefitsInView ? { 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">
Pourquoi nous rejoindre ?
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Nous investissons dans le bien-être et le développement de nos équipes
</p>
</motion.div>
<motion.div
variants={containerVariants}
initial="hidden"
animate={isBenefitsInView ? 'visible' : 'hidden'}
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"
>
{benefits.map((benefit, index) => {
const IconComponent = benefit.icon;
return (
<motion.div
key={index}
variants={itemVariants}
whileHover={{ y: -5 }}
className="bg-white p-6 rounded-2xl shadow-lg border border-gray-100 hover:shadow-xl transition-all"
>
<div className="w-14 h-14 bg-brand-turquoise/10 rounded-xl flex items-center justify-center mb-4">
<IconComponent className="w-7 h-7 text-brand-turquoise" />
</div>
<h3 className="text-xl font-bold text-brand-navy mb-2">{benefit.title}</h3>
<p className="text-gray-600">{benefit.description}</p>
</motion.div>
);
})}
</motion.div>
</div>
</section>
{/* Culture Section */}
<section ref={cultureRef} className="py-20 bg-gradient-to-br from-brand-navy to-brand-navy/95">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<motion.div
initial={{ opacity: 0, x: -50 }}
animate={isCultureInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.8 }}
>
<h2 className="text-4xl lg:text-5xl font-bold text-white mb-6">
Notre culture
</h2>
<p className="text-xl text-white/80 mb-8">
Chez Xpeditis, nous croyons que les meilleures idées viennent d'équipes diverses
et inclusives. Nous valorisons l'autonomie, la créativité et le feedback constructif.
</p>
<ul className="space-y-4">
{[
'Transparence totale sur les décisions et les résultats',
'Feedback continu et culture de l\'amélioration',
'Équilibre vie pro/perso respecté',
'Célébration des succès collectifs',
].map((item, index) => (
<motion.li
key={index}
initial={{ opacity: 0, x: -20 }}
animate={isCultureInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="flex items-center space-x-3 text-white/90"
>
<div className="w-6 h-6 bg-brand-turquoise rounded-full flex items-center justify-center flex-shrink-0">
<ChevronRight className="w-4 h-4 text-white" />
</div>
<span>{item}</span>
</motion.li>
))}
</ul>
</motion.div>
<motion.div
initial={{ opacity: 0, x: 50 }}
animate={isCultureInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.8, delay: 0.2 }}
className="grid grid-cols-2 gap-4"
>
{[1, 2, 3, 4].map((i) => (
<div
key={i}
className="aspect-square bg-white/10 rounded-2xl flex items-center justify-center"
>
<Users className="w-12 h-12 text-white/40" />
</div>
))}
</motion.div>
</div>
</div>
</section>
{/* Jobs Section */}
<section ref={jobsRef} id="jobs" className="py-20">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isJobsInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center mb-12"
>
<h2 className="text-4xl lg:text-5xl font-bold text-brand-navy mb-4">
Nos offres d'emploi
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Trouvez le poste qui correspond à vos ambitions
</p>
</motion.div>
{/* Filters */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={isJobsInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="flex flex-col md:flex-row items-center justify-center space-y-4 md:space-y-0 md:space-x-4 mb-12"
>
<div className="relative">
<select
value={selectedDepartment}
onChange={(e) => setSelectedDepartment(e.target.value)}
className="appearance-none px-6 py-3 pr-10 bg-white border border-gray-300 rounded-lg focus:ring-2 focus:ring-brand-turquoise focus:border-transparent cursor-pointer"
>
{departments.map((dept) => (
<option key={dept.value} value={dept.value}>
{dept.label}
</option>
))}
</select>
<ChevronDown className="absolute right-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400 pointer-events-none" />
</div>
<div className="relative">
<select
value={selectedLocation}
onChange={(e) => setSelectedLocation(e.target.value)}
className="appearance-none px-6 py-3 pr-10 bg-white border border-gray-300 rounded-lg focus:ring-2 focus:ring-brand-turquoise focus:border-transparent cursor-pointer"
>
{locations.map((loc) => (
<option key={loc.value} value={loc.value}>
{loc.label}
</option>
))}
</select>
<ChevronDown className="absolute right-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400 pointer-events-none" />
</div>
</motion.div>
{/* Job Listings */}
<motion.div
variants={containerVariants}
initial="hidden"
animate={isJobsInView ? 'visible' : 'hidden'}
className="space-y-4"
>
{filteredJobs.length === 0 ? (
<div className="text-center py-12">
<Search className="w-16 h-16 text-gray-300 mx-auto mb-4" />
<h3 className="text-xl font-medium text-gray-600">Aucune offre trouvée</h3>
<p className="text-gray-500">Essayez de modifier vos filtres</p>
</div>
) : (
filteredJobs.map((job) => {
const IconComponent = job.icon;
const isExpanded = expandedJob === job.id;
return (
<motion.div
key={job.id}
variants={itemVariants}
className="bg-white rounded-2xl shadow-lg border border-gray-100 overflow-hidden"
>
<div
className="p-6 cursor-pointer hover:bg-gray-50 transition-colors"
onClick={() => setExpandedJob(isExpanded ? null : job.id)}
>
<div className="flex items-center justify-between">
<div className="flex items-center space-x-4">
<div className="w-12 h-12 bg-brand-turquoise/10 rounded-xl flex items-center justify-center">
<IconComponent className="w-6 h-6 text-brand-turquoise" />
</div>
<div>
<h3 className="text-xl font-bold text-brand-navy">{job.title}</h3>
<div className="flex items-center space-x-4 mt-1 text-sm text-gray-500">
<span className="flex items-center space-x-1">
<Building2 className="w-4 h-4" />
<span>{job.department}</span>
</span>
<span className="flex items-center space-x-1">
<MapPin className="w-4 h-4" />
<span>{job.location}</span>
</span>
<span className="flex items-center space-x-1">
<Clock className="w-4 h-4" />
<span>{job.type}</span>
</span>
</div>
</div>
</div>
<div className="flex items-center space-x-4">
<div className="hidden md:flex items-center space-x-2">
{job.remote && (
<span className="px-3 py-1 bg-green-100 text-green-700 text-sm font-medium rounded-full">
Remote OK
</span>
)}
<span className="px-3 py-1 bg-brand-turquoise/10 text-brand-turquoise text-sm font-medium rounded-full">
{job.salary}
</span>
</div>
<ChevronDown
className={`w-6 h-6 text-gray-400 transition-transform ${
isExpanded ? 'transform rotate-180' : ''
}`}
/>
</div>
</div>
</div>
<AnimatePresence>
{isExpanded && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3 }}
className="border-t border-gray-100"
>
<div className="p-6 bg-gray-50">
<p className="text-gray-600 mb-6">{job.description}</p>
<h4 className="font-bold text-brand-navy mb-3">Profil recherché :</h4>
<ul className="space-y-2 mb-6">
{job.requirements.map((req, index) => (
<li key={index} className="flex items-start space-x-2 text-gray-600">
<ChevronRight className="w-5 h-5 text-brand-turquoise flex-shrink-0 mt-0.5" />
<span>{req}</span>
</li>
))}
</ul>
<div className="flex items-center space-x-4">
<Link
href={`/careers/${job.id}`}
className="px-6 py-3 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-all font-medium flex items-center space-x-2"
>
<span>Postuler</span>
<ArrowRight className="w-4 h-4" />
</Link>
<button className="px-6 py-3 border border-gray-300 rounded-lg hover:border-brand-turquoise transition-all font-medium text-gray-700">
En savoir plus
</button>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</motion.div>
);
})
)}
</motion.div>
</div>
</section>
{/* CTA Section */}
<section className="py-20 bg-gray-50">
<div className="max-w-4xl mx-auto px-6 lg:px-8 text-center">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
>
<h2 className="text-4xl font-bold text-brand-navy mb-6">
Pas de poste correspondant ?
</h2>
<p className="text-xl text-gray-600 mb-10">
Envoyez-nous une candidature spontanée ! Nous sommes toujours à la recherche de
talents passionnés pour rejoindre notre aventure.
</p>
<Link
href="/contact"
className="inline-flex items-center space-x-2 px-8 py-4 bg-brand-navy text-white rounded-lg hover:bg-brand-navy/90 transition-all font-semibold text-lg"
>
<span>Candidature spontanée</span>
<ArrowRight className="w-5 h-5" />
</Link>
</motion.div>
</div>
</section>
<LandingFooter />
</div>
);
}

View File

@ -0,0 +1,429 @@
'use client';
import { useRef } from 'react';
import { motion, useInView } from 'framer-motion';
import {
Shield,
UserCheck,
Database,
FileText,
Globe,
Clock,
CheckCircle,
Download,
Trash2,
Edit,
Eye,
Mail,
} from 'lucide-react';
import Link from 'next/link';
import { LandingHeader, LandingFooter } from '@/components/layout';
export default function CompliancePage() {
const heroRef = useRef(null);
const contentRef = useRef(null);
const isHeroInView = useInView(heroRef, { once: true });
const isContentInView = useInView(contentRef, { once: true });
const rights = [
{
icon: Eye,
title: 'Droit d\'accès',
description: 'Obtenez une copie de toutes les données personnelles que nous détenons sur vous.',
},
{
icon: Edit,
title: 'Droit de rectification',
description: 'Faites corriger vos données personnelles si elles sont inexactes ou incomplètes.',
},
{
icon: Trash2,
title: 'Droit à l\'effacement',
description: 'Demandez la suppression de vos données personnelles ("droit à l\'oubli").',
},
{
icon: Download,
title: 'Droit à la portabilité',
description: 'Recevez vos données dans un format structuré, lisible par machine.',
},
];
const principles = [
{
icon: Database,
title: 'Minimisation des données',
description: 'Nous ne collectons que les données strictement nécessaires à nos services.',
},
{
icon: Clock,
title: 'Limitation de conservation',
description: 'Vos données sont conservées uniquement le temps nécessaire.',
},
{
icon: Shield,
title: 'Intégrité et confidentialité',
description: 'Vos données sont protégées contre tout accès non autorisé.',
},
{
icon: FileText,
title: 'Transparence',
description: 'Nous vous informons clairement sur l\'utilisation de vos données.',
},
];
const measures = [
{
category: 'Mesures techniques',
items: [
'Chiffrement des données au repos et en transit',
'Authentification multi-facteurs',
'Journalisation des accès aux données',
'Sauvegardes chiffrées régulières',
'Pseudonymisation des données sensibles',
],
},
{
category: 'Mesures organisationnelles',
items: [
'Délégué à la Protection des Données (DPO) désigné',
'Formation régulière des employés',
'Politiques de sécurité documentées',
'Processus de gestion des incidents',
'Audits de conformité réguliers',
],
},
];
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 },
},
};
return (
<div className="min-h-screen bg-white">
<LandingHeader />
{/* Hero Section */}
<section ref={heroRef} className="relative pt-32 pb-20 bg-gradient-to-br from-brand-navy to-brand-navy/95 overflow-hidden">
<div className="absolute inset-0 opacity-10">
<div className="absolute top-20 left-20 w-96 h-96 bg-brand-turquoise rounded-full blur-3xl" />
<div className="absolute bottom-20 right-20 w-96 h-96 bg-brand-green rounded-full blur-3xl" />
</div>
<div className="relative z-10 max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center"
>
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={isHeroInView ? { scale: 1, opacity: 1 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="inline-flex items-center space-x-2 bg-white/10 backdrop-blur-sm px-4 py-2 rounded-full mb-8 border border-white/20"
>
<Globe className="w-5 h-5 text-brand-turquoise" />
<span className="text-white/90 text-sm font-medium">Conformité européenne</span>
</motion.div>
<h1 className="text-4xl lg:text-6xl font-bold text-white mb-6 leading-tight">
Conformité
<br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-brand-turquoise to-brand-green">
RGPD
</span>
</h1>
<p className="text-xl text-white/80 mb-6 max-w-3xl mx-auto leading-relaxed">
Xpeditis s'engage à respecter le Règlement Général sur la Protection des Données (RGPD)
et à garantir vos droits en matière de protection des données personnelles.
</p>
<div className="flex items-center justify-center space-x-4">
<div className="flex items-center space-x-2 bg-white/10 px-4 py-2 rounded-lg">
<CheckCircle className="w-5 h-5 text-brand-green" />
<span className="text-white text-sm">Conforme RGPD</span>
</div>
<div className="flex items-center space-x-2 bg-white/10 px-4 py-2 rounded-lg">
<UserCheck className="w-5 h-5 text-brand-green" />
<span className="text-white text-sm">DPO désigné</span>
</div>
</div>
</motion.div>
</div>
{/* Wave */}
<div className="absolute bottom-0 left-0 right-0">
<svg className="w-full h-16" viewBox="0 0 1440 60" preserveAspectRatio="none">
<path
d="M0,30 C240,50 480,10 720,30 C960,50 1200,10 1440,30 L1440,60 L0,60 Z"
fill="white"
/>
</svg>
</div>
</section>
{/* Your Rights */}
<section ref={contentRef} className="py-20">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center mb-16"
>
<h2 className="text-3xl lg:text-4xl font-bold text-brand-navy mb-4">
Vos droits RGPD
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Le RGPD vous confère des droits renforcés sur vos données personnelles
</p>
</motion.div>
<motion.div
variants={containerVariants}
initial="hidden"
animate={isContentInView ? 'visible' : 'hidden'}
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8"
>
{rights.map((right, index) => {
const IconComponent = right.icon;
return (
<motion.div
key={index}
variants={itemVariants}
whileHover={{ y: -5 }}
className="bg-white p-8 rounded-2xl shadow-lg border border-gray-100 hover:shadow-xl transition-all text-center"
>
<div className="w-16 h-16 bg-brand-turquoise/10 rounded-full flex items-center justify-center mx-auto mb-4">
<IconComponent className="w-8 h-8 text-brand-turquoise" />
</div>
<h3 className="text-xl font-bold text-brand-navy mb-3">{right.title}</h3>
<p className="text-gray-600">{right.description}</p>
</motion.div>
);
})}
</motion.div>
{/* Exercise Rights CTA */}
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8, delay: 0.4 }}
className="mt-12 text-center"
>
<p className="text-gray-600 mb-4">
Pour exercer vos droits, connectez-vous à votre compte ou contactez notre DPO
</p>
<div className="flex flex-col sm:flex-row items-center justify-center space-y-4 sm:space-y-0 sm:space-x-4">
<Link
href="/login"
className="px-6 py-3 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-colors font-medium"
>
Accéder à mon compte
</Link>
<a
href="mailto:dpo@xpeditis.com"
className="px-6 py-3 bg-brand-navy text-white rounded-lg hover:bg-brand-navy/90 transition-colors font-medium"
>
Contacter le DPO
</a>
</div>
</motion.div>
</div>
</section>
{/* Principles */}
<section className="py-20 bg-gray-50">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
className="text-center mb-16"
>
<h2 className="text-3xl lg:text-4xl font-bold text-brand-navy mb-4">
Nos principes de protection des données
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Des principes fondamentaux qui guident notre traitement des données
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{principles.map((principle, index) => {
const IconComponent = principle.icon;
return (
<motion.div
key={index}
initial={{ opacity: 0, scale: 0.9 }}
whileInView={{ opacity: 1, scale: 1 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="bg-white p-6 rounded-2xl shadow-lg border border-gray-100"
>
<div className="w-12 h-12 bg-brand-green/10 rounded-xl flex items-center justify-center mb-4">
<IconComponent className="w-6 h-6 text-brand-green" />
</div>
<h3 className="text-lg font-bold text-brand-navy mb-2">{principle.title}</h3>
<p className="text-gray-600 text-sm">{principle.description}</p>
</motion.div>
);
})}
</div>
</div>
</section>
{/* Technical & Organizational Measures */}
<section className="py-20">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
className="text-center mb-16"
>
<h2 className="text-3xl lg:text-4xl font-bold text-brand-navy mb-4">
Mesures de protection
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Des mesures techniques et organisationnelles pour assurer la sécurité de vos données
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
{measures.map((measure, index) => (
<motion.div
key={index}
initial={{ opacity: 0, x: index === 0 ? -30 : 30 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="bg-gradient-to-br from-brand-navy to-brand-navy/95 p-8 rounded-2xl"
>
<h3 className="text-xl font-bold text-white mb-6">{measure.category}</h3>
<ul className="space-y-4">
{measure.items.map((item, i) => (
<li key={i} className="flex items-center space-x-3 text-white/80">
<CheckCircle className="w-5 h-5 text-brand-turquoise flex-shrink-0" />
<span>{item}</span>
</li>
))}
</ul>
</motion.div>
))}
</div>
</div>
</section>
{/* Data Processing Register */}
<section className="py-20 bg-gray-50">
<div className="max-w-4xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
className="bg-white p-8 rounded-2xl shadow-lg border border-gray-100"
>
<div className="flex items-start space-x-4">
<div className="w-12 h-12 bg-brand-turquoise/10 rounded-xl flex items-center justify-center flex-shrink-0">
<FileText className="w-6 h-6 text-brand-turquoise" />
</div>
<div>
<h3 className="text-2xl font-bold text-brand-navy mb-4">
Registre des traitements
</h3>
<p className="text-gray-600 mb-6">
Conformément à l'article 30 du RGPD, nous tenons un registre des activités de traitement
des données personnelles. Ce registre documente :
</p>
<ul className="space-y-3 text-gray-600">
<li className="flex items-center space-x-3">
<CheckCircle className="w-5 h-5 text-brand-green flex-shrink-0" />
<span>Les finalités de chaque traitement</span>
</li>
<li className="flex items-center space-x-3">
<CheckCircle className="w-5 h-5 text-brand-green flex-shrink-0" />
<span>Les catégories de données traitées</span>
</li>
<li className="flex items-center space-x-3">
<CheckCircle className="w-5 h-5 text-brand-green flex-shrink-0" />
<span>Les destinataires des données</span>
</li>
<li className="flex items-center space-x-3">
<CheckCircle className="w-5 h-5 text-brand-green flex-shrink-0" />
<span>Les durées de conservation</span>
</li>
<li className="flex items-center space-x-3">
<CheckCircle className="w-5 h-5 text-brand-green flex-shrink-0" />
<span>Les mesures de sécurité appliquées</span>
</li>
</ul>
</div>
</div>
</motion.div>
</div>
</section>
{/* Contact DPO */}
<section className="py-20">
<div className="max-w-4xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
className="bg-gradient-to-br from-brand-navy to-brand-navy/95 p-10 rounded-3xl text-center"
>
<UserCheck className="w-12 h-12 text-brand-turquoise mx-auto mb-4" />
<h3 className="text-2xl font-bold text-white mb-4">
Contacter notre DPO
</h3>
<p className="text-white/80 mb-6 max-w-2xl mx-auto">
Notre Délégué à la Protection des Données est à votre disposition pour toute question
relative au traitement de vos données personnelles ou à l'exercice de vos droits.
</p>
<div className="flex flex-col sm:flex-row items-center justify-center space-y-4 sm:space-y-0 sm:space-x-4">
<a
href="mailto:dpo@xpeditis.com"
className="inline-flex items-center space-x-2 px-6 py-3 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-colors font-medium"
>
<Mail className="w-5 h-5" />
<span>dpo@xpeditis.com</span>
</a>
<Link
href="/privacy"
className="px-6 py-3 bg-white text-brand-navy rounded-lg hover:bg-gray-100 transition-colors font-medium"
>
Politique de confidentialité
</Link>
</div>
</motion.div>
</div>
</section>
<LandingFooter />
</div>
);
}

View File

@ -0,0 +1,565 @@
'use client';
import { useState, useRef } from 'react';
import { motion, useInView } from 'framer-motion';
import {
Mail,
Phone,
MapPin,
Clock,
Send,
MessageSquare,
Headphones,
Building2,
CheckCircle2,
Loader2,
} from 'lucide-react';
import { LandingHeader, LandingFooter } from '@/components/layout';
export default function ContactPage() {
const [formData, setFormData] = useState({
firstName: '',
lastName: '',
email: '',
company: '',
phone: '',
subject: '',
message: '',
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSubmitted, setIsSubmitted] = useState(false);
const [error, setError] = useState('');
const heroRef = useRef(null);
const formRef = useRef(null);
const contactRef = useRef(null);
const isHeroInView = useInView(heroRef, { once: true });
const isFormInView = useInView(formRef, { once: true });
const isContactInView = useInView(contactRef, { once: true });
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError('');
setIsSubmitting(true);
// Simulate form submission
await new Promise((resolve) => setTimeout(resolve, 1500));
setIsSubmitting(false);
setIsSubmitted(true);
};
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>
) => {
setFormData((prev) => ({
...prev,
[e.target.name]: e.target.value,
}));
};
const contactMethods = [
{
icon: Mail,
title: 'Email',
description: 'Envoyez-nous un email',
value: 'contact@xpeditis.com',
link: 'mailto:contact@xpeditis.com',
color: 'from-blue-500 to-cyan-500',
},
{
icon: Phone,
title: 'Téléphone',
description: 'Appelez-nous',
value: '+33 1 23 45 67 89',
link: 'tel:+33123456789',
color: 'from-green-500 to-emerald-500',
},
{
icon: MessageSquare,
title: 'Chat en direct',
description: 'Discutez avec notre équipe',
value: 'Disponible 24/7',
link: '#chat',
color: 'from-purple-500 to-pink-500',
},
{
icon: Headphones,
title: 'Support',
description: 'Centre d\'aide',
value: 'support.xpeditis.com',
link: 'https://support.xpeditis.com',
color: 'from-orange-500 to-red-500',
},
];
const offices = [
{
city: 'Paris',
address: '123 Avenue des Champs-Élysées',
postalCode: '75008 Paris, France',
phone: '+33 1 23 45 67 89',
email: 'paris@xpeditis.com',
isHQ: true,
},
{
city: 'Rotterdam',
address: 'Wilhelminakade 123',
postalCode: '3072 AP Rotterdam, Netherlands',
phone: '+31 10 123 4567',
email: 'rotterdam@xpeditis.com',
isHQ: false,
},
{
city: 'Hambourg',
address: 'Am Sandtorkai 50',
postalCode: '20457 Hamburg, Germany',
phone: '+49 40 123 4567',
email: 'hamburg@xpeditis.com',
isHQ: false,
},
];
const subjects = [
{ value: '', label: 'Sélectionnez un sujet' },
{ value: 'demo', label: 'Demande de démonstration' },
{ value: 'pricing', label: 'Questions sur les tarifs' },
{ value: 'partnership', label: 'Partenariat' },
{ value: 'support', label: 'Support technique' },
{ value: 'press', label: 'Relations presse' },
{ value: 'careers', label: 'Recrutement' },
{ value: 'other', label: 'Autre' },
];
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 },
},
};
return (
<div className="min-h-screen bg-white">
<LandingHeader activePage="contact" />
{/* Hero Section */}
<section ref={heroRef} className="relative pt-32 pb-20 bg-gradient-to-br from-brand-navy to-brand-navy/95 overflow-hidden">
<div className="absolute inset-0 opacity-10">
<div className="absolute top-20 left-20 w-96 h-96 bg-brand-turquoise rounded-full blur-3xl" />
<div className="absolute bottom-20 right-20 w-96 h-96 bg-brand-green rounded-full blur-3xl" />
</div>
<div className="relative z-10 max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center"
>
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={isHeroInView ? { scale: 1, opacity: 1 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="inline-flex items-center space-x-2 bg-white/10 backdrop-blur-sm px-4 py-2 rounded-full mb-8 border border-white/20"
>
<Mail className="w-5 h-5 text-brand-turquoise" />
<span className="text-white/90 text-sm font-medium">Nous contacter</span>
</motion.div>
<h1 className="text-4xl lg:text-6xl font-bold text-white mb-6 leading-tight">
Une question ?
<br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-brand-turquoise to-brand-green">
Nous sommes pour vous
</span>
</h1>
<p className="text-xl text-white/80 mb-10 max-w-3xl mx-auto leading-relaxed">
Notre équipe est disponible pour répondre à toutes vos questions sur notre plateforme,
nos services et nos tarifs. N'hésitez pas à nous contacter !
</p>
</motion.div>
</div>
{/* Wave */}
<div className="absolute bottom-0 left-0 right-0">
<svg className="w-full h-16" viewBox="0 0 1440 60" preserveAspectRatio="none">
<path
d="M0,30 C240,50 480,10 720,30 C960,50 1200,10 1440,30 L1440,60 L0,60 Z"
fill="white"
/>
</svg>
</div>
</section>
{/* Contact Methods */}
<section ref={contactRef} className="py-16 bg-gray-50">
<motion.div
variants={containerVariants}
initial="hidden"
animate={isContactInView ? 'visible' : 'hidden'}
className="max-w-7xl mx-auto px-6 lg:px-8"
>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{contactMethods.map((method, index) => {
const IconComponent = method.icon;
return (
<motion.a
key={index}
href={method.link}
variants={itemVariants}
whileHover={{ y: -5 }}
className="bg-white p-6 rounded-2xl shadow-lg border border-gray-100 hover:shadow-xl transition-all group"
>
<div
className={`w-12 h-12 rounded-xl bg-gradient-to-br ${method.color} flex items-center justify-center mb-4 group-hover:scale-110 transition-transform`}
>
<IconComponent className="w-6 h-6 text-white" />
</div>
<h3 className="text-lg font-bold text-brand-navy mb-1">{method.title}</h3>
<p className="text-gray-500 text-sm mb-2">{method.description}</p>
<p className="text-brand-turquoise font-medium">{method.value}</p>
</motion.a>
);
})}
</div>
</motion.div>
</section>
{/* Contact Form & Info */}
<section ref={formRef} className="py-20">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12">
{/* Form */}
<motion.div
initial={{ opacity: 0, x: -50 }}
animate={isFormInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.8 }}
>
<h2 className="text-3xl font-bold text-brand-navy mb-6">Envoyez-nous un message</h2>
<p className="text-gray-600 mb-8">
Remplissez le formulaire ci-dessous et nous vous répondrons dans les plus brefs délais.
</p>
{isSubmitted ? (
<motion.div
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
className="bg-green-50 border border-green-200 rounded-2xl p-8 text-center"
>
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
<CheckCircle2 className="w-8 h-8 text-green-600" />
</div>
<h3 className="text-2xl font-bold text-green-800 mb-2">Message envoyé !</h3>
<p className="text-green-700 mb-6">
Merci pour votre message. Notre équipe vous répondra dans les 24 heures.
</p>
<button
onClick={() => {
setIsSubmitted(false);
setFormData({
firstName: '',
lastName: '',
email: '',
company: '',
phone: '',
subject: '',
message: '',
});
}}
className="text-brand-turquoise font-medium hover:underline"
>
Envoyer un autre message
</button>
</motion.div>
) : (
<form onSubmit={handleSubmit} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label htmlFor="firstName" className="block text-sm font-medium text-gray-700 mb-2">
Prénom *
</label>
<input
type="text"
id="firstName"
name="firstName"
required
value={formData.firstName}
onChange={handleChange}
className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-brand-turquoise focus:border-transparent transition-all"
placeholder="Jean"
/>
</div>
<div>
<label htmlFor="lastName" className="block text-sm font-medium text-gray-700 mb-2">
Nom *
</label>
<input
type="text"
id="lastName"
name="lastName"
required
value={formData.lastName}
onChange={handleChange}
className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-brand-turquoise focus:border-transparent transition-all"
placeholder="Dupont"
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-2">
Email *
</label>
<input
type="email"
id="email"
name="email"
required
value={formData.email}
onChange={handleChange}
className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-brand-turquoise focus:border-transparent transition-all"
placeholder="jean.dupont@exemple.com"
/>
</div>
<div>
<label htmlFor="phone" className="block text-sm font-medium text-gray-700 mb-2">
Téléphone
</label>
<input
type="tel"
id="phone"
name="phone"
value={formData.phone}
onChange={handleChange}
className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-brand-turquoise focus:border-transparent transition-all"
placeholder="+33 6 12 34 56 78"
/>
</div>
</div>
<div>
<label htmlFor="company" className="block text-sm font-medium text-gray-700 mb-2">
Entreprise
</label>
<input
type="text"
id="company"
name="company"
value={formData.company}
onChange={handleChange}
className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-brand-turquoise focus:border-transparent transition-all"
placeholder="Votre entreprise"
/>
</div>
<div>
<label htmlFor="subject" className="block text-sm font-medium text-gray-700 mb-2">
Sujet *
</label>
<select
id="subject"
name="subject"
required
value={formData.subject}
onChange={handleChange}
className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-brand-turquoise focus:border-transparent transition-all"
>
{subjects.map((subject) => (
<option key={subject.value} value={subject.value}>
{subject.label}
</option>
))}
</select>
</div>
<div>
<label htmlFor="message" className="block text-sm font-medium text-gray-700 mb-2">
Message *
</label>
<textarea
id="message"
name="message"
required
rows={5}
value={formData.message}
onChange={handleChange}
className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-brand-turquoise focus:border-transparent transition-all resize-none"
placeholder="Comment pouvons-nous vous aider ?"
/>
</div>
{error && (
<div className="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-lg">
{error}
</div>
)}
<button
type="submit"
disabled={isSubmitting}
className="w-full px-8 py-4 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-all font-semibold text-lg flex items-center justify-center space-x-2 disabled:opacity-50 disabled:cursor-not-allowed"
>
{isSubmitting ? (
<>
<Loader2 className="w-5 h-5 animate-spin" />
<span>Envoi en cours...</span>
</>
) : (
<>
<Send className="w-5 h-5" />
<span>Envoyer le message</span>
</>
)}
</button>
</form>
)}
</motion.div>
{/* Offices */}
<motion.div
initial={{ opacity: 0, x: 50 }}
animate={isFormInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.8, delay: 0.2 }}
>
<h2 className="text-3xl font-bold text-brand-navy mb-6">Nos bureaux</h2>
<p className="text-gray-600 mb-8">
Retrouvez-nous dans nos bureaux à travers l'Europe ou contactez-nous par email.
</p>
<div className="space-y-6">
{offices.map((office, index) => (
<div
key={index}
className={`bg-white p-6 rounded-2xl border-2 transition-all ${
office.isHQ
? 'border-brand-turquoise shadow-lg'
: 'border-gray-200 hover:border-brand-turquoise/50'
}`}
>
<div className="flex items-start space-x-4">
<div
className={`w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0 ${
office.isHQ ? 'bg-brand-turquoise' : 'bg-gray-100'
}`}
>
<Building2 className={`w-6 h-6 ${office.isHQ ? 'text-white' : 'text-gray-600'}`} />
</div>
<div className="flex-1">
<div className="flex items-center space-x-2 mb-2">
<h3 className="text-xl font-bold text-brand-navy">{office.city}</h3>
{office.isHQ && (
<span className="px-2 py-1 bg-brand-turquoise/10 text-brand-turquoise text-xs font-medium rounded-full">
Siège social
</span>
)}
</div>
<div className="space-y-2 text-gray-600">
<div className="flex items-center space-x-2">
<MapPin className="w-4 h-4 text-gray-400" />
<span>{office.address}</span>
</div>
<div className="flex items-center space-x-2">
<span className="text-gray-400 ml-6">{office.postalCode}</span>
</div>
<div className="flex items-center space-x-2">
<Phone className="w-4 h-4 text-gray-400" />
<a href={`tel:${office.phone.replace(/\s/g, '')}`} className="hover:text-brand-turquoise">
{office.phone}
</a>
</div>
<div className="flex items-center space-x-2">
<Mail className="w-4 h-4 text-gray-400" />
<a href={`mailto:${office.email}`} className="hover:text-brand-turquoise">
{office.email}
</a>
</div>
</div>
</div>
</div>
</div>
))}
</div>
{/* Hours */}
<div className="mt-8 bg-gray-50 p-6 rounded-2xl">
<div className="flex items-center space-x-3 mb-4">
<Clock className="w-6 h-6 text-brand-turquoise" />
<h3 className="text-lg font-bold text-brand-navy">Horaires d'ouverture</h3>
</div>
<div className="space-y-2 text-gray-600">
<div className="flex justify-between">
<span>Lundi - Vendredi</span>
<span className="font-medium">9h00 - 18h00</span>
</div>
<div className="flex justify-between">
<span>Samedi</span>
<span className="font-medium">10h00 - 14h00</span>
</div>
<div className="flex justify-between">
<span>Dimanche</span>
<span className="font-medium text-gray-400">Fermé</span>
</div>
</div>
<p className="mt-4 text-sm text-gray-500">
* Support technique disponible 24/7 pour les clients Enterprise
</p>
</div>
</motion.div>
</div>
</div>
</section>
{/* Map Section */}
<section className="py-20 bg-gray-50">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
className="text-center mb-12"
>
<h2 className="text-3xl font-bold text-brand-navy mb-4">Notre présence en Europe</h2>
<p className="text-gray-600">
Des bureaux stratégiquement situés pour mieux vous servir
</p>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8, delay: 0.2 }}
className="bg-white rounded-2xl shadow-lg overflow-hidden"
>
<div className="aspect-[21/9] bg-gradient-to-br from-brand-navy/5 to-brand-turquoise/5 flex items-center justify-center">
<div className="text-center">
<MapPin className="w-16 h-16 text-brand-turquoise mx-auto mb-4" />
<p className="text-gray-500">Carte interactive bientôt disponible</p>
</div>
</div>
</motion.div>
</div>
</section>
<LandingFooter />
</div>
);
}

View File

@ -0,0 +1,291 @@
'use client';
import { useRef } from 'react';
import { motion, useInView } from 'framer-motion';
import { Cookie, Settings, BarChart3, Target, Shield, ToggleLeft, Mail } from 'lucide-react';
import { LandingHeader, LandingFooter } from '@/components/layout';
export default function CookiesPage() {
const heroRef = useRef(null);
const contentRef = useRef(null);
const isHeroInView = useInView(heroRef, { once: true });
const isContentInView = useInView(contentRef, { once: true });
const cookieTypes = [
{
icon: Shield,
title: 'Cookies essentiels',
description: 'Nécessaires au fonctionnement du site',
required: true,
cookies: [
{ name: 'session_id', purpose: 'Maintien de votre session de connexion', duration: 'Session' },
{ name: 'csrf_token', purpose: 'Protection contre les attaques CSRF', duration: 'Session' },
{ name: 'cookie_consent', purpose: 'Mémorisation de vos préférences cookies', duration: '1 an' },
],
},
{
icon: BarChart3,
title: 'Cookies analytiques',
description: 'Nous aident à améliorer notre plateforme',
required: false,
cookies: [
{ name: '_ga', purpose: 'Google Analytics - Identification des visiteurs', duration: '2 ans' },
{ name: '_gid', purpose: 'Google Analytics - Identification des sessions', duration: '24 heures' },
{ name: '_gat', purpose: 'Google Analytics - Limitation du taux de requêtes', duration: '1 minute' },
],
},
{
icon: Target,
title: 'Cookies marketing',
description: 'Permettent de personnaliser les publicités',
required: false,
cookies: [
{ name: '_fbp', purpose: 'Facebook Pixel - Suivi des conversions', duration: '3 mois' },
{ name: 'li_fat_id', purpose: 'LinkedIn Insight - Attribution marketing', duration: '30 jours' },
{ name: 'hubspotutk', purpose: 'HubSpot - Identification des visiteurs', duration: '13 mois' },
],
},
{
icon: Settings,
title: 'Cookies fonctionnels',
description: 'Améliorent votre expérience utilisateur',
required: false,
cookies: [
{ name: 'language', purpose: 'Mémorisation de votre langue préférée', duration: '1 an' },
{ name: 'theme', purpose: 'Mémorisation du thème (clair/sombre)', duration: '1 an' },
{ name: 'recent_searches', purpose: 'Historique de vos recherches récentes', duration: '30 jours' },
],
},
];
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 },
},
};
return (
<div className="min-h-screen bg-white">
<LandingHeader />
{/* Hero Section */}
<section ref={heroRef} className="relative pt-32 pb-20 bg-gradient-to-br from-brand-navy to-brand-navy/95 overflow-hidden">
<div className="absolute inset-0 opacity-10">
<div className="absolute top-20 left-20 w-96 h-96 bg-brand-turquoise rounded-full blur-3xl" />
<div className="absolute bottom-20 right-20 w-96 h-96 bg-brand-green rounded-full blur-3xl" />
</div>
<div className="relative z-10 max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center"
>
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={isHeroInView ? { scale: 1, opacity: 1 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="inline-flex items-center space-x-2 bg-white/10 backdrop-blur-sm px-4 py-2 rounded-full mb-8 border border-white/20"
>
<Cookie className="w-5 h-5 text-brand-turquoise" />
<span className="text-white/90 text-sm font-medium">Transparence</span>
</motion.div>
<h1 className="text-4xl lg:text-6xl font-bold text-white mb-6 leading-tight">
Politique de
<br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-brand-turquoise to-brand-green">
Cookies
</span>
</h1>
<p className="text-xl text-white/80 mb-6 max-w-3xl mx-auto leading-relaxed">
Découvrez comment nous utilisons les cookies pour améliorer votre expérience
sur Xpeditis et comment vous pouvez gérer vos préférences.
</p>
<p className="text-white/60 text-sm">
Dernière mise à jour : Janvier 2025
</p>
</motion.div>
</div>
{/* Wave */}
<div className="absolute bottom-0 left-0 right-0">
<svg className="w-full h-16" viewBox="0 0 1440 60" preserveAspectRatio="none">
<path
d="M0,30 C240,50 480,10 720,30 C960,50 1200,10 1440,30 L1440,60 L0,60 Z"
fill="white"
/>
</svg>
</div>
</section>
{/* Introduction */}
<section className="py-16 bg-gray-50">
<div className="max-w-4xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
className="bg-white p-8 rounded-2xl shadow-lg border border-gray-100"
>
<h2 className="text-2xl font-bold text-brand-navy mb-4">Qu'est-ce qu'un cookie ?</h2>
<p className="text-gray-600 leading-relaxed mb-4">
Un cookie est un petit fichier texte stocké sur votre appareil (ordinateur, tablette, smartphone)
lorsque vous visitez un site web. Les cookies permettent au site de mémoriser vos actions et
préférences sur une période donnée.
</p>
<p className="text-gray-600 leading-relaxed">
Les cookies ne contiennent pas d'informations personnellement identifiables et ne peuvent pas
accéder aux données stockées sur votre appareil.
</p>
</motion.div>
</div>
</section>
{/* Cookie Types Section */}
<section ref={contentRef} className="py-20">
<div className="max-w-4xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center mb-12"
>
<h2 className="text-3xl font-bold text-brand-navy mb-4">Types de cookies utilisés</h2>
<p className="text-gray-600">
Nous utilisons différents types de cookies sur notre plateforme
</p>
</motion.div>
<motion.div
variants={containerVariants}
initial="hidden"
animate={isContentInView ? 'visible' : 'hidden'}
className="space-y-8"
>
{cookieTypes.map((type, index) => {
const IconComponent = type.icon;
return (
<motion.div
key={index}
variants={itemVariants}
className="bg-white p-8 rounded-2xl shadow-lg border border-gray-100"
>
<div className="flex items-start justify-between mb-6">
<div className="flex items-center space-x-4">
<div className="w-12 h-12 bg-brand-turquoise/10 rounded-xl flex items-center justify-center">
<IconComponent className="w-6 h-6 text-brand-turquoise" />
</div>
<div>
<h3 className="text-xl font-bold text-brand-navy">{type.title}</h3>
<p className="text-gray-500 text-sm">{type.description}</p>
</div>
</div>
{type.required ? (
<span className="px-3 py-1 bg-brand-navy/10 text-brand-navy text-xs font-medium rounded-full">
Requis
</span>
) : (
<div className="flex items-center space-x-2">
<ToggleLeft className="w-8 h-8 text-gray-400" />
<span className="text-sm text-gray-500">Optionnel</span>
</div>
)}
</div>
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-gray-200">
<th className="text-left py-3 px-4 font-semibold text-brand-navy">Nom</th>
<th className="text-left py-3 px-4 font-semibold text-brand-navy">Finalité</th>
<th className="text-left py-3 px-4 font-semibold text-brand-navy">Durée</th>
</tr>
</thead>
<tbody>
{type.cookies.map((cookie, i) => (
<tr key={i} className="border-b border-gray-100 last:border-0">
<td className="py-3 px-4 font-mono text-brand-turquoise">{cookie.name}</td>
<td className="py-3 px-4 text-gray-600">{cookie.purpose}</td>
<td className="py-3 px-4 text-gray-500">{cookie.duration}</td>
</tr>
))}
</tbody>
</table>
</div>
</motion.div>
);
})}
</motion.div>
{/* How to manage cookies */}
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8, delay: 0.4 }}
className="mt-12 bg-gradient-to-br from-gray-50 to-white p-8 rounded-2xl border border-gray-200"
>
<h3 className="text-2xl font-bold text-brand-navy mb-4">Comment gérer vos cookies ?</h3>
<div className="space-y-4 text-gray-600">
<p>
Vous pouvez à tout moment modifier vos préférences en matière de cookies :
</p>
<ul className="list-disc pl-6 space-y-2">
<li>Via notre bandeau de consentement accessible en bas de chaque page</li>
<li>Dans les paramètres de votre navigateur (Chrome, Firefox, Safari, Edge)</li>
<li>En utilisant des outils tiers de gestion des cookies</li>
</ul>
<p className="text-sm text-gray-500 mt-4">
Note : La désactivation de certains cookies peut affecter votre expérience sur notre plateforme.
</p>
</div>
</motion.div>
{/* Contact Section */}
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8, delay: 0.6 }}
className="mt-16 bg-gradient-to-br from-brand-navy to-brand-navy/95 p-10 rounded-3xl text-center"
>
<Mail className="w-12 h-12 text-brand-turquoise mx-auto mb-4" />
<h3 className="text-2xl font-bold text-white mb-4">Des questions sur les cookies ?</h3>
<p className="text-white/80 mb-6">
Notre équipe est disponible pour répondre à toutes vos questions
concernant l'utilisation des cookies sur notre plateforme.
</p>
<a
href="mailto:privacy@xpeditis.com"
className="inline-flex items-center space-x-2 px-6 py-3 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-colors font-medium"
>
<Mail className="w-5 h-5" />
<span>privacy@xpeditis.com</span>
</a>
</motion.div>
</div>
</section>
<LandingFooter />
</div>
);
}

View File

@ -3,7 +3,7 @@
import { useEffect, useRef, useState } from 'react';
import Link from 'next/link';
import Image from 'next/image';
import { motion, useInView, useScroll, useTransform } from 'framer-motion';
import { motion, useInView, useScroll, useTransform, AnimatePresence } from 'framer-motion';
import {
Ship,
TrendingUp,
@ -28,13 +28,27 @@ import {
Building2,
Check,
X,
ChevronDown,
Briefcase,
Newspaper,
Mail,
Info,
} from 'lucide-react';
import { useAuth } from '@/lib/context/auth-context';
export default function LandingPage() {
const [isScrolled, setIsScrolled] = useState(false);
const [isCompanyMenuOpen, setIsCompanyMenuOpen] = useState(false);
const { user, isAuthenticated, loading } = useAuth();
const companyMenuItems = [
{ href: '/about', label: 'À propos', icon: Info, description: 'Notre histoire et mission' },
{ href: '/contact', label: 'Contact', icon: Mail, description: 'Nous contacter' },
{ href: '/careers', label: 'Carrières', icon: Briefcase, description: 'Rejoignez-nous' },
{ href: '/blog', label: 'Blog', icon: BookOpen, description: 'Actualités et insights' },
{ href: '/press', label: 'Presse', icon: Newspaper, description: 'Espace presse' },
];
// Helper function to get user initials
const getUserInitials = () => {
if (!user) return '';
@ -318,6 +332,61 @@ export default function LandingPage() {
Tarifs
</Link>
{/* Menu Entreprise */}
<div
className="relative"
onMouseEnter={() => setIsCompanyMenuOpen(true)}
onMouseLeave={() => setIsCompanyMenuOpen(false)}
>
<button
className="flex items-center space-x-1 text-white hover:text-brand-turquoise transition-colors font-medium"
>
<span>Entreprise</span>
<ChevronDown
className={`w-4 h-4 transition-transform ${isCompanyMenuOpen ? 'rotate-180' : ''}`}
/>
</button>
<AnimatePresence>
{isCompanyMenuOpen && (
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
transition={{ duration: 0.2 }}
className="absolute top-full left-1/2 -translate-x-1/2 pt-4 z-50"
>
<div className="bg-white rounded-2xl shadow-2xl border border-gray-100 overflow-hidden min-w-[280px]">
<div className="p-2">
{companyMenuItems.map((item) => {
const IconComponent = item.icon;
return (
<Link
key={item.href}
href={item.href}
className="flex items-center space-x-3 px-4 py-3 rounded-xl hover:bg-gray-50 transition-colors group"
>
<div className="w-10 h-10 bg-brand-turquoise/10 rounded-lg flex items-center justify-center group-hover:bg-brand-turquoise/20 transition-colors">
<IconComponent className="w-5 h-5 text-brand-turquoise" />
</div>
<div>
<div className="font-medium text-brand-navy group-hover:text-brand-turquoise transition-colors">
{item.label}
</div>
<div className="text-sm text-gray-500">
{item.description}
</div>
</div>
</Link>
);
})}
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
{/* Affichage conditionnel: connecté vs non connecté */}
{loading ? (
<div className="w-8 h-8 rounded-full bg-white/20 animate-pulse" />

View File

@ -0,0 +1,578 @@
'use client';
import { useRef } from 'react';
import { motion, useInView } from 'framer-motion';
import {
Newspaper,
Download,
ExternalLink,
Calendar,
Mail,
Phone,
FileText,
Image as ImageIcon,
Video,
Award,
TrendingUp,
Users,
Globe,
ArrowRight,
Quote,
} from 'lucide-react';
import { LandingHeader, LandingFooter } from '@/components/layout';
export default function PressPage() {
const heroRef = useRef(null);
const newsRef = useRef(null);
const resourcesRef = useRef(null);
const contactRef = useRef(null);
const milestonesRef = useRef(null);
const isHeroInView = useInView(heroRef, { once: true });
const isNewsInView = useInView(newsRef, { once: true });
const isResourcesInView = useInView(resourcesRef, { once: true });
const isContactInView = useInView(contactRef, { once: true });
const isMilestonesInView = useInView(milestonesRef, { once: true });
const pressReleases = [
{
id: 1,
title: 'Xpeditis lève 15 millions d\'euros pour accélérer son expansion européenne',
date: '15 janvier 2025',
excerpt:
'La startup française de fret maritime digital annonce une levée de fonds Série A menée par Partech et Eurazeo.',
category: 'Financement',
pdfUrl: '#',
},
{
id: 2,
title: 'Xpeditis franchit le cap des 500 clients actifs',
date: '8 janvier 2025',
excerpt:
'La plateforme B2B de fret maritime confirme sa position de leader en Europe avec une croissance de 200% en 2024.',
category: 'Croissance',
pdfUrl: '#',
},
{
id: 3,
title: 'Partenariat stratégique avec CMA CGM',
date: '15 décembre 2024',
excerpt:
'Xpeditis intègre l\'offre complète du groupe CMA CGM, offrant encore plus de choix à ses utilisateurs.',
category: 'Partenariat',
pdfUrl: '#',
},
{
id: 4,
title: 'Lancement de nouvelles fonctionnalités de tracking en temps réel',
date: '1er décembre 2024',
excerpt:
'La plateforme enrichit son offre avec un système de suivi des conteneurs amélioré et des notifications proactives.',
category: 'Produit',
pdfUrl: '#',
},
{
id: 5,
title: 'Ouverture du bureau de Rotterdam',
date: '15 novembre 2024',
excerpt:
'Xpeditis poursuit son expansion avec l\'ouverture d\'un nouveau bureau aux Pays-Bas pour servir le marché Benelux.',
category: 'Expansion',
pdfUrl: '#',
},
];
const mediaCoverage = [
{
outlet: 'Les Echos',
title: 'Xpeditis, la startup qui digitalise le fret maritime',
date: '12 janvier 2025',
url: '#',
logo: '/assets/logos/media/les-echos.png',
},
{
outlet: 'BFM Business',
title: 'Comment l\'IA révolutionne la logistique maritime',
date: '10 janvier 2025',
url: '#',
logo: '/assets/logos/media/bfm.png',
},
{
outlet: 'Journal de la Marine Marchande',
title: 'Les plateformes digitales au service des transitaires',
date: '5 janvier 2025',
url: '#',
logo: '/assets/logos/media/jmm.png',
},
{
outlet: 'Tech.eu',
title: 'French logistics startup Xpeditis raises €15M',
date: '15 janvier 2025',
url: '#',
logo: '/assets/logos/media/tech-eu.png',
},
];
const pressKitItems = [
{
icon: ImageIcon,
title: 'Logos & Visuels',
description: 'Logos en haute résolution (PNG, SVG) et visuels de la plateforme',
downloadUrl: '#',
format: 'ZIP - 12 MB',
},
{
icon: FileText,
title: 'Dossier de presse',
description: 'Présentation complète de Xpeditis, chiffres clés et biographies des fondateurs',
downloadUrl: '#',
format: 'PDF - 4 MB',
},
{
icon: Video,
title: 'Vidéos & B-Roll',
description: 'Vidéos de présentation et séquences B-Roll pour vos reportages',
downloadUrl: '#',
format: 'MP4 - 250 MB',
},
];
const milestones = [
{ year: '2021', event: 'Création de Xpeditis', icon: Award },
{ year: '2022', event: 'Première version lancée', icon: TrendingUp },
{ year: '2023', event: 'Levée Seed de 3M€', icon: TrendingUp },
{ year: '2024', event: '500 clients actifs', icon: Users },
{ year: '2025', event: 'Série A - 15M€', icon: Globe },
];
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 },
},
};
return (
<div className="min-h-screen bg-white">
<LandingHeader activePage="press" />
{/* Hero Section */}
<section ref={heroRef} className="relative pt-32 pb-20 bg-gradient-to-br from-brand-navy to-brand-navy/95 overflow-hidden">
<div className="absolute inset-0 opacity-10">
<div className="absolute top-20 left-20 w-96 h-96 bg-brand-turquoise rounded-full blur-3xl" />
<div className="absolute bottom-20 right-20 w-96 h-96 bg-brand-green rounded-full blur-3xl" />
</div>
<div className="relative z-10 max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center"
>
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={isHeroInView ? { scale: 1, opacity: 1 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="inline-flex items-center space-x-2 bg-white/10 backdrop-blur-sm px-4 py-2 rounded-full mb-8 border border-white/20"
>
<Newspaper className="w-5 h-5 text-brand-turquoise" />
<span className="text-white/90 text-sm font-medium">Espace Presse</span>
</motion.div>
<h1 className="text-4xl lg:text-6xl font-bold text-white mb-6 leading-tight">
Espace Presse
<br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-brand-turquoise to-brand-green">
Xpeditis
</span>
</h1>
<p className="text-xl text-white/80 mb-10 max-w-3xl mx-auto leading-relaxed">
Retrouvez tous nos communiqués de presse, ressources médias et informations
pour les journalistes. Notre équipe communication est à votre disposition.
</p>
<div className="flex flex-col sm:flex-row items-center justify-center space-y-4 sm:space-y-0 sm:space-x-6">
<a
href="#resources"
className="group px-8 py-4 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-all hover:shadow-2xl font-semibold text-lg flex items-center space-x-2"
>
<Download className="w-5 h-5" />
<span>Kit Presse</span>
</a>
<a
href="#contact"
className="px-8 py-4 bg-white text-brand-navy rounded-lg hover:bg-gray-100 transition-all font-semibold text-lg"
>
Contact Presse
</a>
</div>
</motion.div>
</div>
{/* Wave */}
<div className="absolute bottom-0 left-0 right-0">
<svg className="w-full h-16" viewBox="0 0 1440 60" preserveAspectRatio="none">
<path
d="M0,30 C240,50 480,10 720,30 C960,50 1200,10 1440,30 L1440,60 L0,60 Z"
fill="white"
/>
</svg>
</div>
</section>
{/* Key Stats */}
<section className="py-16 bg-gray-50">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8">
{[
{ value: '15M€', label: 'Levée de fonds' },
{ value: '500+', label: 'Clients actifs' },
{ value: '50+', label: 'Compagnies maritimes' },
{ value: '15', label: 'Pays couverts' },
].map((stat, index) => (
<motion.div
key={index}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="text-center"
>
<div className="text-5xl font-bold text-brand-turquoise mb-2">{stat.value}</div>
<div className="text-gray-600 font-medium">{stat.label}</div>
</motion.div>
))}
</div>
</div>
</section>
{/* Press Releases */}
<section ref={newsRef} className="py-20">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isNewsInView ? { 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">
Communiqués de Presse
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Les dernières actualités officielles de Xpeditis
</p>
</motion.div>
<motion.div
variants={containerVariants}
initial="hidden"
animate={isNewsInView ? 'visible' : 'hidden'}
className="space-y-6"
>
{pressReleases.map((release) => (
<motion.div
key={release.id}
variants={itemVariants}
className="bg-white rounded-2xl shadow-lg border border-gray-100 p-6 hover:shadow-xl transition-all group"
>
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
<div className="flex-1">
<div className="flex items-center space-x-3 mb-2">
<span className="px-3 py-1 bg-brand-turquoise/10 text-brand-turquoise text-sm font-medium rounded-full">
{release.category}
</span>
<span className="flex items-center space-x-1 text-gray-500 text-sm">
<Calendar className="w-4 h-4" />
<span>{release.date}</span>
</span>
</div>
<h3 className="text-xl font-bold text-brand-navy mb-2 group-hover:text-brand-turquoise transition-colors">
{release.title}
</h3>
<p className="text-gray-600">{release.excerpt}</p>
</div>
<div className="flex items-center space-x-3">
<a
href={release.pdfUrl}
className="flex items-center space-x-2 px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors"
>
<Download className="w-4 h-4" />
<span>PDF</span>
</a>
<a
href={`/press/${release.id}`}
className="flex items-center space-x-2 px-4 py-2 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-colors"
>
<span>Lire</span>
<ArrowRight className="w-4 h-4" />
</a>
</div>
</div>
</motion.div>
))}
</motion.div>
</div>
</section>
{/* Media Coverage */}
<section className="py-20 bg-gray-50">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
className="text-center mb-16"
>
<h2 className="text-4xl lg:text-5xl font-bold text-brand-navy mb-4">
Ils parlent de nous
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Retrouvez les articles de presse mentionnant Xpeditis
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{mediaCoverage.map((article, index) => (
<motion.a
key={index}
href={article.url}
target="_blank"
rel="noopener noreferrer"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
whileHover={{ y: -5 }}
className="bg-white p-6 rounded-2xl shadow-lg border border-gray-100 hover:shadow-xl transition-all group"
>
<div className="flex items-start space-x-4">
<div className="w-16 h-16 bg-gray-100 rounded-xl flex items-center justify-center flex-shrink-0">
<Newspaper className="w-8 h-8 text-gray-400" />
</div>
<div className="flex-1">
<div className="flex items-center justify-between mb-2">
<span className="font-bold text-brand-turquoise">{article.outlet}</span>
<ExternalLink className="w-4 h-4 text-gray-400 group-hover:text-brand-turquoise transition-colors" />
</div>
<h3 className="text-lg font-bold text-brand-navy mb-2 group-hover:text-brand-turquoise transition-colors">
{article.title}
</h3>
<span className="text-gray-500 text-sm">{article.date}</span>
</div>
</div>
</motion.a>
))}
</div>
</div>
</section>
{/* Press Kit Resources */}
<section ref={resourcesRef} id="resources" className="py-20">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isResourcesInView ? { 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">
Kit Presse
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Téléchargez tous les éléments dont vous avez besoin pour vos articles
</p>
</motion.div>
<motion.div
variants={containerVariants}
initial="hidden"
animate={isResourcesInView ? 'visible' : 'hidden'}
className="grid grid-cols-1 md:grid-cols-3 gap-8"
>
{pressKitItems.map((item, index) => {
const IconComponent = item.icon;
return (
<motion.div
key={index}
variants={itemVariants}
whileHover={{ y: -10 }}
className="bg-white p-8 rounded-2xl shadow-lg border border-gray-100 hover:shadow-xl transition-all"
>
<div className="w-16 h-16 bg-brand-turquoise/10 rounded-2xl flex items-center justify-center mb-6">
<IconComponent className="w-8 h-8 text-brand-turquoise" />
</div>
<h3 className="text-xl font-bold text-brand-navy mb-2">{item.title}</h3>
<p className="text-gray-600 mb-4">{item.description}</p>
<div className="flex items-center justify-between">
<span className="text-sm text-gray-500">{item.format}</span>
<a
href={item.downloadUrl}
className="flex items-center space-x-2 text-brand-turquoise font-medium hover:underline"
>
<Download className="w-4 h-4" />
<span>Télécharger</span>
</a>
</div>
</motion.div>
);
})}
</motion.div>
</div>
</section>
{/* Milestones */}
<section ref={milestonesRef} className="py-20 bg-gradient-to-br from-brand-navy to-brand-navy/95">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isMilestonesInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center mb-16"
>
<h2 className="text-4xl lg:text-5xl font-bold text-white mb-4">
Notre Parcours
</h2>
<p className="text-xl text-white/80 max-w-2xl mx-auto">
Les grandes étapes de l'histoire de Xpeditis
</p>
</motion.div>
<div className="flex flex-wrap justify-center gap-8">
{milestones.map((milestone, index) => {
const IconComponent = milestone.icon;
return (
<motion.div
key={index}
initial={{ opacity: 0, scale: 0.8 }}
animate={isMilestonesInView ? { opacity: 1, scale: 1 } : {}}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="text-center"
>
<div className="w-20 h-20 bg-brand-turquoise rounded-full flex items-center justify-center mx-auto mb-4">
<IconComponent className="w-10 h-10 text-white" />
</div>
<div className="text-2xl font-bold text-brand-turquoise mb-1">{milestone.year}</div>
<div className="text-white/80 max-w-[150px]">{milestone.event}</div>
</motion.div>
);
})}
</div>
</div>
</section>
{/* Press Contact */}
<section ref={contactRef} id="contact" className="py-20">
<div className="max-w-4xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isContactInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center mb-12"
>
<h2 className="text-4xl lg:text-5xl font-bold text-brand-navy mb-4">
Contact Presse
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Notre équipe communication est à votre disposition pour toute demande d'interview,
d'information ou de partenariat média.
</p>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={isContactInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="bg-white rounded-3xl shadow-xl border border-gray-100 p-8 lg:p-12"
>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<div>
<h3 className="text-2xl font-bold text-brand-navy mb-6">Relations Presse</h3>
<div className="space-y-4">
<div className="flex items-center space-x-4">
<div className="w-12 h-12 bg-brand-turquoise/10 rounded-xl flex items-center justify-center">
<Mail className="w-6 h-6 text-brand-turquoise" />
</div>
<div>
<div className="text-sm text-gray-500">Email</div>
<a
href="mailto:presse@xpeditis.com"
className="text-lg font-medium text-brand-navy hover:text-brand-turquoise transition-colors"
>
presse@xpeditis.com
</a>
</div>
</div>
<div className="flex items-center space-x-4">
<div className="w-12 h-12 bg-brand-turquoise/10 rounded-xl flex items-center justify-center">
<Phone className="w-6 h-6 text-brand-turquoise" />
</div>
<div>
<div className="text-sm text-gray-500">Téléphone</div>
<a
href="tel:+33123456790"
className="text-lg font-medium text-brand-navy hover:text-brand-turquoise transition-colors"
>
+33 1 23 45 67 90
</a>
</div>
</div>
</div>
</div>
<div>
<h3 className="text-2xl font-bold text-brand-navy mb-6">Responsable Communication</h3>
<div className="flex items-start space-x-4">
<div className="w-16 h-16 bg-brand-turquoise/10 rounded-full flex items-center justify-center flex-shrink-0">
<Users className="w-8 h-8 text-brand-turquoise" />
</div>
<div>
<div className="text-lg font-bold text-brand-navy">Camille Dumont</div>
<div className="text-brand-turquoise font-medium mb-2">Directrice Communication</div>
<p className="text-gray-600 text-sm">
Disponible pour les interviews, demandes d'information et partenariats médias.
</p>
</div>
</div>
</div>
</div>
<div className="mt-8 pt-8 border-t border-gray-100">
<div className="flex items-start space-x-4 bg-gray-50 p-6 rounded-xl">
<Quote className="w-8 h-8 text-brand-turquoise flex-shrink-0" />
<div>
<p className="text-gray-600 italic mb-4">
"Nous sommes toujours ravis d'échanger avec les journalistes sur notre mission de
révolutionner le fret maritime. N'hésitez pas à nous contacter pour toute demande."
</p>
<div className="text-sm">
<span className="font-bold text-brand-navy">Jean-Pierre Durand</span>
<span className="text-gray-500"> - CEO & Co-fondateur</span>
</div>
</div>
</div>
</div>
</motion.div>
</div>
</section>
<LandingFooter />
</div>
);
}

View File

@ -0,0 +1,229 @@
'use client';
import { useRef } from 'react';
import { motion, useInView } from 'framer-motion';
import { Shield, Eye, Lock, UserCheck, Database, Globe, Mail, Calendar } from 'lucide-react';
import { LandingHeader, LandingFooter } from '@/components/layout';
export default function PrivacyPage() {
const heroRef = useRef(null);
const contentRef = useRef(null);
const isHeroInView = useInView(heroRef, { once: true });
const isContentInView = useInView(contentRef, { once: true });
const sections = [
{
icon: Database,
title: '1. Données collectées',
content: `Nous collectons les données suivantes :
**Données d'identification** : nom, prénom, adresse email professionnelle, numéro de téléphone
**Données professionnelles** : nom de l'entreprise, fonction, numéro SIRET
**Données de connexion** : adresse IP, logs de connexion, données de navigation
**Données de transaction** : historique des réservations, devis, factures
**Données de communication** : échanges avec notre service client`,
},
{
icon: Eye,
title: '2. Utilisation des données',
content: `Vos données sont utilisées pour :
Fournir et améliorer nos services de réservation de fret maritime
Gérer votre compte et vos préférences
Traiter vos demandes de devis et réservations
Vous envoyer des communications commerciales (avec votre consentement)
Assurer la sécurité de notre plateforme
Respecter nos obligations légales et réglementaires`,
},
{
icon: Lock,
title: '3. Protection des données',
content: `Nous mettons en œuvre des mesures de sécurité robustes :
Chiffrement SSL/TLS pour toutes les communications
Chiffrement des données sensibles au repos (AES-256)
Authentification à deux facteurs disponible
Audits de sécurité réguliers
Formation continue de nos équipes
Hébergement sur des serveurs certifiés ISO 27001`,
},
{
icon: UserCheck,
title: '4. Vos droits',
content: `Conformément au RGPD, vous disposez des droits suivants :
**Droit d'accès** : obtenir une copie de vos données personnelles
**Droit de rectification** : corriger vos données inexactes
**Droit à l'effacement** : demander la suppression de vos données
**Droit à la portabilité** : recevoir vos données dans un format structuré
**Droit d'opposition** : vous opposer au traitement de vos données
**Droit de limitation** : limiter le traitement de vos données
Pour exercer ces droits, contactez-nous à : privacy@xpeditis.com`,
},
{
icon: Globe,
title: '5. Transferts internationaux',
content: `Vos données peuvent être transférées vers des pays hors UE dans le cadre de nos services de fret maritime international. Ces transferts sont encadrés par :
Des clauses contractuelles types approuvées par la Commission européenne
Des certifications adéquates (ex: Privacy Shield pour certains prestataires)
Le consentement explicite pour certains transferts spécifiques`,
},
{
icon: Calendar,
title: '6. Conservation des données',
content: `Nous conservons vos données selon les durées suivantes :
**Données de compte** : durée de la relation commerciale + 3 ans
**Données de transaction** : 10 ans (obligations comptables)
**Données de connexion** : 1 an
**Données marketing** : 3 ans après le dernier contact
À l'expiration de ces délais, vos données sont supprimées ou anonymisées.`,
},
];
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 },
},
};
return (
<div className="min-h-screen bg-white">
<LandingHeader />
{/* Hero Section */}
<section ref={heroRef} className="relative pt-32 pb-20 bg-gradient-to-br from-brand-navy to-brand-navy/95 overflow-hidden">
<div className="absolute inset-0 opacity-10">
<div className="absolute top-20 left-20 w-96 h-96 bg-brand-turquoise rounded-full blur-3xl" />
<div className="absolute bottom-20 right-20 w-96 h-96 bg-brand-green rounded-full blur-3xl" />
</div>
<div className="relative z-10 max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center"
>
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={isHeroInView ? { scale: 1, opacity: 1 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="inline-flex items-center space-x-2 bg-white/10 backdrop-blur-sm px-4 py-2 rounded-full mb-8 border border-white/20"
>
<Shield className="w-5 h-5 text-brand-turquoise" />
<span className="text-white/90 text-sm font-medium">Protection des données</span>
</motion.div>
<h1 className="text-4xl lg:text-6xl font-bold text-white mb-6 leading-tight">
Politique de
<br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-brand-turquoise to-brand-green">
Confidentialité
</span>
</h1>
<p className="text-xl text-white/80 mb-6 max-w-3xl mx-auto leading-relaxed">
Chez Xpeditis, la protection de vos données personnelles est une priorité absolue.
Cette politique explique comment nous collectons, utilisons et protégeons vos informations.
</p>
<p className="text-white/60 text-sm">
Dernière mise à jour : Janvier 2025
</p>
</motion.div>
</div>
{/* Wave */}
<div className="absolute bottom-0 left-0 right-0">
<svg className="w-full h-16" viewBox="0 0 1440 60" preserveAspectRatio="none">
<path
d="M0,30 C240,50 480,10 720,30 C960,50 1200,10 1440,30 L1440,60 L0,60 Z"
fill="white"
/>
</svg>
</div>
</section>
{/* Content Section */}
<section ref={contentRef} className="py-20">
<div className="max-w-4xl mx-auto px-6 lg:px-8">
<motion.div
variants={containerVariants}
initial="hidden"
animate={isContentInView ? 'visible' : 'hidden'}
className="space-y-12"
>
{sections.map((section, index) => {
const IconComponent = section.icon;
return (
<motion.div
key={index}
variants={itemVariants}
className="bg-white p-8 rounded-2xl shadow-lg border border-gray-100"
>
<div className="flex items-start space-x-4">
<div className="w-12 h-12 bg-brand-turquoise/10 rounded-xl flex items-center justify-center flex-shrink-0">
<IconComponent className="w-6 h-6 text-brand-turquoise" />
</div>
<div>
<h2 className="text-2xl font-bold text-brand-navy mb-4">{section.title}</h2>
<div className="text-gray-600 leading-relaxed whitespace-pre-line prose prose-sm max-w-none">
{section.content.split('**').map((part, i) =>
i % 2 === 1 ? <strong key={i}>{part}</strong> : part
)}
</div>
</div>
</div>
</motion.div>
);
})}
</motion.div>
{/* Contact Section */}
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8, delay: 0.6 }}
className="mt-16 bg-gradient-to-br from-brand-navy to-brand-navy/95 p-10 rounded-3xl text-center"
>
<Mail className="w-12 h-12 text-brand-turquoise mx-auto mb-4" />
<h3 className="text-2xl font-bold text-white mb-4">Des questions ?</h3>
<p className="text-white/80 mb-6">
Pour toute question concernant notre politique de confidentialité ou vos données personnelles,
contactez notre Délégué à la Protection des Données.
</p>
<a
href="mailto:privacy@xpeditis.com"
className="inline-flex items-center space-x-2 px-6 py-3 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-colors font-medium"
>
<Mail className="w-5 h-5" />
<span>privacy@xpeditis.com</span>
</a>
</motion.div>
</div>
</section>
<LandingFooter />
</div>
);
}

View File

@ -0,0 +1,335 @@
'use client';
import { useRef } from 'react';
import { motion, useInView } from 'framer-motion';
import {
Shield,
Lock,
Server,
Eye,
AlertTriangle,
CheckCircle,
Key,
FileCheck,
Mail,
} from 'lucide-react';
import { LandingHeader, LandingFooter } from '@/components/layout';
export default function SecurityPage() {
const heroRef = useRef(null);
const contentRef = useRef(null);
const isHeroInView = useInView(heroRef, { once: true });
const isContentInView = useInView(contentRef, { once: true });
const securityFeatures = [
{
icon: Lock,
title: 'Chiffrement de bout en bout',
description:
'Toutes les communications sont chiffrées avec TLS 1.3. Vos données sensibles sont chiffrées au repos avec AES-256.',
},
{
icon: Key,
title: 'Authentification sécurisée',
description:
'Authentification à deux facteurs (2FA) disponible. Mots de passe hashés avec Argon2id, le standard le plus robuste.',
},
{
icon: Server,
title: 'Infrastructure certifiée',
description:
'Hébergement sur AWS avec certifications ISO 27001, SOC 2 Type II et conformité RGPD.',
},
{
icon: Eye,
title: 'Surveillance 24/7',
description:
'Monitoring continu de notre infrastructure. Détection et réponse aux incidents en temps réel.',
},
{
icon: FileCheck,
title: 'Audits réguliers',
description:
'Tests de pénétration annuels par des experts indépendants. Programme de bug bounty actif.',
},
{
icon: AlertTriangle,
title: 'Plan de continuité',
description:
'Sauvegardes automatiques quotidiennes. Plan de reprise d\'activité testé régulièrement.',
},
];
const certifications = [
{ name: 'ISO 27001', description: 'Système de management de la sécurité de l\'information' },
{ name: 'SOC 2 Type II', description: 'Contrôles de sécurité, disponibilité et confidentialité' },
{ name: 'RGPD', description: 'Conformité au Règlement Général sur la Protection des Données' },
{ name: 'PCI DSS', description: 'Norme de sécurité des données de paiement' },
];
const practices = [
{
title: 'Développement sécurisé',
items: [
'Revue de code systématique',
'Analyse statique du code (SAST)',
'Tests de sécurité automatisés',
'Gestion des dépendances',
],
},
{
title: 'Protection des données',
items: [
'Minimisation des données collectées',
'Pseudonymisation des données',
'Contrôle d\'accès granulaire',
'Journalisation des accès',
],
},
{
title: 'Réponse aux incidents',
items: [
'Équipe de sécurité dédiée',
'Procédures de notification',
'Analyse post-incident',
'Amélioration continue',
],
},
];
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 },
},
};
return (
<div className="min-h-screen bg-white">
<LandingHeader />
{/* Hero Section */}
<section ref={heroRef} className="relative pt-32 pb-20 bg-gradient-to-br from-brand-navy to-brand-navy/95 overflow-hidden">
<div className="absolute inset-0 opacity-10">
<div className="absolute top-20 left-20 w-96 h-96 bg-brand-turquoise rounded-full blur-3xl" />
<div className="absolute bottom-20 right-20 w-96 h-96 bg-brand-green rounded-full blur-3xl" />
</div>
<div className="relative z-10 max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center"
>
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={isHeroInView ? { scale: 1, opacity: 1 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="inline-flex items-center space-x-2 bg-white/10 backdrop-blur-sm px-4 py-2 rounded-full mb-8 border border-white/20"
>
<Shield className="w-5 h-5 text-brand-turquoise" />
<span className="text-white/90 text-sm font-medium">Sécurité maximale</span>
</motion.div>
<h1 className="text-4xl lg:text-6xl font-bold text-white mb-6 leading-tight">
Votre sécurité,
<br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-brand-turquoise to-brand-green">
Notre priorité
</span>
</h1>
<p className="text-xl text-white/80 mb-6 max-w-3xl mx-auto leading-relaxed">
Chez Xpeditis, nous mettons en œuvre les meilleures pratiques de sécurité
pour protéger vos données et garantir la continuité de vos opérations.
</p>
</motion.div>
</div>
{/* Wave */}
<div className="absolute bottom-0 left-0 right-0">
<svg className="w-full h-16" viewBox="0 0 1440 60" preserveAspectRatio="none">
<path
d="M0,30 C240,50 480,10 720,30 C960,50 1200,10 1440,30 L1440,60 L0,60 Z"
fill="white"
/>
</svg>
</div>
</section>
{/* Security Features */}
<section ref={contentRef} className="py-20">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center mb-16"
>
<h2 className="text-3xl lg:text-4xl font-bold text-brand-navy mb-4">
Mesures de sécurité
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Une infrastructure robuste pour protéger vos données
</p>
</motion.div>
<motion.div
variants={containerVariants}
initial="hidden"
animate={isContentInView ? 'visible' : 'hidden'}
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"
>
{securityFeatures.map((feature, index) => {
const IconComponent = feature.icon;
return (
<motion.div
key={index}
variants={itemVariants}
whileHover={{ y: -5 }}
className="bg-white p-8 rounded-2xl shadow-lg border border-gray-100 hover:shadow-xl transition-all"
>
<div className="w-14 h-14 bg-brand-turquoise/10 rounded-xl flex items-center justify-center mb-4">
<IconComponent className="w-7 h-7 text-brand-turquoise" />
</div>
<h3 className="text-xl font-bold text-brand-navy mb-3">{feature.title}</h3>
<p className="text-gray-600">{feature.description}</p>
</motion.div>
);
})}
</motion.div>
</div>
</section>
{/* Certifications */}
<section className="py-20 bg-gray-50">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
className="text-center mb-16"
>
<h2 className="text-3xl lg:text-4xl font-bold text-brand-navy mb-4">
Certifications & Conformité
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Nos engagements validés par des organismes indépendants
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{certifications.map((cert, index) => (
<motion.div
key={index}
initial={{ opacity: 0, scale: 0.9 }}
whileInView={{ opacity: 1, scale: 1 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="bg-white p-6 rounded-2xl shadow-lg border border-gray-100 text-center"
>
<div className="w-16 h-16 bg-brand-green/10 rounded-full flex items-center justify-center mx-auto mb-4">
<CheckCircle className="w-8 h-8 text-brand-green" />
</div>
<h3 className="text-xl font-bold text-brand-navy mb-2">{cert.name}</h3>
<p className="text-gray-600 text-sm">{cert.description}</p>
</motion.div>
))}
</div>
</div>
</section>
{/* Security Practices */}
<section className="py-20">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
className="text-center mb-16"
>
<h2 className="text-3xl lg:text-4xl font-bold text-brand-navy mb-4">
Nos pratiques de sécurité
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Une approche proactive de la sécurité à chaque étape
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{practices.map((practice, index) => (
<motion.div
key={index}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: index * 0.1 }}
className="bg-gradient-to-br from-brand-navy to-brand-navy/95 p-8 rounded-2xl"
>
<h3 className="text-xl font-bold text-white mb-6">{practice.title}</h3>
<ul className="space-y-4">
{practice.items.map((item, i) => (
<li key={i} className="flex items-center space-x-3 text-white/80">
<CheckCircle className="w-5 h-5 text-brand-turquoise flex-shrink-0" />
<span>{item}</span>
</li>
))}
</ul>
</motion.div>
))}
</div>
</div>
</section>
{/* Report Vulnerability */}
<section className="py-20 bg-gray-50">
<div className="max-w-4xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
className="bg-gradient-to-br from-brand-navy to-brand-navy/95 p-10 rounded-3xl text-center"
>
<AlertTriangle className="w-12 h-12 text-brand-turquoise mx-auto mb-4" />
<h3 className="text-2xl font-bold text-white mb-4">
Signaler une vulnérabilité
</h3>
<p className="text-white/80 mb-6 max-w-2xl mx-auto">
Vous avez découvert une faille de sécurité ? Nous prenons très au sérieux
la sécurité de notre plateforme. Contactez notre équipe de sécurité pour
un signalement responsable.
</p>
<a
href="mailto:security@xpeditis.com"
className="inline-flex items-center space-x-2 px-6 py-3 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-colors font-medium"
>
<Mail className="w-5 h-5" />
<span>security@xpeditis.com</span>
</a>
</motion.div>
</div>
</section>
<LandingFooter />
</div>
);
}

View File

@ -0,0 +1,240 @@
'use client';
import { useRef } from 'react';
import { motion, useInView } from 'framer-motion';
import { FileText, Users, CreditCard, AlertTriangle, Scale, Gavel, Mail } from 'lucide-react';
import { LandingHeader, LandingFooter } from '@/components/layout';
export default function TermsPage() {
const heroRef = useRef(null);
const contentRef = useRef(null);
const isHeroInView = useInView(heroRef, { once: true });
const isContentInView = useInView(contentRef, { once: true });
const sections = [
{
icon: Users,
title: '1. Objet et acceptation',
content: `Les présentes Conditions Générales d'Utilisation (CGU) régissent l'utilisation de la plateforme Xpeditis, accessible à l'adresse www.xpeditis.com.
En accédant à notre plateforme et en utilisant nos services, vous acceptez sans réserve les présentes CGU. Si vous n'acceptez pas ces conditions, vous ne devez pas utiliser nos services.
Xpeditis se réserve le droit de modifier ces CGU à tout moment. Les utilisateurs seront informés de toute modification par email et/ou notification sur la plateforme.`,
},
{
icon: FileText,
title: '2. Description des services',
content: `Xpeditis propose une plateforme B2B de réservation de fret maritime permettant :
La recherche et comparaison de tarifs de transport maritime
La réservation de conteneurs auprès de compagnies maritimes partenaires
Le suivi en temps réel des expéditions
La gestion documentaire (Bill of Lading, certificats, etc.)
L'accès à un tableau de bord analytique
Xpeditis agit en qualité d'intermédiaire technologique et ne se substitue pas aux transporteurs maritimes dans l'exécution des prestations de transport.`,
},
{
icon: Users,
title: '3. Inscription et compte utilisateur',
content: `**Conditions d'inscription**
L'inscription est réservée aux professionnels du transport et de la logistique (transitaires, commissionnaires, etc.). L'utilisateur doit fournir des informations exactes et complètes.
**Responsabilité du compte**
L'utilisateur est responsable de la confidentialité de ses identifiants et de toutes les activités effectuées sous son compte. Il s'engage à notifier immédiatement Xpeditis en cas d'utilisation non autorisée.
**Suspension et résiliation**
Xpeditis peut suspendre ou résilier un compte en cas de violation des CGU, d'activité frauduleuse ou de non-paiement.`,
},
{
icon: CreditCard,
title: '4. Tarification et paiement',
content: `**Tarifs affichés**
Les tarifs affichés sur la plateforme sont indicatifs et peuvent varier selon la disponibilité et les conditions du marché. Le tarif définitif est confirmé lors de la validation de la réservation.
**Modalités de paiement**
Les paiements s'effectuent par virement bancaire ou carte bancaire. Les factures sont payables selon les conditions convenues (généralement 30 jours).
**Frais supplémentaires**
Des frais additionnels peuvent s'appliquer (surcharges carburant, frais portuaires, etc.). Ces frais sont clairement indiqués avant validation.`,
},
{
icon: AlertTriangle,
title: '5. Responsabilité',
content: `**Limitation de responsabilité**
Xpeditis agit en tant qu'intermédiaire technologique. La responsabilité du transport incombe aux compagnies maritimes selon leurs conditions générales et les conventions internationales applicables.
**Force majeure**
Xpeditis ne peut être tenue responsable des retards ou annulations dus à des cas de force majeure (intempéries, grèves, pandémies, etc.).
**Disponibilité de la plateforme**
Xpeditis s'efforce de maintenir la plateforme disponible 24h/24. Cependant, des interruptions peuvent survenir pour maintenance ou raisons techniques.`,
},
{
icon: Scale,
title: '6. Propriété intellectuelle',
content: `Tous les éléments de la plateforme Xpeditis (logo, design, textes, logiciels, bases de données) sont protégés par les droits de propriété intellectuelle.
L'utilisateur s'engage à :
Ne pas reproduire, modifier ou distribuer le contenu de la plateforme
Ne pas utiliser les données à des fins concurrentielles
Ne pas tenter de désassembler ou décompiler le logiciel
Respecter les marques et logos de Xpeditis et de ses partenaires`,
},
{
icon: Gavel,
title: '7. Droit applicable et litiges',
content: `**Droit applicable**
Les présentes CGU sont régies par le droit français.
**Résolution des litiges**
En cas de litige, les parties s'engagent à rechercher une solution amiable. À défaut, les tribunaux de Paris seront seuls compétents.
**Médiation**
Conformément aux dispositions du Code de la consommation, l'utilisateur peut recourir gratuitement au service de médiation auquel Xpeditis est adhérent.`,
},
];
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 },
},
};
return (
<div className="min-h-screen bg-white">
<LandingHeader />
{/* Hero Section */}
<section ref={heroRef} className="relative pt-32 pb-20 bg-gradient-to-br from-brand-navy to-brand-navy/95 overflow-hidden">
<div className="absolute inset-0 opacity-10">
<div className="absolute top-20 left-20 w-96 h-96 bg-brand-turquoise rounded-full blur-3xl" />
<div className="absolute bottom-20 right-20 w-96 h-96 bg-brand-green rounded-full blur-3xl" />
</div>
<div className="relative z-10 max-w-7xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }}
className="text-center"
>
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={isHeroInView ? { scale: 1, opacity: 1 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="inline-flex items-center space-x-2 bg-white/10 backdrop-blur-sm px-4 py-2 rounded-full mb-8 border border-white/20"
>
<FileText className="w-5 h-5 text-brand-turquoise" />
<span className="text-white/90 text-sm font-medium">Cadre juridique</span>
</motion.div>
<h1 className="text-4xl lg:text-6xl font-bold text-white mb-6 leading-tight">
Conditions Générales
<br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-brand-turquoise to-brand-green">
d'Utilisation
</span>
</h1>
<p className="text-xl text-white/80 mb-6 max-w-3xl mx-auto leading-relaxed">
Ces conditions régissent votre utilisation de la plateforme Xpeditis.
Veuillez les lire attentivement avant d'utiliser nos services.
</p>
<p className="text-white/60 text-sm">
Dernière mise à jour : Janvier 2025
</p>
</motion.div>
</div>
{/* Wave */}
<div className="absolute bottom-0 left-0 right-0">
<svg className="w-full h-16" viewBox="0 0 1440 60" preserveAspectRatio="none">
<path
d="M0,30 C240,50 480,10 720,30 C960,50 1200,10 1440,30 L1440,60 L0,60 Z"
fill="white"
/>
</svg>
</div>
</section>
{/* Content Section */}
<section ref={contentRef} className="py-20">
<div className="max-w-4xl mx-auto px-6 lg:px-8">
<motion.div
variants={containerVariants}
initial="hidden"
animate={isContentInView ? 'visible' : 'hidden'}
className="space-y-12"
>
{sections.map((section, index) => {
const IconComponent = section.icon;
return (
<motion.div
key={index}
variants={itemVariants}
className="bg-white p-8 rounded-2xl shadow-lg border border-gray-100"
>
<div className="flex items-start space-x-4">
<div className="w-12 h-12 bg-brand-turquoise/10 rounded-xl flex items-center justify-center flex-shrink-0">
<IconComponent className="w-6 h-6 text-brand-turquoise" />
</div>
<div>
<h2 className="text-2xl font-bold text-brand-navy mb-4">{section.title}</h2>
<div className="text-gray-600 leading-relaxed whitespace-pre-line prose prose-sm max-w-none">
{section.content.split('**').map((part, i) =>
i % 2 === 1 ? <strong key={i}>{part}</strong> : part
)}
</div>
</div>
</div>
</motion.div>
);
})}
</motion.div>
{/* Contact Section */}
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8, delay: 0.6 }}
className="mt-16 bg-gradient-to-br from-brand-navy to-brand-navy/95 p-10 rounded-3xl text-center"
>
<Mail className="w-12 h-12 text-brand-turquoise mx-auto mb-4" />
<h3 className="text-2xl font-bold text-white mb-4">Besoin de précisions ?</h3>
<p className="text-white/80 mb-6">
Pour toute question concernant nos conditions générales d'utilisation,
notre équipe juridique est à votre disposition.
</p>
<a
href="mailto:legal@xpeditis.com"
className="inline-flex items-center space-x-2 px-6 py-3 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-colors font-medium"
>
<Mail className="w-5 h-5" />
<span>legal@xpeditis.com</span>
</a>
</motion.div>
</div>
</section>
<LandingFooter />
</div>
);
}

View File

@ -0,0 +1,168 @@
'use client';
import Link from 'next/link';
import Image from 'next/image';
import { MapPin, Globe } from 'lucide-react';
export function LandingFooter() {
return (
<footer className="bg-brand-navy text-white py-16">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-12 mb-12">
{/* Company Info */}
<div className="lg:col-span-2">
<Image
src="/assets/logos/logo-white.png"
alt="Xpeditis"
width={160}
height={55}
className="h-auto mb-6"
/>
<p className="text-white/70 text-sm mb-6 leading-relaxed">
Xpeditis est la plateforme B2B leader pour le fret maritime en Europe. Nous
connectons les transitaires avec les plus grandes compagnies maritimes mondiales.
</p>
<div className="flex space-x-4">
<a
href="#"
className="w-10 h-10 bg-white/10 hover:bg-brand-turquoise rounded-full flex items-center justify-center transition-colors"
>
<span className="sr-only">LinkedIn</span>
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" />
</svg>
</a>
<a
href="#"
className="w-10 h-10 bg-white/10 hover:bg-brand-turquoise rounded-full flex items-center justify-center transition-colors"
>
<span className="sr-only">Twitter</span>
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z" />
</svg>
</a>
</div>
</div>
{/* Products */}
<div>
<h4 className="font-bold text-lg mb-4 text-white">Produits</h4>
<ul className="space-y-3 text-white/70 text-sm">
<li>
<Link href="/#features" className="hover:text-brand-turquoise transition-colors">
Fonctionnalités
</Link>
</li>
<li>
<Link href="/#tools" className="hover:text-brand-turquoise transition-colors">
Outils & Calculateurs
</Link>
</li>
<li>
<Link href="/#pricing" className="hover:text-brand-turquoise transition-colors">
Tarifs
</Link>
</li>
<li>
<Link href="/api" className="hover:text-brand-turquoise transition-colors">
API Documentation
</Link>
</li>
<li>
<Link
href="/integrations"
className="hover:text-brand-turquoise transition-colors"
>
Intégrations
</Link>
</li>
</ul>
</div>
{/* Company */}
<div>
<h4 className="font-bold text-lg mb-4 text-white">Entreprise</h4>
<ul className="space-y-3 text-white/70 text-sm">
<li>
<Link href="/about" className="hover:text-brand-turquoise transition-colors">
À propos
</Link>
</li>
<li>
<Link href="/contact" className="hover:text-brand-turquoise transition-colors">
Contact
</Link>
</li>
<li>
<Link href="/careers" className="hover:text-brand-turquoise transition-colors">
Carrières
</Link>
</li>
<li>
<Link href="/blog" className="hover:text-brand-turquoise transition-colors">
Blog
</Link>
</li>
<li>
<Link href="/press" className="hover:text-brand-turquoise transition-colors">
Presse
</Link>
</li>
</ul>
</div>
{/* Legal */}
<div>
<h4 className="font-bold text-lg mb-4 text-white">Légal</h4>
<ul className="space-y-3 text-white/70 text-sm">
<li>
<Link href="/privacy" className="hover:text-brand-turquoise transition-colors">
Politique de confidentialité
</Link>
</li>
<li>
<Link href="/terms" className="hover:text-brand-turquoise transition-colors">
Conditions générales
</Link>
</li>
<li>
<Link href="/cookies" className="hover:text-brand-turquoise transition-colors">
Politique de cookies
</Link>
</li>
<li>
<Link href="/security" className="hover:text-brand-turquoise transition-colors">
Sécurité
</Link>
</li>
<li>
<Link href="/compliance" className="hover:text-brand-turquoise transition-colors">
Conformité RGPD
</Link>
</li>
</ul>
</div>
</div>
{/* Bottom Footer */}
<div className="border-t border-white/10 pt-8">
<div className="flex flex-col md:flex-row items-center justify-between space-y-4 md:space-y-0">
<div className="text-white/50 text-sm">
© 2025 Xpeditis SAS. Tous droits réservés.
</div>
<div className="flex items-center space-x-6 text-sm text-white/50">
<span className="flex items-center space-x-2">
<MapPin className="w-4 h-4" />
<span>Paris, France</span>
</span>
<span className="flex items-center space-x-2">
<Globe className="w-4 h-4" />
<span>50+ Pays</span>
</span>
</div>
</div>
</div>
</div>
</footer>
);
}

View File

@ -0,0 +1,214 @@
'use client';
import { useEffect, useState } from 'react';
import Link from 'next/link';
import Image from 'next/image';
import { motion, AnimatePresence } from 'framer-motion';
import {
ChevronDown,
Briefcase,
Newspaper,
Mail,
Info,
BookOpen,
LayoutDashboard,
} from 'lucide-react';
import { useAuth } from '@/lib/context/auth-context';
interface LandingHeaderProps {
transparentOnTop?: boolean;
activePage?: 'about' | 'contact' | 'careers' | 'blog' | 'press';
}
export function LandingHeader({ transparentOnTop = false, activePage }: LandingHeaderProps) {
const [isScrolled, setIsScrolled] = useState(false);
const [isCompanyMenuOpen, setIsCompanyMenuOpen] = useState(false);
const { user, isAuthenticated, loading } = useAuth();
const companyMenuItems = [
{ href: '/about', label: 'À propos', icon: Info, description: 'Notre histoire et mission' },
{ href: '/contact', label: 'Contact', icon: Mail, description: 'Nous contacter' },
{ href: '/careers', label: 'Carrières', icon: Briefcase, description: 'Rejoignez-nous' },
{ href: '/blog', label: 'Blog', icon: BookOpen, description: 'Actualités et insights' },
{ href: '/press', label: 'Presse', icon: Newspaper, description: 'Espace presse' },
];
const getUserInitials = () => {
if (!user) return '';
const firstInitial = user.firstName?.charAt(0)?.toUpperCase() || '';
const lastInitial = user.lastName?.charAt(0)?.toUpperCase() || '';
return firstInitial + lastInitial || user.email?.charAt(0)?.toUpperCase() || '?';
};
const getFullName = () => {
if (!user) return '';
if (user.firstName && user.lastName) {
return `${user.firstName} ${user.lastName}`;
}
return user.email || '';
};
useEffect(() => {
if (!transparentOnTop) {
setIsScrolled(true);
return;
}
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, [transparentOnTop]);
const isActiveLink = (href: string) => {
if (!activePage) return false;
return href === `/${activePage}`;
};
return (
<motion.nav
initial={{ y: -100 }}
animate={{ y: 0 }}
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${
isScrolled ? 'bg-brand-navy/95 backdrop-blur-md shadow-lg' : 'bg-transparent'
}`}
>
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<div className="flex items-center justify-between h-20">
<Link href="/" className="flex items-center space-x-2">
<Image
src="/assets/logos/logo-white.png"
alt="Xpeditis"
width={70}
height={80}
priority
className="h-auto"
/>
</Link>
<div className="hidden md:flex items-center space-x-8">
<Link
href="/#features"
className="text-white hover:text-brand-turquoise transition-colors font-medium"
>
Fonctionnalités
</Link>
<Link
href="/#tools"
className="text-white hover:text-brand-turquoise transition-colors font-medium"
>
Outils
</Link>
<Link
href="/#pricing"
className="text-white hover:text-brand-turquoise transition-colors font-medium"
>
Tarifs
</Link>
{/* Menu Entreprise */}
<div
className="relative"
onMouseEnter={() => setIsCompanyMenuOpen(true)}
onMouseLeave={() => setIsCompanyMenuOpen(false)}
>
<button
className={`flex items-center space-x-1 transition-colors font-medium ${
activePage ? 'text-brand-turquoise' : 'text-white hover:text-brand-turquoise'
}`}
>
<span>Entreprise</span>
<ChevronDown
className={`w-4 h-4 transition-transform ${isCompanyMenuOpen ? 'rotate-180' : ''}`}
/>
</button>
<AnimatePresence>
{isCompanyMenuOpen && (
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
transition={{ duration: 0.2 }}
className="absolute top-full left-1/2 -translate-x-1/2 pt-4 z-50"
>
<div className="bg-white rounded-2xl shadow-2xl border border-gray-100 overflow-hidden min-w-[280px]">
<div className="p-2">
{companyMenuItems.map((item) => {
const IconComponent = item.icon;
const isActive = isActiveLink(item.href);
return (
<Link
key={item.href}
href={item.href}
className={`flex items-center space-x-3 px-4 py-3 rounded-xl transition-colors group ${
isActive ? 'bg-brand-turquoise/10' : 'hover:bg-gray-50'
}`}
>
<div className={`w-10 h-10 rounded-lg flex items-center justify-center transition-colors ${
isActive
? 'bg-brand-turquoise/20'
: 'bg-brand-turquoise/10 group-hover:bg-brand-turquoise/20'
}`}>
<IconComponent className="w-5 h-5 text-brand-turquoise" />
</div>
<div>
<div className={`font-medium transition-colors ${
isActive
? 'text-brand-turquoise'
: 'text-brand-navy group-hover:text-brand-turquoise'
}`}>
{item.label}
</div>
<div className="text-sm text-gray-500">
{item.description}
</div>
</div>
</Link>
);
})}
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
{/* Affichage conditionnel: connecté vs non connecté */}
{loading ? (
<div className="w-8 h-8 rounded-full bg-white/20 animate-pulse" />
) : isAuthenticated && user ? (
<Link
href="/dashboard"
className="flex items-center space-x-3 group"
>
<div className="w-10 h-10 rounded-full bg-brand-turquoise flex items-center justify-center text-white font-semibold text-sm border-2 border-white/30 group-hover:border-white transition-colors">
{getUserInitials()}
</div>
<span className="text-white font-medium group-hover:text-brand-turquoise transition-colors max-w-[150px] truncate">
{getFullName()}
</span>
<LayoutDashboard className="w-5 h-5 text-white/70 group-hover:text-brand-turquoise transition-colors" />
</Link>
) : (
<>
<Link
href="/login"
className="text-white hover:text-brand-turquoise transition-colors font-medium"
>
Connexion
</Link>
<Link
href="/register"
className="px-6 py-2.5 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-all hover:shadow-lg font-medium"
>
Commencer Gratuitement
</Link>
</>
)}
</div>
</div>
</div>
</motion.nav>
);
}

View File

@ -0,0 +1,2 @@
export { LandingHeader } from './LandingHeader';
export { LandingFooter } from './LandingFooter';

View File

@ -1,388 +0,0 @@
/**
* Privacy Policy Page
* GDPR Compliant
*/
import React from 'react';
import Head from 'next/head';
export default function PrivacyPage() {
return (
<>
<Head>
<title>Privacy Policy | Xpeditis</title>
<meta
name="description"
content="Privacy Policy for Xpeditis - GDPR compliant data protection"
/>
</Head>
<div className="min-h-screen bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
<div className="max-w-4xl mx-auto bg-white shadow-lg rounded-lg p-8">
<h1 className="text-4xl font-bold text-gray-900 mb-6">Privacy Policy</h1>
<p className="text-sm text-gray-500 mb-8">
Last Updated: October 14, 2025
<br />
GDPR Compliant
</p>
<div className="prose prose-lg max-w-none">
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">1. Introduction</h2>
<p className="text-gray-700 mb-4">
Xpeditis ("we," "our," or "us") is committed to protecting your privacy. This
Privacy Policy explains how we collect, use, disclose, and safeguard your
information when you use our maritime freight booking platform.
</p>
<p className="text-gray-700 mb-4">
This policy complies with the General Data Protection Regulation (GDPR) and other
applicable data protection laws.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">2. Data Controller</h2>
<div className="bg-gray-50 p-4 rounded-lg mb-4">
<p className="text-gray-700">
<strong>Company Name:</strong> Xpeditis
<br />
<strong>Email:</strong> privacy@xpeditis.com
<br />
<strong>Address:</strong> [Company Address]
<br />
<strong>DPO Email:</strong> dpo@xpeditis.com
</p>
</div>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
3. Information We Collect
</h2>
<h3 className="text-xl font-semibold text-gray-800 mb-2">3.1 Personal Information</h3>
<p className="text-gray-700 mb-4">We collect the following personal information:</p>
<ul className="list-disc pl-6 text-gray-700 mb-4">
<li>
<strong>Account Information:</strong> Name, email address, phone number, company
name, job title
</li>
<li>
<strong>Authentication Data:</strong> Password (hashed), OAuth tokens, 2FA
credentials
</li>
<li>
<strong>Booking Information:</strong> Shipper/consignee details, cargo
descriptions, container specifications
</li>
<li>
<strong>Payment Information:</strong> Billing address (payment card data is
processed by third-party processors)
</li>
<li>
<strong>Communication Data:</strong> Support tickets, emails, chat messages
</li>
</ul>
<h3 className="text-xl font-semibold text-gray-800 mb-2">
3.2 Technical Information
</h3>
<ul className="list-disc pl-6 text-gray-700 mb-4">
<li>
<strong>Log Data:</strong> IP address, browser type, device information, operating
system
</li>
<li>
<strong>Usage Data:</strong> Pages visited, features used, time spent, click
patterns
</li>
<li>
<strong>Cookies:</strong> Session cookies, preference cookies, analytics cookies
</li>
<li>
<strong>Performance Data:</strong> Error logs, crash reports, API response times
</li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
4. Legal Basis for Processing (GDPR)
</h2>
<p className="text-gray-700 mb-4">
We process your data based on the following legal grounds:
</p>
<ul className="list-disc pl-6 text-gray-700 mb-4">
<li>
<strong>Contract Performance:</strong> To provide booking and shipment services
</li>
<li>
<strong>Legitimate Interests:</strong> Platform security, fraud prevention,
service improvement
</li>
<li>
<strong>Legal Obligation:</strong> Tax compliance, anti-money laundering, data
retention laws
</li>
<li>
<strong>Consent:</strong> Marketing communications, optional analytics, cookies
</li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
5. How We Use Your Information
</h2>
<ul className="list-disc pl-6 text-gray-700 mb-4">
<li>Provide, operate, and maintain the Platform</li>
<li>Process bookings and manage shipments</li>
<li>Communicate with you about your account and services</li>
<li>Send transactional emails (booking confirmations, notifications)</li>
<li>Provide customer support</li>
<li>Detect and prevent fraud, abuse, and security incidents</li>
<li>Analyze usage patterns and improve the Platform</li>
<li>Comply with legal obligations</li>
<li>Send marketing communications (with your consent)</li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
6. Data Sharing and Disclosure
</h2>
<p className="text-gray-700 mb-4">We may share your information with:</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">6.1 Service Providers</h3>
<ul className="list-disc pl-6 text-gray-700 mb-4">
<li>
<strong>Shipping Carriers:</strong> Maersk, MSC, CMA CGM, etc. (for booking
execution)
</li>
<li>
<strong>Cloud Infrastructure:</strong> AWS/GCP (data hosting)
</li>
<li>
<strong>Email Services:</strong> SendGrid/AWS SES (transactional emails)
</li>
<li>
<strong>Analytics:</strong> Sentry (error tracking), Google Analytics (usage
analytics)
</li>
<li>
<strong>Payment Processors:</strong> Stripe (payment processing)
</li>
</ul>
<h3 className="text-xl font-semibold text-gray-800 mb-2">6.2 Legal Requirements</h3>
<p className="text-gray-700 mb-4">
We may disclose your information if required by law, court order, or government
request, or to protect our rights, property, or safety.
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">6.3 Business Transfers</h3>
<p className="text-gray-700 mb-4">
In the event of a merger, acquisition, or sale of assets, your information may be
transferred to the acquiring entity.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
7. International Data Transfers
</h2>
<p className="text-gray-700 mb-4">
Your data may be transferred to and processed in countries outside the European
Economic Area (EEA). We ensure adequate protection through:
</p>
<ul className="list-disc pl-6 text-gray-700 mb-4">
<li>Standard Contractual Clauses (SCCs)</li>
<li>EU-US Data Privacy Framework</li>
<li>Adequacy decisions by the European Commission</li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">8. Data Retention</h2>
<p className="text-gray-700 mb-4">We retain your data for the following periods:</p>
<ul className="list-disc pl-6 text-gray-700 mb-4">
<li>
<strong>Account Data:</strong> Until account deletion + 30 days
</li>
<li>
<strong>Booking Data:</strong> 7 years (for legal and tax compliance)
</li>
<li>
<strong>Audit Logs:</strong> 2 years
</li>
<li>
<strong>Analytics Data:</strong> 26 months
</li>
<li>
<strong>Marketing Consent:</strong> Until withdrawal + 30 days
</li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
9. Your Data Protection Rights (GDPR)
</h2>
<p className="text-gray-700 mb-4">You have the following rights:</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">9.1 Right to Access</h3>
<p className="text-gray-700 mb-4">
You can request a copy of all personal data we hold about you.
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">
9.2 Right to Rectification
</h3>
<p className="text-gray-700 mb-4">You can correct inaccurate or incomplete data.</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">
9.3 Right to Erasure ("Right to be Forgotten")
</h3>
<p className="text-gray-700 mb-4">
You can request deletion of your data, subject to legal retention requirements.
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">
9.4 Right to Data Portability
</h3>
<p className="text-gray-700 mb-4">
You can receive your data in a structured, machine-readable format (JSON/CSV).
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">9.5 Right to Object</h3>
<p className="text-gray-700 mb-4">
You can object to processing based on legitimate interests or for marketing
purposes.
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">
9.6 Right to Restrict Processing
</h3>
<p className="text-gray-700 mb-4">
You can request limitation of processing in certain circumstances.
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">
9.7 Right to Withdraw Consent
</h3>
<p className="text-gray-700 mb-4">
You can withdraw consent for marketing or optional data processing at any time.
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">
9.8 Right to Lodge a Complaint
</h3>
<p className="text-gray-700 mb-4">
You can file a complaint with your local data protection authority.
</p>
<div className="bg-blue-50 border-l-4 border-blue-500 p-4 mt-4">
<p className="text-blue-900">
<strong>To exercise your rights:</strong> Email privacy@xpeditis.com or use the
"Data Export" / "Delete Account" features in your account settings.
</p>
</div>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">10. Security Measures</h2>
<p className="text-gray-700 mb-4">
We implement industry-standard security measures:
</p>
<ul className="list-disc pl-6 text-gray-700 mb-4">
<li>
<strong>Encryption:</strong> TLS 1.3 for data in transit, AES-256 for data at rest
</li>
<li>
<strong>Authentication:</strong> Password hashing (bcrypt), JWT tokens, 2FA
support
</li>
<li>
<strong>Access Control:</strong> Role-based access control (RBAC), principle of
least privilege
</li>
<li>
<strong>Monitoring:</strong> Security logging, intrusion detection, regular audits
</li>
<li>
<strong>Compliance:</strong> OWASP Top 10 protection, regular penetration testing
</li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
11. Cookies and Tracking
</h2>
<p className="text-gray-700 mb-4">We use the following types of cookies:</p>
<ul className="list-disc pl-6 text-gray-700 mb-4">
<li>
<strong>Essential Cookies:</strong> Required for authentication and security
(cannot be disabled)
</li>
<li>
<strong>Functional Cookies:</strong> Remember your preferences and settings
</li>
<li>
<strong>Analytics Cookies:</strong> Help us understand how you use the Platform
(optional)
</li>
<li>
<strong>Marketing Cookies:</strong> Used for targeted advertising (optional,
requires consent)
</li>
</ul>
<p className="text-gray-700 mb-4">
You can manage cookie preferences in your browser settings or through our cookie
consent banner.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">12. Children's Privacy</h2>
<p className="text-gray-700 mb-4">
The Platform is not intended for users under 18 years of age. We do not knowingly
collect personal information from children.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
13. Changes to This Policy
</h2>
<p className="text-gray-700 mb-4">
We may update this Privacy Policy from time to time. We will notify you of
significant changes via email or platform notification. Continued use after changes
constitutes acceptance.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">14. Contact Us</h2>
<p className="text-gray-700 mb-4">
For privacy-related questions or to exercise your data protection rights:
</p>
<div className="bg-gray-50 p-4 rounded-lg">
<p className="text-gray-700">
<strong>Email:</strong> privacy@xpeditis.com
<br />
<strong>DPO Email:</strong> dpo@xpeditis.com
<br />
<strong>Address:</strong> [Company Address]
<br />
<strong>Phone:</strong> [Company Phone]
</p>
</div>
</section>
</div>
</div>
</div>
</>
);
}

View File

@ -1,233 +0,0 @@
/**
* Terms & Conditions Page
*/
import React from 'react';
import Head from 'next/head';
export default function TermsPage() {
return (
<>
<Head>
<title>Terms & Conditions | Xpeditis</title>
<meta
name="description"
content="Terms and Conditions for Xpeditis maritime freight booking platform"
/>
</Head>
<div className="min-h-screen bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
<div className="max-w-4xl mx-auto bg-white shadow-lg rounded-lg p-8">
<h1 className="text-4xl font-bold text-gray-900 mb-6">Terms & Conditions</h1>
<p className="text-sm text-gray-500 mb-8">Last Updated: October 14, 2025</p>
<div className="prose prose-lg max-w-none">
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">1. Acceptance of Terms</h2>
<p className="text-gray-700 mb-4">
By accessing and using Xpeditis ("the Platform"), you accept and agree to be bound
by the terms and provision of this agreement. If you do not agree to abide by the
above, please do not use this service.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
2. Description of Service
</h2>
<p className="text-gray-700 mb-4">
Xpeditis is a B2B SaaS platform that provides maritime freight booking and
management services, including:
</p>
<ul className="list-disc pl-6 text-gray-700 mb-4">
<li>Real-time shipping rate search and comparison</li>
<li>Online container booking</li>
<li>Shipment tracking and management</li>
<li>Document management</li>
<li>Integration with carrier APIs</li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">3. User Accounts</h2>
<h3 className="text-xl font-semibold text-gray-800 mb-2">3.1 Registration</h3>
<p className="text-gray-700 mb-4">
To use the Platform, you must register for an account and provide accurate, current,
and complete information. You are responsible for maintaining the confidentiality of
your account credentials.
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">3.2 Account Security</h3>
<p className="text-gray-700 mb-4">
You are responsible for all activities that occur under your account. You must
immediately notify us of any unauthorized use of your account.
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">3.3 Account Termination</h3>
<p className="text-gray-700 mb-4">
We reserve the right to suspend or terminate your account if you violate these Terms
or engage in fraudulent, abusive, or illegal activity.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">4. Booking and Payments</h2>
<h3 className="text-xl font-semibold text-gray-800 mb-2">4.1 Booking Process</h3>
<p className="text-gray-700 mb-4">
All bookings made through the Platform are subject to availability and confirmation
by the carrier. Xpeditis acts as an intermediary and does not guarantee booking
acceptance.
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">4.2 Pricing</h3>
<p className="text-gray-700 mb-4">
Rates displayed on the Platform are provided by carriers and may change. Final
pricing is confirmed upon booking acceptance. All prices are subject to applicable
surcharges, taxes, and fees.
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-2">4.3 Payment Terms</h3>
<p className="text-gray-700 mb-4">
Payment terms are established between you and the carrier. Xpeditis may facilitate
payment processing but is not responsible for payment disputes.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">5. User Obligations</h2>
<p className="text-gray-700 mb-4">You agree to:</p>
<ul className="list-disc pl-6 text-gray-700 mb-4">
<li>Provide accurate and complete booking information</li>
<li>Comply with all applicable laws and regulations</li>
<li>Not use the Platform for illegal or unauthorized purposes</li>
<li>Not interfere with or disrupt the Platform's operation</li>
<li>Not attempt to gain unauthorized access to any part of the Platform</li>
<li>Not transmit viruses, malware, or malicious code</li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
6. Intellectual Property
</h2>
<p className="text-gray-700 mb-4">
All content, features, and functionality of the Platform, including but not limited
to text, graphics, logos, icons, images, audio clips, and software, are the
exclusive property of Xpeditis and protected by copyright, trademark, and other
intellectual property laws.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
7. Limitation of Liability
</h2>
<p className="text-gray-700 mb-4">
TO THE MAXIMUM EXTENT PERMITTED BY LAW, XPEDITIS SHALL NOT BE LIABLE FOR ANY
INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES, INCLUDING BUT NOT
LIMITED TO LOSS OF PROFITS, DATA, USE, OR GOODWILL, ARISING OUT OF OR IN CONNECTION
WITH YOUR USE OF THE PLATFORM.
</p>
<p className="text-gray-700 mb-4">
Xpeditis acts as an intermediary between freight forwarders and carriers. We are not
responsible for:
</p>
<ul className="list-disc pl-6 text-gray-700 mb-4">
<li>Carrier performance, delays, or cancellations</li>
<li>Cargo damage, loss, or theft</li>
<li>Customs issues or regulatory compliance</li>
<li>Force majeure events</li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">8. Indemnification</h2>
<p className="text-gray-700 mb-4">
You agree to indemnify, defend, and hold harmless Xpeditis and its officers,
directors, employees, and agents from any claims, losses, damages, liabilities, and
expenses arising out of your use of the Platform or violation of these Terms.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
9. Data Protection and Privacy
</h2>
<p className="text-gray-700 mb-4">
Your use of the Platform is also governed by our Privacy Policy. By using the
Platform, you consent to the collection, use, and disclosure of your information as
described in the Privacy Policy.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
10. Third-Party Services
</h2>
<p className="text-gray-700 mb-4">
The Platform may contain links to third-party websites or services. Xpeditis is not
responsible for the content, privacy policies, or practices of third-party sites.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
11. Service Availability
</h2>
<p className="text-gray-700 mb-4">
We strive to provide continuous service availability but do not guarantee that the
Platform will be uninterrupted, secure, or error-free. We reserve the right to
suspend or discontinue any part of the Platform at any time.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
12. Modifications to Terms
</h2>
<p className="text-gray-700 mb-4">
We reserve the right to modify these Terms at any time. Changes will be effective
immediately upon posting. Your continued use of the Platform after changes
constitutes acceptance of the modified Terms.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">13. Governing Law</h2>
<p className="text-gray-700 mb-4">
These Terms shall be governed by and construed in accordance with the laws of
[Jurisdiction], without regard to its conflict of law provisions.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">14. Dispute Resolution</h2>
<p className="text-gray-700 mb-4">
Any disputes arising out of or relating to these Terms or the Platform shall be
resolved through binding arbitration in accordance with the rules of [Arbitration
Body].
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">15. Contact Information</h2>
<p className="text-gray-700 mb-4">
If you have any questions about these Terms, please contact us at:
</p>
<div className="bg-gray-50 p-4 rounded-lg">
<p className="text-gray-700">
<strong>Email:</strong> legal@xpeditis.com
<br />
<strong>Address:</strong> [Company Address]
<br />
<strong>Phone:</strong> [Company Phone]
</p>
</div>
</section>
</div>
</div>
</div>
</>
);
}