134 lines
6.4 KiB
TypeScript
134 lines
6.4 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from 'react';
|
|
import Link from 'next/link';
|
|
import { useRouter } from 'next/navigation';
|
|
import { Search, MapPin, Briefcase, TrendingUp, Loader2, ArrowRight } from 'lucide-react';
|
|
import { generateSlug } from '@/lib/utils';
|
|
import { Business, BlogPost } from '@/types';
|
|
import BusinessCard from '@/components/BusinessCard';
|
|
import { useUser } from '@/components/UserProvider';
|
|
import HomeSlider from '@/components/HomeSlider';
|
|
|
|
interface Props {
|
|
initialFeatured: Business[];
|
|
initialPosts: BlogPost[];
|
|
initialCategories: any[];
|
|
initialSlides: any[];
|
|
}
|
|
|
|
const HomeClient = ({ initialFeatured, initialPosts, initialCategories, initialSlides }: Props) => {
|
|
const router = useRouter();
|
|
const { user, settings } = useUser();
|
|
const [searchTerm, setSearchTerm] = useState('');
|
|
const [locationTerm, setLocationTerm] = useState('');
|
|
const [featuredBusinesses, setFeaturedBusinesses] = useState<Business[]>(initialFeatured);
|
|
const [posts, setPosts] = useState<BlogPost[]>(initialPosts);
|
|
const [categories, setCategories] = useState<any[]>(initialCategories);
|
|
const [slides, setSlides] = useState<any[]>(initialSlides);
|
|
const [loading, setLoading] = useState(false);
|
|
const [loadingPosts, setLoadingPosts] = useState(false);
|
|
|
|
const handleSearch = (searchTerm: string, locationTerm: string) => {
|
|
const params = new URLSearchParams();
|
|
if (searchTerm) params.append('q', searchTerm);
|
|
if (locationTerm) params.append('location', locationTerm);
|
|
router.push(`/annuaire?${params.toString()}`);
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
{/* Dynamic Hero Slider */}
|
|
<HomeSlider slides={slides} onSearch={handleSearch} />
|
|
|
|
{/* Featured Categories */}
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
|
<h2 className="text-3xl font-bold text-gray-900 mb-10 font-serif text-center">Secteurs en vedette</h2>
|
|
<div className="flex flex-wrap justify-center gap-4 sm:gap-6">
|
|
{(settings?.homeCategories || categories.slice(0, 4).map(c => c.name)).map((cat: string, idx: number) => (
|
|
<Link
|
|
key={idx}
|
|
href={`/annuaire?category=${encodeURIComponent(cat)}`}
|
|
className="group cursor-pointer bg-white p-6 rounded-xl border border-gray-100 shadow-sm hover:shadow-md hover:border-brand-200 transition-all text-center w-[calc(50%-0.5rem)] sm:w-48 lg:w-56 flex flex-col items-center"
|
|
>
|
|
<div className="w-12 h-12 bg-brand-50 text-brand-600 rounded-full flex items-center justify-center mb-4 group-hover:bg-brand-600 group-hover:text-white transition-colors">
|
|
<Briefcase className="w-6 h-6" />
|
|
</div>
|
|
<h3 className="font-semibold text-gray-900 text-sm sm:text-base line-clamp-2">{cat}</h3>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Featured Businesses */}
|
|
<div className="bg-gray-50 py-16">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="flex justify-between items-end mb-8">
|
|
<div>
|
|
<h2 className="text-3xl font-bold text-gray-900 font-serif">Entreprises à la une</h2>
|
|
<p className="text-gray-500 mt-2">Découvrez les pépites de notre communauté.</p>
|
|
</div>
|
|
<Link href="/annuaire" className="text-brand-600 font-medium hover:text-brand-700 flex items-center">
|
|
Voir tout l'annuaire <TrendingUp className="w-4 h-4 ml-1" />
|
|
</Link>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
{featuredBusinesses.map(biz => (
|
|
<BusinessCard key={biz.id} business={biz} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Blog Section */}
|
|
{settings?.homeBlogShow !== false && (
|
|
<div className="py-16">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="flex justify-between items-end mb-8">
|
|
<div>
|
|
<h2 className="text-3xl font-bold text-gray-900 font-serif">{settings?.homeBlogTitle || "Derniers Articles"}</h2>
|
|
<p className="text-gray-500 mt-2">{settings?.homeBlogSubtitle || "Toutes les actualités de l'entrepreneuriat africain."}</p>
|
|
</div>
|
|
<Link href="/actualites" className="text-brand-600 font-medium hover:text-brand-700 flex items-center">
|
|
Voir les actualités <ArrowRight className="w-4 h-4 ml-1" />
|
|
</Link>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
|
{posts
|
|
.filter(post => {
|
|
if (settings?.homeBlogSelection === 'manual') {
|
|
return settings.homeBlogIds?.includes(post.id);
|
|
}
|
|
if (settings?.homeBlogSelection === 'category') {
|
|
return post.tags?.some((tag: string) => settings.homeBlogCategories?.includes(tag));
|
|
}
|
|
return true;
|
|
})
|
|
.slice(0, settings?.homeBlogCount || 3)
|
|
.map(post => (
|
|
<Link key={post.id} href={`/actualites/${post.slug ? generateSlug(post.slug) : post.id}`} className="group bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden hover:shadow-md transition-all">
|
|
<div className="h-48 overflow-hidden">
|
|
<img src={post.imageUrl} alt={post.title} className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500" width={400} height={300} loading="lazy" />
|
|
</div>
|
|
<div className="p-6">
|
|
<h3 className="text-xl font-bold text-gray-900 mb-2 line-clamp-2 group-hover:text-brand-600 transition-colors">{post.title}</h3>
|
|
<p className="text-gray-500 text-sm line-clamp-3 mb-4">{post.excerpt}</p>
|
|
<div className="flex items-center justify-between mt-auto pt-4 border-t border-gray-50">
|
|
<span className="text-xs font-medium text-gray-400">{new Date(post.date).toLocaleDateString('fr-FR')}</span>
|
|
<span className="text-brand-600 font-bold text-xs">Lire la suite →</span>
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default HomeClient;
|