feat(procurement): transceiver search box — find a part, click for prices/suppliers/availability/price-chart

This commit is contained in:
Rene Fichtmueller 2026-06-11 10:12:01 +00:00
parent 5d69f0160c
commit c6b5bcf844

View File

@ -1770,6 +1770,16 @@ function fmtSpd(gbps) {
<!-- PROCUREMENT INTEL TAB --> <!-- PROCUREMENT INTEL TAB -->
<div id="tab-procurement" class="hidden"> <div id="tab-procurement" class="hidden">
<!-- Transceiver-Suche -->
<div style="margin-bottom:1.25rem;border:1px solid var(--border);border-radius:10px;padding:0.9rem 1rem;background:var(--surface2)">
<div style="font-size:0.8rem;font-weight:700;color:var(--text-bright);margin-bottom:0.5rem">🔎 Transceiver suchen — Preise, Anbieter, Verfügbarkeit &amp; Signale</div>
<div style="display:flex;gap:0.5rem;flex-wrap:wrap">
<input id="proc-tx-search" type="text" onkeydown="if(event.key==='Enter')procTxSearch()" placeholder="Part-Number oder Name, z.B. SFP-10G-LR, QSFP28-100G…" style="flex:1;min-width:240px;padding:0.5rem 0.7rem;border:1px solid var(--border);border-radius:7px;background:var(--surface);color:var(--text);font-size:0.85rem">
<button onclick="procTxSearch()" style="padding:0.5rem 1.1rem;border:none;border-radius:7px;background:var(--accent);color:#fff;font-weight:600;font-size:0.85rem;cursor:pointer">Suchen</button>
</div>
<div id="proc-tx-results" style="margin-top:0.6rem"></div>
</div>
<!-- Sub-nav --> <!-- Sub-nav -->
<div style="display:flex;gap:0.5rem;margin-bottom:1.25rem;flex-wrap:wrap;align-items:center"> <div style="display:flex;gap:0.5rem;margin-bottom:1.25rem;flex-wrap:wrap;align-items:center">
<button onclick="showProcSection('signals')" id="proc-btn-signals" class="proc-btn proc-btn-active">Reorder Signals</button> <button onclick="showProcSection('signals')" id="proc-btn-signals" class="proc-btn proc-btn-active">Reorder Signals</button>
@ -10534,6 +10544,38 @@ function showTokenHelp(job) {
else { alert(msg); } else { alert(msg); }
} }
/* ── Procurement: Transceiver-Suche ────────────────────────────────────── */
async function procTxSearch() {
var q = (el('proc-tx-search').value || '').trim();
var box = el('proc-tx-results');
if (!q) { box.innerHTML = '<div style="color:var(--text-dim);font-size:0.78rem">Bitte Part-Number oder Name eingeben.</div>'; return; }
box.innerHTML = '<div style="color:var(--text-dim);font-size:0.78rem">Suche…</div>';
try {
var d = await api('/api/transceivers?q=' + encodeURIComponent(q) + '&limit=25');
var rows = d.data || [];
if (!rows.length) { box.innerHTML = '<div style="color:var(--text-dim);font-size:0.78rem">Kein Transceiver gefunden für „' + esc(q) + '".</div>'; return; }
var seen = {};
var html = '<div style="font-size:0.72rem;color:var(--text-dim);margin-bottom:0.35rem">' + (d.total || rows.length) + ' Treffer — klicken für Details (Preise, Anbieter, Verfügbarkeit, Preisverlauf):</div>';
html += '<div style="display:flex;flex-direction:column;gap:2px;max-height:340px;overflow-y:auto">';
rows.forEach(function(r) {
// dedupe by part_number (mehrere OEM-Zeilen)
var key = (r.part_number || r.id);
if (seen[key]) return; seen[key] = 1;
var spd = (typeof fmtSpd === 'function') ? fmtSpd(r.speed_gbps) : (r.speed_gbps + 'G');
html += '<div onclick="openTxDetail(\'' + esc(String(r.id)) + '\')" style="cursor:pointer;display:flex;align-items:center;gap:0.6rem;padding:6px 8px;border-radius:6px;border:1px solid var(--border)" onmouseover="this.style.background=\'var(--surface2)\'" onmouseout="this.style.background=\'\'">'
+ '<span style="font-family:var(--mono);font-size:0.78rem;font-weight:600;color:var(--text-bright);min-width:140px">' + esc(r.part_number || r.standard_name || '—') + '</span>'
+ '<span style="font-size:0.7rem;color:var(--text-dim)">' + esc(r.form_factor || '') + ' · ' + spd + (r.reach_label ? ' · ' + esc(r.reach_label) : '') + '</span>'
+ '<span style="font-size:0.68rem;color:var(--text-dim);margin-left:auto">' + esc(r.vendor_name || '') + '</span>'
+ '</div>';
});
html += '</div>';
box.innerHTML = html;
} catch (e) {
box.innerHTML = '<div style="color:var(--text-dim);font-size:0.78rem">Suche fehlgeschlagen: ' + esc(e.message) + '</div>';
}
}
async function loadProcurementPulse() { async function loadProcurementPulse() {
var pulse = el('ov-proc-pulse'); var pulse = el('ov-proc-pulse');
var moversCard = el('ov-movers-card'); var moversCard = el('ov-movers-card');