86 lines
2.6 KiB
JavaScript
86 lines
2.6 KiB
JavaScript
/**
|
||
* Dashboard-KPIs + Activity-Feed Component (Alpine.js)
|
||
*
|
||
* Used in: dashboard.html and app.html (default landing page)
|
||
*
|
||
* Loads:
|
||
* GET /api/v1/dashboard/kpis → { open_deals_count, pipeline_value, won_this_month, conversion_rate }
|
||
* GET /api/v1/dashboard/feed?limit=20 → ActivityFeedItem[]
|
||
*
|
||
* Renders: 4 KPI cards + an activity feed list.
|
||
*
|
||
* R-5: x-text only. User-controlled strings are not interpolated as HTML.
|
||
*/
|
||
|
||
import { api } from '/js/api.js';
|
||
|
||
export function dashboardKpis() {
|
||
return {
|
||
loading: true,
|
||
kpis: null,
|
||
feed: [],
|
||
error: null,
|
||
|
||
async load() {
|
||
this.loading = true;
|
||
this.error = null;
|
||
try {
|
||
// Fetch KPIs and feed in parallel
|
||
const [kpis, feed] = await Promise.all([
|
||
api.get('/dashboard/kpis'),
|
||
api.get('/dashboard/feed?limit=20'),
|
||
]);
|
||
this.kpis = kpis;
|
||
this.feed = Array.isArray(feed) ? feed : (feed && feed.items) || [];
|
||
} catch (err) {
|
||
this.error = err.message || 'Fehler beim Laden der Dashboard-Daten.';
|
||
if (window.Alpine) {
|
||
Alpine.store('notifications').error(this.error);
|
||
}
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
},
|
||
|
||
formatCurrency(value) {
|
||
if (value === null || value === undefined) return '–';
|
||
const num = Number(value);
|
||
if (Number.isNaN(num)) return '–';
|
||
return num.toLocaleString('de-DE', {
|
||
style: 'currency',
|
||
currency: 'EUR',
|
||
maximumFractionDigits: 0,
|
||
});
|
||
},
|
||
|
||
formatPercent(value) {
|
||
if (value === null || value === undefined) return '–';
|
||
const num = Number(value);
|
||
if (Number.isNaN(num)) return '–';
|
||
// Backend may return 0-1 or 0-100. Heuristic: >1 → already in %.
|
||
const pct = num > 1 ? num : num * 100;
|
||
return pct.toFixed(1) + ' %';
|
||
},
|
||
|
||
formatDate(iso) {
|
||
if (!iso) return '';
|
||
try {
|
||
return new Date(iso).toLocaleDateString('de-DE');
|
||
} catch {
|
||
return iso;
|
||
}
|
||
},
|
||
};
|
||
}
|
||
|
||
// Register globally for `x-data="dashboardKpis()"`
|
||
if (typeof window !== 'undefined') {
|
||
document.addEventListener('alpine:init', () => {
|
||
if (window.Alpine) {
|
||
window.Alpine.data('dashboardKpis', dashboardKpis);
|
||
}
|
||
});
|
||
}
|
||
|
||
export default dashboardKpis;
|