UNPKG

@kodeme-io/next-core-analytics

Version:

Analytics, charts, dashboards, and reporting for Next.js applications

925 lines (766 loc) โ€ข 22.4 kB
# @kodeme-io/next-core-analytics Analytics, charts, dashboards, and reporting components for Next.js applications with TypeScript support and real-time data visualization. ## ๐Ÿš€ Features - **๐Ÿ“Š KPI Cards** - Display key metrics with trends and comparisons - **๐Ÿ“ˆ Rich Charts** - Line, bar, pie, donut, area, scatter, radar charts using Recharts - **๐ŸŽฏ Dashboard Builder** - Create custom, responsive dashboards - **๐Ÿ“ Export Functionality** - PDF, Excel, CSV, JSON export with real library implementations - **๐Ÿ“Š Data Aggregation** - Sum, avg, min, max, count with grouping - **โฐ Time Series Analysis** - Time-based data processing and visualization - **๐Ÿ”„ Real-time Updates** - Live data streaming and WebSocket support - **โ™ฟ Accessible** - WCAG compliant with keyboard navigation - **๐Ÿ”ง TypeScript Native** - Full type safety and IntelliSense support - **๐ŸŒ Internationalization** - Built-in support for multiple locales and currencies - **โœ… Data Validation** - Zod-powered validation for all data inputs - **๐Ÿ›ก๏ธ Error Boundaries** - Graceful error handling and recovery - **โšก Performance Optimized** - React.memo and useMemo optimizations ## ๐Ÿ“ฆ Installation ```bash npm install @kodeme-io/next-core-analytics # or yarn add @kodeme-io/next-core-analytics # or pnpm add @kodeme-io/next-core-analytics ``` ### Peer Dependencies ```bash npm install react react-dom recharts date-fns ``` ### Dependencies The package includes the following dependencies: - `recharts` - Chart rendering - `date-fns` - Date manipulation - `jspdf` - PDF export - `xlsx` - Excel export - `zod` - Data validation ## ๐ŸŽฏ Quick Start ### Basic Analytics Dashboard ```tsx 'use client' import { KPICard, ChartContainer, Dashboard, useAnalytics, type KPIMetric, type ChartConfig, type DashboardLayout } from '@kodeme-io/next-core-analytics' const salesMetrics: KPIMetric[] = [ { id: 'revenue', label: 'Total Revenue', value: 2500000, previousValue: 2100000, format: 'currency', trend: 'up', trendValue: 19.0, icon: <div>๐Ÿ’ฐ</div>, color: 'text-green-600' }, { id: 'orders', label: 'Total Orders', value: 1250, previousValue: 1100, format: 'number', trend: 'up', trendValue: 13.6, icon: <div>๐Ÿ“ฆ</div>, color: 'text-blue-600' }, { id: 'conversion', label: 'Conversion Rate', value: 3.2, previousValue: 2.8, format: 'percentage', trend: 'up', trendValue: 14.3, icon: <div>๐Ÿ“ˆ</div>, color: 'text-purple-600' } ] const salesChartConfig: ChartConfig = { type: 'line', data: [ { name: 'Jan', value: 1800000 }, { name: 'Feb', value: 2100000 }, { name: 'Mar', value: 2500000 }, { name: 'Apr', value: 2300000 }, { name: 'May', value: 2800000 }, { name: 'Jun', value: 2500000 } ], xKey: 'name', yKey: 'value', colors: ['#3b82f6'], title: 'Monthly Revenue Trend', subtitle: 'Revenue performance over the last 6 months' } const salesDashboard: DashboardLayout = { id: 'sales-dashboard', name: 'Sales Dashboard', widgets: [ { id: 'kpi-row', type: 'kpi', title: 'Key Metrics', config: { metrics: salesMetrics }, span: { cols: 12, rows: 2 } }, { id: 'revenue-chart', type: 'chart', title: 'Revenue Trend', config: salesChartConfig, span: { cols: 8, rows: 4 } } ], refreshInterval: 300 } export default function SalesDashboard() { const { data, loading, error, refresh } = useAnalytics({ endpoint: '/api/analytics/sales', params: { period: '6m' }, refreshInterval: 30000 // 30 seconds }) if (loading) return <div>Loading dashboard...</div> if (error) return <div>Error loading dashboard</div> return ( <div className="p-6"> <div className="flex justify-between items-center mb-6"> <h1 className="text-3xl font-bold">Sales Analytics</h1> <button onClick={refresh} className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600" > Refresh </button> </div> <Dashboard layout={salesDashboard} data={data} /> </div> ) } ``` ## ๐Ÿ“š Core Concepts ### KPI Card Structure ```typescript interface KPIMetric { id: string // Unique metric identifier label: string // Display label value: number | string // Current value previousValue?: number // Previous period value format?: 'number' | 'currency' | 'percentage' | 'duration' // Value formatting trend?: 'up' | 'down' | 'neutral' // Trend direction trendValue?: number // Trend percentage icon?: React.ReactNode // Custom icon color?: string // Custom color class prefix?: string // Value prefix suffix?: string // Value suffix // Internationalization options locale?: string // Locale for number formatting (e.g., 'en-US', 'de-DE') currency?: string // Currency code (e.g., 'USD', 'EUR', 'IDR') numberFormatOptions?: Intl.NumberFormatOptions // Custom formatting options } ``` ### Chart Configuration ```typescript interface ChartConfig { type: ChartType // Chart type (line, bar, area, pie, donut, scatter, radar) data: ChartDataPoint[] // Chart data xKey?: string // X-axis data key yKey?: string | string[] // Y-axis data key(s) colors?: string[] // Custom colors legend?: boolean // Show legend grid?: boolean // Show grid tooltip?: boolean // Show tooltip title?: string // Chart title subtitle?: string // Chart subtitle } ``` ### Dashboard Layout ```typescript interface DashboardLayout { id: string // Dashboard identifier name: string // Dashboard name widgets: DashboardWidget[] // Dashboard widgets refreshInterval?: number // Auto-refresh interval (seconds) filters?: DashboardFilter[] // Dashboard filters } interface DashboardWidget { id: string // Widget identifier type: 'chart' | 'kpi' | 'table' | 'custom' // Widget type title: string // Widget title description?: string // Widget description config: ChartConfig | KPICardConfig | any // Widget configuration span?: { // Grid span cols?: number // Column span (1-12) rows?: number // Row span (1-6) } } ``` ## ๐ŸŽจ Components ### KPICard Display key performance metrics with optional trends and comparisons: ```tsx <KPICard metric={{ id: 'revenue', label: 'Total Revenue', value: 1500000, previousValue: 1200000, format: 'currency', trend: 'up', trendValue: 25, icon: <RevenueIcon />, color: 'text-green-600' }} variant="default" // 'default' | 'compact' | 'detailed' className="custom-kpi-card" /> ``` **Variants:** - `default` - Standard card with trend and value - `compact` - Minimal design for dense layouts - `detailed` - Extended view with previous values **Formats:** - `number` - Formatted with thousand separators - `currency` - IDR currency format (default) - `percentage` - Percentage with decimal precision - `duration` - Hours and minutes format ### ChartContainer Responsive chart wrapper with loading and error states: ```tsx <ChartContainer config={{ type: 'line', data: salesData, xKey: 'month', yKey: 'revenue', colors: ['#3b82f6'], title: 'Monthly Revenue', grid: true, tooltip: true }} loading={false} error={null} className="chart-container" height={400} /> ``` **Chart Types:** - `line` - Line charts for trends - `bar` - Bar charts for comparisons - `area` - Area charts for cumulative data - `pie` - Pie charts for proportions - `donut` - Donut charts with center space - `scatter` - Scatter plots for correlations - `radar` - Radar charts for multi-dimensional data ### Dashboard Full dashboard layout with grid system and widgets: ```tsx <Dashboard layout={dashboardLayout} data={analyticsData} onWidgetClick={(widgetId) => console.log('Widget clicked:', widgetId)} onFilterChange={(filters) => console.log('Filters changed:', filters)} className="analytics-dashboard" loading={false} error={null} /> ``` ### ExportButton Export dashboard or chart data in multiple formats: ```tsx <ExportButton config={{ format: 'pdf', filename: 'sales-report', data: chartData, title: 'Sales Report', includeCharts: true }} onExportComplete={(filename) => console.log('Exported:', filename)} className="export-button" /> ``` **Export Formats:** - `pdf` - PDF reports with charts and tables - `excel` - Excel spreadsheets with multiple sheets - `csv` - CSV files for data analysis - `json` - JSON data for integration ## ๐Ÿ“Š Data Processing ### Data Aggregation ```tsx import { aggregateData } from '@kodeme-io/next-core-analytics' // Aggregate sales data by region const aggregatedSales = aggregateData(salesData, { field: 'revenue', type: 'sum', groupBy: 'region' }) // Calculate average order value const avgOrderValue = aggregateData(orderData, { field: 'orderValue', type: 'avg' }) ``` **Aggregation Types:** - `sum` - Sum of values - `avg` - Average of values - `min` - Minimum value - `max` - Maximum value - `count` - Count of records ### Time Series Processing ```tsx import { processTimeSeries } from '@kodeme-io/next-core-analytics' // Process daily sales data into weekly aggregates const weeklyData = processTimeSeries(dailySales, { dateField: 'date', valueField: 'revenue', granularity: 'week', fillGaps: true }) ``` **Time Granularities:** - `hour` - Hourly aggregation - `day` - Daily aggregation - `week` - Weekly aggregation - `month` - Monthly aggregation - `quarter` - Quarterly aggregation - `year` - Yearly aggregation ### Comparison Analysis ```tsx import { calculateComparison } from '@kodeme-io/next-core-analytics' // Calculate period-over-period growth const comparison = calculateComparison({ currentPeriod: { start: new Date('2024-01-01'), end: new Date('2024-01-31') }, previousPeriod: { start: new Date('2023-12-01'), end: new Date('2023-12-31') }, metric: 'revenue', data: salesData }) console.log(`Revenue ${comparison.trend === 'up' ? 'increased' : 'decreased'} by ${comparison.percentChange}%`) ``` ## ๐Ÿ”„ Advanced Usage ### Real-time Data ```tsx function RealTimeDashboard() { const { data, subscribe, unsubscribe } = useAnalytics({ endpoint: '/api/analytics/realtime', realtime: true }) useEffect(() => { const handleRealtimeUpdate = (newData) => { console.log('Real-time data update:', newData) } subscribe('data-updated', handleRealtimeUpdate) return () => { unsubscribe('data-updated') } }, [subscribe, unsubscribe]) return ( <Dashboard layout={realtimeLayout} data={data} /> ) } ``` ### Custom Charts ```tsx import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts' function CustomSalesChart({ data }: { data: any[] }) { return ( <ResponsiveContainer width="100%" height={400}> <LineChart data={data}> <CartesianGrid strokeDasharray="3 3" /> <XAxis dataKey="month" /> <YAxis /> <Tooltip /> <Line type="monotone" dataKey="revenue" stroke="#3b82f6" strokeWidth={2} dot={{ fill: '#3b82f6', strokeWidth: 2, r: 4 }} activeDot={{ r: 6 }} /> </LineChart> </ResponsiveContainer> ) } ``` ### Multi-series Charts ```tsx const multiSeriesConfig: ChartConfig = { type: 'line', data: [ { month: 'Jan', revenue: 1000000, profit: 200000, expenses: 800000 }, { month: 'Feb', revenue: 1200000, profit: 250000, expenses: 950000 }, { month: 'Mar', revenue: 1100000, profit: 180000, expenses: 920000 } ], xKey: 'month', yKey: ['revenue', 'profit', 'expenses'], colors: ['#3b82f6', '#10b981', '#ef4444'], title: 'Financial Overview', legend: true } ``` ### Custom Dashboard Filters ```tsx const dashboardWithFilters: DashboardLayout = { id: 'filtered-dashboard', name: 'Filtered Dashboard', widgets: [/* ... */], filters: [ { id: 'date-range', type: 'date', label: 'Date Range', value: { start: '2024-01-01', end: '2024-12-31' } }, { id: 'region', type: 'multiselect', label: 'Regions', value: ['all'], options: [ { label: 'All Regions', value: 'all' }, { label: 'North America', value: 'na' }, { label: 'Europe', value: 'eu' }, { label: 'Asia Pacific', value: 'apac' } ] }, { id: 'product-category', type: 'select', label: 'Product Category', value: 'all', options: [ { label: 'All Categories', value: 'all' }, { label: 'Electronics', value: 'electronics' }, { label: 'Clothing', value: 'clothing' }, { label: 'Food', value: 'food' } ] } ] } ``` ## ๐ŸŽจ Styling and Theming ### Custom Color Schemes ```tsx const customTheme = { primary: '#6366f1', secondary: '#8b5cf6', success: '#10b981', warning: '#f59e0b', error: '#ef4444', neutral: '#6b7280' } const themedChartConfig: ChartConfig = { type: 'bar', data: salesData, xKey: 'month', yKey: 'revenue', colors: [customTheme.primary, customTheme.secondary], title: 'Sales by Month' } ``` ### Responsive Design ```tsx // Responsive grid layout const responsiveDashboard: DashboardLayout = { id: 'responsive-dashboard', name: 'Responsive Dashboard', widgets: [ { id: 'kpi-cards', type: 'kpi', title: 'Metrics', config: { metrics: kpiMetrics }, span: { cols: 12, rows: 2 } // Full width on desktop }, { id: 'main-chart', type: 'chart', title: 'Trends', config: chartConfig, span: { cols: 8, rows: 4 } // 8/12 columns }, { id: 'secondary-chart', type: 'chart', title: 'Breakdown', config: pieChartConfig, span: { cols: 4, rows: 4 } // 4/12 columns } ] } ``` ## ๐Ÿงช Testing The package includes comprehensive test coverage: ```bash # Run tests npm test # Run with coverage npm run test:coverage # Run tests in watch mode npm run test:watch ``` ### Testing Analytics Components ```tsx import { render, screen } from '@testing-library/react' import { KPICard } from '@kodeme-io/next-core-analytics' test('KPI card renders correctly', () => { const metric = { id: 'test-metric', label: 'Test Metric', value: 1000, format: 'number' as const, trend: 'up' as const, trendValue: 10 } render(<KPICard metric={metric} />) expect(screen.getByText('Test Metric')).toBeInTheDocument() expect(screen.getByText('1.000')).toBeInTheDocument() expect(screen.getByText('10%')).toBeInTheDocument() }) ``` ## ๐ŸŒ Internationalization ### Currency and Number Formatting The analytics package now supports internationalization out of the box: ```tsx import { KPICard, currencyFormatters } from '@kodeme-io/next-core-analytics' // Indonesian Rupiah <KPICard metric={{ id: 'revenue', label: 'Total Revenue', value: 1500000, format: 'currency', locale: 'id-ID', currency: 'IDR' }} /> // Euro with German locale <KPICard metric={{ id: 'revenue-eur', label: 'Revenue (EUR)', value: 1500, format: 'currency', locale: 'de-DE', currency: 'EUR' }} /> // Or use pre-configured formatters const formattedValue = currencyFormatters.EUR(1500) ``` ### Custom Formatters ```tsx import { createFormatter, formatValue } from '@kodeme-io/next-core-analytics' const customFormatter = createFormatter({ format: 'currency', currency: 'GBP', locale: 'en-GB' }) ``` ## โœ… Data Validation ### Built-in Validation All components include automatic data validation using Zod schemas: ```tsx import { KPICard, validateKPI, KPIMetricSchema } from '@kodeme-io/next-core-analytics' // Manual validation const isValidKPI = validateKPI(kpiData) // Safe validation with error handling import { safeValidate } from '@kodeme-io/next-core-analytics' const result = safeValidate(KPIMetricSchema, metricData) if (!result.success) { console.error('Validation errors:', result.errors) } ``` ### Performance Monitoring ```tsx import { validationMonitor } from '@kodeme-io/next-core-analytics' // Get validation statistics const stats = validationMonitor.getStats() console.log('Average validation time:', stats.averageValidationTime) console.log('Success rate:', stats.successRate) ``` ## ๐Ÿ›ก๏ธ Error Boundaries ### Component-Level Error Handling ```tsx import { AnalyticsErrorBoundary, KPIErrorBoundary, ChartErrorBoundary, DashboardErrorBoundary } from '@kodeme-io/next-core-analytics' // Wrap your entire dashboard <DashboardErrorBoundary> <Dashboard layout={dashboardLayout} /> </DashboardErrorBoundary> // Or specific components <KPIErrorBoundary> <KPICard metric={metric} /> </KPIErrorBoundary> <ChartErrorBoundary> <ChartContainer config={chartConfig} /> </ChartErrorBoundary> ``` ### Error Handling Hooks ```tsx import { useErrorHandler } from '@kodeme-io/next-core-analytics' function MyComponent() { const { error, captureError, resetError } = useErrorHandler() if (error) { return ( <div> <p>Error: {error.message}</p> <button onClick={resetError}>Retry</button> </div> ) } // Your component logic } ``` ## ๐Ÿ”ง API Reference ### Hooks ```typescript // Main analytics hook (enhanced with real API support) export function useAnalytics(options?: { endpoint?: string params?: Record<string, any> refreshInterval?: number realtime?: boolean method?: 'GET' | 'POST' headers?: Record<string, string> cache?: RequestCache }): { data: any loading: boolean error: Error | null refresh: () => void subscribe: (event: string, callback: Function) => void unsubscribe: (event: string) => void } // Error handling hook export function useErrorHandler(): { error: Error | null captureError: (error: Error) => void resetError: () => void } ``` ### Utilities ```typescript // Data aggregation export function aggregateData(data: any[], config: AggregationConfig): any[] // Time series processing export function processTimeSeries(data: any[], config: TimeSeriesConfig): any[] // Comparison analysis export function calculateComparison(config: ComparisonConfig): ComparisonData // Formatting utilities export function formatValue(value: number | string, options: FormatValueOptions): string export function formatTrendValue(value: number, format?: 'percentage' | 'number'): string export function formatDuration(seconds: number): string // Validation utilities export function validateKPI(metric: unknown): KPIMetric export function validateChartData(data: unknown[]): ChartDataPoint[] export function validateDashboardLayout(layout: unknown): DashboardLayout export function safeValidate<T>(schema: z.ZodSchema<T>, data: unknown): ValidationResult<T> ``` ### Component Props ```typescript // KPICard props export interface KPICardProps { metric: KPIMetric variant?: 'default' | 'compact' | 'detailed' className?: string } // ChartContainer props export interface ChartContainerProps { config: ChartConfig loading?: boolean error?: string | null className?: string height?: number } // Dashboard props export interface DashboardProps { layout: DashboardLayout data?: any onWidgetClick?: (widgetId: string) => void onFilterChange?: (filters: Record<string, any>) => void className?: string loading?: boolean error?: string | null } ``` ## ๐Ÿ” Troubleshooting ### Common Issues 1. **Charts Not Rendering** - Check if data is properly formatted - Verify xKey and yKey match data structure - Ensure recharts is installed as a dependency 2. **KPI Values Not Formatting** - Verify format type matches value type - Check if value is number for numeric formats - Ensure locale settings are correct 3. **Export Not Working** - Check if export libraries are installed - Verify data structure matches export requirements - Ensure proper file permissions ### Debug Mode Enable debug logging: ```tsx const analytics = useAnalytics({ endpoint: '/api/analytics', debug: true }) ``` ## ๐Ÿš€ Performance Tips 1. **Data Caching** - Cache API responses to reduce network requests 2. **Virtualization** - Use virtual scrolling for large datasets 3. **Lazy Loading** - Load charts and data on demand 4. **Debounced Updates** - Debounce real-time data updates 5. **Component Memoization** - Components are optimized with React.memo 6. **Value Memoization** - Expensive calculations are memoized ```tsx // Caching example const cachedAnalytics = useMemo(() => { return processAnalyticsData(rawData) }, [rawData]) // Debounced refresh const debouncedRefresh = useMemo( () => debounce(refresh, 1000), [refresh] ) // Components are already optimized - no manual memoization needed <KPICard metric={metric} variant="compact" /> <ChartContainer config={chartConfig} /> ``` ### Performance Monitoring The package includes built-in performance monitoring: ```tsx import { validationMonitor } from '@kodeme-io/next-core-analytics' // Get real-time performance metrics const stats = validationMonitor.getStats() console.log({ totalValidations: stats.totalValidations, averageTime: stats.averageValidationTime, successRate: stats.successRate }) ``` ## ๐Ÿค Contributing 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Add tests for new functionality 5. Submit a pull request ## ๐Ÿ“„ License MIT License - see LICENSE file for details ## ๐Ÿ”— Related Packages - [@kodeme-io/next-core-forms](../forms/README.md) - Form components and validation - [@kodeme-io/next-core-workflow](../workflow/README.md) - Workflow management - [@kodeme-io/next-core-ui](../ui/README.md) - UI components ## ๐Ÿ“ž Support - Documentation: [Full documentation](https://docs.abc-food.com/next-core/analytics) - Issues: [GitHub Issues](https://github.com/abc-food/next-core/issues) - Discord: [Community Discord](https://discord.gg/abc-food)