// MendiArt — Página principal (mobile) // Marca: azul #1A2FA0, naranja #F05A0A const C = { azul: '#1A2FA0', azulDark: '#0E1F7F', naranja: '#F05A0A', naranjaDark: '#D04A00', verde: '#25D366', bg: '#F7F7F7', text: '#1A1A1A', muted: '#6B7280', line: '#E7E8EE', chipGray: '#F1F2F6', }; // ─── Iconos (line, 1.6 stroke) ─────────────────────────────── const Icon = { Search: ({s=22, c='#111'}) => ( ), Cart: ({s=22, c='#111'}) => ( ), Home: ({s=22, c='#111'}) => ( ), Grid: ({s=22, c='#111'}) => ( ), Check: ({s=22, c='#111'}) => ( ), Truck: ({s=24, c='#111'}) => ( ), Store: ({s=24, c='#111'}) => ( ), Compat: ({s=24, c='#111'}) => ( ), Wrench: ({s=24, c='#111'}) => ( ), Tag: ({s=24, c='#111'}) => ( ), Instagram: ({s=24, c='#fff'}) => ( ), Facebook: ({s=24, c='#fff'}) => ( ), YouTube: ({s=24, c='#fff'}) => ( ), Plus: ({s=18, c='#fff'}) => ( ), Minus: ({s=18, c='#fff'}) => ( ), WhatsApp: ({s=28, c='#fff'}) => ( ), }; // ─── Logo ───────────────────────────────────────────────────── function Logo({ size = 'md', dark = false }) { const h = size === 'lg' ? 60 : size === 'sm' ? 30 : 44; return ( MendiArt ); } // ─── Cinta scrolleable (marquee continuo) ───────────────────── const TICKER_DEFAULT = ['Envíos a todo Mendoza', 'Consultá por WhatsApp', 'Buscador de compatibilidad', 'Retiro en el día', 'Precios especiales para distribuidores', 'Servicio técnico de impresoras']; function Ticker({ cintaMensajes }) { let items = TICKER_DEFAULT; if (cintaMensajes) { try { const parsed = typeof cintaMensajes === 'string' ? JSON.parse(cintaMensajes) : cintaMensajes; if (Array.isArray(parsed) && parsed.length > 0) items = parsed; } catch {} } const set = (key) => (
{items.map((t, i) => ( {t} ))}
); return (
{set('a')}{set('b')}{set('c')}
); } // ─── Navbar ────────────────────────────────────────────────── function Navbar({ cartCount, onSearchClick, onCartClick }) { return (
); } const iconBtn = { width: 40, height: 40, borderRadius: 12, border: 'none', background: 'transparent', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', }; // ─── Hero ──────────────────────────────────────────────────── function Hero({ onCatalog, slogan, subtitulo }) { const textoSlogan = slogan || 'Todo para imprimir mejor.'; const textoSub = subtitulo || 'Papel fotográfico, tintas y cartuchos para tu impresora.'; return (
Mendoza, Argentina

{textoSlogan}

{textoSub}

{/* logo flotante — esquina inferior derecha del hero */}
); } // ─── Beneficios ────────────────────────────────────────────── function Benefits() { const items = [ { ic: Icon.Truck, t: 'Envío a domicilio' }, { ic: Icon.Store, t: 'Retiro en local' }, { ic: Icon.Compat, t: 'Compatibilidad' }, { ic: Icon.Wrench, t: 'Serv. técnico' }, { ic: Icon.Tag, t: 'Precio distribuidor' }, ]; return (
{items.map(({ ic: I, t }) => (
{t}
))}
); } // ─── Buscador ──────────────────────────────────────────────── function SearchBar({ value, onChange }) { return (
onChange(e.target.value)} placeholder="Buscar producto o modelo…" style={{ flex: 1, border: 'none', outline: 'none', fontFamily: 'inherit', fontSize: 14.5, color: C.text, background: 'transparent', }} /> {value && ( )}
); } // ─── Categorías chips ──────────────────────────────────────── function Categories({ active, onPick, cats }) { return (
{cats.map(c => { const isActive = c === active; return ( ); })}
); } // ─── Producto: placeholder con stripes ─────────────────────── function ProductImage({ kind, tone }) { const palettes = { cyan: ['#E6F4FA', '#1A2FA0', 'cyan ink'], magenta: ['#FBEAF2', '#1A2FA0', 'magenta ink'], yellow: ['#FFF5DC', '#1A2FA0', 'yellow ink'], black: ['#E9EAF0', '#1A2FA0', 'black ink'], paper: ['#FAF7F0', '#1A2FA0', 'photo paper'], service: ['#EEF0FA', '#1A2FA0', 'service'], multi: ['#F2EAFB', '#1A2FA0', 'multipack'], }; const [bg, fg, label] = palettes[tone] || palettes.cyan; return (
{kind === 'bottle' && ( )} {kind === 'cartridge' && ( )} {kind === 'paper' && ( )} {kind === 'service' && ( )} {label}
); } // ─── Imagen real o placeholder ─────────────────────────────── function ProductImg({ p, radius = 12 }) { const [error, setError] = React.useState(false); if (p.fotos && p.fotos.length > 0 && !error) { return (
{p.name} setError(true)} />
); } return ; } // ─── Card producto ─────────────────────────────────────────── function ProductCard({ p, qty, onAdd, onRemove, onConsult, onOpen }) { const outOfStock = !p.stock; return (
{!outOfStock ? (
${p.price.toLocaleString('es-AR')} IVA inc. · Sin IVA: ${p.price_sin_iva.toLocaleString('es-AR')}
{qty > 0 ? (
{qty}
) : ( )}
) : ( )}
); } const qtyBtn = { width: 28, height: 28, borderRadius: 999, border: 'none', background: 'transparent', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', }; // ─── Bottom nav ────────────────────────────────────────────── function BottomNav({ active, onPick, cartCount }) { const items = [ { id: 'home', t: 'Inicio', I: Icon.Home }, { id: 'cat', t: 'Catálogo', I: Icon.Grid }, { id: 'compat', t: 'Compatibilidad', I: Icon.Compat }, { id: 'cart', t: 'Carrito', I: Icon.Cart, badge: cartCount }, ]; return (
{items.map(({ id, t, I, badge }) => { const isActive = id === active; const c = isActive ? C.azul : C.muted; return ( ); })}
); } // ─── Vista Carrito ─────────────────────────────────────────── function CartView({ cart, products, waNum, onRemove, onAdd, onClear }) { const items = Object.entries(cart) .map(([id, qty]) => ({ p: products.find(x => x.id === id), qty })) .filter(({ p }) => p); const total = items.reduce((s, { p, qty }) => s + p.price * qty, 0); const pedirPorWA = () => { if (items.length === 0) return; const lineas = items.map(({ p, qty }) => `• ${p.name} x${qty} — $${(p.price * qty).toLocaleString('es-AR')}` ).join('\n'); const msg = encodeURIComponent( `Hola! Quiero hacer el siguiente pedido:\n\n${lineas}\n\nTotal: $${total.toLocaleString('es-AR')}` ); if (waNum) window.open(`https://wa.me/${waNum}?text=${msg}`, '_blank'); }; return (

Carrito

{items.length > 0 && ( )}
{items.length === 0 ? (
Tu carrito está vacío
) : (
{items.map(({ p, qty }) => (
{p.name}
${p.price.toLocaleString('es-AR')} c/u
{qty}
))}
)}
{items.length > 0 && (
Total ${total.toLocaleString('es-AR')}
)}
); } // ─── WhatsApp FAB ──────────────────────────────────────────── function WhatsAppFAB({ onClick }) { return ( ); } // ─── Toast ─────────────────────────────────────────────────── function Toast({ msg, visible }) { return (
{msg}
); } // ─── API ───────────────────────────────────────────────────── const API = 'https://sg.mendiart.com.ar'; const MEDIA = 'https://sg.mendiart.com.ar/media/productos'; function mapProduct(p) { const cat = (p.categoria || '').toLowerCase(); const color = (p.color_tinta || '').toLowerCase(); const nombre = (p.nombre_producto || '').toLowerCase(); let kind = 'bottle'; if (cat.includes('papel')) kind = 'paper'; else if (cat.includes('cartucho')) kind = 'cartridge'; else if (cat.includes('serv')) kind = 'service'; let tone = 'cyan'; if (kind === 'paper') tone = 'paper'; else if (kind === 'service') tone = 'service'; else if (color.includes('magenta')) tone = 'magenta'; else if (color.includes('amarill') || color.includes('yellow')) tone = 'yellow'; else if (color.includes('negro') || color.includes('black')) tone = 'black'; else if (nombre.includes('pack') || nombre.includes('kit')) tone = 'multi'; const iva = p.porcentaje_iva || 21; const price = Math.round(p.precio_venta || 0); const price_sin_iva = Math.round(price / (1 + iva / 100)); return { id: p.id_producto, cat: p.categoria || 'General', name: p.nombre_producto, descripcion: p.descripcion_web || '', compat: p.compatible_con || '', marca: p.marca || '', calidad: p.calidad || '', cantidad_por_unidad: p.cantidad_por_unidad || '', color_tinta: p.color_tinta || '', price_sin_iva, fotos: Array.isArray(p.fotos) ? p.fotos : [], video_youtube_id: p.video_youtube_id || '', price, kind, tone, stock: (p.stock || 0) > 0, }; } // ─── App ───────────────────────────────────────────────────── function App() { const [active, setActive] = React.useState(''); const [tab, setTab] = React.useState('home'); const [search, setSearch] = React.useState(''); const [cart, setCart] = React.useState({}); const [toast, setToast] = React.useState({ msg: '', show: false }); const [view, setView] = React.useState({ kind: 'home', productId: null }); const [products, setProducts] = React.useState([]); const [categories, setCategories] = React.useState([]); const [config, setConfig] = React.useState({}); const [loading, setLoading] = React.useState(true); const scrollRef = React.useRef(null); const catalogRef = React.useRef(null); React.useEffect(() => { Promise.all([ fetch(`${API}/web/categorias`).then(r => r.json()), fetch(`${API}/web/productos`).then(r => r.json()), fetch(`${API}/web/config`).then(r => r.json()), ]).then(([cats, prods, cfg]) => { setCategories(cats); setProducts(prods.map(mapProduct)); setConfig(cfg); if (cats.length > 0) setActive(cats[0]); setLoading(false); }).catch(() => setLoading(false)); }, []); React.useEffect(() => { if (config.meta_descripcion) { const meta = document.querySelector('meta[name="description"]'); if (meta) meta.setAttribute('content', config.meta_descripcion); } }, [config.meta_descripcion]); const cartCount = Object.values(cart).reduce((a, b) => a + b, 0); const showToast = (msg) => { setToast({ msg, show: true }); clearTimeout(window.__toastT); window.__toastT = setTimeout(() => setToast(t => ({ ...t, show: false })), 1800); }; const waNum = (config.whatsapp || '').replace(/\D/g, ''); const add = (id) => { setCart(c => ({ ...c, [id]: (c[id] || 0) + 1 })); const p = products.find(x => x.id === id); if (p && !cart[id]) showToast(`Agregado: ${p.name.split('·')[0].trim()}`); }; const remove = (id) => { setCart(c => { const n = (c[id] || 0) - 1; const copy = { ...c }; if (n <= 0) delete copy[id]; else copy[id] = n; return copy; }); }; const consult = (p) => { const msg = encodeURIComponent(`Hola, consulto por ${p.name}. ¿Tienen stock disponible?`); if (waNum) window.open(`https://wa.me/${waNum}?text=${msg}`, '_blank'); else showToast(`Consulta sobre ${p.name.split('·')[0].trim()}…`); }; const openProduct = (id) => setView({ kind: 'product', productId: id }); const goHome = () => setView({ kind: 'home', productId: null }); if (loading) { return (
{}} onCartClick={() => {}} />
Cargando catálogo…
); } // Cart view if (tab === 'cart' && view.kind !== 'product') { return (
setCart({})} />
); } // Product view if (view.kind === 'product') { const p = products.find(x => x.id === view.productId); if (!p) { goHome(); return null; } return (
{ setTab('cart'); goHome(); }} />
{ setTab(t); goHome(); }} cartCount={cartCount} />
); } const filtered = products.filter(p => { const matchesCat = !active || p.cat === active; const matchesSearch = search === '' || p.name.toLowerCase().includes(search.toLowerCase()) || (p.compat || '').toLowerCase().includes(search.toLowerCase()); return matchesCat && matchesSearch; }); const direccion = config.direccion || 'Sobremonte 448, Dorrego, Guaymallén, Mendoza'; const horarios = config.horarios || 'Lun a Vie 9 a 19hs · Sáb 9 a 13hs'; return (
{ if (catalogRef.current && scrollRef.current) { const top = catalogRef.current.getBoundingClientRect().top - scrollRef.current.getBoundingClientRect().top + scrollRef.current.scrollTop; scrollRef.current.scrollTo({ top, behavior: 'smooth' }); } }} onCartClick={() => setTab('cart')} /> { if (catalogRef.current && scrollRef.current) { const top = catalogRef.current.getBoundingClientRect().top - scrollRef.current.getBoundingClientRect().top + scrollRef.current.scrollTop; scrollRef.current.scrollTo({ top, behavior: 'smooth' }); } setTab('cat'); }} />

{active}

{filtered.length} productos
{filtered.map(p => ( ))} {filtered.length === 0 && (
No encontramos productos{active && <> en {active}} {search && <> para «{search}»}.
)}

{direccion} · {horarios}

{(config.instagram || config.facebook || config.youtube || waNum) && (
{config.instagram && ( )} {config.facebook && ( )} {config.youtube && ( )} {waNum && ( )}
)}
{ if (waNum) window.open(`https://wa.me/${waNum}`, '_blank'); else showToast('Abriendo WhatsApp…'); }} />
); } Object.assign(window, { App, C, Icon, ProductImage, ProductImg, MEDIA, qtyBtn, iconBtn });