Upload app/webui/components/dashboard-kpis.js

This commit is contained in:
2026-06-04 00:06:28 +00:00
parent e0af525a47
commit 222e48301e
+85
View File
@@ -0,0 +1,85 @@
/**
* 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;