"use client"; import { useState, useEffect, useCallback } from 'react'; import { apiClient } from '@/lib/api-client'; import type { CycleCalculationRequest, CycleCalculationResponse, RefrigerantInfo } from '@/types/api'; export default function CycleCalculatorModern() { const [refrigerants, setRefrigerants] = useState([]); const [selectedRefrigerant, setSelectedRefrigerant] = useState('R290'); const [cycleData, setCycleData] = useState(null); const [inputType, setInputType] = useState<'temperature' | 'pressure'>('pressure'); const [evaporatingValue, setEvaporatingValue] = useState('3'); const [condensingValue, setCondensingValue] = useState('12'); const [superheating, setSuperheating] = useState('0'); const [subcooling, setSubcooling] = useState('2'); const [massFlowRate, setMassFlowRate] = useState('1.0'); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); useEffect(() => { apiClient.getRefrigerants() .then(setRefrigerants) .catch(err => { console.error('Failed to load refrigerants:', err); setError('Cannot connect to API on port 8001'); }); }, []); const handleCalculate = useCallback(async () => { if (!selectedRefrigerant) return; setLoading(true); setError(null); try { const req: CycleCalculationRequest = { refrigerant: selectedRefrigerant, superheat: parseFloat(superheating) || 0, subcool: parseFloat(subcooling) || 0, compressor_efficiency: 0.7, mass_flow: parseFloat(massFlowRate) || 1.0, } as CycleCalculationRequest; if (inputType === 'temperature') { req.evap_temperature = parseFloat(evaporatingValue) || 0; req.cond_temperature = parseFloat(condensingValue) || 0; } else { req.evap_pressure = parseFloat(evaporatingValue) || 1; req.cond_pressure = parseFloat(condensingValue) || 1; } const response = await apiClient.calculateCycle(req); setCycleData(response); // dispatch overlay event try { if (response && response.points && response.points.length > 0) { const cyclePoints = response.points.map(p => ({ enthalpy: p.enthalpy || 0, pressure: p.pressure })); const ev = new CustomEvent('cycle:calculated', { detail: { refrigerant: selectedRefrigerant, points: cyclePoints } }); window.dispatchEvent(ev); } } catch (_) {} } catch (err: any) { setError(err?.message || String(err)); } finally { setLoading(false); } }, [selectedRefrigerant, inputType, evaporatingValue, condensingValue, massFlowRate, superheating, subcooling]); // debounce 200ms useEffect(() => { let mounted = true; const id = setTimeout(() => { if (mounted) handleCalculate(); }, 200); return () => { mounted = false; clearTimeout(id); }; }, [selectedRefrigerant, inputType, evaporatingValue, condensingValue, massFlowRate, superheating, subcooling, handleCalculate]); // Auto-calculate on initial load useEffect(() => { if (refrigerants.length > 0 && selectedRefrigerant && !cycleData) { handleCalculate(); } }, [refrigerants.length, selectedRefrigerant]); const coolingCapacity = cycleData?.performance?.cooling_capacity ?? 0; const compressorPower = cycleData?.performance?.compressor_power ?? 0; return ( <>
{/* SIDEBAR - exact copy from PHDiagramModern */} {/* MAIN AREA - EXACT COPY from PHDiagramModern structure */}
{cycleData && (
{/* Header section - EXACT COPY from PHDiagramModern */}

Thermodynamic Cycle {cycleData.refrigerant}

{/* COP Info - EXACT COPY from PHDiagramModern */} {cycleData.performance && (
COP (Heat Pump) = {cycleData.performance.cop.toFixed(2)} / COP (Refrigerator) = {(cycleData.performance.cop - 1).toFixed(2)}
)} {/* Performance Cards - ELEGANT WHITE DESIGN */}

Performance Metrics

{/* COP Card */}
🎯
COP
Coefficient
{cycleData.performance.cop.toFixed(2)}
{/* Cooling Capacity Card */}
❄️
Cooling
Capacity
{coolingCapacity.toFixed(1)} kW
{/* Compressor Power Card */}
⚙️
Power
Compressor
{compressorPower.toFixed(1)} kW
{/* Compression Ratio Card */}
📊
Ratio
Compression
{cycleData.performance.compression_ratio.toFixed(2)}
{/* Cycle State Points - ELEGANT WHITE CARDS */}

🔄 Cycle State Points

{cycleData.points.map((p, index) => { // Define icons and colors for each point const pointStyles = [ { icon: '🌡️', color: '#3b82f6', bg: 'linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)', label: 'Point 1' }, { icon: '🔥', color: '#ef4444', bg: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)', label: 'Point 2' }, { icon: '💧', color: '#10b981', bg: 'linear-gradient(135deg, #10b981 0%, #059669 100%)', label: 'Point 3' }, { icon: '❄️', color: '#06b6d4', bg: 'linear-gradient(135deg, #06b6d4 0%, #0891b2 100%)', label: 'Point 4' } ]; const style = pointStyles[index] || pointStyles[0]; return (
{/* Decorative gradient bar */}
{/* Header with icon */}
{style.icon}
{p.description}
{style.label}
{/* Properties Grid */}
{/* Pressure */}
Pressure {p.pressure.toFixed(2)} bar
{/* Temperature */}
Temperature {(p.temperature || 0).toFixed(1)} °C
{/* Enthalpy */}
Enthalpy {(p.enthalpy || 0).toFixed(1)} kJ/kg
); })}
)} {!cycleData && (
{loading ? 'Calculating cycle...' : 'Adjust sliders — results will appear here (auto-calculated)'}
)}
); }