diff --git a/packages/api/src/db/queries.ts b/packages/api/src/db/queries.ts
index b0cf7e8..7c8481c 100644
--- a/packages/api/src/db/queries.ts
+++ b/packages/api/src/db/queries.ts
@@ -352,9 +352,20 @@ export async function getFlexoptixSuggestions(switchId: string) {
CASE WHEN t.price_verified_eur IS NOT NULL THEN 'EUR'
ELSE (SELECT po.currency FROM price_observations po
WHERE po.transceiver_id = t.id ORDER BY po.time DESC LIMIT 1)
- END AS latest_currency
+ END AS latest_currency,
+ so.warehouse_de_qty,
+ so.warehouse_global_qty,
+ so.backorder_qty,
+ so.backorder_estimated_date
FROM transceivers t
JOIN vendors v ON t.vendor_id = v.id
+ LEFT JOIN LATERAL (
+ SELECT warehouse_de_qty, warehouse_global_qty, backorder_qty, backorder_estimated_date
+ FROM stock_observations
+ WHERE transceiver_id = t.id
+ ORDER BY time DESC
+ LIMIT 1
+ ) so ON true
WHERE LOWER(v.name) = 'flexoptix'
AND t.form_factor IN (
SELECT form_factor FROM switch_form_factors WHERE form_factor IS NOT NULL
diff --git a/packages/dashboard/index.html b/packages/dashboard/index.html
index 1a89e0d..3bb04b1 100644
--- a/packages/dashboard/index.html
+++ b/packages/dashboard/index.html
@@ -4310,10 +4310,18 @@ async function openSwitchDetail(id) {
+ '';
fch += '
Passend für diesen Switch — FlexBox-Codierung möglich
';
+ // Format speed_gbps → "1.6T", "400G", "100G" etc.
+ function fmtSpeed(gbps) {
+ if (!gbps) return '?';
+ var n = parseFloat(gbps);
+ if (n >= 1000) return (n / 1000) + 'T';
+ return Math.round(n) + 'G';
+ }
+
// Group by speed class
var foGroups = {};
foAll.forEach(function(t) {
- var key = (t.speed_gbps ? t.speed_gbps + 'G' : (t.speed || '?')) + ' ' + (t.form_factor || '?');
+ var key = fmtSpeed(t.speed_gbps) + ' ' + (t.form_factor || '?');
if (!foGroups[key]) foGroups[key] = [];
foGroups[key].push(t);
});
@@ -4342,10 +4350,27 @@ async function openSwitchDetail(id) {
var shopHref = t.product_page_url || ('https://www.flexoptix.net/en/search/ajax/suggest/?q=' + encodeURIComponent(t.part_number || t.standard_name || ''));
var reach = t.reach_label ? '' + esc(t.reach_label) + '' : '';
+ // Stock badges
+ var stockHtml = '';
+ var deQty = parseInt(t.warehouse_de_qty) || 0;
+ var glQty = parseInt(t.warehouse_global_qty) || 0;
+ var boQty = parseInt(t.backorder_qty) || 0;
+ if (deQty > 0 || glQty > 0 || boQty > 0) {
+ stockHtml += '';
+ if (deQty > 0) stockHtml += 'DE ' + deQty + ' Stk';
+ if (glQty > 0) stockHtml += 'Global ' + glQty + ' Stk';
+ if (boQty > 0) {
+ var boDate = t.backorder_estimated_date ? ' bis ' + new Date(t.backorder_estimated_date).toLocaleDateString('de-DE', {day:'2-digit',month:'2-digit'}) : '';
+ stockHtml += 'Zulauf ' + boQty + boDate + '';
+ }
+ stockHtml += '
';
+ }
+
fch += ''
+ '
'
- + '
' + esc(t.part_number || t.standard_name || t.slug) + ''
- + reach
+ + '
' + esc(t.part_number || t.standard_name || t.slug) + ''
+ + reach + '
'
+ + stockHtml
+ '
'
+ (priceStr
? '
' + priceStr + ''