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
89 lines
2.4 KiB
TypeScript
89 lines
2.4 KiB
TypeScript
interface EnvironmentGaugeProps {
|
|
label: string;
|
|
value: number;
|
|
unit: string;
|
|
target: number;
|
|
min: number;
|
|
max: number;
|
|
compact?: boolean;
|
|
}
|
|
|
|
export default function EnvironmentGauge({
|
|
label,
|
|
value,
|
|
unit,
|
|
target,
|
|
min,
|
|
max,
|
|
compact = false,
|
|
}: EnvironmentGaugeProps) {
|
|
const isLow = value < min;
|
|
const isHigh = value > max;
|
|
const isOptimal = value >= min && value <= max;
|
|
|
|
const statusColor = isOptimal
|
|
? 'text-green-600'
|
|
: isLow || isHigh
|
|
? 'text-red-600'
|
|
: 'text-yellow-600';
|
|
|
|
const bgColor = isOptimal
|
|
? 'bg-green-100'
|
|
: isLow || isHigh
|
|
? 'bg-red-100'
|
|
: 'bg-yellow-100';
|
|
|
|
if (compact) {
|
|
return (
|
|
<div className={`rounded p-1 ${bgColor}`}>
|
|
<p className="text-xs text-gray-600">{label}</p>
|
|
<p className={`text-sm font-bold ${statusColor}`}>
|
|
{typeof value === 'number' ? value.toFixed(0) : value}
|
|
{unit && <span className="text-xs">{unit}</span>}
|
|
</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const deviation = value - target;
|
|
const deviationPercent = ((value - min) / (max - min)) * 100;
|
|
|
|
return (
|
|
<div className={`rounded-lg p-4 ${bgColor}`}>
|
|
<div className="flex justify-between items-center mb-2">
|
|
<span className="text-sm font-medium text-gray-700">{label}</span>
|
|
<span className={`text-2xl font-bold ${statusColor}`}>
|
|
{value.toFixed(1)}{unit}
|
|
</span>
|
|
</div>
|
|
|
|
<div className="relative h-2 bg-gray-200 rounded-full overflow-hidden">
|
|
<div
|
|
className="absolute h-full bg-green-400"
|
|
style={{
|
|
left: `${((min - (min - 10)) / ((max + 10) - (min - 10))) * 100}%`,
|
|
width: `${((max - min) / ((max + 10) - (min - 10))) * 100}%`,
|
|
}}
|
|
/>
|
|
<div
|
|
className={`absolute h-4 w-1 -top-1 ${statusColor.replace('text-', 'bg-')}`}
|
|
style={{
|
|
left: `${Math.min(100, Math.max(0, ((value - (min - 10)) / ((max + 10) - (min - 10))) * 100))}%`,
|
|
}}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex justify-between text-xs text-gray-500 mt-1">
|
|
<span>{min}{unit}</span>
|
|
<span className="font-medium">Target: {target}{unit}</span>
|
|
<span>{max}{unit}</span>
|
|
</div>
|
|
|
|
{deviation !== 0 && (
|
|
<p className={`text-xs mt-2 ${statusColor}`}>
|
|
{deviation > 0 ? '+' : ''}{deviation.toFixed(1)}{unit} from target
|
|
</p>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|