Components: - FarmCard: Farm summary display with status and metrics - ZoneGrid: Multi-level zone layout visualization - ZoneDetailCard: Individual zone details with environment readings - EnvironmentGauge: Real-time environmental parameter display - BatchProgress: Crop batch progress tracking with health scores - RecipeSelector: Growing recipe browser and selector - AlertPanel: Environment alerts display and management - GrowthStageIndicator: Visual growth stage progress tracker - ResourceUsageChart: Energy/water usage analytics visualization Pages: - /vertical-farm: Dashboard with farm listing and stats - /vertical-farm/register: Multi-step farm registration form - /vertical-farm/[farmId]: Farm detail view with zones and alerts - /vertical-farm/[farmId]/zones: Zone management with batch starting - /vertical-farm/[farmId]/batches: Batch management and harvesting - /vertical-farm/[farmId]/analytics: Farm analytics and performance metrics
124 lines
5.3 KiB
TypeScript
124 lines
5.3 KiB
TypeScript
import { ResourceUsage } from '../../lib/vertical-farming/types';
|
|
|
|
interface ResourceUsageChartProps {
|
|
usage: ResourceUsage;
|
|
showBenchmarks?: boolean;
|
|
}
|
|
|
|
export default function ResourceUsageChart({ usage, showBenchmarks = true }: ResourceUsageChartProps) {
|
|
const formatCurrency = (value: number) =>
|
|
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value);
|
|
|
|
const efficiencyColor = usage.efficiencyVsBenchmark >= 100
|
|
? 'text-green-600'
|
|
: usage.efficiencyVsBenchmark >= 80
|
|
? 'text-yellow-600'
|
|
: 'text-red-600';
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Summary Stats */}
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
<div className="bg-blue-50 rounded-lg p-4">
|
|
<p className="text-sm text-blue-700">Electricity</p>
|
|
<p className="text-2xl font-bold text-blue-900">{usage.electricityKwh.toLocaleString()} kWh</p>
|
|
<p className="text-sm text-blue-600">{formatCurrency(usage.electricityCostUsd)}</p>
|
|
</div>
|
|
<div className="bg-cyan-50 rounded-lg p-4">
|
|
<p className="text-sm text-cyan-700">Water</p>
|
|
<p className="text-2xl font-bold text-cyan-900">{usage.waterUsageL.toLocaleString()} L</p>
|
|
<p className="text-sm text-cyan-600">{formatCurrency(usage.waterCostUsd)}</p>
|
|
</div>
|
|
<div className="bg-green-50 rounded-lg p-4">
|
|
<p className="text-sm text-green-700">CO2</p>
|
|
<p className="text-2xl font-bold text-green-900">{usage.co2UsedKg.toFixed(1)} kg</p>
|
|
<p className="text-sm text-green-600">{formatCurrency(usage.co2CostUsd)}</p>
|
|
</div>
|
|
<div className="bg-purple-50 rounded-lg p-4">
|
|
<p className="text-sm text-purple-700">Nutrients</p>
|
|
<p className="text-2xl font-bold text-purple-900">{usage.nutrientsUsedL.toFixed(1)} L</p>
|
|
<p className="text-sm text-purple-600">{formatCurrency(usage.nutrientCostUsd)}</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Efficiency Metrics */}
|
|
<div className="bg-white rounded-lg shadow p-6">
|
|
<h4 className="font-semibold text-gray-900 mb-4">Efficiency Per kg Produce</h4>
|
|
<div className="grid grid-cols-3 gap-4">
|
|
<div className="text-center">
|
|
<p className="text-3xl font-bold text-blue-600">{usage.kwhPerKgProduce.toFixed(1)}</p>
|
|
<p className="text-sm text-gray-600">kWh/kg</p>
|
|
{showBenchmarks && (
|
|
<p className="text-xs text-gray-500">
|
|
Industry: {usage.industryBenchmarkKwhPerKg} kWh/kg
|
|
</p>
|
|
)}
|
|
</div>
|
|
<div className="text-center">
|
|
<p className="text-3xl font-bold text-cyan-600">{usage.litersPerKgProduce.toFixed(1)}</p>
|
|
<p className="text-sm text-gray-600">L/kg</p>
|
|
{showBenchmarks && (
|
|
<p className="text-xs text-gray-500">
|
|
Industry: {usage.industryBenchmarkLitersPerKg} L/kg
|
|
</p>
|
|
)}
|
|
</div>
|
|
<div className="text-center">
|
|
<p className="text-3xl font-bold text-green-600">{formatCurrency(usage.costPerKgProduce)}</p>
|
|
<p className="text-sm text-gray-600">$/kg</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Renewable & Recycled */}
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="bg-white rounded-lg shadow p-4">
|
|
<div className="flex justify-between items-center mb-2">
|
|
<span className="text-sm text-gray-600">Renewable Energy</span>
|
|
<span className="font-semibold text-green-600">{usage.renewablePercent}%</span>
|
|
</div>
|
|
<div className="w-full bg-gray-200 rounded-full h-3">
|
|
<div
|
|
className="bg-green-500 h-3 rounded-full"
|
|
style={{ width: `${usage.renewablePercent}%` }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="bg-white rounded-lg shadow p-4">
|
|
<div className="flex justify-between items-center mb-2">
|
|
<span className="text-sm text-gray-600">Water Recycled</span>
|
|
<span className="font-semibold text-cyan-600">{usage.waterRecycledPercent}%</span>
|
|
</div>
|
|
<div className="w-full bg-gray-200 rounded-full h-3">
|
|
<div
|
|
className="bg-cyan-500 h-3 rounded-full"
|
|
style={{ width: `${usage.waterRecycledPercent}%` }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Overall Efficiency */}
|
|
{showBenchmarks && (
|
|
<div className="bg-gray-50 rounded-lg p-4 text-center">
|
|
<p className="text-sm text-gray-600 mb-2">Overall Efficiency vs Industry Benchmark</p>
|
|
<p className={`text-4xl font-bold ${efficiencyColor}`}>
|
|
{usage.efficiencyVsBenchmark.toFixed(0)}%
|
|
</p>
|
|
<p className="text-sm text-gray-500 mt-1">
|
|
{usage.efficiencyVsBenchmark >= 100
|
|
? 'Outperforming industry average'
|
|
: usage.efficiencyVsBenchmark >= 80
|
|
? 'Near industry average'
|
|
: 'Below industry average - optimization needed'}
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
{/* Period Info */}
|
|
<p className="text-xs text-gray-500 text-center">
|
|
Period: {new Date(usage.periodStart).toLocaleDateString()} - {new Date(usage.periodEnd).toLocaleDateString()}
|
|
</p>
|
|
</div>
|
|
);
|
|
}
|