import React from 'react'; import { useAuth } from '../contexts/AuthContext'; import { useData } from '../contexts/DataContext'; import { Wrench, Package, ClipboardList, AlertTriangle, TrendingUp, Clock, CheckCircle, XCircle } from 'lucide-react'; const Dashboard: React.FC = () => { const { user } = useAuth(); const { machines, inventory, tasks, problems } = useData(); // Calculate statistics const machinesInField = machines.filter(m => m.status === 'out').length; const machinesAvailable = machines.filter(m => m.status === 'in').length; const machinesInMaintenance = machines.filter(m => m.status === 'maintenance').length; const lowStockItems = inventory.filter(item => item.quantity <= item.minStock).length; const totalInventoryValue = inventory.reduce((sum, item) => sum + item.quantity, 0); const pendingTasks = tasks.filter(t => t.status === 'pending').length; const completedTasks = tasks.filter(t => t.status === 'completed').length; const activeTasks = tasks.filter(t => t.status === 'in_progress').length; const openProblems = problems.filter(p => ['open', 'assigned', 'in_progress'].includes(p.status)).length; const resolvedProblems = problems.filter(p => p.status === 'resolved').length; const highPriorityProblems = problems.filter(p => p.priority === 'high' && p.status !== 'confirmed').length; const StatCard: React.FC<{ title: string; value: number | string; icon: React.ComponentType<any>; color: string; subtitle?: string; }> = ({ title, value, icon: Icon, color, subtitle }) => ( <div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200 card-hover"> <div className="flex items-center"> <div className={`flex-shrink-0 ${color}`}> <Icon className="h-8 w-8" /> </div> <div className="ml-4 w-0 flex-1"> <dl> <dt className="text-sm font-medium text-gray-500 truncate">{title}</dt> <dd className="text-2xl font-semibold text-gray-900">{value}</dd> {subtitle && ( <dd className="text-xs text-gray-600 mt-1">{subtitle}</dd> )} </dl> </div> </div> </div> ); const RecentActivity = () => { const recentProblems = problems .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()) .slice(0, 5); const recentTasks = tasks .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()) .slice(0, 5); return ( <div className="bg-white shadow-sm rounded-lg border border-gray-200"> <div className="px-6 py-4 border-b border-gray-200"> <h3 className="text-lg font-semibold text-gray-900">Recent Activity</h3> </div> <div className="divide-y divide-gray-200"> {recentProblems.map((problem) => { const machine = machines.find(m => m.id === problem.machineId); return ( <div key={`problem-${problem.id}`} className="px-6 py-4 flex items-start space-x-3"> <AlertTriangle className="h-5 w-5 text-red-500 mt-0.5 flex-shrink-0" /> <div className="flex-1 min-w-0"> <p className="text-sm text-gray-900 font-medium">{problem.title}</p> <p className="text-xs text-gray-500"> {machine?.name} β’ {problem.location} β’ {new Date(problem.createdAt).toLocaleDateString()} </p> <span className={`inline-flex items-center px-2 py-1 rounded-full text-xs font-medium mt-1 ${ problem.status === 'open' ? 'bg-red-100 text-red-800' : problem.status === 'assigned' ? 'bg-yellow-100 text-yellow-800' : problem.status === 'in_progress' ? 'bg-blue-100 text-blue-800' : problem.status === 'resolved' ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800' }`}> {problem.status.replace('_', ' ')} </span> </div> </div> ); })} {recentTasks.map((task) => { const machine = machines.find(m => m.id === task.machineId); return ( <div key={`task-${task.id}`} className="px-6 py-4 flex items-start space-x-3"> <ClipboardList className="h-5 w-5 text-blue-500 mt-0.5 flex-shrink-0" /> <div className="flex-1 min-w-0"> <p className="text-sm text-gray-900 font-medium">{task.title}</p> <p className="text-xs text-gray-500"> {machine?.name} β’ {task.location} β’ {new Date(task.createdAt).toLocaleDateString()} </p> <span className={`inline-flex items-center px-2 py-1 rounded-full text-xs font-medium mt-1 ${ task.status === 'pending' ? 'bg-yellow-100 text-yellow-800' : task.status === 'in_progress' ? 'bg-blue-100 text-blue-800' : 'bg-green-100 text-green-800' }`}> {task.status.replace('_', ' ')} </span> </div> </div> ); })} </div> </div> ); }; return ( <div className="space-y-6"> {/* Header */} <div> <h1 className="text-3xl font-bold text-gray-900"> Welcome back, {user?.name} </h1> <p className="mt-1 text-sm text-gray-600"> Here's what's happening with your drilling operations today. </p> </div> {/* Stats Grid */} <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6"> <StatCard title="Machines in Field" value={machinesInField} icon={Wrench} color="text-orange-600" subtitle="Currently deployed" /> <StatCard title="Available Machines" value={machinesAvailable} icon={CheckCircle} color="text-green-600" subtitle="Ready for deployment" /> <StatCard title="Low Stock Alerts" value={lowStockItems} icon={Package} color="text-red-600" subtitle="Items need restocking" /> <StatCard title="Open Problems" value={openProblems} icon={AlertTriangle} color="text-red-600" subtitle="Require attention" /> </div> {/* Secondary Stats */} <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6"> <StatCard title="Pending Tasks" value={pendingTasks} icon={Clock} color="text-yellow-600" subtitle="Awaiting assignment" /> <StatCard title="Active Tasks" value={activeTasks} icon={TrendingUp} color="text-blue-600" subtitle="In progress" /> <StatCard title="Maintenance" value={machinesInMaintenance} icon={XCircle} color="text-gray-600" subtitle="Machines under service" /> <StatCard title="High Priority Issues" value={highPriorityProblems} icon={AlertTriangle} color="text-red-600" subtitle="Critical problems" /> </div> {/* Summary Cards */} <div className="grid grid-cols-1 lg:grid-cols-3 gap-6"> <div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200"> <h3 className="text-lg font-semibold text-gray-900 mb-4">Fleet Status</h3> <div className="space-y-3"> <div className="flex justify-between items-center"> <span className="text-sm text-gray-600">In Field</span> <span className="text-sm font-medium text-gray-900">{machinesInField}</span> </div> <div className="flex justify-between items-center"> <span className="text-sm text-gray-600">Available</span> <span className="text-sm font-medium text-gray-900">{machinesAvailable}</span> </div> <div className="flex justify-between items-center"> <span className="text-sm text-gray-600">In Maintenance</span> <span className="text-sm font-medium text-gray-900">{machinesInMaintenance}</span> </div> <div className="pt-2 border-t border-gray-200"> <div className="flex justify-between items-center"> <span className="text-sm font-medium text-gray-900">Total Fleet</span> <span className="text-sm font-bold text-gray-900">{machines.length}</span> </div> </div> </div> </div> <div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200"> <h3 className="text-lg font-semibold text-gray-900 mb-4">Tasks Overview</h3> <div className="space-y-3"> <div className="flex justify-between items-center"> <span className="text-sm text-gray-600">Pending</span> <span className="text-sm font-medium text-gray-900">{pendingTasks}</span> </div> <div className="flex justify-between items-center"> <span className="text-sm text-gray-600">Active</span> <span className="text-sm font-medium text-gray-900">{activeTasks}</span> </div> <div className="flex justify-between items-center"> <span className="text-sm text-gray-600">Completed</span> <span className="text-sm font-medium text-gray-900">{completedTasks}</span> </div> <div className="pt-2 border-t border-gray-200"> <div className="flex justify-between items-center"> <span className="text-sm font-medium text-gray-900">Total Tasks</span> <span className="text-sm font-bold text-gray-900">{tasks.length}</span> </div> </div> </div> </div> <div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200"> <h3 className="text-lg font-semibold text-gray-900 mb-4">Inventory Status</h3> <div className="space-y-3"> <div className="flex justify-between items-center"> <span className="text-sm text-gray-600">Total Items</span> <span className="text-sm font-medium text-gray-900">{inventory.length}</span> </div> <div className="flex justify-between items-center"> <span className="text-sm text-gray-600">Low Stock</span> <span className="text-sm font-medium text-red-600">{lowStockItems}</span> </div> <div className="flex justify-between items-center"> <span className="text-sm text-gray-600">Total Quantity</span> <span className="text-sm font-medium text-gray-900">{totalInventoryValue}</span> </div> <div className="pt-2 border-t border-gray-200"> <div className="flex justify-between items-center"> <span className="text-sm font-medium text-gray-900">Problems</span> <span className="text-sm font-bold text-gray-900"> {openProblems} Open / {resolvedProblems} Resolved </span> </div> </div> </div> </div> </div> {/* Recent Activity */} <div className="grid grid-cols-1 lg:grid-cols-1 gap-6"> <RecentActivity /> </div> </div> ); }; export default Dashboard; - Follow Up Deployment
db9dbd6
verified