// admin.jsx — Back-office AUTOMOTORES OMEGA const { useState, useEffect, useRef, useMemo } = React; const ADMIN_PASSWORD = 'omega2026'; // Cambiable. En producción usar auth real. // Icons reusados del sitio público const AIcon = { Arrow: (p) => , Plus: (p) => , Pencil: (p) => , Trash: (p) => , Check: (p) => , X: (p) => , Eye: (p) => , Upload: (p) => , Search: (p) => , Download: (p) => , Logout: (p) => , Drag: (p) => , Car: (p) => , Inbox: (p) => , Users: (p) => }; const fmtPriceARS = (n) => n ? '$' + new Intl.NumberFormat('es-AR').format(Math.round(n)) : '—'; const fmtKm = (n) => n ? new Intl.NumberFormat('es-AR').format(n) + ' km' : '—'; // === LOGIN (Supabase email + password) === const LoginScreen = ({ onAuth }) => { const [email, setEmail] = useState(''); const [pwd, setPwd] = useState(''); const [err, setErr] = useState(''); const [loading, setLoading] = useState(false); const submit = async (e) => { e.preventDefault(); setLoading(true); setErr(''); try { const _em = email.indexOf('@')<0 ? email.trim().toLowerCase()+'@automotoresomega.com' : email.trim(); await window.OMEGA_STORE.signIn(_em, pwd); onAuth(); } catch (e) { setErr(e.message || 'Credenciales inválidas'); setTimeout(() => setErr(''), 4000); } finally { setLoading(false); } }; return (
OMEGA
Back-office

Acceso al panel

Iniciá sesión con tu cuenta OMEGA.

{window.OMEGA_STORE?.__local && (
Modo local · datos guardados en este navegador.
Acceso: admin@omega / omega2026
)}
setEmail(e.target.value)} placeholder="vos@automotoresomega.com" autoFocus required style={{marginBottom:16}} /> setPwd(e.target.value)} placeholder="••••••••" required /> {err &&
{err}
}
); }; // === TOAST === const Toast = ({ msg, type, onClose }) => { useEffect(() => { const t = setTimeout(onClose, 3500); return () => clearTimeout(t); }, [onClose]); return (
{type === 'success' ? : } {msg}
); }; // === CONFIRM MODAL === const ConfirmModal = ({ title, msg, onConfirm, onCancel, confirmLabel = 'Confirmar' }) => (
e.stopPropagation()}>

{title}

{msg}

); // === DASHBOARD === const Dashboard = ({ vehicles, profile, onEdit, onNew, onDelete, onTogglePublished, onLogout, onTab }) => { const [q, setQ] = useState(''); const [filterMarca, setFilterMarca] = useState('Todas'); const [filterStatus, setFilterStatus] = useState('todos'); const [confirm, setConfirm] = useState(null); const marcas = ['Todas', ...Array.from(new Set(vehicles.map(v => v.marca))).sort()]; const filtered = useMemo(() => { return vehicles.filter(v => { if (filterMarca !== 'Todas' && v.marca !== filterMarca) return false; if (filterStatus === 'publicados' && v.draft) return false; if (filterStatus === 'borradores' && !v.draft) return false; if (filterStatus === 'sinfotos' && v.photos && v.photos.length > 0) return false; if (q && !(`${v.marca} ${v.modelo} ${v.patente||''}`.toLowerCase().includes(q.toLowerCase()))) return false; return true; }); }, [vehicles, q, filterMarca, filterStatus]); const stats = useMemo(() => ({ total: vehicles.length, publicados: vehicles.filter(v => !v.draft).length, sinFotos: vehicles.filter(v => !v.photos || v.photos.length === 0).length, valorTotal: vehicles.reduce((s,v) => s + (v.precio||0), 0) }), [vehicles]); return (
Espejo en vivo · sistema.automotoresomega.com

Catálogo OMEGA

Los autos se cargan y se dan de baja desde tu sistema de gestión. Acá agregás las fotos y los datos de vidriera para que se vean en la web.

Total en stock
{stats.total}
Publicados
{stats.publicados}
Sin fotos
{stats.sinFotos}
Valor de inventario
{fmtPriceARS(stats.valorTotal)}
setQ(e.target.value)}/>
{filtered.length === 0 ? (
Sin autos en stock

No hay autos para mostrar

Cuando cargues autos en el sistema de gestión (estado "en stock"), aparecen acá automáticamente para ponerles fotos.

) : ( {filtered.map(v => ( ))}
Foto Vehículo Año KM Precio Patente En la web Acciones
{v.photos && v.photos.length > 0 ? {v.modelo}/ :
SIN FOTO
}
{v.marca}
{v.modelo} · {v.color}
{v.anio || '—'} {fmtKm(v.km)} {fmtPriceARS(v.precio)} {v.patente ? {v.patente} : }
{v.photos && v.photos.length > 0 && ( )}
)}
{confirm && ( { onDelete(confirm.id); setConfirm(null); }} onCancel={() => setConfirm(null)} /> )}
); }; // === TOP BAR compartida === const AdminTopBar = ({ profile, active, onTab, onLogout, extraActions }) => { const puede = (s) => profile?.role === 'admin' || (profile?.secciones || []).includes(s); return (
OMEGA
Back-office
{profile?.nombre || profile?.email} · {profile?.role}
Ver sitio
); }; Object.assign(window, { LoginScreen, Dashboard, AdminTopBar, Toast, ConfirmModal, AIcon, fmtPriceARS, fmtKm, ADMIN_PASSWORD });