327 lines
17 KiB
HTML
327 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="es">
|
|
<head>
|
|
<script>(function(){var t=localStorage.getItem("pos_theme")||"industrial";document.documentElement.setAttribute("data-theme",t);})()</script>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>MercadoLibre — Nexus Autoparts POS</title>
|
|
<link rel="stylesheet" href="/pos/static/css/chat.css" />
|
|
<link rel="stylesheet" href="/pos/static/css/tokens.css" />
|
|
<link rel="stylesheet" href="/pos/static/css/common.css" />
|
|
<link rel="stylesheet" href="/pos/static/css/pos-ui.css?v=2" />
|
|
<link rel="stylesheet" href="/pos/static/css/sidebar.css" />
|
|
<link rel="stylesheet" href="/pos/static/css/pos-glass.css" />
|
|
<link rel="stylesheet" href="/pos/static/css/inventory.css" />
|
|
<link rel="manifest" href="/pos/static/pwa/manifest.json" />
|
|
<meta name="theme-color" content="#F5A623" />
|
|
<link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" />
|
|
<style>
|
|
.meli-status { display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:20px;font-size:12px;font-weight:600; }
|
|
.meli-status--active { background:#d4edda;color:#155724; }
|
|
.meli-status--paused { background:#fff3cd;color:#856404; }
|
|
.meli-status--closed { background:#f8d7da;color:#721c24; }
|
|
.meli-status--pending { background:#e2e3e5;color:#383d41; }
|
|
.meli-card { background:var(--color-surface-1);border:1px solid var(--color-border);border-radius:var(--radius-md);padding:var(--space-4); }
|
|
.meli-grid { display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:var(--space-4); }
|
|
.meli-connect-btn { display:inline-flex;align-items:center;gap:8px;padding:10px 20px;background:#FFE600;color:#2D3277;border:none;border-radius:var(--radius-md);font-weight:700;cursor:pointer; }
|
|
.meli-connect-btn:hover { filter:brightness(0.95); }
|
|
.meli-config-row { display:flex;gap:var(--space-4);flex-wrap:wrap;margin-bottom:var(--space-4); }
|
|
.meli-config-row label { display:block;font-size:var(--text-caption);color:var(--color-text-muted);margin-bottom:4px; }
|
|
.meli-config-row input, .meli-config-row select { padding:8px 12px;border:1px solid var(--color-border);border-radius:var(--radius-sm);background:var(--color-surface-0);color:var(--color-text-primary); }
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<!-- =========================================================================
|
|
THEME SWITCHER BAR
|
|
========================================================================= -->
|
|
|
|
<header class="theme-bar" role="banner">
|
|
<div class="theme-bar__left">
|
|
<div class="theme-bar__store">
|
|
<span class="theme-bar__dot"></span>
|
|
Nexus Autoparts
|
|
</div>
|
|
<div class="theme-bar__sep"></div>
|
|
<span class="theme-bar__label">MercadoLibre — Integración</span>
|
|
</div>
|
|
<div class="theme-bar__right">
|
|
<span class="theme-bar__label">Tema:</span>
|
|
<button class="theme-btn theme-btn--industrial is-active" data-theme-target="industrial" onclick="setTheme('industrial')">
|
|
<span class="theme-btn__swatch"></span>
|
|
Industrial
|
|
</button>
|
|
<button class="theme-btn theme-btn--modern" data-theme-target="modern" onclick="setTheme('modern')">
|
|
<span class="theme-btn__swatch"></span>
|
|
Moderno
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- =========================================================================
|
|
APP SHELL
|
|
========================================================================= -->
|
|
|
|
<div class="app-shell">
|
|
|
|
<!-- -----------------------------------------------------------------------
|
|
SIDEBAR NAVIGATION
|
|
----------------------------------------------------------------------- -->
|
|
|
|
<aside class="sidebar" role="navigation" aria-label="Navegación principal">
|
|
<div class="sidebar__brand">
|
|
<div class="brand-logo">NA</div>
|
|
<div class="brand-name">
|
|
<span class="brand-name__primary">Nexus</span>
|
|
<span class="brand-name__sub">Autoparts POS</span>
|
|
</div>
|
|
</div>
|
|
<nav class="sidebar__nav">
|
|
<div class="nav-section-label">Principal</div>
|
|
<a class="nav-item" href="/pos/dashboard">
|
|
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
<rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/>
|
|
<rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/>
|
|
</svg>
|
|
<span>Dashboard</span>
|
|
</a>
|
|
<a class="nav-item" href="/pos/sale">
|
|
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
<rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8M12 17v4"/>
|
|
</svg>
|
|
<span>POS</span>
|
|
</a>
|
|
<a class="nav-item" href="/pos/catalog">
|
|
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M4 6h16M4 10h16M4 14h16M4 18h16"/>
|
|
</svg>
|
|
<span>Catálogo</span>
|
|
</a>
|
|
<a class="nav-item" href="/pos/inventory">
|
|
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/>
|
|
<polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/>
|
|
</svg>
|
|
<span>Inventario</span>
|
|
</a>
|
|
<div class="nav-section-label">Gestión</div>
|
|
<a class="nav-item" href="/pos/customers">
|
|
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
|
|
<circle cx="9" cy="7" r="4"/>
|
|
<path d="M23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/>
|
|
</svg>
|
|
<span>Clientes</span>
|
|
</a>
|
|
<a class="nav-item" href="/pos/marketplace">
|
|
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/>
|
|
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/>
|
|
</svg>
|
|
<span>Marketplace B2B</span>
|
|
</a>
|
|
<a class="nav-item is-active" href="/pos/marketplace-external" aria-current="page">
|
|
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
<rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8M12 17v4"/>
|
|
</svg>
|
|
<span>MercadoLibre</span>
|
|
</a>
|
|
<a class="nav-item" href="/pos/invoicing">
|
|
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
<polyline points="14 2 14 8 20 8"/>
|
|
<line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/>
|
|
<polyline points="10 9 9 9 8 9"/>
|
|
</svg>
|
|
<span>Facturación</span>
|
|
</a>
|
|
<a class="nav-item" href="/pos/config">
|
|
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="12" cy="12" r="3"/>
|
|
<path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 4.93a10 10 0 0 0 0 14.14"/>
|
|
</svg>
|
|
<span>Configuración</span>
|
|
</a>
|
|
</nav>
|
|
<div class="sidebar__footer">
|
|
<div class="sidebar__user-avatar" id="sidebarAvatar">U</div>
|
|
<div class="sidebar__user-info">
|
|
<div class="sidebar__user-name" id="sidebarName">Usuario</div>
|
|
<div class="sidebar__user-role" id="sidebarRole">—</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- -----------------------------------------------------------------------
|
|
MAIN CONTENT
|
|
----------------------------------------------------------------------- -->
|
|
|
|
<main class="main" role="main">
|
|
|
|
<!-- Page Header -->
|
|
<div class="page-header">
|
|
<div class="page-header__title-group">
|
|
<span class="page-header__eyebrow">Marketplace</span>
|
|
<h1 class="page-header__title">MercadoLibre</h1>
|
|
</div>
|
|
<div class="page-header__actions">
|
|
<a class="btn btn--ghost" href="/pos/dashboard">
|
|
<svg viewBox="0 0 24 24"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
|
|
Dashboard
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab Bar -->
|
|
<div class="tab-bar">
|
|
<button class="tab-btn is-active" role="tab" aria-selected="true" aria-controls="panel-config" onclick="switchTab('config')">
|
|
Configuración
|
|
</button>
|
|
<button class="tab-btn" role="tab" aria-selected="false" aria-controls="panel-listings" onclick="switchTab('listings')">
|
|
Publicaciones
|
|
</button>
|
|
<button class="tab-btn" role="tab" aria-selected="false" aria-controls="panel-orders" onclick="switchTab('orders')">
|
|
Órdenes
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Tab Panels -->
|
|
<div class="tab-panels" id="tab-panels">
|
|
|
|
<!-- ══════════ TAB: Configuración ══════════ -->
|
|
<div class="tab-panel is-active" id="panel-config" role="tabpanel">
|
|
<div class="meli-card" style="max-width:600px;">
|
|
<h3 style="margin:0 0 var(--space-4);font-family:var(--font-heading);">Conexión con MercadoLibre</h3>
|
|
<div id="configStatus">
|
|
<div class="skeleton skeleton--text" style="width:120px;"></div>
|
|
</div>
|
|
<div id="configForm" style="display:none;margin-top:var(--space-4);">
|
|
<p style="margin-bottom:var(--space-3);font-size:var(--text-body-sm);color:var(--color-text-secondary);">
|
|
Para conectar, necesitas una <strong>aplicación de MercadoLibre</strong>.
|
|
Ve a <a href="https://developers.mercadolibre.com.mx" target="_blank">developers.mercadolibre.com.mx</a>
|
|
y crea una app. Luego pega los datos aquí:
|
|
</p>
|
|
<div class="meli-config-row">
|
|
<div>
|
|
<label>Client ID</label>
|
|
<input type="text" id="cfgClientId" placeholder="Tu App ID" style="width:200px;" />
|
|
</div>
|
|
<div>
|
|
<label>Client Secret</label>
|
|
<input type="password" id="cfgClientSecret" placeholder="Tu Secret Key" style="width:200px;" />
|
|
</div>
|
|
</div>
|
|
<div class="meli-config-row">
|
|
<div>
|
|
<label>Categoría Default</label>
|
|
<input type="text" id="cfgCategory" placeholder="MLM1747" style="width:150px;" />
|
|
</div>
|
|
<div>
|
|
<label>Modo de Envío</label>
|
|
<select id="cfgShipping">
|
|
<option value="me2">MercadoEnvíos (me2)</option>
|
|
<option value="custom">Propio (custom)</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<button class="meli-connect-btn" onclick="startOAuth()">🔗 Conectar con MercadoLibre</button>
|
|
</div>
|
|
<div id="configConnected" style="display:none;margin-top:var(--space-4);">
|
|
<div style="display:flex;align-items:center;gap:12px;margin-bottom:var(--space-3);">
|
|
<div style="width:48px;height:48px;border-radius:50%;background:#FFE600;display:flex;align-items:center;justify-content:center;font-weight:800;color:#2D3277;">ML</div>
|
|
<div>
|
|
<div style="font-weight:700;" id="connectedNickname">Usuario ML</div>
|
|
<div style="font-size:var(--text-caption);color:var(--color-text-muted);" id="connectedSite">MLM</div>
|
|
</div>
|
|
</div>
|
|
<button class="btn btn--danger btn--sm" onclick="disconnectMeli()">Desconectar</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ══════════ TAB: Publicaciones ══════════ -->
|
|
<div class="tab-panel" id="panel-listings" role="tabpanel">
|
|
<div class="toolbar">
|
|
<div class="search-box">
|
|
<svg viewBox="0 0 24 24" stroke-linecap="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
|
|
<input type="text" id="listingSearch" placeholder="Buscar publicación..." oninput="filterListings()" />
|
|
</div>
|
|
<select class="select-filter" id="listingStatusFilter" onchange="filterListings()">
|
|
<option value="">Todos los estados</option>
|
|
<option value="active">Activas</option>
|
|
<option value="paused">Pausadas</option>
|
|
<option value="closed">Cerradas</option>
|
|
</select>
|
|
<div class="toolbar__spacer"></div>
|
|
<button class="btn btn--primary" onclick="loadListings()">🔄 Actualizar</button>
|
|
</div>
|
|
<div id="listingsContainer" class="meli-grid"></div>
|
|
<div id="listingsPagination" class="table-footer" style="margin-top:var(--space-4);"></div>
|
|
</div>
|
|
|
|
<!-- ══════════ TAB: Órdenes ══════════ -->
|
|
<div class="tab-panel" id="panel-orders" role="tabpanel">
|
|
<div class="toolbar">
|
|
<div class="search-box">
|
|
<svg viewBox="0 0 24 24" stroke-linecap="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
|
|
<input type="text" id="orderSearch" placeholder="Buscar orden..." oninput="filterOrders()" />
|
|
</div>
|
|
<select class="select-filter" id="orderStatusFilter" onchange="filterOrders()">
|
|
<option value="">Todos los estados</option>
|
|
<option value="pending">Pendientes</option>
|
|
<option value="confirmed">Confirmadas</option>
|
|
<option value="packed">Empacadas</option>
|
|
<option value="shipped">Enviadas</option>
|
|
<option value="delivered">Entregadas</option>
|
|
<option value="cancelled">Canceladas</option>
|
|
</select>
|
|
<div class="toolbar__spacer"></div>
|
|
<button class="btn btn--primary" onclick="loadOrders()">🔄 Actualizar</button>
|
|
</div>
|
|
<div class="table-wrapper">
|
|
<table class="data-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Orden ML</th>
|
|
<th>Comprador</th>
|
|
<th style="text-align:right">Total</th>
|
|
<th>Estado Nexus</th>
|
|
<th>Fecha</th>
|
|
<th>Acciones</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="ordersTableBody"></tbody>
|
|
</table>
|
|
<div id="ordersPagination" class="table-footer"></div>
|
|
</div>
|
|
</div>
|
|
|
|
</div><!-- /tab-panels -->
|
|
|
|
</main>
|
|
|
|
</div><!-- /app-shell -->
|
|
|
|
<!-- ══════════ Order Detail Modal ══════════ -->
|
|
<div class="inv-modal-overlay" id="orderModal">
|
|
<div class="inv-modal inv-modal--wide">
|
|
<div class="inv-modal__header">
|
|
<h3>Detalle de Orden ML</h3>
|
|
<button class="inv-modal__close" onclick="closeModal('orderModal')">×</button>
|
|
</div>
|
|
<div class="inv-modal__body" id="orderModalBody">cargando...</div>
|
|
<div class="inv-modal__footer" id="orderModalFooter"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/pos/static/js/i18n.js" defer></script>
|
|
<script src="/pos/static/js/app-init.js" defer></script>
|
|
<script src="/pos/static/js/splash-loader.js?v=1" defer></script>
|
|
<script src="/pos/static/js/pos-utils.js?v=2" defer></script>
|
|
<script src="/pos/static/js/sidebar.js" defer></script>
|
|
<script src="/pos/static/js/marketplace_external.js?v=4" defer></script>
|
|
<script>if('serviceWorker' in navigator){navigator.serviceWorker.register('/pos/sw.js',{scope:'/pos/'});}</script>
|
|
</body>
|
|
</html>
|