Some checks failed
CI/CD Pipeline / Backend - Build, Test & Push (push) Failing after 10m59s
CI/CD Pipeline / Frontend - Build, Test & Push (push) Successful in 37m59s
CI/CD Pipeline / Integration Tests (push) Has been skipped
CI/CD Pipeline / Deployment Summary (push) Has been skipped
CI/CD Pipeline / Deploy to Portainer (push) Has been skipped
CI/CD Pipeline / Discord Notification (Success) (push) Has been skipped
CI/CD Pipeline / Discord Notification (Failure) (push) Has been skipped
222 lines
9.4 KiB
TypeScript
222 lines
9.4 KiB
TypeScript
'use client';
|
|
|
|
import { useRef } from 'react';
|
|
import Link from 'next/link';
|
|
import { motion, useInView } from 'framer-motion';
|
|
import { Ship, Home, ArrowRight, LayoutDashboard, Anchor } from 'lucide-react';
|
|
import { LandingHeader, LandingFooter } from '@/components/layout';
|
|
|
|
export default function NotFound() {
|
|
const heroRef = useRef(null);
|
|
const isHeroInView = useInView(heroRef, { once: true });
|
|
|
|
return (
|
|
<div className="min-h-screen bg-white flex flex-col">
|
|
<LandingHeader transparentOnTop={true} />
|
|
|
|
{/* Hero Section */}
|
|
<section
|
|
ref={heroRef}
|
|
className="relative flex-1 flex items-center justify-center overflow-hidden"
|
|
>
|
|
{/* Background */}
|
|
<div className="absolute inset-0 bg-gradient-to-br from-brand-navy via-brand-navy/95 to-brand-navy/90">
|
|
<div className="absolute inset-0 opacity-10">
|
|
<div className="absolute top-10 left-10 w-72 h-72 lg:w-96 lg:h-96 bg-brand-turquoise rounded-full blur-3xl" />
|
|
<div className="absolute bottom-32 right-10 w-72 h-72 lg:w-96 lg:h-96 bg-brand-green rounded-full blur-3xl" />
|
|
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-64 h-64 bg-brand-turquoise/50 rounded-full blur-3xl" />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div className="relative z-10 max-w-4xl mx-auto px-6 text-center pt-32 pb-40">
|
|
{/* Badge */}
|
|
<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-10 border border-white/20"
|
|
>
|
|
<Anchor className="w-5 h-5 text-brand-turquoise" />
|
|
<span className="text-white/90 text-sm font-medium font-heading">
|
|
Erreur 404
|
|
</span>
|
|
</motion.div>
|
|
|
|
{/* Animated Ship + Waves illustration */}
|
|
<motion.div
|
|
initial={{ opacity: 0, scale: 0.8 }}
|
|
animate={isHeroInView ? { opacity: 1, scale: 1 } : {}}
|
|
transition={{ duration: 0.8, delay: 0.3 }}
|
|
className="relative mb-8 flex justify-center"
|
|
>
|
|
<div className="relative w-64 h-40 lg:w-80 lg:h-48">
|
|
{/* Ship */}
|
|
<svg
|
|
viewBox="0 0 200 120"
|
|
className="absolute inset-0 w-full h-full animate-float"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
{/* Hull */}
|
|
<path
|
|
d="M40 75 L55 95 L145 95 L160 75 Z"
|
|
fill="#34CCCD"
|
|
opacity="0.9"
|
|
/>
|
|
{/* Deck */}
|
|
<rect x="60" y="58" width="80" height="17" rx="2" fill="white" opacity="0.9" />
|
|
{/* Bridge */}
|
|
<rect x="85" y="35" width="35" height="23" rx="2" fill="white" opacity="0.85" />
|
|
{/* Window */}
|
|
<rect x="92" y="40" width="8" height="6" rx="1" fill="#34CCCD" opacity="0.7" />
|
|
<rect x="105" y="40" width="8" height="6" rx="1" fill="#34CCCD" opacity="0.7" />
|
|
{/* Smokestack */}
|
|
<rect x="95" y="22" width="12" height="13" rx="1" fill="#10183A" opacity="0.8" />
|
|
<rect x="95" y="22" width="12" height="4" rx="1" fill="#34CCCD" opacity="0.6" />
|
|
{/* Mast */}
|
|
<line x1="102" y1="10" x2="102" y2="22" stroke="white" strokeWidth="1.5" opacity="0.7" />
|
|
{/* Flag */}
|
|
<path d="M102 10 L115 15 L102 20" fill="#34CCCD" opacity="0.8" />
|
|
{/* Containers on deck */}
|
|
<rect x="65" y="60" width="12" height="10" rx="1" fill="#067224" opacity="0.7" />
|
|
<rect x="79" y="60" width="12" height="10" rx="1" fill="#34CCCD" opacity="0.5" />
|
|
<rect x="130" y="60" width="12" height="10" rx="1" fill="#067224" opacity="0.5" />
|
|
<rect x="144" y="60" width="10" height="10" rx="1" fill="white" opacity="0.3" />
|
|
</svg>
|
|
|
|
{/* Waves layer 1 */}
|
|
<svg
|
|
viewBox="0 0 400 30"
|
|
className="absolute bottom-0 left-1/2 -translate-x-1/2 w-[150%] animate-wave"
|
|
preserveAspectRatio="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<path
|
|
d="M0,15 C50,5 100,25 150,15 C200,5 250,25 300,15 C350,5 400,25 400,15 L400,30 L0,30 Z"
|
|
fill="#34CCCD"
|
|
opacity="0.3"
|
|
/>
|
|
</svg>
|
|
|
|
{/* Waves layer 2 */}
|
|
<svg
|
|
viewBox="0 0 400 30"
|
|
className="absolute -bottom-1 left-1/2 -translate-x-1/2 w-[160%] animate-wave-slow"
|
|
preserveAspectRatio="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<path
|
|
d="M0,18 C60,8 120,28 180,18 C240,8 300,28 360,18 L400,18 L400,30 L0,30 Z"
|
|
fill="#34CCCD"
|
|
opacity="0.15"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* 404 */}
|
|
<motion.h1
|
|
initial={{ opacity: 0, y: 30 }}
|
|
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
|
|
transition={{ duration: 0.8, delay: 0.4 }}
|
|
className="text-8xl lg:text-[12rem] font-bold text-white mb-2 leading-none font-heading tracking-tight"
|
|
>
|
|
404
|
|
</motion.h1>
|
|
|
|
{/* Subtitle */}
|
|
<motion.h2
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
|
|
transition={{ duration: 0.8, delay: 0.5 }}
|
|
className="text-3xl lg:text-5xl font-bold mb-6 font-heading"
|
|
>
|
|
<span className="text-transparent bg-clip-text bg-gradient-to-r from-brand-turquoise to-brand-green">
|
|
Page introuvable
|
|
</span>
|
|
</motion.h2>
|
|
|
|
{/* Description */}
|
|
<motion.p
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
|
|
transition={{ duration: 0.8, delay: 0.6 }}
|
|
className="text-lg lg:text-xl text-white/70 mb-12 max-w-2xl mx-auto leading-relaxed font-body"
|
|
>
|
|
Ce navire a pris le large... La page que vous cherchez
|
|
n'existe pas ou a été déplacée.
|
|
</motion.p>
|
|
|
|
{/* CTA Buttons */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={isHeroInView ? { opacity: 1, y: 0 } : {}}
|
|
transition={{ duration: 0.8, delay: 0.7 }}
|
|
className="flex flex-col sm:flex-row items-center justify-center space-y-4 sm:space-y-0 sm:space-x-6"
|
|
>
|
|
<Link
|
|
href="/"
|
|
className="group px-8 py-4 bg-brand-turquoise text-white rounded-lg hover:bg-brand-turquoise/90 transition-all hover:shadow-2xl hover:scale-105 font-semibold text-lg w-full sm:w-auto flex items-center justify-center space-x-2 font-heading"
|
|
>
|
|
<Home className="w-5 h-5" />
|
|
<span>Retour à l'accueil</span>
|
|
<ArrowRight className="w-5 h-5 group-hover:translate-x-1 transition-transform" />
|
|
</Link>
|
|
|
|
<Link
|
|
href="/dashboard"
|
|
className="group px-8 py-4 bg-white/10 backdrop-blur-sm text-white border border-white/20 rounded-lg hover:bg-white/20 transition-all hover:shadow-xl font-semibold text-lg w-full sm:w-auto flex items-center justify-center space-x-2 font-heading"
|
|
>
|
|
<LayoutDashboard className="w-5 h-5" />
|
|
<span>Tableau de bord</span>
|
|
</Link>
|
|
</motion.div>
|
|
</div>
|
|
|
|
{/* Bottom wave */}
|
|
<div className="absolute bottom-0 left-0 right-0">
|
|
<svg
|
|
className="w-full h-16 lg:h-24"
|
|
viewBox="0 0 1440 120"
|
|
preserveAspectRatio="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<path
|
|
d="M0,60 C240,90 480,30 720,60 C960,90 1200,30 1440,60 L1440,120 L0,120 Z"
|
|
fill="white"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
</section>
|
|
|
|
<LandingFooter />
|
|
|
|
<style jsx global>{`
|
|
@keyframes float {
|
|
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
|
25% { transform: translateY(-6px) rotate(1deg); }
|
|
75% { transform: translateY(4px) rotate(-1deg); }
|
|
}
|
|
@keyframes wave {
|
|
0% { transform: translateX(-50%) translateX(0); }
|
|
100% { transform: translateX(-50%) translateX(-50px); }
|
|
}
|
|
@keyframes wave-slow {
|
|
0% { transform: translateX(-50%) translateX(0); }
|
|
100% { transform: translateX(-50%) translateX(50px); }
|
|
}
|
|
.animate-float {
|
|
animation: float 4s ease-in-out infinite;
|
|
}
|
|
.animate-wave {
|
|
animation: wave 3s ease-in-out infinite alternate;
|
|
}
|
|
.animate-wave-slow {
|
|
animation: wave-slow 4s ease-in-out infinite alternate;
|
|
}
|
|
`}</style>
|
|
</div>
|
|
);
|
|
}
|