window.BriefingCharts = (function () { var charts = {}; function destroyAll() { Object.keys(charts).forEach(function (k) { if (charts[k]) { charts[k].destroy(); charts[k] = null; } }); } function parseContent(content) { var parts = (content || '').split(/\n---\n/); var ai = parts[0] || ''; var summary = ''; var actions = []; var sm = ai.match(/##\s*Samenvatting\s*\n([\s\S]*?)(?=##\s*Actiepunten|$)/i); if (sm) summary = sm[1].trim(); var am = ai.match(/##\s*Actiepunten[^\n]*\n([\s\S]*)/i); if (am) { actions = am[1].split('\n').map(function (l) { return l.replace(/^[-*]\s*/, '').trim(); }).filter(Boolean); } if (!summary && ai.trim()) summary = ai.trim().slice(0, 600); return { summary: summary, actions: actions }; } function chartColors() { return { gold: 'rgba(232, 168, 56, 0.85)', goldDim: 'rgba(232, 168, 56, 0.35)', cyan: 'rgba(56, 189, 248, 0.85)', green: 'rgba(62, 207, 142, 0.85)', red: 'rgba(239, 68, 68, 0.85)', gray: 'rgba(107, 114, 128, 0.85)', grid: 'rgba(148, 163, 184, 0.12)', text: '#94a3b8', }; } function renderPipeline(canvas, stats) { if (!canvas) return; var rows = stats.deals_by_stage || []; var c = chartColors(); charts.pipeline = new Chart(canvas, { type: 'bar', data: { labels: rows.map(function (r) { return r.stage || '?'; }), datasets: [{ label: 'Pipeline EUR', data: rows.map(function (r) { return Number(r.total) || 0; }), backgroundColor: c.gold, borderRadius: 6, }], }, options: { responsive: true, maintainAspectRatio: true, plugins: { legend: { display: false }, title: { display: true, text: 'Pipeline per stage', color: c.text } }, scales: { y: { ticks: { color: c.text, callback: function (v) { return '€' + v.toLocaleString('nl-NL'); } }, grid: { color: c.grid } }, x: { ticks: { color: c.text }, grid: { display: false } }, }, }, }); } function renderSentiment(canvas, stats) { if (!canvas) return; var files = stats.nas_files || []; var counts = { positive: 0, neutral: 0, negative: 0 }; files.forEach(function (f) { var s = (f.sentiment_label || 'neutral').toLowerCase(); if (counts[s] !== undefined) counts[s]++; }); if (!files.length) { counts.neutral = 1; } var c = chartColors(); charts.sentiment = new Chart(canvas, { type: 'doughnut', data: { labels: ['Positief', 'Neutraal', 'Negatief'], datasets: [{ data: [counts.positive, counts.neutral, counts.negative], backgroundColor: [c.green, c.gray, c.red], borderWidth: 0 }], }, options: { responsive: true, maintainAspectRatio: true, plugins: { legend: { position: 'bottom', labels: { color: c.text } }, title: { display: true, text: 'NAS sentiment', color: c.text } }, }, }); } function renderWords(canvas, stats) { if (!canvas) return; var rows = (stats.top_words || []).slice(0, 8); var c = chartColors(); charts.words = new Chart(canvas, { type: 'bar', data: { labels: rows.map(function (r) { return r.lemma; }), datasets: [{ label: 'Count', data: rows.map(function (r) { return Number(r.total) || 0; }), backgroundColor: c.cyan, borderRadius: 6, }], }, options: { indexAxis: 'y', responsive: true, maintainAspectRatio: true, plugins: { legend: { display: false }, title: { display: true, text: 'Top woorden NAS', color: c.text } }, scales: { x: { ticks: { color: c.text }, grid: { color: c.grid } }, y: { ticks: { color: c.text }, grid: { display: false } }, }, }, }); } function renderAgents(canvas, stats) { if (!canvas) return; var events = stats.recent_events || []; var map = {}; events.forEach(function (e) { var a = e.agent_name || 'other'; map[a] = (map[a] || 0) + 1; }); var labels = Object.keys(map); var values = labels.map(function (k) { return map[k]; }); var c = chartColors(); charts.agents = new Chart(canvas, { type: 'polarArea', data: { labels: labels, datasets: [{ data: values, backgroundColor: [c.gold, c.cyan, c.green, c.red, c.gray, c.goldDim] }], }, options: { responsive: true, maintainAspectRatio: true, plugins: { legend: { position: 'bottom', labels: { color: c.text } }, title: { display: true, text: 'Agent activiteit', color: c.text } }, scales: { r: { ticks: { display: false }, grid: { color: c.grid } } }, }, }); } function renderKpis(container, stats) { if (!container) return; var items = [ { label: 'Pipeline', value: '€' + Math.round(stats.pipeline_eur || 0).toLocaleString('nl-NL'), cls: 'green' }, { label: 'Klanten', value: stats.clients || 0, cls: 'purple' }, { label: 'Deals', value: stats.deals || 0, cls: '' }, { label: 'NAS docs', value: stats.nas_docs || 0, cls: 'cyan' }, { label: 'Goedkeuringen', value: stats.pending_approvals || 0, cls: 'amber' }, ]; container.innerHTML = items.map(function (it) { return '
Geen NAS documenten.
'; return; } container.innerHTML = '| Bestand | Type | Sentiment | Woorden |
|---|---|---|---|
| ' + (f.filename || '') + ' | ' + (f.doc_type || '') + ' | ' + (f.sentiment_label || '') + ' | ' + (f.word_count || '—') + ' |
Geen openstaande goedkeuringen 🎉
'; return; } container.innerHTML = items.map(function (it) { return '