Mejora 2: Implementada edición en línea para el texto de los titulares.
This commit is contained in:
		| @@ -1,5 +1,8 @@ | ||||
| import { useEffect, useState, useCallback } from 'react'; | ||||
| import { Box, Button, Stack, Chip, CircularProgress, Accordion, AccordionSummary, AccordionDetails, Typography } from '@mui/material'; | ||||
| 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'; | ||||
| @@ -7,26 +10,25 @@ 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 { useNotification } from '../hooks/useNotification'; | ||||
| import FormularioConfiguracion from './FormularioConfiguracion'; | ||||
| import TablaTitulares from './TablaTitulares'; | ||||
| import AddTitularModal from './AddTitularModal'; | ||||
| import EditarTitularModal from './EditarTitularModal'; | ||||
| import { PowerSwitch } from './PowerSwitch'; | ||||
| import ConfirmationModal from './ConfirmationModal'; | ||||
| import type { ActualizarTitularPayload } from '../services/apiService'; | ||||
|  | ||||
| const Dashboard = () => { | ||||
|   const [titulares, setTitulares] = useState<Titular[]>([]); | ||||
|   const [config, setConfig] = useState<Configuracion | null>(null); | ||||
|   const [addModalOpen, setAddModalOpen] = useState(false); | ||||
|   const [isGeneratingCsv, setIsGeneratingCsv] = useState(false); | ||||
|   const [titularAEditar, setTitularAEditar] = useState<Titular | null>(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 [titularAEditar, setTitularAEditar] = useState<Titular | null>(null); | ||||
|  | ||||
|   const onTitularesActualizados = useCallback((titularesActualizados: Titular[]) => { | ||||
|     setTitulares(titularesActualizados); | ||||
|   }, []); | ||||
| @@ -36,12 +38,9 @@ const Dashboard = () => { | ||||
|   ]); | ||||
|  | ||||
|   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({ | ||||
| @@ -54,16 +53,39 @@ const Dashboard = () => { | ||||
|     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 }); | ||||
|       } | ||||
|     }; | ||||
|     setConfirmState({ open: true, onConfirm }); | ||||
|   }; | ||||
|  | ||||
|   const handleSaveEdit = async (id: number, payload: ActualizarTitularPayload) => { | ||||
|     try { | ||||
|       await api.actualizarTitular(id, payload); | ||||
|       showNotification('Titular actualizado', 'success'); | ||||
|     } catch (err) { | ||||
|       showNotification('Error al guardar los cambios', 'error'); | ||||
|       console.error("Error al guardar cambios:", err); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   const handleSwitchChange = async (event: React.ChangeEvent<HTMLInputElement>) => { | ||||
|     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 }); | ||||
|     } | ||||
|   }; | ||||
| @@ -79,21 +101,6 @@ const Dashboard = () => { | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   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); | ||||
| @@ -129,16 +136,6 @@ const Dashboard = () => { | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   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 ( | ||||
|     <> | ||||
|       <Box | ||||
| @@ -196,6 +193,7 @@ const Dashboard = () => { | ||||
|         onReorder={handleReorder} | ||||
|         onDelete={handleDelete} | ||||
|         onEdit={(titular) => setTitularAEditar(titular)} | ||||
|         onSave={handleSaveEdit} | ||||
|       /> | ||||
|  | ||||
|       <AddTitularModal | ||||
| @@ -203,13 +201,6 @@ const Dashboard = () => { | ||||
|         onClose={() => setAddModalOpen(false)} | ||||
|         onAdd={handleAdd} | ||||
|       /> | ||||
|  | ||||
|       <EditarTitularModal | ||||
|         open={titularAEditar !== null} | ||||
|         onClose={() => setTitularAEditar(null)} | ||||
|         onSave={handleSaveEdit} | ||||
|         titular={titularAEditar} | ||||
|       /> | ||||
|       <ConfirmationModal | ||||
|         open={confirmState.open} | ||||
|         onClose={() => setConfirmState({ open: false, onConfirm: null })} | ||||
| @@ -217,6 +208,12 @@ const Dashboard = () => { | ||||
|         title="Confirmar Eliminación" | ||||
|         message="¿Estás seguro de que quieres eliminar este titular? Esta acción no se puede deshacer." | ||||
|       /> | ||||
|       <EditarTitularModal | ||||
|         open={titularAEditar !== null} | ||||
|         onClose={() => setTitularAEditar(null)} | ||||
|         onSave={(id, texto, viñeta) => handleSaveEdit(id, { texto, viñeta: viñeta || null })} | ||||
|         titular={titularAEditar} | ||||
|       /> | ||||
|     </> | ||||
|   ); | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user