From 3e780ce6b7685aff055798e974fc1f1f121350f8 Mon Sep 17 00:00:00 2001 From: Rene Fichtmueller Date: Wed, 1 Apr 2026 23:32:01 +0200 Subject: [PATCH] feat: add tooltips throughout Procurement Intelligence tab + rename nav - Rename nav tab and sub-nav from 'Procurement Intel' to 'Procurement Intelligence' - Add data-tip tooltips to all 8 ABC table column headers - Add title attributes to signal badges, ABC class badges, supply risk, stock/price/lead trend spans, signal strength bar - Add hover descriptions to Market Intelligence type icons, buy signal badges, technology tags, impact horizon, source - Add hover descriptions to Lifecycle Events type icons, buy signal badges, impact level, effective date - Tooltips explain business meaning of every data point (e.g. ABC classification formula, demand score composition, supply risk levels) --- packages/dashboard/index.html | 76 +++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 26 deletions(-) diff --git a/packages/dashboard/index.html b/packages/dashboard/index.html index b6ec5ca..62fb3c0 100644 --- a/packages/dashboard/index.html +++ b/packages/dashboard/index.html @@ -747,7 +747,7 @@
News
Finder
Blog Engine
-
Procurement Intel
+
Procurement Intelligence
@@ -992,7 +992,7 @@
- +
@@ -1023,14 +1023,14 @@
- - - - - - - - + + + + + + + +
ClassProductForm FactorDemand ScoreCompat.VendorsSupply RiskSignalClassProductForm FactorDemand ScoreCompat.VendorsSupply RiskSignal
Loading...
@@ -3244,7 +3244,8 @@ function renderSignals(filterSig) { try { reasons = JSON.parse(r.reasons || '[]'); } catch(e) {} var sigClass = 'signal-' + (r.signal || 'monitor').replace('_','-'); var badgeClass = 'sig-badge-' + (r.signal || 'monitor').replace('_now','').replace('_',''); - var abcBadge = r.abc_class ? '' + r.abc_class + '' : ''; + var abcTitles = { A:'Class A โ€” high turnover product, top 20% by value. Prioritize stock availability.', B:'Class B โ€” medium turnover. Standard replenishment cycle.', C:'Class C โ€” low turnover. Order on demand only.' }; + var abcBadge = r.abc_class ? '' + r.abc_class + '' : ''; var strengthPct = Math.round((r.signal_strength || 0) * 100); var productName = r.standard_name || r.part_number || r.slug || 'โ€”'; var imgHtml = ''; @@ -3260,19 +3261,19 @@ function renderSignals(filterSig) { + '
' + '
' + '
' - + '' + (signalIcon[r.signal] || '') + ' ' + (signalLabel[r.signal] || r.signal) + '' + + '' + (signalIcon[r.signal] || '') + ' ' + (signalLabel[r.signal] || r.signal) + '' + abcBadge - + (r.supply_risk ? '' + esc(r.supply_risk) + ' risk' : '') + + (r.supply_risk ? '' + esc(r.supply_risk) + ' risk' : '') + '
' + '
' + (reasons.length ? reasons.map(function(r2) { return 'โ†’ ' + esc(r2); }).join('
') : 'Insufficient data') + '
' + '
' - + (r.stock_trend ? 'Stock: ' + r.stock_trend + '' : '') - + (r.price_trend ? 'Price: ' + r.price_trend + '' : '') - + (r.lead_time_weeks ? 'Lead: ' + r.lead_time_weeks + 'w' : '') + + (r.stock_trend ? 'Stock: ' + r.stock_trend + '' : '') + + (r.price_trend ? 'Price: ' + r.price_trend + '' : '') + + (r.lead_time_weeks ? 'Lead: ' + r.lead_time_weeks + 'w' : '') + '
' - + '
' + + '
' + '
' + '
' + '
Signal strength: ' + strengthPct + '%
' @@ -3326,25 +3327,35 @@ async function loadProcMarketIntel() { capex_cycle:'๐Ÿ’ฐ', trade_show:'๐ŸŽช', standard_ratified:'๐Ÿ“‹', standard_draft:'๐Ÿ“', distributor_lead_time:'๐Ÿšš', supply_chain:'๐Ÿญ', tender:'๐Ÿ“‘' }; + var typeDesc = { + capex_cycle:'Capital expenditure cycle event โ€” customer budget release, fiscal year start, major infrastructure spend', + trade_show:'Trade show or conference (OFC, ECOC, MWC, IEEE) โ€” often signals new product launches and technology shifts', + standard_ratified:'IEEE/MSA standard officially ratified โ€” technology is production-ready, adoption typically accelerates', + standard_draft:'Standard in draft phase โ€” technology is emerging, early adopters phase', + distributor_lead_time:'Distributor lead time change โ€” indicates supply chain pressure or inventory build-up', + supply_chain:'Supply chain event โ€” factory capacity, shortage, logistics disruption', + tender:'Public or enterprise tender/RFP published โ€” indicates near-term procurement demand' + }; container.innerHTML = items.map(function(item) { var sig = item.buy_signal_implication || 'none'; var badgeClass = 'intel-' + sig.replace('_now','').replace('_',''); var sigLabel = { buy_now:'๐Ÿ”ด Buy Now', wait:'๐ŸŸก Wait', hold:'๐ŸŸข Hold', monitor:'๐Ÿ”ต Monitor', none:'โ€”' }; + var sigDesc = { buy_now:'Buy Now: this market event suggests immediate procurement โ€” prices or availability will worsen', wait:'Wait: conditions suggest holding off โ€” better pricing or availability expected soon', hold:'Hold: market stable, no urgency to act', monitor:'Monitor: track this development, not yet actionable', none:'No specific procurement implication' }; var techs = (item.technologies || []).map(function(t) { - return '' + esc(t) + ''; + return '' + esc(t) + ''; }).join(' '); return '
' + '
' - + '' + (typeIcon[item.intel_type] || '๐Ÿ“Š') + '' + + '' + (typeIcon[item.intel_type] || '๐Ÿ“Š') + '' + '
' - + '' + (sigLabel[sig] || sig) + '' + + '' + (sigLabel[sig] || sig) + '' + '
' + esc(item.title) + '
' + '
' + '
' + esc(item.summary || '') + '
' + (techs ? '
' + techs + '
' : '') + '
' - + '' + esc(item.source_name) + '' - + (item.impact_horizon_months ? 'Impact: ~' + item.impact_horizon_months + ' months' : '') + + '' + esc(item.source_name) + '' + + (item.impact_horizon_months ? 'Impact: ~' + item.impact_horizon_months + ' months' : '') + '
' + '
'; }).join(''); @@ -3367,23 +3378,36 @@ async function loadProcLifecycle() { standard_draft:'๐Ÿ“', capex_peak:'๐Ÿ’ฐ', trade_show:'๐ŸŽช', supply_risk:'โš ๏ธ', tender:'๐Ÿ“‘', price_floor:'๐Ÿ“‰' }; + var typeDesc = { + eol_announced:'End-of-Life announced โ€” vendor has confirmed a product or standard will be discontinued. Start planning migration.', + eol_effective:'End-of-Life effective โ€” product is no longer manufactured or supported. Immediately find replacements.', + standard_ratified:'Standard officially ratified by IEEE or MSA โ€” technology is mature, safe to deploy at scale.', + standard_draft:'Standard in draft โ€” technology is emerging. Early adopters phase, compatibility not yet guaranteed.', + capex_peak:'Capital expenditure peak โ€” major procurement wave expected. May affect availability and pricing.', + trade_show:'Trade show event (OFC, ECOC, MWC) โ€” often triggers new product launches and price adjustments.', + supply_risk:'Supply chain risk identified โ€” potential shortage, capacity constraint, or geopolitical factor.', + tender:'Public or enterprise tender published โ€” indicates confirmed near-term demand from large buyer.', + price_floor:'Price floor reached โ€” technology has hit bottom pricing. Unlikely to drop further; good time to stock up.' + }; var impactColor = { critical:'#c1121f', high:'#c1121f', medium:'var(--yellow)', low:'var(--green)' }; + var impactDesc = { critical:'Critical impact โ€” immediate action required', high:'High impact โ€” plan response within weeks', medium:'Medium impact โ€” monitor and prepare response', low:'Low impact โ€” informational' }; var sigLabel = { buy_now:'๐Ÿ”ด Buy Now', wait:'๐ŸŸก Wait', hold:'๐ŸŸข Hold', monitor:'๐Ÿ”ต Monitor' }; + var sigDesc = { buy_now:'Buy Now: this event signals immediate procurement urgency', wait:'Wait: better conditions expected after this event resolves', hold:'Hold: no change to current procurement strategy', monitor:'Monitor: track how this event develops before acting' }; container.innerHTML = items.map(function(item) { var ic = impactColor[item.impact_level] || 'var(--text-dim)'; var productInfo = item.part_number ? esc(item.part_number) + (item.form_factor ? ' ยท ' + esc(item.form_factor) : '') : ''; var dateStr = item.effective_date ? new Date(item.effective_date).toLocaleDateString('de-DE') : ''; - return '
' + return '
' + '
' - + '' + (typeIcon[item.event_type] || '๐Ÿ“Œ') + '' + + '' + (typeIcon[item.event_type] || '๐Ÿ“Œ') + '' + '
' - + (item.buy_signal ? '' + (sigLabel[item.buy_signal] || item.buy_signal) + '' : '') + + (item.buy_signal ? '' + (sigLabel[item.buy_signal] || item.buy_signal) + '' : '') + '
' + esc(item.title) + '
' + '
' + (item.description ? '
' + esc(item.description.substring(0, 200)) + (item.description.length > 200 ? 'โ€ฆ' : '') + '
' : '') + '
' + '' + esc(item.source_name || '') + (productInfo ? ' ยท ' + productInfo : '') + '' - + (dateStr ? '' + dateStr + '' : '') + + (dateStr ? '' + dateStr + '' : '') + '
' + '
'; }).join('');