first commit
This commit is contained in:
122
pages/DirectoryPage.tsx
Normal file
122
pages/DirectoryPage.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Search } from 'lucide-react';
|
||||
import { MOCK_BUSINESSES } from '../services/mockData';
|
||||
import { CATEGORIES } from '../types';
|
||||
import BusinessCard from '../components/BusinessCard';
|
||||
import DirectoryHero from '../components/DirectoryHero';
|
||||
|
||||
const DirectoryPage = () => {
|
||||
const [filterCategory, setFilterCategory] = useState('All');
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
|
||||
const useQuery = () => {
|
||||
return new URLSearchParams(useLocation().search);
|
||||
}
|
||||
const query = useQuery();
|
||||
|
||||
useEffect(() => {
|
||||
const q = query.get('q');
|
||||
if (q) setSearchQuery(q);
|
||||
}, [query]);
|
||||
|
||||
const featuredBusiness = useMemo(() => {
|
||||
return MOCK_BUSINESSES.find(b => b.isFeatured);
|
||||
}, []);
|
||||
|
||||
const filteredBusinesses = useMemo(() => {
|
||||
return MOCK_BUSINESSES.filter(b => {
|
||||
const matchesCategory = filterCategory === 'All' || b.category === filterCategory;
|
||||
const matchesSearch = b.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
b.description.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
b.tags.some(t => t.toLowerCase().includes(searchQuery.toLowerCase()));
|
||||
return matchesCategory && matchesSearch;
|
||||
});
|
||||
}, [filterCategory, searchQuery]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* New Hero Section */}
|
||||
{featuredBusiness && <DirectoryHero featuredBusiness={featuredBusiness} />}
|
||||
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div className="flex flex-col md:flex-row gap-8">
|
||||
{/* Filters Sidebar */}
|
||||
<div className="w-full md:w-64 flex-shrink-0">
|
||||
<div className="bg-white p-6 rounded-xl shadow-sm border border-gray-100 sticky top-24">
|
||||
<h3 className="font-bold text-lg mb-4 flex items-center"><Search className="w-4 h-4 mr-2"/> Filtres</h3>
|
||||
|
||||
<div className="mb-6">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Recherche</label>
|
||||
<input
|
||||
type="text"
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className="w-full border-gray-300 rounded-md shadow-sm focus:ring-brand-500 focus:border-brand-500 sm:text-sm p-2 border"
|
||||
placeholder="Nom, mot-clé..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-6">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Catégorie</label>
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
id="cat-all"
|
||||
name="category"
|
||||
type="radio"
|
||||
checked={filterCategory === 'All'}
|
||||
onChange={() => setFilterCategory('All')}
|
||||
className="focus:ring-brand-500 h-4 w-4 text-brand-600 border-gray-300"
|
||||
/>
|
||||
<label htmlFor="cat-all" className="ml-3 text-sm text-gray-600">Toutes</label>
|
||||
</div>
|
||||
{CATEGORIES.map(cat => (
|
||||
<div key={cat} className="flex items-center">
|
||||
<input
|
||||
id={`cat-${cat}`}
|
||||
name="category"
|
||||
type="radio"
|
||||
checked={filterCategory === cat}
|
||||
onChange={() => setFilterCategory(cat)}
|
||||
className="focus:ring-brand-500 h-4 w-4 text-brand-600 border-gray-300"
|
||||
/>
|
||||
<label htmlFor={`cat-${cat}`} className="ml-3 text-sm text-gray-600 truncate" title={cat}>{cat}</label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Results Grid */}
|
||||
<div className="flex-1">
|
||||
<div className="mb-4 flex justify-between items-center">
|
||||
<h1 className="text-2xl font-bold font-serif text-gray-900">Annuaire des entreprises</h1>
|
||||
<span className="text-sm text-gray-500">{filteredBusinesses.length} résultats</span>
|
||||
</div>
|
||||
|
||||
{filteredBusinesses.length > 0 ? (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{filteredBusinesses.map(biz => (
|
||||
<BusinessCard key={biz.id} business={biz} />
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center py-20 bg-white rounded-xl border border-gray-100 border-dashed">
|
||||
<div className="mx-auto h-12 w-12 text-gray-400">
|
||||
<Search className="h-12 w-12" />
|
||||
</div>
|
||||
<h3 className="mt-2 text-sm font-medium text-gray-900">Aucun résultat</h3>
|
||||
<p className="mt-1 text-sm text-gray-500">Essayez d'ajuster vos filtres de recherche.</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DirectoryPage;
|
||||
Reference in New Issue
Block a user