// admin-editor.jsx — Formulario de carga/edición de vehículo const { useState, useEffect, useRef } = React; const CARROCERIAS = ["Sedán", "Hatchback", "SUV", "Pickup", "Coupé", "Utilitario", "Monovolumen", "Moto"]; const COMBUSTIBLES = ["Nafta", "Diésel", "Híbrido", "Eléctrico", "GNC"]; const TRANSMISIONES = ["Manual", "Automática", "CVT"]; const TAGS = ["", "DESTACADO", "PREMIUM", "NUEVO", "COLECCIÓN"]; // === PHOTO UPLOADER === const PhotoUploader = ({ photos, onChange, onAddBlob, onDeletePhoto }) => { const [drag, setDrag] = useState(false); const [dragIdx, setDragIdx] = useState(null); const [overIdx, setOverIdx] = useState(null); const fileInputRef = useRef(); const handleFiles = async (files) => { const accepted = Array.from(files).filter(f => f.type.startsWith('image/')); for (const f of accepted) { await onAddBlob(f); } }; const onDrop = (e) => { e.preventDefault(); setDrag(false); if (e.dataTransfer && e.dataTransfer.files) handleFiles(e.dataTransfer.files); }; // Reorder const onTileDragStart = (i) => setDragIdx(i); const onTileDragOver = (e, i) => { e.preventDefault(); setOverIdx(i); }; const onTileDrop = (e, i) => { e.preventDefault(); if (dragIdx === null || dragIdx === i) { setDragIdx(null); setOverIdx(null); return; } const next = [...photos]; const [moved] = next.splice(dragIdx, 1); next.splice(i, 0, moved); onChange(next); setDragIdx(null); setOverIdx(null); }; return (
{e.preventDefault(); setDrag(true);}} onDragLeave={()=>setDrag(false)} onDrop={onDrop} onClick={()=>fileInputRef.current?.click()} >
Arrastrá las fotos acá
o hacé click para seleccionar · JPG, PNG, WEBP
handleFiles(e.target.files)} />
{photos.length > 0 && (
Arrastrá las fotos para reordenarlas. La primera es la portada que se muestra en el catálogo.
{photos.map((p, i) => (
onTileDragStart(i)} onDragOver={(e)=>onTileDragOver(e, i)} onDrop={(e)=>onTileDrop(e, i)} onDragEnd={()=>{setDragIdx(null); setOverIdx(null);}} > {String(i+1).padStart(2,'0')} {i === 0 && Portada}
))}
{photos.length} foto{photos.length === 1 ? '' : 's'} cargada{photos.length === 1 ? '' : 's'}
)}
); }; // Resuelve idb:KEY a ObjectURL para previsualización const PhotoPreview = ({ src }) => { const [resolved, setResolved] = useState(null); useEffect(() => { let cancelled = false; if (!src) { setResolved(null); return; } if (src.startsWith('idb:')) { window.OMEGA_STORE.resolvePhoto(src).then(url => { if (!cancelled) setResolved(url); }); } else { setResolved(src); } return () => { cancelled = true; }; }, [src]); if (!resolved) return null; return ; }; // === EDITOR === const VehicleEditor = ({ vehicle, isNew, onSave, onCancel, onLogout }) => { const blank = { id: '', marca: '', modelo: '', anio: '', km: '', precio: '', combustible: 'Nafta', transmision: 'Manual', color: '', carroceria: 'Sedán', patente: '', tag: '', descripcion: '', equipamiento: '', photos: [], draft: true }; const [form, setForm] = useState(() => { if (vehicle) return { ...blank, ...vehicle }; return { ...blank, id: 'ome-' + Date.now().toString(36) }; }); const [saving, setSaving] = useState(false); const set = (k, v) => setForm(f => ({ ...f, [k]: v })); const handleAddBlob = async (blob) => { const ref = await window.OMEGA_STORE.addPhoto(form.patente || form.id, blob); setForm(f => ({ ...f, photos: [...(f.photos||[]), ref] })); }; const handleDeletePhoto = async (src, idx) => { const next = (form.photos || []).filter((_,i) => i !== idx); setForm(f => ({ ...f, photos: next })); if (src) await window.OMEGA_STORE.deletePhoto(src); }; const handleReorder = (next) => setForm(f => ({ ...f, photos: next })); const submit = async (publishMode) => { setSaving(true); const out = { ...form, marca: (form.marca||'').trim(), modelo: (form.modelo||'').trim(), color: (form.color||'').trim(), patente: (form.patente||'').trim().toUpperCase(), anio: form.anio ? parseInt(form.anio) : null, km: form.km ? parseInt(form.km) : 0, precio: form.precio ? parseFloat(form.precio) : 0, draft: publishMode === 'draft', // draft = oculto de la web photos: form.photos || [] }; await onSave(out); setSaving(false); }; return (
OMEGA
Back-office
Gestión de fotos y vidriera

{form.marca || 'Veh\u00edculo'} {form.modelo}

{/* Datos */}

1Datos del auto

Estos datos vienen de tu sistema de gestión y son de sólo lectura. Para cambiarlos, editá el auto en sistema.automotoresomega.com.

2Datos de vidriera

Estos datos los controlás vos para que el auto se vea completo en la web.
SE AUTODETECTAN DEL MODELO
{TAGS.map(t => ( ))}