Files
foodlinkk-command-center/cockpit/templates/beurs.html
T
Aissa 5d60d33db1 Platform bundle: marketing publish, IT ops, packaging, agents mesh.
Volledige Foodlinkk Command Center uitbreiding met social automatisering,
reclamefolder filters, Proxmox monitoring en documentatie.
2026-06-09 00:41:27 +00:00

222 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block extra_head %}
<link rel="stylesheet" href="/static/css/hermes.css" />
<link rel="stylesheet" href="/static/css/beurs.css?v=1" />
{% endblock %}
{% block content %}
<div class="beurs-shell" x-data="beursHub()" x-init="init()">
<header class="beurs-hero">
<div>
<h1>Beurs & Live Intel <span class="live-badge">Live</span></h1>
<p class="hero-sub">Supermarkt aandelen · halal trends · concept lab · platform events</p>
<small x-text="'Laatste refresh: ' + (lastRefresh || '—')"></small>
</div>
<div class="beurs-hero-actions">
<button class="btn btn-pulse" @click="refreshAll()" :disabled="busy">↻ Alles verversen</button>
<a href="/" class="btn">Herman Dashboard</a>
</div>
</header>
<div class="neo-tab-bar" role="tablist">
<button type="button" class="neo-tab" :class="{ active: tab === 'beurs' }" @click="setTab('beurs')">
<span class="neo-tab-icon">📈</span><span>Beurs Live</span>
</button>
<button type="button" class="neo-tab" :class="{ active: tab === 'trends' }" @click="setTab('trends')">
<span class="neo-tab-icon">☪️</span><span>Halal & Trends</span>
</button>
<button type="button" class="neo-tab" :class="{ active: tab === 'concepten' }" @click="setTab('concepten')">
<span class="neo-tab-icon">💡</span><span>Concept Lab</span>
</button>
<button type="button" class="neo-tab" :class="{ active: tab === 'events' }" @click="setTab('events')">
<span class="neo-tab-icon"></span><span>Platform Live</span>
<span class="neo-tab-badge" x-show="platformStats.pending_approvals" x-text="platformStats.pending_approvals"></span>
</button>
<div class="neo-tab-indicator" :style="indicatorStyle"></div>
</div>
<!-- BEURS LIVE -->
<section x-show="tab === 'beurs'" x-cloak class="beurs-section">
<div class="beurs-summary-row">
<div class="beurs-stat-card">
<span>Gem. dag %</span>
<strong :class="(summary.avg_change_pct||0) >= 0 ? 'up' : 'down'" x-text="((summary.avg_change_pct||0) >= 0 ? '+' : '') + (summary.avg_change_pct||0) + '%'"></strong>
</div>
<div class="beurs-stat-card">
<span>Beursgenoteerd</span>
<strong x-text="summary.listed_count || listed.length"></strong>
</div>
<div class="beurs-stat-card">
<span>NL privé ketens</span>
<strong x-text="summary.unlisted_nl_count || unlisted.length"></strong>
</div>
<div class="beurs-stat-card source-card">
<span>Databron</span>
<strong><a href="https://finance.yahoo.com" target="_blank" rel="noopener">Yahoo Finance ↗</a></strong>
</div>
</div>
<h2 class="section-label"><span class="hm-live-dot"></span> Beursgenoteerde supermarkten</h2>
<div class="beurs-grid">
<template x-for="s in listed" :key="s.symbol">
<article class="beurs-card" :class="'trend-' + (s.trend || 'flat')">
<div class="beurs-card-head">
<div class="beurs-chain-dot" :style="'background:' + (s.color || '#38bdf8')"></div>
<div>
<strong x-text="s.symbol"></strong>
<small x-text="s.name"></small>
</div>
<span class="beurs-pct" :class="(s.change_pct||0) >= 0 ? 'up' : 'down'"
x-text="((s.change_pct||0) >= 0 ? '▲' : '▼') + ' ' + Math.abs(s.change_pct||0).toFixed(2) + '%'"></span>
</div>
<div class="beurs-chains" x-text="(s.chains||[]).join(' · ')"></div>
<div class="beurs-price" x-show="s.price != null">
<span x-text="Number(s.price).toFixed(2)"></span>
<small x-text="s.currency"></small>
<span class="market-state" x-text="s.market_state"></span>
</div>
<svg class="beurs-spark" x-show="(s.sparkline||[]).length" viewBox="0 0 100 30" preserveAspectRatio="none">
<polyline fill="none" stroke-width="2" :stroke="(s.change_pct||0) >= 0 ? '#4ade80' : '#fb7185'" :points="sparkPoints(s.sparkline)"/>
</svg>
<div class="beurs-eq"><span></span><span></span><span></span><span></span><span></span><span></span></div>
<div class="beurs-sources">
<a class="btn-source" :href="s.source_url" target="_blank" rel="noopener">Yahoo Finance ↗</a>
<small x-text="s.exchange"></small>
</div>
</article>
</template>
</div>
<h2 class="section-label" style="margin-top:1.5rem">Nederlandse ketens · niet beursgenoteerd</h2>
<p class="hint">Jumbo, Plus, Dirk, Lidl en ALDI zijn geen beursgenoteerde entiteiten — geen live koers via Yahoo Finance.</p>
<div class="beurs-grid unlisted">
<template x-for="u in unlisted" :key="u.name">
<article class="beurs-card unlisted-card">
<div class="beurs-card-head">
<div class="beurs-chain-dot" :style="'background:' + (u.color || '#64748b')"></div>
<div>
<strong x-text="u.name"></strong>
<small x-text="u.parent"></small>
</div>
<span class="beurs-tag">Privé</span>
</div>
<div class="beurs-chains" x-text="(u.chains||[]).join(' · ')"></div>
<p class="unlisted-note" x-text="u.note || u.exchange"></p>
<div class="beurs-sources">
<a class="btn-source" :href="u.source_url" target="_blank" rel="noopener">Keten info ↗</a>
</div>
</article>
</template>
</div>
</section>
<!-- HALAL & TRENDS -->
<section x-show="tab === 'trends'" x-cloak class="beurs-section">
<div class="beurs-two-col">
<div class="panel-inner">
<h2>☪️ Halal vlees trends <span class="live-badge">RSS Live</span></h2>
<template x-for="h in trends.halal_meat_trends" :key="h.link">
<div class="feed-card">
<span class="tag tag-halal">HALAL VLEES</span>
<a :href="h.source_url || h.link" target="_blank" rel="noopener"><strong x-text="h.title"></strong></a>
<p x-text="(h.summary||'').substring(0,160)"></p>
<div class="feed-actions">
<a class="btn-source" :href="h.link" target="_blank">Artikel ↗</a>
<a class="btn-source" :href="h.feed_url" target="_blank">Bron feed ↗</a>
</div>
</div>
</template>
<p x-show="!trends.halal_meat_trends?.length" class="muted">Geen halal vlees trends — refresh RSS feeds.</p>
</div>
<div class="panel-inner">
<h2>🍱 Top gerechten & maaltijden</h2>
<template x-for="d in trends.top_dishes" :key="d.dish_keyword">
<div class="feed-card dish-card">
<div class="dish-rank">
<strong x-text="d.dish_keyword"></strong>
<span class="tag tag-dish" x-text="d.mentions + '× in feed'"></span>
</div>
<a x-show="d.latest_link" :href="d.source_url" target="_blank" rel="noopener">
<small x-text="d.latest_title"></small>
</a>
<div class="feed-actions" x-show="d.latest_link">
<a class="btn-source" :href="d.latest_link" target="_blank">Bron artikel ↗</a>
</div>
</div>
</template>
<h3 style="margin-top:1.25rem">Markt trends DB</h3>
<template x-for="t in trends.market_trends" :key="t.trend_name">
<div class="feed-card">
<strong x-text="t.trend_name"></strong>
<p x-text="t.description"></p>
<span class="tag tag-trend" x-text="'Kans ' + Math.round((t.opportunity_score||0)*100) + '%'"></span>
</div>
</template>
</div>
</div>
</section>
<!-- CONCEPT LAB -->
<section x-show="tab === 'concepten'" x-cloak class="beurs-section">
<div class="concept-header">
<h2>💡 Concept Lab</h2>
<p class="hint">Automatisch gegenereerde productconcepten op basis van live beurs, halal trends en top gerechten.</p>
<button class="btn btn-pulse-green" @click="loadConcepts()" :disabled="busy">↻ Nieuwe concepten</button>
</div>
<div class="concept-grid">
<template x-for="c in concepts" :key="c.id">
<article class="concept-card">
<span class="concept-num" x-text="'#' + c.id"></span>
<p x-text="c.concept"></p>
<div class="concept-based">
<small x-text="'Gebaseerd op: ' + (c.based_on?.dish || '') + ' · ' + (c.based_on?.market_signal || '')"></small>
</div>
<div class="feed-actions">
<template x-for="(url, i) in (c.source_urls||[])" :key="i">
<a class="btn-source" :href="url" target="_blank" rel="noopener">Bron <span x-text="i+1"></span></a>
</template>
</div>
</article>
</template>
</div>
</section>
<!-- PLATFORM LIVE -->
<section x-show="tab === 'events'" x-cloak class="beurs-section">
<div class="beurs-summary-row">
<div class="beurs-stat-card"><span>Events totaal</span><strong x-text="platformStats.total_events||0"></strong></div>
<div class="beurs-stat-card"><span>Laatste uur</span><strong x-text="platformStats.events_last_hour||0"></strong></div>
<div class="beurs-stat-card warn"><span>Wacht op OK</span><strong x-text="platformStats.pending_approvals||0"></strong></div>
</div>
<div class="events-toolbar">
<select class="form-input" x-model="eventFilter" @change="loadEvents()">
<option value="">Alle agents</option>
<option value="herman">Herman</option>
<option value="retail_intel">Retail Intel</option>
<option value="rss_feeds">RSS Feeds</option>
<option value="wholesale_scraper">Wholesale</option>
<option value="halal_registry">Halal</option>
<option value="hermes">Hermes</option>
</select>
<span class="live-badge">Auto-refresh 5s</span>
</div>
<div class="events-stream">
<template x-for="ev in events" :key="ev.id">
<a class="event-row" :href="ev.click_url" :target="ev.is_external ? '_blank' : '_self'" rel="noopener">
<span class="event-time" x-text="(ev.created_at||'').substring(11,16)"></span>
<span class="event-agent badge" x-text="ev.agent_name"></span>
<span class="event-title" x-text="ev.title"></span>
<span class="event-status" :class="'st-'+ev.status" x-text="ev.status"></span>
<span class="event-source" x-text="ev.is_external ? '↗ extern' : '→ platform'"></span>
</a>
</template>
<p x-show="!events.length" class="muted">Geen events gelogd.</p>
</div>
</section>
</div>
{% endblock %}
{% block scripts %}
<script src="/static/js/beurs.js?v=1"></script>
{% endblock %}