import React, { useEffect, useState, useRef } from 'react'; import { API_URL } from '../config.js'; import { authFetch } from '../utils/authFetch.js'; import { HexColorPicker } from "react-colorful"; export default function Lighting() { const [state, setState] = useState({ power: '', red: 0, blue: 0, green: 0, brightness: 100 }); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [success, setSuccess] = useState(false); useEffect(() => { authFetch(`${API_URL}/lighting/state`) .then(res => res.json()) .then(data => { setState(data); setLoading(false); }) .catch(() => { setError('Failed to fetch lighting state'); setLoading(false); }); }, []); // Live update handler const debounceRef = useRef(); const updateLighting = newState => { // If brightness is 0, force power off let { power, red, green, blue, brightness } = newState; if (brightness === 0) power = 'off'; const prev = state; if ( power === prev.power && red === prev.red && green === prev.green && blue === prev.blue && brightness === prev.brightness ) return; setState({ ...newState, power }); setLoading(true); setSuccess(false); if (debounceRef.current) clearTimeout(debounceRef.current); debounceRef.current = setTimeout(() => { const payload = { power, red, green, blue, brightness }; authFetch(`${API_URL}/lighting/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }) .then(res => res.json()) .then(data => { // Only update state if all fields are present, otherwise preserve previous setState(prev => ({ power: typeof data.power === 'string' ? data.power : prev.power, red: typeof data.red === 'number' ? data.red : prev.red, green: typeof data.green === 'number' ? data.green : prev.green, blue: typeof data.blue === 'number' ? data.blue : prev.blue, brightness: typeof data.brightness === 'number' ? data.brightness : prev.brightness, })); setLoading(false); setSuccess(true); }) .catch(() => { setError('Failed to update lighting state'); setLoading(false); }); }, 400); // 400ms debounce }; const handlePowerToggle = () => { const newPower = state.power === 'on' ? 'off' : 'on'; updateLighting({ ...state, power: newPower }); }; const handleColorChange = hex => { const rgb = hexToRgb(hex); updateLighting({ power: state.power, // always preserve current power state red: rgb.red, green: rgb.green, blue: rgb.blue }); }; const handleSubmit = e => { e.preventDefault(); setLoading(true); setSuccess(false); authFetch(`${API_URL}/lighting/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(state), }) .then(res => res.json()) .then(data => { setState(data); setLoading(false); setSuccess(true); }) .catch(() => { setError('Failed to update lighting state'); setLoading(false); }); }; // Guard against undefined values const colorPreview = `rgb(${state.red ?? 0},${state.green ?? 0},${state.blue ?? 0})`; return (