// 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}) => (
{children}
); const kmLabel = filters.kmMax >= 300000 ? '' : `Hasta ${fmtKm(filters.kmMax)}`; const precioLabel = (filters.precioMin>0 || filters.precioMax<70000000) ? `${filters.precioMin>0?money(filters.precioMin):'$0'} – ${filters.precioMax<70000000?money(filters.precioMax):'$70M+'}` : ''; const anioLabel = (filters.anioMin>1980 || filters.anioMax<2026) ? `${filters.anioMin}–${filters.anioMax}` : ''; const reset = () => setFilters({ marca:'Todas', modelo:'Todos', version:'Todas', carroceria:'Todas', combustible:'Todos', transmision:'Todas', precioMin:0, precioMax:70000000, anioMin:1980, anioMax:2026, kmMax:300000, soloConFotos:false, soloDestacados:false, q:'' }); const set1 = (patch) => setFilters(f => ({...f, ...patch})); // Chips de filtros activos (removibles) const activeChips = []; if (filters.q) activeChips.push({ k:'q', label:`"${filters.q}"`, clear:()=>set1({q:''}) }); if (filters.marca!=='Todas') activeChips.push({ k:'marca', label:filters.marca, clear:()=>setMarca('Todas') }); if (filters.modelo!=='Todos') activeChips.push({ k:'modelo', label:filters.modelo, clear:()=>setModelo('Todos') }); if (filters.version!=='Todas') activeChips.push({ k:'version', label:filters.version.replace(new RegExp('^'+filters.modelo+'\\s*','i'),'').trim()||filters.version, clear:()=>set1({version:'Todas'}) }); if (precioLabel) activeChips.push({ k:'precio', label:precioLabel, clear:()=>set1({precioMin:0,precioMax:70000000}) }); if (anioLabel) activeChips.push({ k:'anio', label:anioLabel, clear:()=>set1({anioMin:1980,anioMax:2026}) }); if (kmLabel) activeChips.push({ k:'km', label:kmLabel, clear:()=>set1({kmMax:300000}) }); if (filters.carroceria!=='Todas') activeChips.push({ k:'carro', label:filters.carroceria, clear:()=>set1({carroceria:'Todas'}) }); if (filters.combustible!=='Todos') activeChips.push({ k:'comb', label:filters.combustible, clear:()=>set1({combustible:'Todos'}) }); if (filters.transmision!=='Todas') activeChips.push({ k:'trans', label:filters.transmision, clear:()=>set1({transmision:'Todas'}) }); if (filters.soloConFotos) activeChips.push({ k:'fotos', label:'Con fotos', clear:()=>set1({soloConFotos:false}) }); if (filters.soloDestacados) activeChips.push({ k:'dest', label:'Destacados', clear:()=>set1({soloDestacados:false}) }); return (
{!embedded && (
Catálogo · Mendoza

Toda la flota disponible.

{vehicles.length} unidades seleccionadas, inspeccionadas y listas para entrega. Filtrá por marca, tipo, presupuesto o año.

)}
{filtered.length} / {vehicles.length} unidades
Ordenar
{filtered.length === 0 ? (
) : (
{filtered.map(v => )}
)}
); }; Object.assign(window, { CatalogScreen });