diff --git a/matrix.db b/matrix.db
index 898c929..e5e5217 100644
Binary files a/matrix.db and b/matrix.db differ
diff --git a/static/css/index.css b/static/css/index.css
index 8a8d766..12825f7 100644
--- a/static/css/index.css
+++ b/static/css/index.css
@@ -687,6 +687,7 @@
.vendor-tooltip.visible {
opacity: 1;
transform: translateY(0) scale(1);
+ pointer-events: auto;
}
.vtt-logo {
width: 100%;
@@ -754,3 +755,46 @@
border: 1px solid #d0e0ff;
}
.vtt-link:hover { opacity: .85; }
+ /* Vendor info bar in results */
+ .vendor-info-bar {
+ display: flex;
+ align-items: flex-start;
+ gap: 18px;
+ background: linear-gradient(135deg, #f0f5ff 0%, #e8f0ff 100%);
+ border: 1px solid #c8d8f5;
+ border-radius: 16px;
+ padding: 16px 20px;
+ margin-bottom: 18px;
+ }
+ .vendor-info-bar + .vendor-info-bar { margin-top: -8px; }
+ .vib-logo {
+ flex-shrink: 0;
+ width: 100px;
+ height: 64px;
+ background: #fff;
+ border-radius: 10px;
+ border: 1px solid #dae6ff;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 8px 10px;
+ }
+ .vib-logo img { max-width: 100%; max-height: 48px; object-fit: contain; }
+ .vib-logo-text { font-size: 18px; font-weight: 800; color: #3978e0; }
+ .vib-info { flex: 1; min-width: 0; }
+ .vib-name { font-size: 15px; font-weight: 800; color: #1a3e79; margin: 0 0 5px; }
+ .vib-desc { font-size: 13px; color: #4a5d7a; line-height: 1.55; margin: 0 0 10px; }
+ .vib-links { display: flex; gap: 8px; flex-wrap: wrap; }
+ .vib-link {
+ display: inline-flex;
+ align-items: center;
+ font-size: 12px;
+ font-weight: 700;
+ padding: 4px 12px;
+ border-radius: 999px;
+ text-decoration: none;
+ transition: .15s ease;
+ }
+ .vib-link.mont { background: linear-gradient(135deg, #1f4ea3, #3978e0); color: #fff; }
+ .vib-link.site { background: #fff; color: #2a5aaa; border: 1px solid #c8d8f5; }
+ .vib-link:hover { opacity: .82; transform: translateY(-1px); }
diff --git a/static/js/index.js b/static/js/index.js
index 5d9ec59..30c2f64 100644
--- a/static/js/index.js
+++ b/static/js/index.js
@@ -30,8 +30,12 @@
const tooltip = document.createElement('div');
tooltip.className = 'vendor-tooltip';
document.body.appendChild(tooltip);
+ tooltip.addEventListener('mouseenter', () => { overTooltip = true; clearTimeout(hideTimer); });
+ tooltip.addEventListener('mouseleave', () => { overTooltip = false; hideTooltip(); });
let tooltipTimer = null;
+ let hideTimer = null;
+ let overTooltip = false;
let vendorMap = {};
function buildVendorMap() {
@@ -82,8 +86,12 @@
tooltip.classList.add('visible');
}
- function hideTooltip() {
- tooltip.classList.remove('visible');
+ function hideTooltip(immediate) {
+ clearTimeout(hideTimer);
+ if (immediate) { tooltip.classList.remove('visible'); return; }
+ hideTimer = setTimeout(() => {
+ if (!overTooltip) tooltip.classList.remove('visible');
+ }, 120);
}
@@ -244,6 +252,8 @@
function renderResults() {
const { allowedCategories, allowedVendors, allowedProducts, productsByVendor, categoriesByProduct } = visibleSets();
const productsById = new Map(state.data.products.map(p => [p.id, p]));
+ const vendorsById = new Map(state.data.vendors.map(v => [v.id, v]));
+ const isIb = state.scope === 'ib';
const rows = [];
for (const vendor of state.data.vendors) {
@@ -257,7 +267,7 @@
});
const products = productIds.map(pId => productsById.get(pId)).filter(Boolean);
if (products.length === 0) continue;
- rows.push({ vendor: vendor.name, products });
+ rows.push({ vendor, products });
}
el.resultRows.innerHTML = "";
@@ -266,21 +276,51 @@
return;
}
+ // Vendor info bars for selected vendors
+ if (state.selectedVendors.size > 0) {
+ for (const vid of state.selectedVendors) {
+ const v = vendorsById.get(vid);
+ if (!v) continue;
+ const bar = document.createElement('div');
+ bar.className = 'vendor-info-bar';
+ const logoInner = v.logo
+ ? ``
+ : `${v.name.slice(0,2).toUpperCase()}`;
+ let linksHtml = '';
+ if (v.mont_page) linksHtml += `MONT ↗`;
+ if (v.website) linksHtml += `Сайт ↗`;
+ bar.innerHTML = `
+