// DETALLE de vehículo — galería de fotos (o 360° fallback), ficha técnica, calculadora de cuotas const DetailScreen = ({ vehicleId, onBack, onNav, onSelectVehicle }) => { const v = window.OMEGA_HELPERS.byId(vehicleId); const { fmtPrice, fmtPrecio, fmtKm } = window.OMEGA_HELPERS; const { vehicles } = window.OMEGA_DATA; const hasPhotos = v && v.photos && v.photos.length > 0; // Galería de fotos const [activePhoto, setActivePhoto] = useState(0); const [lightbox, setLightbox] = useState(false); // 360 viewer (fallback) const [rotation, setRotation] = useState(0); const [auto360, setAuto360] = useState(true); const dragRef = useRef({ active: false, startX: 0, startRot: 0 }); useEffect(() => { if (hasPhotos || !auto360) return; let raf; let last = performance.now(); const tick = (t) => { const dt = t - last; last = t; setRotation(r => (r + dt * 0.04) % 360); raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); return () => cancelAnimationFrame(raf); }, [auto360, hasPhotos]); const onDown = (e) => { setAuto360(false); const x = (e.touches ? e.touches[0].clientX : e.clientX); dragRef.current = { active: true, startX: x, startRot: rotation }; }; const onMove = (e) => { if (!dragRef.current.active) return; const x = (e.touches ? e.touches[0].clientX : e.clientX); const dx = x - dragRef.current.startX; setRotation(((dragRef.current.startRot + dx * 0.6) % 360 + 360) % 360); }; const onUp = () => { dragRef.current.active = false; }; useEffect(() => { window.addEventListener('mousemove', onMove); window.addEventListener('mouseup', onUp); window.addEventListener('touchmove', onMove); window.addEventListener('touchend', onUp); return () => { window.removeEventListener('mousemove', onMove); window.removeEventListener('mouseup', onUp); window.removeEventListener('touchmove', onMove); window.removeEventListener('touchend', onUp); }; }, []); // Lightbox keyboard useEffect(() => { if (!lightbox) return; const onKey = (e) => { if (e.key === 'Escape') setLightbox(false); if (e.key === 'ArrowRight') setActivePhoto(p => (p+1) % v.photos.length); if (e.key === 'ArrowLeft') setActivePhoto(p => (p-1+v.photos.length) % v.photos.length); }; document.body.style.overflow = 'hidden'; window.addEventListener('keydown', onKey); return () => { document.body.style.overflow = ''; window.removeEventListener('keydown', onKey); }; }, [lightbox, v]); // Calculadora de cuotas const [calc, setCalc] = useState({ anticipoPct: 30, plazo: 36 }); const tnaAnual = 0.42; // 42% TNA estimada const result = useMemo(() => { if (!v) return null; const total = v.precio; const anticipo = Math.round(total * (calc.anticipoPct / 100)); const capital = total - anticipo; const i = tnaAnual / 12; const n = calc.plazo; const cuota = capital * (i * Math.pow(1+i, n)) / (Math.pow(1+i, n) - 1); return { anticipo, capital, cuota: Math.round(cuota), total: Math.round(cuota * n) + anticipo }; }, [v, calc]); if (!v) return
Vehículo no encontrado.
; const related = vehicles.filter(x => x.carroceria === v.carroceria && x.id !== v.id).slice(0,3); return (
{/* Breadcrumb */}
/ / {v.marca} · {v.modelo}
{/* IZQUIERDA: galería de fotos o 360 fallback */}
{hasPhotos ? (
setLightbox(true)}> {`${v.marca}
{activePhoto + 1} / {v.photos.length}
Click para ampliar
{v.photos.length > 1 && ( )}
{v.photos.map((p, i) => ( ))}
) : (
360° · arrastrá para girar
{Math.round(rotation)}°
{['EXTERIOR','INTERIOR','MOTOR','BAÚL','DETALLES','TABLERO'].map((t,i) => (
{t}
))}
)}
{/* DERECHA: precio, ficha, CTA */}
{/* CALCULADORA DE CUOTAS */}
Financiación en vivo

Calculá tu cuota.

Movimientos los slider y vé el resultado al instante. TNA estimada {Math.round(tnaAnual*100)}% — sujeta a aprobación.

{fmtPrice(result.anticipo)}
setCalc({...calc, anticipoPct:+e.target.value})} className="range-input"/>
{calc.plazo} cuotas
setCalc({...calc, plazo:+e.target.value})} className="range-input"/>
Cuota mensual estimada
{fmtPrice(result.cuota)}
Anticipo{fmtPrice(result.anticipo)}
Capital a financiar{fmtPrice(result.capital)}
Plazo{calc.plazo} meses
Total con intereses{fmtPrice(result.total)}
{/* FICHA TÉCNICA */}
Ficha técnica completa

Especificaciones.

{/* RELACIONADOS */} {related.length > 0 && (
Te puede interesar

Otras unidades {v.carroceria}.

{related.map(rv => )}
)} {/* LIGHTBOX */} {lightbox && hasPhotos && (
setLightbox(false)}> {`${v.marca}e.stopPropagation()}/>
{activePhoto+1} / {v.photos.length}
)}
); }; const SpecBlock = ({ title, rows }) => (

{title}

{rows.map(([k,vv],i) => (
{k}
{vv}
))}
); Object.assign(window, { DetailScreen });