5d60d33db1
Volledige Foodlinkk Command Center uitbreiding met social automatisering, reclamefolder filters, Proxmox monitoring en documentatie.
101 lines
3.2 KiB
JavaScript
101 lines
3.2 KiB
JavaScript
window.beursHub = function () {
|
|
return {
|
|
tab: new URLSearchParams(location.search).get('tab') || 'beurs',
|
|
busy: false,
|
|
lastRefresh: '',
|
|
listed: [],
|
|
unlisted: [],
|
|
summary: {},
|
|
trends: { halal_meat_trends: [], top_dishes: [], market_trends: [] },
|
|
concepts: [],
|
|
events: [],
|
|
platformStats: {},
|
|
eventFilter: '',
|
|
pollTimer: null,
|
|
indicatorStyle: { left: '0%', width: '25%' },
|
|
|
|
init() {
|
|
this.updateIndicator();
|
|
this.refreshAll();
|
|
this.pollTimer = setInterval(() => {
|
|
if (this.tab === 'events') this.loadEvents(false);
|
|
}, 5000);
|
|
},
|
|
|
|
setTab(t) {
|
|
this.tab = t;
|
|
const url = new URL(location.href);
|
|
url.searchParams.set('tab', t);
|
|
history.replaceState({}, '', url);
|
|
this.updateIndicator();
|
|
if (t === 'trends' && !this.trends.halal_meat_trends?.length) this.loadTrends();
|
|
if (t === 'concepten' && !this.concepts.length) this.loadConcepts();
|
|
if (t === 'events') this.loadEvents();
|
|
},
|
|
|
|
updateIndicator() {
|
|
const tabs = ['beurs', 'trends', 'concepten', 'events'];
|
|
const i = tabs.indexOf(this.tab);
|
|
const w = 100 / tabs.length;
|
|
this.indicatorStyle = { left: (i * w) + '%', width: w + '%' };
|
|
},
|
|
|
|
sparkPoints(arr) {
|
|
if (!arr || !arr.length) return '';
|
|
const min = Math.min.apply(null, arr);
|
|
const max = Math.max.apply(null, arr);
|
|
const range = max - min || 1;
|
|
return arr.map(function (v, idx) {
|
|
var x = (idx / (arr.length - 1 || 1)) * 100;
|
|
var y = 28 - ((v - min) / range) * 24;
|
|
return x.toFixed(1) + ',' + y.toFixed(1);
|
|
}).join(' ');
|
|
},
|
|
|
|
async refreshAll() {
|
|
this.busy = true;
|
|
try {
|
|
await Promise.all([
|
|
this.loadMarket(),
|
|
this.loadTrends(),
|
|
this.loadConcepts(),
|
|
this.loadEvents(false),
|
|
]);
|
|
this.lastRefresh = new Date().toLocaleString('nl-NL');
|
|
if (typeof Cockpit !== 'undefined') Cockpit.toast('Beurs data bijgewerkt', 'success');
|
|
} catch (e) {
|
|
if (typeof Cockpit !== 'undefined') Cockpit.toast(e.message, 'error');
|
|
}
|
|
this.busy = false;
|
|
},
|
|
|
|
async loadMarket() {
|
|
const d = await fetch('/api/retail/market/supermarkets').then(function (r) { return r.json(); });
|
|
this.listed = d.listed || [];
|
|
this.unlisted = d.unlisted_nl || [];
|
|
this.summary = d.summary || {};
|
|
},
|
|
|
|
async loadTrends() {
|
|
const d = await fetch('/api/retail/market/food-trends').then(function (r) { return r.json(); });
|
|
this.trends = d;
|
|
},
|
|
|
|
async loadConcepts() {
|
|
const d = await fetch('/api/retail/market/concepts?limit=6').then(function (r) { return r.json(); });
|
|
this.concepts = d.concepts || [];
|
|
},
|
|
|
|
async loadEvents(toast) {
|
|
var q = this.eventFilter ? '?limit=80&agent=' + encodeURIComponent(this.eventFilter) : '?limit=80';
|
|
try {
|
|
var r = await fetch('/api/live/platform' + q).then(function (x) { return x.json(); });
|
|
this.events = r.events || [];
|
|
this.platformStats = r.stats || {};
|
|
} catch (e) {
|
|
if (toast !== false && typeof Cockpit !== 'undefined') Cockpit.toast(e.message, 'error');
|
|
}
|
|
},
|
|
};
|
|
};
|