150 lines
7.1 KiB
TypeScript
150 lines
7.1 KiB
TypeScript
import React, { useEffect } from 'react';
|
||
import Image from 'next/image';
|
||
import { URLS } from '@/lib/config/constants';
|
||
import { FeatureBadge, FeatureItem, SectionTitle } from './PopupComponents';
|
||
import { cn, commonClasses } from '@/lib/utils';
|
||
import type { Service } from '@/types/service';
|
||
import type { Translation } from '@/types/i18n';
|
||
import { ClipboardList, Zap, Check, Lock, Rocket } from 'lucide-react';
|
||
|
||
interface PopupProps {
|
||
service: Service;
|
||
onClose: () => void;
|
||
translations: Translation['common'];
|
||
}
|
||
|
||
export const Popup: React.FC<PopupProps> = ({ service, onClose, translations }) => {
|
||
// Empêcher le scroll du body quand la popup est ouverte
|
||
useEffect(() => {
|
||
const originalStyle = document.body.style.overflow;
|
||
document.body.style.overflow = 'hidden';
|
||
|
||
return () => {
|
||
document.body.style.overflow = originalStyle || 'unset';
|
||
};
|
||
}, []);
|
||
|
||
return (
|
||
<div className="fixed inset-0 bg-black/60 flex justify-center items-center z-50 p-4 backdrop-blur-md animate-fadeIn">
|
||
<div className="bg-white text-gray-800 rounded-3xl max-w-4xl w-full max-h-[90vh] shadow-2xl relative animate-slideUp border border-gray-200 overflow-hidden">
|
||
|
||
{/* Bouton de fermeture fixe au-dessus du contenu */}
|
||
<div className="absolute top-4 right-4 z-50">
|
||
<button
|
||
onClick={onClose}
|
||
className={cn(
|
||
'bg-white/90 hover:bg-white border border-gray-300',
|
||
'text-xl cursor-pointer text-gray-700',
|
||
'flex items-center justify-center w-10 h-10 sm:w-12 sm:h-12 rounded-full',
|
||
commonClasses.transition,
|
||
commonClasses.hoverScale,
|
||
'shadow-lg backdrop-blur-sm'
|
||
)}
|
||
aria-label={translations.close}
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
|
||
{/* Contenu avec scroll vertical uniquement */}
|
||
<div className="overflow-y-auto overflow-x-hidden max-h-[90vh] popup-content">
|
||
{/* Header */}
|
||
<div className="relative bg-gradient-to-r from-blue-600 to-blue-500 p-6 sm:p-8 text-white pr-16 sm:pr-20">
|
||
<div className="flex flex-col lg:flex-row items-center lg:items-start mb-4">
|
||
<div className="w-16 h-16 sm:w-20 sm:h-20 lg:w-24 lg:h-24 bg-white/20 rounded-3xl flex items-center justify-center mb-4 lg:mb-0 lg:mr-8 backdrop-blur-sm">
|
||
{service.iconType === 'image' ? (
|
||
<Image
|
||
src={service.image as string}
|
||
alt={service.name}
|
||
width={48}
|
||
height={48}
|
||
className="w-12 h-12 sm:w-14 sm:h-14 lg:w-16 lg:h-16 object-contain"
|
||
/>
|
||
) : service.lucideIcon ? (
|
||
<service.lucideIcon className="w-12 h-12 sm:w-14 sm:h-14 lg:w-16 lg:h-16 text-white" strokeWidth={1.5} />
|
||
) : (
|
||
<span className="text-3xl sm:text-4xl lg:text-5xl">{service.icon}</span>
|
||
)}
|
||
</div>
|
||
<div className="text-center lg:text-left flex-1">
|
||
<h2 className="font-heading text-2xl sm:text-3xl lg:text-4xl mt-0 mb-3 lg:mb-4 leading-tight font-bold text-white">
|
||
{service.name}
|
||
</h2>
|
||
<div className="text-white/90 text-base sm:text-lg lg:text-xl font-medium">
|
||
Service d'hébergement professionnel
|
||
</div>
|
||
<div className="mt-4 lg:mt-6 flex flex-wrap gap-2 justify-center lg:justify-start">
|
||
<span className="bg-white/20 text-white px-3 py-1 rounded-full text-sm font-medium backdrop-blur-sm">Haute disponibilité</span>
|
||
<span className="bg-white/20 text-white px-3 py-1 rounded-full text-sm font-medium backdrop-blur-sm">Open Source</span>
|
||
<span className="bg-white/20 text-white px-3 py-1 rounded-full text-sm font-medium backdrop-blur-sm">Communautaire</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Content - Forcer le fond blanc */}
|
||
<div className="p-6 sm:p-8 bg-white">
|
||
{/* Description */}
|
||
<SectionTitle icon={ClipboardList} title="Description détaillée" />
|
||
<div className="bg-gradient-to-br from-blue-50 to-blue-100/50 rounded-2xl p-4 lg:p-6 border border-blue-200 mb-8">
|
||
<p className="text-gray-700 leading-relaxed text-base sm:text-lg lg:text-xl mb-4">
|
||
{service.description}
|
||
</p>
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mt-6">
|
||
<FeatureBadge
|
||
icon={Check}
|
||
title="99.9% Uptime"
|
||
subtitle="Disponibilité garantie"
|
||
/>
|
||
<FeatureBadge
|
||
icon={Lock}
|
||
title="Sécurisé"
|
||
subtitle="SSL & Backups"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Fonctionnalités */}
|
||
<SectionTitle icon={Zap} title={translations.discoverFeatures} />
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-8">
|
||
{service.features.map((feature, index) => (
|
||
<FeatureItem key={index} feature={feature} index={index} />
|
||
))}
|
||
</div>
|
||
|
||
{/* Call to action */}
|
||
<div className="pt-6 lg:pt-8 border-t border-gray-200">
|
||
<a
|
||
href={service.url}
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
className={cn(
|
||
'w-full inline-flex items-center justify-center',
|
||
'bg-gradient-to-r from-blue-600 to-blue-500 text-white',
|
||
'border-0 py-4 px-6 sm:px-8 rounded-2xl cursor-pointer no-underline',
|
||
'font-bold tracking-wide shadow-lg',
|
||
commonClasses.transition,
|
||
commonClasses.hoverScale,
|
||
'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500',
|
||
'text-base lg:text-lg'
|
||
)}
|
||
>
|
||
<Rocket className="w-6 h-6 lg:w-7 lg:h-7 mr-3" strokeWidth={2} />
|
||
<span>Accéder à {service.name}</span>
|
||
</a>
|
||
|
||
<p className="text-center text-sm text-gray-500 mt-4">
|
||
Besoin d'aide ? Rejoignez notre <a href={URLS.social.discord} className={cn('text-blue-600 hover:text-blue-700 font-medium', commonClasses.transition)}>Discord</a> pour obtenir du support
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Decorative elements */}
|
||
<div className="absolute top-0 right-0 w-16 h-16 sm:w-24 sm:h-24 lg:w-32 lg:h-32 bg-blue-100/30 rounded-full -translate-y-8 translate-x-8 sm:-translate-y-12 sm:translate-x-12 lg:-translate-y-16 lg:translate-x-16 hidden sm:block pointer-events-none"></div>
|
||
<div className="absolute bottom-0 left-0 w-12 h-12 sm:w-16 sm:h-16 lg:w-24 lg:h-24 bg-blue-50 rounded-full translate-y-6 -translate-x-6 sm:translate-y-8 sm:-translate-x-8 lg:translate-y-12 lg:-translate-x-12 hidden sm:block pointer-events-none"></div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|