import { useCallback, useEffect, useState } from 'react';
import SearchBar from '../components/SearchBar';
import ListingCard from '../components/ListingCard';
import { publicService } from '../services/publicService';
import type { Listing } from '../types';
import { Filter, X, Grid, List as ListIcon, TrendingUp, Search, Zap } from 'lucide-react';
import { processCategoriesForSelect, type FlatCategory } from '../utils/categoryTreeUtils';
import { motion, AnimatePresence } from 'framer-motion';
import SEO from '../components/SEO';
import { WebsiteSearchSchema, OrganizationSchema } from '../components/SchemaMarkup';
export default function HomePage() {
const [listings, setListings] = useState
([]);
const [flatCategories, setFlatCategories] = useState([]);
const [loading, setLoading] = useState(true);
// Search State
const [searchText, setSearchText] = useState('');
const [selectedCatId, setSelectedCatId] = useState(null);
const [dynamicFilters, setDynamicFilters] = useState>({});
useEffect(() => {
loadInitialData();
}, []);
const loadInitialData = async () => {
setLoading(true);
try {
const [latestListings, cats] = await Promise.all([
publicService.getLatestListings(),
publicService.getCategories()
]);
setListings(latestListings);
setFlatCategories(processCategoriesForSelect(cats));
} catch (e) {
console.error(e);
} finally {
setLoading(false);
}
};
const performSearch = useCallback(async () => {
setLoading(true);
try {
const { default: api } = await import('../services/api');
const response = await api.post('/listings/search', {
query: searchText,
categoryId: selectedCatId,
attributes: dynamicFilters
});
setListings(response.data);
} catch (e) {
console.error(e);
} finally {
setLoading(false);
}
}, [searchText, selectedCatId, dynamicFilters]);
useEffect(() => {
if (selectedCatId || Object.keys(dynamicFilters).length > 0 || searchText) {
performSearch();
}
}, [selectedCatId, dynamicFilters, searchText, performSearch]);
const handleSearchSubmit = (q: string) => {
setSearchText(q);
performSearch();
};
const clearFilters = () => {
setDynamicFilters({});
setSelectedCatId(null);
setSearchText('');
loadInitialData();
};
return (
{/* --- HERO SECTION REFINADO --- */}
{/* Capas de fondo: Orbes de luz y textura */}
{/* Badge superior estilizado */}
Marketplace Oficial Diario El Día
Tu próximo
gran hallazgo
Explora miles de clasificados verificados con la confianza de siempre, ahora en una experiencia digital Premium.
{/* Buscador con efecto Glassmorphism */}
{/* Sugerencias rápidas */}
Tendencias:
{['Departamentos', 'Camionetas', 'Motos', 'Servicios'].map((tag) => (
#{tag}
))}
{/* Degradado hacia la sección blanca de abajo */}
{/* Main Content Layout */}
{/* SIDEBAR: Advanced Filters */}
Filtros
{(selectedCatId || Object.keys(dynamicFilters).length > 0 || searchText) && (
Limpiar
)}
{/* Category Selection */}
Rubro Principal
{
setSelectedCatId(Number(e.target.value) || null);
setDynamicFilters({});
}}
>
Todos los rubros
{flatCategories.map(cat => (
{cat.label}
))}
{/* Dynamic Attributes */}
{selectedCatId && (
Búsqueda avanzada
{Object.keys(dynamicFilters).length > 0 && (
{Object.entries(dynamicFilters).map(([k, v]) => (
{v}
{
const next = { ...dynamicFilters }; delete next[k]; setDynamicFilters(next);
}}
/>
))}
)}
)}
{/* MAIN LIST: Content Grid */}
{loading ? 'Sincronizando...' : selectedCatId
? flatCategories.find(c => c.id === selectedCatId)?.name
: 'Últimos Clasificados'}
{listings.length} resultados
{/* Grid Container */}
{loading ? (
{[1, 2, 3, 4, 5, 6].map(i => (
))}
) : listings.length === 0 ? (
Sin resultados
No hay avisos que coincidan con los criterios aplicados actualmente.
Restablecer vista
) : (
{listings.map((listing, idx) => (
))}
)}
);
}