import { useEffect, useState, useCallback } from 'react'; import { Box, Button, Stack, Chip, CircularProgress, Accordion, AccordionSummary, AccordionDetails, Typography } from '@mui/material'; import AddIcon from '@mui/icons-material/Add'; import SyncIcon from '@mui/icons-material/Sync'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import type { Titular, Configuracion } from '../types'; import * as api from '../services/apiService'; import { useSignalR } from '../hooks/useSignalR'; import { useNotification } from '../hooks/useNotification'; // <-- Importar hook de notificación import FormularioConfiguracion from './FormularioConfiguracion'; import TablaTitulares from './TablaTitulares'; import AddTitularModal from './AddTitularModal'; import EditarTitularModal from './EditarTitularModal'; import { PowerSwitch } from './PowerSwitch'; import ConfirmationModal from './ConfirmationModal'; const Dashboard = () => { const [titulares, setTitulares] = useState([]); const [config, setConfig] = useState(null); const [addModalOpen, setAddModalOpen] = useState(false); const [isGeneratingCsv, setIsGeneratingCsv] = useState(false); const [titularAEditar, setTitularAEditar] = useState(null); // Estado para el modal de confirmación const [confirmState, setConfirmState] = useState<{ open: boolean; onConfirm: (() => void) | null }>({ open: false, onConfirm: null }); const { showNotification } = useNotification(); const onTitularesActualizados = useCallback((titularesActualizados: Titular[]) => { setTitulares(titularesActualizados); }, []); const { connectionStatus } = useSignalR([ { eventName: 'TitularesActualizados', callback: onTitularesActualizados } ]); useEffect(() => { // Obtenemos la configuración persistente const fetchConfig = api.obtenerConfiguracion(); // Obtenemos el estado inicial del switch (que siempre será 'false') const fetchEstado = api.getEstadoProceso(); // Cuando ambas promesas se resuelvan, construimos el estado inicial Promise.all([fetchConfig, fetchEstado]) .then(([configData, estadoData]) => { setConfig({ ...configData, scrapingActivo: estadoData.activo }); }) .catch(error => console.error("Error al cargar datos iniciales:", error)); api.obtenerTitulares().then(setTitulares); }, []); const handleSwitchChange = async (event: React.ChangeEvent) => { if (!config) return; const isChecked = event.target.checked; setConfig({ ...config, scrapingActivo: isChecked }); try { // Llamamos al nuevo endpoint para cambiar solo el estado await api.setEstadoProceso(isChecked); } catch (err) { console.error("Error al cambiar estado del proceso", err); // Revertir en caso de error setConfig({ ...config, scrapingActivo: !isChecked }); } }; const handleReorder = async (titularesReordenados: Titular[]) => { setTitulares(titularesReordenados); const payload = titularesReordenados.map((item, index) => ({ id: item.id, nuevoOrden: index })); try { await api.actualizarOrdenTitulares(payload); } catch (err) { console.error("Error al reordenar:", err); api.obtenerTitulares().then(setTitulares); } }; const handleDelete = (id: number) => { const onConfirm = async () => { try { await api.eliminarTitular(id); showNotification('Titular eliminado correctamente', 'success'); } catch (err) { showNotification('Error al eliminar el titular', 'error'); console.error("Error al eliminar:", err); } finally { setConfirmState({ open: false, onConfirm: null }); // Cierra el modal } }; setConfirmState({ open: true, onConfirm }); }; const handleAdd = async (texto: string) => { try { await api.crearTitularManual(texto); showNotification('Titular manual añadido', 'success'); } catch (err) { showNotification('Error al añadir el titular', 'error'); console.error("Error al añadir titular:", err); } }; const getStatusChip = () => { switch (connectionStatus) { case 'Connected': return ; case 'Reconnecting': case 'Connecting': return ; default: return ; } } const handleGenerateCsv = async () => { setIsGeneratingCsv(true); try { await api.generarCsvManual(); showNotification('CSV generado manualmente', 'success'); } catch (error) { showNotification('Error al generar el CSV', 'error'); console.error("Error al generar CSV manualmente", error); } finally { setIsGeneratingCsv(false); } }; const handleSaveEdit = async (id: number, texto: string, viñeta: string) => { try { await api.actualizarTitular(id, { texto, viñeta: viñeta || null }); showNotification('Titular actualizado', 'success'); } catch (err) { showNotification('Error al guardar los cambios', 'error'); console.error("Error al guardar cambios:", err); } }; return ( <> Estado del Servidor {getStatusChip()} {config ? ( ) : } }> Configuración setTitularAEditar(titular)} /> setAddModalOpen(false)} onAdd={handleAdd} /> setTitularAEditar(null)} onSave={handleSaveEdit} titular={titularAEditar} /> setConfirmState({ open: false, onConfirm: null })} onConfirm={() => confirmState.onConfirm?.()} title="Confirmar Eliminación" message="¿Estás seguro de que quieres eliminar este titular? Esta acción no se puede deshacer." /> ); }; export default Dashboard;