import { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { Play, Square, Zap, BatteryCharging, Clock, Activity, Loader2, ArrowLeft, } from 'lucide-react'; import { motion, AnimatePresence } from 'framer-motion'; import { SectionCard } from '@/components/ui/SectionCard'; import { getAuthHeader } from '@/utils/apiAuthHeader'; import { useToast } from '@/components/ToastContext'; export default function ChargerDashboard() { const { chargerId } = useParams(); // Obter o chargerId da URL const [dados, setDados] = useState(null); const [ampLimit, setAmpLimit] = useState(6); const [maxAmps, setMaxAmps] = useState(32); const [error, setError] = useState(''); const [loading, setLoading] = useState(true); const [busy, setBusy] = useState(false); const navigate = useNavigate(); const showToast = useToast(); // Buscar status do carregador useEffect(() => { if (!chargerId) { setError("Carregador não encontrado!"); setLoading(false); return; } let cancelado = false; async function fetchStatus() { setLoading(true); setError(''); try { const res = await fetch(`/api/chargers/${chargerId}/status`, { headers: getAuthHeader(), }); const json = await res.json(); if (!res.ok || !json.success) throw new Error(json.message || 'Erro ao obter status'); if (!cancelado) { setDados(json.data); setAmpLimit(json.data.ampLimit ?? 6); setMaxAmps(json.data.maxAmps ?? 32); } } catch (err) { if (!cancelado) setError(err.message || 'Falha ao buscar status'); } finally { if (!cancelado) setLoading(false); } } fetchStatus(); const interval = setInterval(fetchStatus, 8000); return () => { cancelado = true; clearInterval(interval); }; }, [chargerId]); // Atualizar a requisição sempre que o chargerId mudar // Enviar comandos (iniciar/parar carregamento) async function handleAction(action) { if (!chargerId) return; // Adicionar verificação extra para chargerId setBusy(true); try { const res = await fetch(`/api/chargers/${chargerId}/${action}`, { method: 'POST', headers: { ...getAuthHeader(), 'Content-Type': 'application/json', }, body: JSON.stringify({ ampLimit }), }); const json = await res.json(); if (!res.ok || !json.success) throw new Error(json.message || 'Erro ao enviar comando'); setDados(json.data); showToast( action === 'start' ? 'Carregamento iniciado' : 'Carregamento parado', 'success' ); setError(''); } catch (err) { setError(err.message); showToast(err.message, 'error'); } finally { setBusy(false); } } return (
} > {error && ( {error} )} {(loading || busy) ? (
{busy ? 'Enviando comando...' : 'Carregando status...'}
) : ( dados && ( <> {/* Potência em destaque */}
7 ? 'border-yellow-400 opacity-60' : 'border-blue-200 opacity-30'}`} />
7 ? 'border-yellow-500' : 'border-blue-600'} flex flex-col items-center justify-center text-blue-700`} > 7 ? 'text-yellow-500' : 'text-blue-600' }`} > {dados.currentPower} kW Potência
{/* Informações detalhadas */}
} label="Estado" value={dados.status} valueClass="text-blue-600" /> } label="Tempo de carregamento" value={dados.timeRemaining} /> } label="Potência" value={ {dados.potenciaAtual} kW } /> } label="Modo" value={dados.modo?.toUpperCase()} valueClass="text-indigo-600 font-bold" />
{/* Slider para Amperagem */}
setAmpLimit(Number(e.target.value))} className="w-full accent-blue-600" aria-valuenow={ampLimit} aria-valuemin={6} aria-valuemax={maxAmps} disabled={busy} />
6 A {maxAmps} A
{/* Botões */}
handleAction('start')} className="bg-green-600 hover:bg-green-700 text-white px-5 py-2 rounded-xl shadow font-medium transition flex items-center gap-2 active:scale-95 focus:outline-none focus:ring-2 focus:ring-green-400" disabled={busy} aria-label="Iniciar carregamento" > Iniciar handleAction('stop')} className="bg-red-500 hover:bg-red-600 text-white px-5 py-2 rounded-xl shadow font-medium transition flex items-center gap-2 active:scale-95 focus:outline-none focus:ring-2 focus:ring-red-400" disabled={busy} aria-label="Parar carregamento" > Parar
) )}
); } function InfoItem({ icon, label, value, valueClass = '' }) { return (
{icon} {label}
{value}
); }