Improve CEO cockpit clarity and Revenue visuals, with Hermes briefing.

Tighten overview KPIs/pipeline height, add selectable Revenue views and a resizable sidebar, and keep supporting Hermes/Wereldexport updates.
This commit is contained in:
Aissa
2026-07-30 11:53:43 +00:00
parent 5dd69a1138
commit 62239f0a4e
14 changed files with 1876 additions and 647 deletions
+50
View File
@@ -5,6 +5,7 @@ function revenueCockpit() {
savedAt: '',
_pollStop: null,
viewMode: 'cockpit',
visualMode: 'table',
goals: { vision_text: '', horizon_text: '', mid_text: '', tagline: '' },
projects: [],
dbProjects: [],
@@ -45,6 +46,8 @@ function revenueCockpit() {
async init() {
localStorage.setItem('foodlinkk-persona', 'ceo');
const saved = localStorage.getItem('rc-visual-mode');
if (saved === 'table' || saved === 'bars' || saved === 'cards') this.visualMode = saved;
await this.loadLive();
await this.loadDbQuiet();
if (window.CockpitLive) {
@@ -126,6 +129,53 @@ function revenueCockpit() {
return t.length <= n ? t : t.slice(0, n).trim() + '…';
},
setVisualMode(mode) {
if (mode !== 'table' && mode !== 'bars' && mode !== 'cards') return;
this.visualMode = mode;
localStorage.setItem('rc-visual-mode', mode);
},
styleLabel(style) {
const map = { green: 'Live', red: 'Inactief', orange: 'Oranje', yellow: 'Strategisch', blue: 'Blauw', white: 'Neutraal' };
return map[style] || 'Neutraal';
},
rankedRows() {
const rows = this.visualRows().slice();
rows.sort((a, b) => (Number(b.margin_month) || 0) - (Number(a.margin_month) || 0));
return rows;
},
cardRows() {
return this.rankedRows().filter((r) => r.margin_month != null || (r.next_steps || '').trim());
},
async setCockpitStyle(style) {
const p = this.selectedProject;
if (!p) return;
if (!p.db_id) {
p.row_style = style;
if (window.Cockpit) Cockpit.toast('Lokaal gezet — sync DB om te bewaren', 'info');
return;
}
try {
await fetch('/api/revenue-cockpit/projects/' + p.db_id, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ row_style: style }),
});
p.row_style = style;
const pi = this.projects.findIndex((x) => this.projectKey(x) === this.projectKey(p));
if (pi >= 0) this.projects[pi].row_style = style;
const di = this.dbProjects.findIndex((x) => x.id === p.db_id);
if (di >= 0) this.dbProjects[di].row_style = style;
if (window.Cockpit) Cockpit.toast('Status → ' + this.styleLabel(style), 'success');
} catch (e) {
if (window.Cockpit) Cockpit.toast('Kleur wijzigen mislukt', 'error');
}
},
styleColor(style) {
const map = {
green: '#22c55e', red: '#ef4444', orange: '#f59e0b',