feat: Reports & Analytics page, CSV export, notification bell in header

- Reports page with overview stats, client growth chart, email activity chart
- Engagement breakdown (engaged/warm/cooling/cold) with stacked bar
- Industry and tag distribution charts
- At-risk client lists (cold + cooling)
- CSV export button downloads all clients
- Notification bell in top bar: overdue events, upcoming events, stale clients, pending drafts
- Dismissable notifications with priority indicators
- Added Reports to sidebar nav between Network and Settings
This commit is contained in:
2026-01-29 13:04:53 +00:00
parent e7c2e396c0
commit 4c7a8be5b8
5 changed files with 535 additions and 1 deletions

View File

@@ -404,6 +404,49 @@ class ApiClient {
}
return response.json();
}
// Reports & Analytics
async getReportsOverview(): Promise<any> {
return this.fetch('/reports/overview');
}
async getReportsGrowth(): Promise<any> {
return this.fetch('/reports/growth');
}
async getReportsIndustries(): Promise<any[]> {
return this.fetch('/reports/industries');
}
async getReportsTags(): Promise<any[]> {
return this.fetch('/reports/tags');
}
async getReportsEngagement(): Promise<any> {
return this.fetch('/reports/engagement');
}
async getNotifications(): Promise<any> {
return this.fetch('/reports/notifications');
}
async exportClientsCSV(): Promise<void> {
const token = this.getToken();
const headers: HeadersInit = token ? { Authorization: `Bearer ${token}` } : {};
const response = await fetch(`${API_BASE}/reports/export/clients`, {
headers,
credentials: 'include',
});
if (!response.ok) throw new Error('Export failed');
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `clients-export-${new Date().toISOString().split('T')[0]}.csv`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}
}
export const api = new ApiClient();