Toda la flota disponible.
{vehicles.length} unidades seleccionadas, inspeccionadas y listas para entrega. Filtrá por marca, tipo, presupuesto o año.
// CATÁLOGO con filtros laterales // embedded=true → se usa dentro del home (sin su propio hero, el home ya tiene uno) const CatalogScreen = ({ initialSearch, onSelectVehicle, embedded }) => { const { vehicles, marcas, carrocerias, combustibles, transmisiones } = window.OMEGA_DATA; const { fmtPrice } = window.OMEGA_HELPERS; const [filters, setFilters] = useState({ marca: initialSearch?.marca || 'Todas', modelo: 'Todos', version: 'Todas', carroceria: initialSearch?.carroceria || 'Todas', combustible: 'Todos', transmision: 'Todas', precioMin: 0, precioMax: initialSearch?.precioMax || 70000000, anioMin: 1980, anioMax: 2026, kmMax: 300000, soloConFotos: false, soloDestacados: false, q: '' }); const [verMasMarcas, setVerMasMarcas] = useState(false); const { fmtKm } = window.OMEGA_HELPERS; const [sort, setSort] = useState('relevancia'); // En mobile arrancan colapsados para que las cards se vean primero const [showFilters, setShowFilters] = useState(typeof window !== 'undefined' ? window.innerWidth > 860 : true); const filtered = useMemo(() => { let out = vehicles.filter(v => { if (filters.marca !== 'Todas' && v.marca !== filters.marca) return false; if (filters.modelo !== 'Todos' && ((v.modelo||'').trim().split(/\s+/)[0].toUpperCase()) !== filters.modelo) return false; if (filters.version !== 'Todas' && v.modelo !== filters.version) return false; if (filters.carroceria !== 'Todas' && v.carroceria !== filters.carroceria) return false; if (filters.combustible !== 'Todos' && v.combustible !== filters.combustible) return false; if (filters.transmision !== 'Todas' && v.transmision !== filters.transmision) return false; if (v.precio < filters.precioMin || v.precio > filters.precioMax) return false; if (v.anio && (v.anio < filters.anioMin || v.anio > filters.anioMax)) return false; if (filters.kmMax < 300000 && (v.km || 0) > filters.kmMax) return false; if (filters.soloConFotos && !(v.photos && v.photos.length > 0)) return false; if (filters.soloDestacados && !v.tag) return false; if (filters.q && !(`${v.marca} ${v.modelo} ${v.carroceria}`.toLowerCase().includes(filters.q.toLowerCase()))) return false; return true; }); if (sort === 'precio-asc') out.sort((a,b)=>a.precio-b.precio); else if (sort === 'precio-desc') out.sort((a,b)=>b.precio-a.precio); else if (sort === 'anio-desc') out.sort((a,b)=>b.anio-a.anio); else if (sort === 'km-asc') out.sort((a,b)=>a.km-b.km); return out; }, [vehicles, filters, sort]); // ── Híbrido deRuedas: desplegables + acordeón (mobile) ── const marcaCount = useMemo(() => { const c = {}; vehicles.forEach(v => { c[v.marca] = (c[v.marca]||0)+1; }); return c; }, [vehicles]); const carroCount = useMemo(() => { const c = {}; vehicles.forEach(v => { if(v.carroceria) c[v.carroceria] = (c[v.carroceria]||0)+1; }); return c; }, [vehicles]); const combCount = useMemo(() => { const c = {}; vehicles.forEach(v => { if(v.combustible) c[v.combustible] = (c[v.combustible]||0)+1; }); return c; }, [vehicles]); const transCount = useMemo(() => { const c = {}; vehicles.forEach(v => { if(v.transmision) c[v.transmision] = (c[v.transmision]||0)+1; }); return c; }, [vehicles]); const baseModelo = (m) => (m||'').trim().split(/\s+/)[0].toUpperCase(); // Modelos disponibles para la marca elegida (cascada, con conteo) const modelosOpts = useMemo(() => { const c = {}; vehicles.filter(v => filters.marca==='Todas' || v.marca===filters.marca) .forEach(v => { const b = baseModelo(v.modelo); if (b) c[b] = (c[b]||0)+1; }); return Object.keys(c).sort().map(k => ({ value:k, label:`${k} (${c[k]})` })); }, [vehicles, filters.marca]); // Versiones disponibles para marca+modelo (cascada, con conteo) const versionOpts = useMemo(() => { if (filters.modelo==='Todos') return []; const c = {}; vehicles.filter(v => (filters.marca==='Todas' || v.marca===filters.marca) && baseModelo(v.modelo)===filters.modelo) .forEach(v => { c[v.modelo] = (c[v.modelo]||0)+1; }); return Object.keys(c).sort().map(k => { const ver = k.replace(new RegExp('^'+filters.modelo+'\\s*','i'),'').trim() || k; return { value:k, label:`${ver} (${c[k]})` }; }); }, [vehicles, filters.marca, filters.modelo]); const setMarca = (m) => setFilters(f => ({...f, marca:m, modelo:'Todos', version:'Todas'})); const setModelo = (m) => setFilters(f => ({...f, modelo:m, version:'Todas'})); const money = (n) => n >= 1000000 ? `$${(n/1000000).toLocaleString('es-AR',{maximumFractionDigits:1})}M` : `$${Math.round(n/1000)}k`; const PRECIO_STEPS = [0,5,10,15,20,25,30,40,50,60,70].map(n=>n*1000000); const ANIOS = []; for (let y=2026; y>=1980; y--) ANIOS.push(y); const KM_STEPS = [50000,100000,150000,200000,250000]; const [openSec, setOpenSec] = useState({ marca:true }); const toggleSec = (k)=> setOpenSec(s=>({...s,[k]:!s[k]})); const AccBlock = ({id,label,value,children}) => (
{vehicles.length} unidades seleccionadas, inspeccionadas y listas para entrega. Filtrá por marca, tipo, presupuesto o año.