Files
afrov2/components/HomeSlider.tsx

214 lines
8.7 KiB
TypeScript

"use client";
import React, { useState, useEffect } from 'react';
import Link from 'next/link';
import { Search, MapPin, ChevronLeft, ChevronRight, ArrowRight } from 'lucide-react';
interface HomeSlide {
id: string;
type: 'BUSINESS' | 'CUSTOM';
businessId?: string | null;
business?: any;
title?: string | null;
subtitle?: string | null;
imageUrl?: string | null;
linkUrl?: string | null;
}
interface Props {
slides: HomeSlide[];
onSearch: (searchTerm: string, locationTerm: string) => void;
}
const HomeSlider = ({ slides, onSearch }: Props) => {
const [current, setCurrent] = useState(0);
const [searchTerm, setSearchTerm] = useState('');
const [locationTerm, setLocationTerm] = useState('');
// Auto-slide every 6 seconds
useEffect(() => {
if (slides.length <= 1) return;
const interval = setInterval(() => {
setCurrent((prev) => (prev === slides.length - 1 ? 0 : prev + 1));
}, 6000);
return () => clearInterval(interval);
}, [slides.length]);
const handleSearchSubmit = (e: React.FormEvent) => {
e.preventDefault();
onSearch(searchTerm, locationTerm);
};
// If no slides, show default hero
if (slides.length === 0) {
return (
<div className="relative bg-dark-900 overflow-hidden min-h-[600px] flex items-center">
<div className="absolute inset-0 opacity-40">
<img
src="https://images.unsplash.com/photo-1522071820081-009f0129c71c?ixlib=rb-4.0.3&auto=format&fit=crop&w=1740&q=80"
className="w-full h-full object-cover"
alt="Default Banner"
/>
</div>
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 lg:py-32 w-full">
<div className="max-w-3xl">
<h1 className="text-4xl md:text-6xl font-serif font-bold text-white mb-6 tracking-tight animate-in fade-in slide-in-from-left-4 duration-700">
Boostez votre visibilité dans <br />
<span className="text-brand-500">l'écosystème africain</span>
</h1>
<p className="text-xl text-gray-300 mb-8 max-w-2xl animate-in fade-in slide-in-from-left-4 duration-700 delay-150">
L'annuaire 2.0 qui connecte les talents, les entrepreneurs et les entreprises de la diaspora et du continent.
</p>
<SearchForm
searchTerm={searchTerm}
setSearchTerm={setSearchTerm}
locationTerm={locationTerm}
setLocationTerm={setLocationTerm}
onSubmit={handleSearchSubmit}
/>
</div>
</div>
</div>
);
}
return (
<div className="relative h-[650px] md:h-[700px] overflow-hidden bg-black">
{slides.map((slide, index) => (
<div
key={slide.id}
className={`absolute inset-0 transition-opacity duration-1000 ease-in-out ${
index === current ? 'opacity-100 z-10' : 'opacity-0 z-0'
}`}
>
{/* Background Image */}
<div className="absolute inset-0">
<img
src={slide.type === 'BUSINESS' ? (slide.business?.coverUrl || slide.business?.logoUrl) : (slide.imageUrl || '')}
className={`w-full h-full object-cover transition-transform duration-[6000ms] ease-linear ${
index === current ? 'scale-110' : 'scale-100'
}`}
alt=""
/>
<div className="absolute inset-0 bg-gradient-to-r from-black/80 via-black/40 to-transparent" />
</div>
{/* Content */}
<div className="relative h-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center">
<div className={`max-w-3xl transition-all duration-700 delay-300 ${
index === current ? 'translate-x-0 opacity-100' : '-translate-x-10 opacity-0'
}`}>
{slide.type === 'BUSINESS' && (
<div className="inline-flex items-center gap-2 px-3 py-1 bg-brand-600/20 border border-brand-500/30 rounded-full mb-6">
<span className="w-2 h-2 bg-brand-500 rounded-full animate-pulse" />
<span className="text-brand-400 text-xs font-bold uppercase tracking-widest">Entreprise à la une</span>
</div>
)}
<h1 className="text-4xl md:text-6xl font-serif font-bold text-white mb-6 tracking-tight leading-tight">
{slide.type === 'BUSINESS' ? (
<>Découvrez <span className="text-brand-500">{slide.business?.name}</span></>
) : (
slide.title
)}
</h1>
<p className="text-xl text-gray-300 mb-8 max-w-2xl line-clamp-3">
{slide.type === 'BUSINESS' ? (
slide.business?.description
) : (
slide.subtitle
)}
</p>
<div className="flex flex-wrap gap-4 items-center">
<Link
href={slide.type === 'BUSINESS' ? `/annuaire/${slide.business?.id}` : (slide.linkUrl || '#')}
className="inline-flex items-center gap-2 bg-brand-600 text-white px-8 py-4 rounded-lg font-bold hover:bg-brand-700 transition-all shadow-lg shadow-brand-600/20 hover:scale-105"
>
{slide.type === 'BUSINESS' ? 'Voir la fiche' : 'En savoir plus'}
<ArrowRight className="w-5 h-5" />
</Link>
</div>
</div>
</div>
</div>
))}
{/* Static Search Overlay (Always visible on top of slides) */}
<div className="absolute bottom-12 md:bottom-20 left-0 right-0 z-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SearchForm
searchTerm={searchTerm}
setSearchTerm={setSearchTerm}
locationTerm={locationTerm}
setLocationTerm={setLocationTerm}
onSubmit={handleSearchSubmit}
/>
</div>
</div>
{/* Navigation Arrows */}
{slides.length > 1 && (
<>
<button
onClick={() => setCurrent(current === 0 ? slides.length - 1 : current - 1)}
className="absolute left-4 top-1/2 -translate-y-1/2 z-30 p-3 rounded-full bg-white/10 text-white hover:bg-white/20 transition-all backdrop-blur-sm"
>
<ChevronLeft className="w-6 h-6" />
</button>
<button
onClick={() => setCurrent(current === slides.length - 1 ? 0 : current + 1)}
className="absolute right-4 top-1/2 -translate-y-1/2 z-30 p-3 rounded-full bg-white/10 text-white hover:bg-white/20 transition-all backdrop-blur-sm"
>
<ChevronRight className="w-6 h-6" />
</button>
{/* Indicators */}
<div className="absolute bottom-6 left-1/2 -translate-x-1/2 z-30 flex gap-2">
{slides.map((_, i) => (
<button
key={i}
onClick={() => setCurrent(i)}
className={`w-2.5 h-2.5 rounded-full transition-all ${
i === current ? 'bg-brand-500 w-8' : 'bg-white/40'
}`}
/>
))}
</div>
</>
)}
</div>
);
};
const SearchForm = ({ searchTerm, setSearchTerm, locationTerm, setLocationTerm, onSubmit }: any) => (
<form onSubmit={onSubmit} className="max-w-4xl bg-white/95 backdrop-blur-md p-2 rounded-xl shadow-2xl flex flex-col md:flex-row gap-2 border border-white/20 animate-in fade-in slide-in-from-bottom-4 duration-700 delay-500">
<div className="flex-1 relative">
<Search className="absolute left-3 top-3.5 text-gray-400 w-5 h-5" />
<input
type="text"
placeholder="Que recherchez-vous ? (ex: Traiteur, Photographe...)"
className="w-full pl-10 pr-4 py-3.5 rounded-lg focus:outline-none text-gray-900 font-medium"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
</div>
<div className="md:w-1/3 relative border-t md:border-t-0 md:border-l border-gray-100">
<MapPin className="absolute left-3 top-3.5 text-gray-400 w-5 h-5" />
<input
type="text"
placeholder="Où ? (ex: Dakar)"
className="w-full pl-10 pr-4 py-3.5 rounded-lg focus:outline-none text-gray-900 font-medium"
value={locationTerm}
onChange={(e) => setLocationTerm(e.target.value)}
/>
</div>
<button type="submit" className="bg-brand-600 text-white px-10 py-3.5 rounded-lg font-bold hover:bg-brand-700 transition-all hover:scale-105 active:scale-95 shadow-lg shadow-brand-600/30">
Rechercher
</button>
</form>
);
export default HomeSlider;