localgreenchain/components/vertical-farm/EnvironmentGauge.tsx
Claude 2f7f22ca22
Add vertical farming UI components and pages
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
2025-11-22 18:35:57 +00:00

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>
);
}