// 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 (
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 => (
))}
set('equipamiento', e.target.value)} placeholder="Airbags, ABS, Climatizador, Cámara trasera, CarPlay..."/>
{/* Fotos */}
);
};
Object.assign(window, { PhotoUploader, VehicleEditor, PhotoPreview });