localgreenchain/pages/api/analytics/export.ts
Claude 816c3b3f2e
Implement Agent 7: Advanced Analytics Dashboard
Add comprehensive analytics system with:
- Analytics data layer (aggregator, metrics, trends, cache)
- 6 API endpoints (overview, plants, transport, farms, sustainability, export)
- 6 chart components (LineChart, BarChart, PieChart, AreaChart, Gauge, Heatmap)
- 5 dashboard widgets (KPICard, TrendIndicator, DataTable, DateRangePicker, FilterPanel)
- 5 dashboard pages (overview, plants, transport, farms, sustainability)
- Export functionality (CSV, JSON)

Dependencies added: recharts, d3, date-fns

Also includes minor fixes:
- Fix EnvironmentalForm spread type error
- Fix AgentOrchestrator Map iteration issues
- Fix next.config.js image domains undefined error
- Add downlevelIteration to tsconfig
2025-11-23 04:02:07 +00:00

155 lines
4.5 KiB
TypeScript

/**
* Analytics Export API
* Exports analytics data in various formats (CSV, JSON)
*/
import type { NextApiRequest, NextApiResponse } from 'next';
import {
getAnalyticsOverview,
getPlantAnalytics,
getTransportAnalytics,
getFarmAnalytics,
getSustainabilityAnalytics,
TimeRange,
AnalyticsFilters,
} from '../../../lib/analytics';
import { format } from 'date-fns';
interface ExportData {
overview?: any;
plants?: any;
transport?: any;
farms?: any;
sustainability?: any;
}
function convertToCSV(data: any[], headers: string[]): string {
const headerRow = headers.join(',');
const rows = data.map(item =>
headers.map(header => {
const value = item[header];
if (value === null || value === undefined) return '';
if (typeof value === 'string' && value.includes(',')) {
return `"${value.replace(/"/g, '""')}"`;
}
return String(value);
}).join(',')
);
return [headerRow, ...rows].join('\n');
}
function generatePlantCSV(plantData: any): string {
const speciesData = plantData.plantsBySpecies.map((s: any) => ({
species: s.species,
count: s.count,
percentage: s.percentage,
trend: s.trend,
}));
return convertToCSV(speciesData, ['species', 'count', 'percentage', 'trend']);
}
function generateTransportCSV(transportData: any): string {
const methodData = transportData.eventsByMethod.map((m: any) => ({
method: m.method,
count: m.count,
distanceKm: m.distanceKm,
carbonKg: m.carbonKg,
efficiency: m.efficiency,
}));
return convertToCSV(methodData, ['method', 'count', 'distanceKm', 'carbonKg', 'efficiency']);
}
function generateSustainabilityCSV(sustainData: any): string {
const goalsData = sustainData.goals.map((g: any) => ({
name: g.name,
target: g.target,
current: g.current,
unit: g.unit,
progress: g.progress,
status: g.status,
}));
return convertToCSV(goalsData, ['name', 'target', 'current', 'unit', 'progress', 'status']);
}
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== 'GET') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const exportFormat = (req.query.format as string) || 'json';
const timeRange = (req.query.timeRange as TimeRange) || '30d';
const sections = req.query.sections
? (req.query.sections as string).split(',')
: ['overview', 'plants', 'transport', 'farms', 'sustainability'];
const filters: AnalyticsFilters = { timeRange };
const exportData: ExportData = {};
// Fetch requested sections
if (sections.includes('overview')) {
exportData.overview = await getAnalyticsOverview(filters);
}
if (sections.includes('plants')) {
exportData.plants = await getPlantAnalytics(filters);
}
if (sections.includes('transport')) {
exportData.transport = await getTransportAnalytics(filters);
}
if (sections.includes('farms')) {
exportData.farms = await getFarmAnalytics(filters);
}
if (sections.includes('sustainability')) {
exportData.sustainability = await getSustainabilityAnalytics(filters);
}
const timestamp = format(new Date(), 'yyyy-MM-dd_HH-mm-ss');
if (exportFormat === 'csv') {
// Generate combined CSV
let csvContent = '';
if (exportData.plants) {
csvContent += '# Plant Analytics - Species Distribution\n';
csvContent += generatePlantCSV(exportData.plants);
csvContent += '\n\n';
}
if (exportData.transport) {
csvContent += '# Transport Analytics - By Method\n';
csvContent += generateTransportCSV(exportData.transport);
csvContent += '\n\n';
}
if (exportData.sustainability) {
csvContent += '# Sustainability Goals\n';
csvContent += generateSustainabilityCSV(exportData.sustainability);
}
res.setHeader('Content-Type', 'text/csv');
res.setHeader('Content-Disposition', `attachment; filename=analytics_export_${timestamp}.csv`);
return res.status(200).send(csvContent);
}
// Default: JSON format
res.setHeader('Content-Type', 'application/json');
res.setHeader('Content-Disposition', `attachment; filename=analytics_export_${timestamp}.json`);
return res.status(200).json({
exportedAt: new Date().toISOString(),
timeRange,
sections,
data: exportData,
});
} catch (error) {
console.error('Analytics export error:', error);
res.status(500).json({
success: false,
error: 'Failed to export analytics data',
});
}
}