| | 1 | 1 | | import React from 'react'; |
| | 1 | 2 | | import { |
| | 1 | 3 | | BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, |
| | 1 | 4 | | PieChart, Pie, Cell, Sector |
| | 1 | 5 | | } from 'recharts'; |
| | 1 | 6 | | import { useMaintenance } from '../context/MaintenanceContext.js'; |
| | 1 | 7 | | |
| | 1 | 8 | | const COLORS = ['#2ecc71', '#f1c40f', '#e74c3c', '#3498db']; |
| | 1 | 9 | | |
| | 1 | 10 | | export function AnalyticsPanel() { |
| | 17 | 11 | | const { machines, inventory } = useMaintenance(); |
| | 17 | 12 | | |
| | 17 | 13 | | // 1. Prepare Machine Status Data for Pie Chart |
| | 17 | 14 | | const statusCounts = (machines || []).reduce((acc, m) => { |
| | 2 | 15 | | const rawStatus = m.status || 'unknown'; |
| | 2 | 16 | | const status = rawStatus.charAt(0).toUpperCase() + rawStatus.slice(1); |
| | 2 | 17 | | acc[status] = (acc[status] || 0) + 1; |
| | 2 | 18 | | return acc; |
| | 17 | 19 | | }, {}); |
| | 17 | 20 | | |
| | 17 | 21 | | const pieData = Object.keys(statusCounts).map(status => ({ |
| | 2 | 22 | | name: status, |
| | 2 | 23 | | value: statusCounts[status] |
| | 17 | 24 | | })); |
| | 17 | 25 | | |
| | 17 | 26 | | // 2. Prepare Inventory Data for Bar Chart |
| | 17 | 27 | | const barData = inventory.map(item => ({ |
| | 1 | 28 | | name: item.part_name, |
| | 1 | 29 | | stock: item.quantity, |
| | 1 | 30 | | min: item.min_stock_level |
| | 17 | 31 | | })); |
| | 17 | 32 | | |
| | 17 | 33 | | return ( |
| | 17 | 34 | | <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px', marginTop: '20px' }}> |
| | 17 | 35 | | {/* Machine Status Distribution */} |
| | 17 | 36 | | <div style={{ backgroundColor: 'white', padding: '20px', borderRadius: '12px', boxShadow: '0 4px 6px rgba(0, |
| | 17 | 37 | | <h4 style={{ margin: '0 0 20px 0', color: '#2c3e50' }}>Asset Status Distribution</h4> |
| | 17 | 38 | | <div style={{ width: '100%', height: 250 }}> |
| | 17 | 39 | | <ResponsiveContainer> |
| | 17 | 40 | | <PieChart> |
| | 17 | 41 | | <Pie |
| | 17 | 42 | | data={pieData} |
| | 17 | 43 | | cx="50%" |
| | 17 | 44 | | cy="50%" |
| | 17 | 45 | | innerRadius={60} |
| | 17 | 46 | | outerRadius={80} |
| | 17 | 47 | | paddingAngle={5} |
| | 17 | 48 | | dataKey="value" |
| | 17 | 49 | | > |
| | 17 | 50 | | {pieData.map((entry, index) => ( |
| | 2 | 51 | | <Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} /> |
| | 17 | 52 | | ))} |
| | 17 | 53 | | </Pie> |
| | 17 | 54 | | <Tooltip /> |
| | 17 | 55 | | <Legend verticalAlign="bottom" height={36} /> |
| | 17 | 56 | | </PieChart> |
| | 17 | 57 | | </ResponsiveContainer> |
| | 17 | 58 | | </div> |
| | 17 | 59 | | </div> |
| | 17 | 60 | | |
| | 17 | 61 | | {/* Inventory Stock Levels */} |
| | 17 | 62 | | <div style={{ backgroundColor: 'white', padding: '20px', borderRadius: '12px', boxShadow: '0 4px 6px rgba(0, |
| | 17 | 63 | | <h4 style={{ margin: '0 0 20px 0', color: '#2c3e50' }}>Inventory Levels vs Min Stock</h4> |
| | 17 | 64 | | <div style={{ width: '100%', height: 250 }}> |
| | 17 | 65 | | <ResponsiveContainer> |
| | 17 | 66 | | <BarChart |
| | 17 | 67 | | data={barData} |
| | 17 | 68 | | layout="vertical" |
| | 17 | 69 | | margin={{ top: 5, right: 30, left: 40, bottom: 5 }} |
| | 17 | 70 | | > |
| | 17 | 71 | | <CartesianGrid strokeDasharray="3 3" /> |
| | 17 | 72 | | <XAxis type="number" /> |
| | 17 | 73 | | <YAxis dataKey="name" type="category" width={100} style={{ fontSize: '0.7rem' }} /> |
| | 17 | 74 | | <Tooltip /> |
| | 17 | 75 | | <Legend /> |
| | 17 | 76 | | <Bar dataKey="stock" fill="#3498db" name="Current Stock" /> |
| | 17 | 77 | | <Bar dataKey="min" fill="#e74c3c" name="Minimum Level" /> |
| | 17 | 78 | | </BarChart> |
| | 17 | 79 | | </ResponsiveContainer> |
| | 17 | 80 | | </div> |
| | 17 | 81 | | </div> |
| | 17 | 82 | | </div> |
| | 17 | 83 | | ); |
| | 17 | 84 | | } |