diff --git a/packages/dashboard/index.html b/packages/dashboard/index.html index 0d5cb24..34a5749 100644 --- a/packages/dashboard/index.html +++ b/packages/dashboard/index.html @@ -413,14 +413,14 @@ .panel::-webkit-scrollbar { width: 4px; } .panel::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; } .panel-close { - position: absolute; top: 1rem; right: 1rem; - background: var(--surface2); border: 1px solid var(--border); - color: var(--text-dim); width: 32px; height: 32px; border-radius: var(--radius-md); - cursor: pointer; font-size: 1.1rem; + position: absolute; top: 0.75rem; right: 0.75rem; + background: rgba(255,255,255,0.14); border: 1.5px solid rgba(255,255,255,0.28); + color: rgba(255,255,255,0.92); width: 38px; height: 38px; border-radius: 8px; + cursor: pointer; font-size: 1.3rem; font-weight: 700; display: flex; align-items: center; justify-content: center; - transition: all 0.2s; + transition: all 0.2s; box-shadow: 0 2px 10px rgba(0,0,0,0.35); z-index: 10; } - .panel-close:hover { background: var(--accent); color: #fff; border-color: var(--accent); } + .panel-close:hover { background: var(--accent); color: #fff; border-color: var(--accent); box-shadow: 0 2px 12px rgba(255,102,0,0.4); } .panel-title { font-family: var(--font-heading); font-size: 1.3rem; font-weight: 400; color: var(--text-bright); @@ -959,6 +959,24 @@ function buildDOM(parent, html) { parent.appendChild(t.content.cloneNode(true)); } +// Build a human-readable descriptive product name from available fields +function txDescName(t) { + // Use description field if populated and meaningful (not just the SKU) + if (t.description && t.description.length > 10 && t.description !== t.standard_name && t.description !== t.slug) { + return t.description; + } + // Construct from specs + var parts = []; + if (t.speed) parts.push(t.speed); + if (t.form_factor) parts.push(t.form_factor); + if (t.reach_label) parts.push(t.reach_label); + else if (t.reach_meters) parts.push(t.reach_meters + ' km'); + if (t.wavelengths) parts.push('\u03bb' + t.wavelengths); // λ + if (t.connector) parts.push(t.connector); + if (t.fiber_type) parts.push(t.fiber_type); + return parts.join(', ') || ''; +} + function openPanel(html) { var p = el('detail-panel'); buildDOM(el('panel-content'), html); @@ -1750,7 +1768,9 @@ function searchTransceivers() { buildDOM(el('tx-table'), lastTxData.map(function(t) { return '' + '' - + '' + esc(t.standard_name || t.slug) + '' + + '
' + esc(t.part_number || t.standard_name || t.slug) + '
' + + (txDescName(t) && txDescName(t) !== (t.part_number || t.standard_name || t.slug) ? '
' + esc(txDescName(t)) + '
' : '') + + '' + '' + esc(t.vendor_name || '—') + '' + '' + esc(t.form_factor) + '' + '' + esc(t.speed) + '' @@ -1775,6 +1795,16 @@ async function openTxDetail(id) { var t = data.data || data.transceiver || data; var h = ''; + // Product name header — above the image + var descName = txDescName(t); + var sku = t.part_number || t.standard_name || t.slug; + h += '
'; + h += '
' + esc(sku) + '
'; + if (descName && descName !== sku) { + h += '
' + esc(descName) + '
'; + } + h += '
'; + // Image section var hasRealImage = t.image_url || (t.vendor_name === 'FLEXOPTIX' && FF_REFERENCE_IMAGES[t.form_factor]); h += '
';