feat(ui): infinite scroll, saved filters, product timeline, image comparator, customers bulk toolbar, dark mode refinements
This commit is contained in:
@@ -1314,6 +1314,15 @@
|
||||
html += '<span id="imgUploadStatus" style="display:block;margin-top:4px;font-size:var(--text-caption);color:var(--color-text-muted);"></span>';
|
||||
html += '</div>';
|
||||
|
||||
// Action buttons
|
||||
html += '<div style="display:flex;gap:8px;justify-content:center;margin-bottom:16px;padding-bottom:16px;border-bottom:1px solid var(--color-border);">';
|
||||
html += '<button class="btn btn--ghost btn--sm" onclick="showProductTimeline(' + data.id + ')">📅 Timeline</button>';
|
||||
if (data.image_url) {
|
||||
html += '<button class="btn btn--ghost btn--sm" onclick="showImageCompare(\'' + esc(data.image_url) + '\')">🖼️ Comparar</button>';
|
||||
}
|
||||
html += '<button class="btn btn--ghost btn--sm" onclick="viewHistory(' + data.id + ')">📜 Historial</button>';
|
||||
html += '</div>';
|
||||
|
||||
// Product info header
|
||||
html += '<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:16px;padding-bottom:16px;border-bottom:1px solid var(--color-border);">';
|
||||
html += '<div><span style="font-size:var(--text-caption);color:var(--color-text-muted);text-transform:uppercase;display:block;">ID Inventario</span><strong style="font-family:var(--font-mono);">' + data.id + '</strong></div>';
|
||||
@@ -1535,9 +1544,76 @@
|
||||
window.autoMatchCompat = autoMatchCompat;
|
||||
window.removeCompat = removeCompat;
|
||||
|
||||
// ─── Product Timeline ──────────────────────────────────────────
|
||||
window.showProductTimeline = function(itemId) {
|
||||
var modal = document.getElementById('productTimelineModal');
|
||||
var body = document.getElementById('productTimelineBody');
|
||||
body.innerHTML = '<div style="padding:20px;"><div class="skeleton skeleton--text"></div><div class="skeleton skeleton--text-sm"></div></div>';
|
||||
modal.classList.add('is-open');
|
||||
|
||||
apiFetch(API + '/items/' + itemId + '/history').then(function(data) {
|
||||
var history = (data && data.data) ? data.data : [];
|
||||
var html = '<div class="timeline">';
|
||||
html += '<div class="timeline__item"><div class="timeline__dot timeline__dot--green"></div><div class="timeline__content"><div class="timeline__date">Producto creado</div><div class="timeline__title">Registro inicial en inventario</div></div></div>';
|
||||
history.forEach(function(h) {
|
||||
var color = h.quantity > 0 ? 'timeline__dot--green' : (h.quantity < 0 ? 'timeline__dot--red' : 'timeline__dot--blue');
|
||||
var title = (h.type || 'Movimiento') + ' · ' + (h.quantity > 0 ? '+' : '') + h.quantity + ' unidades';
|
||||
html += '<div class="timeline__item"><div class="timeline__dot ' + color + '"></div><div class="timeline__content">' +
|
||||
'<div class="timeline__date">' + esc(h.date) + ' · ' + esc(h.employee) + '</div>' +
|
||||
'<div class="timeline__title">' + esc(title) + '</div>' +
|
||||
(h.notes ? '<div class="timeline__desc">' + esc(h.notes) + '</div>' : '') +
|
||||
'</div></div>';
|
||||
});
|
||||
html += '</div>';
|
||||
body.innerHTML = html;
|
||||
});
|
||||
};
|
||||
|
||||
// ─── Image Comparator ──────────────────────────────────────────
|
||||
window.showImageCompare = function(imageUrl) {
|
||||
var modal = document.getElementById('imageCompareModal');
|
||||
document.getElementById('imgCompareNew').src = imageUrl + '?t=' + Date.now();
|
||||
document.getElementById('imgCompareOld').src = imageUrl + '?t=' + (Date.now() - 1);
|
||||
modal.classList.add('is-open');
|
||||
setTimeout(function() { if (typeof initImageComparator === 'function') initImageComparator('#imgCompareContainer'); }, 100);
|
||||
};
|
||||
|
||||
// ─── Infinite Scroll ───────────────────────────────────────────
|
||||
var _infiniteScrollInstance = null;
|
||||
function setupInfiniteScroll() {
|
||||
if (_infiniteScrollInstance) _infiniteScrollInstance.disconnect();
|
||||
var sentinel = document.createElement('div');
|
||||
sentinel.id = 'inventoryScrollSentinel';
|
||||
sentinel.style.cssText = 'height:1px;';
|
||||
var wrapper = document.querySelector('.table-wrapper');
|
||||
if (wrapper) wrapper.appendChild(sentinel);
|
||||
_infiniteScrollInstance = new InfiniteScroll({
|
||||
sentinelParent: wrapper,
|
||||
onLoad: function(done) {
|
||||
if (!currentSearch && currentPage < (window._inventoryTotalPages || 999)) {
|
||||
loadItems(currentPage + 1);
|
||||
}
|
||||
if (done) done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Saved Filters ─────────────────────────────────────────────
|
||||
function renderSavedFilters() {
|
||||
var container = document.getElementById('savedFiltersContainer');
|
||||
if (!container) return;
|
||||
SavedFilters.renderChips('savedFiltersContainer', function(filters) {
|
||||
if (filters.search) {
|
||||
var el = document.getElementById('productSearch');
|
||||
if (el) { el.value = filters.search; loadItems(1, filters.search); }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// =====================================================================
|
||||
// INIT — load stock on page load
|
||||
// =====================================================================
|
||||
|
||||
loadItems(1);
|
||||
renderSavedFilters();
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user