@@ -1804,7 +1853,7 @@ function goToTab(tabName) {
if (tabName === 'news') loadNews(1);
if (tabName === 'vendors') loadVendors();
if (tabName === 'standards') loadStandardsList();
- if (tabName === 'blog') loadBlogDrafts();
+ if (tabName === 'blog') { loadBlogDrafts(); loadSLLInsights(); }
if (tabName === 'finder') document.getElementById('finder-switch-input').focus();
if (tabName === 'crawlers') loadCrawlerStatus();
if (tabName === 'procurement') loadProcurement();
@@ -2669,16 +2718,26 @@ async function openTxDetail(id) {
var iVer = t.image_verified === true;
var dVer = t.details_verified === true;
var fVer = t.fully_verified === true;
+ // Competitor verified: at least 1 price from a non-Flexoptix vendor in last 30 days
+ var allPricesForBadge = (t.competitor_prices || []).filter(function(p) { return p.url && p.price > 0; });
+ var cVer = allPricesForBadge.some(function(p) {
+ return p.vendor_name && p.vendor_name.toUpperCase().indexOf('FLEXOPTIX') === -1;
+ });
var verItems = [];
if (pVer) verItems.push('β Price');
if (iVer) verItems.push('β Image');
if (dVer) verItems.push('β Details');
- if (fVer) {
+ if (cVer) verItems.push('β Competitor');
+ else verItems.push('β³ Competitor');
+ // 100% VERIFIED requires all 4: Price + Image + Details + Competitor
+ var fullyVerified = fVer && cVer;
+ if (fullyVerified) {
// Inside the green bar: all text must be white/light β not #2d6a4f (same as bg)
var fvItems = [];
if (pVer) fvItems.push('β Price');
if (iVer) fvItems.push('β Image');
if (dVer) fvItems.push('β Details');
+ fvItems.push('β Competitor');
h += '
'
+ 'β 100% VERIFIED'
+ 'β'
@@ -4003,7 +4062,7 @@ function pollBlogLlm(id, attempt) {
var badge = document.querySelector('.ri[data-blog-id="' + id + '"] .blog-status-badge');
if (badge) {
badge.className = 'b b-green blog-status-badge';
- badge.textContent = 'ready';
+ badge.textContent = 'ready β';
}
api('/api/blog/' + id).then(function(data) {
if (data.draft) {
@@ -4016,7 +4075,7 @@ function pollBlogLlm(id, attempt) {
var badge = document.querySelector('.ri[data-blog-id="' + id + '"] .blog-status-badge');
if (badge) {
badge.className = 'b b-yellow blog-status-badge';
- badge.textContent = 'step ' + p.step + '/10';
+ badge.textContent = 'step ' + p.step + '/14';
}
pollBlogLlm(id, attempt + 1);
}
@@ -4206,7 +4265,7 @@ async function loadBlogDrafts() {
buildDOM(el('blog-list'), drafts.map(function(d) {
var p = progressMap[d.id] || {};
var isRunning = p.running === true;
- // Status badge: generating β step X/10, done β ready, published β published, review β review
+ // Status badge: generating β step X/N, review/fo-blog done β ready β, approved β approved, published β published, draft β draft
var statusLabel, statusClass;
if (isRunning) {
statusLabel = p.step ? 'step ' + p.step + '/' + (p.total || 14) : 'generatingβ¦';
@@ -4214,10 +4273,10 @@ async function loadBlogDrafts() {
} else if (d.status === 'published') {
statusLabel = 'published';
statusClass = 'b-green';
- } else if (d.status === 'review') {
- statusLabel = 'review';
- statusClass = 'b-yellow';
- } else if (d.pipeline_steps_completed >= 10 || (d.generated_by || '').includes('fo-blog')) {
+ } else if (d.status === 'approved') {
+ statusLabel = 'approved β';
+ statusClass = 'b-green';
+ } else if (d.status === 'review' || d.pipeline_steps_completed >= 10 || (d.generated_by || '').includes('fo-blog')) {
statusLabel = 'ready β';
statusClass = 'b-green';
} else {
@@ -4335,9 +4394,10 @@ async function updateBlogStatus(id, status) {
async function regenerateBlog(id) {
showToast('Regeneratingβ¦', 'LLM pipeline wird neu gestartet');
try {
+ var token = window.loadToken ? window.loadToken() : '';
var data = await fetch(API + '/api/blog/' + id + '/regenerate', {
method: 'POST',
- headers: { 'Content-Type': 'application/json' }
+ headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }
}).then(function(r) { return r.json(); });
if (data.success) {
showToast('Gestartet', 'LLM lΓ€uft β Status wird aktualisiert');
@@ -4350,6 +4410,153 @@ async function regenerateBlog(id) {
} catch(e) { showToast('Error', e.message, true); }
}
+// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+// SLL v1.0 β Self-Learning Loop
+// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+async function loadSLLInsights() {
+ var token = window.loadToken ? window.loadToken() : '';
+ var el = document.getElementById('sll-insights-content');
+ var badge = document.getElementById('sll-status-badge');
+ if (!el) return;
+ try {
+ var r = await fetch(API + '/api/blog/sll/insights', { headers: { 'Authorization': 'Bearer ' + token } });
+ var d = await r.json();
+ if (!d.success) { el.innerHTML = 'Error loading SLL data'; return; }
+
+ var stats = d.stats;
+ var ready = d.sll_ready;
+ badge.textContent = ready ? 'Active β ' + stats.total_posts + ' posts' : 'Needs data β ' + stats.total_posts + '/5 posts';
+ badge.style.background = ready ? 'rgba(34,197,94,0.2)' : 'rgba(234,179,8,0.2)';
+ badge.style.color = ready ? '#4ade80' : '#fbbf24';
+
+ var h = '
';
+ h += '
' + (stats.best_score || 0) + '
Best Score
';
+ h += '
' + (stats.tiers.gold || 0) + '
π₯ Gold
';
+ h += '
' + (stats.tiers.silver || 0) + '
π₯ Silver
';
+ h += '
' + (stats.tiers.miss || 0) + '
Miss
';
+ h += '
';
+
+ var winners = d.learned_patterns.winners || [];
+ var losers = d.learned_patterns.losers || [];
+
+ if (winners.length > 0) {
+ h += '