Files
Chatbot-ElDia/chatbot-admin/src/components/ContextManager.tsx

213 lines
6.8 KiB
TypeScript
Raw Normal View History

2025-11-18 14:34:26 -03:00
// src/components/AdminPanel.tsx
import React, { useState, useEffect, useCallback } from 'react';
import axios from 'axios';
import { DataGrid, GridActionsCellItem } from '@mui/x-data-grid';
import type { GridColDef } from '@mui/x-data-grid';
import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Alert, DialogContentText, TextField } from '@mui/material';
import EditIcon from '@mui/icons-material/Edit';
import DeleteIcon from '@mui/icons-material/Delete';
import AddIcon from '@mui/icons-material/Add';
import apiClient from '../api/apiClient';
interface ContextoItem {
id: number;
clave: string;
valor: string;
descripcion: string;
fechaActualizacion: string;
}
interface ContextManagerProps {
onAuthError: () => void;
}
const ContextManager: React.FC<ContextManagerProps> = ({ onAuthError }) => {
const [rows, setRows] = useState<ContextoItem[]>([]);
const [open, setOpen] = useState(false);
const [isEdit, setIsEdit] = useState(false);
const [currentRow, setCurrentRow] = useState<Partial<ContextoItem>>({});
const [error, setError] = useState<string | null>(null);
// Estado para el diálogo de confirmación de borrado
const [confirmOpen, setConfirmOpen] = useState(false);
const [itemToDelete, setItemToDelete] = useState<number | null>(null);
const fetchData = useCallback(async () => {
try {
const response = await apiClient.get('/api/admin/contexto');
setRows(response.data);
} catch (err) {
setError('No se pudieron cargar los datos.');
if (axios.isAxiosError(err) && err.response?.status === 401) {
onAuthError();
}
}
}, [onAuthError]);
useEffect(() => {
fetchData();
}, [fetchData]);
const handleOpen = (item?: ContextoItem) => {
if (item) {
setIsEdit(true);
setCurrentRow(item);
} else {
setIsEdit(false);
setCurrentRow({ clave: '', valor: '', descripcion: '' });
}
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const handleSave = async () => {
try {
if (isEdit) {
await apiClient.put(`/api/admin/contexto/${currentRow.id}`, currentRow);
} else {
await apiClient.post('/api/admin/contexto', currentRow);
}
fetchData();
handleClose();
} catch (err) {
setError('Error al guardar el item.');
}
};
// Abre el diálogo de confirmación
const handleDeleteClick = (id: number) => {
setItemToDelete(id);
setConfirmOpen(true);
};
// Cierra el diálogo de confirmación
const handleConfirmClose = () => {
setConfirmOpen(false);
setItemToDelete(null);
};
// Ejecuta la eliminación si se confirma
const handleConfirmDelete = async () => {
if (itemToDelete !== null) {
try {
await apiClient.delete(`/api/admin/contexto/${itemToDelete}`);
fetchData();
} catch (err) {
setError('Error al eliminar el item.');
} finally {
handleConfirmClose();
}
}
};
const columns: GridColDef[] = [
{ field: 'clave', headerName: 'Clave', width: 200 },
{ field: 'valor', headerName: 'Valor', width: 350 },
{ field: 'descripcion', headerName: 'Descripción', flex: 1 },
{
field: 'fechaActualizacion',
headerName: 'Última Actualización',
width: 200,
valueGetter: (value) => new Date(value).toLocaleString(),
},
{
field: 'actions',
type: 'actions',
width: 100,
getActions: (params) => [
<GridActionsCellItem
icon={<EditIcon />}
label="Editar"
onClick={() => handleOpen(params.row as ContextoItem)}
/>,
<GridActionsCellItem
icon={<DeleteIcon />}
label="Eliminar"
// Llama a la función que abre el diálogo
onClick={() => handleDeleteClick(params.id as number)}
/>,
],
},
];
return (
<Box sx={{ p: 4 }}>
{error && <Alert severity="error" sx={{ mb: 2 }}>{error}</Alert>}
<Button startIcon={<AddIcon />} variant="contained" onClick={() => handleOpen()} sx={{ mb: 1 }}>
Añadir Nuevo Item
</Button>
<Box sx={{ height: 600, width: '100%' }}>
<DataGrid rows={rows} columns={columns} pageSizeOptions={[10, 25, 50, 100]} />
</Box>
<Box sx={{ p: 4 }}>
{error && <Alert severity="error" sx={{ mb: 2 }}>{error}</Alert>}
<Button startIcon={<AddIcon />} variant="contained" onClick={() => handleOpen()} sx={{ mb: 1 }}>
Añadir Nuevo Item
</Button>
<Box sx={{ height: 600, width: '100%' }}>
<DataGrid rows={rows} columns={columns} pageSizeOptions={[10, 25, 50, 100]} />
</Box>
{/* --- DIÁLOGO DE EDICIÓN/CREACIÓN --- */}
<Dialog open={open} onClose={handleClose} fullWidth maxWidth="sm">
<DialogTitle>{isEdit ? 'Editar Item' : 'Añadir Nuevo Item'}</DialogTitle>
<DialogContent>
<TextField
margin="dense"
label="Clave"
fullWidth
value={currentRow.clave || ''}
disabled={isEdit} // La clave no se puede editar una vez creada
onChange={(e) => setCurrentRow({ ...currentRow, clave: e.target.value })}
helperText={!isEdit ? "Esta clave no se podrá modificar en el futuro." : ""}
/>
<TextField
margin="dense"
label="Valor"
fullWidth
multiline
rows={4}
value={currentRow.valor || ''}
onChange={(e) => setCurrentRow({ ...currentRow, valor: e.target.value })}
/>
<TextField
margin="dense"
label="Descripción"
fullWidth
value={currentRow.descripcion || ''}
onChange={(e) => setCurrentRow({ ...currentRow, descripcion: e.target.value })}
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancelar</Button>
<Button onClick={handleSave} variant="contained">Guardar</Button>
</DialogActions>
</Dialog>
{/* --- DIÁLOGO DE CONFIRMACIÓN DE BORRADO --- */}
<Dialog
open={confirmOpen}
onClose={handleConfirmClose}
>
<DialogTitle>Confirmar Eliminación</DialogTitle>
<DialogContent>
<DialogContentText>
¿Estás seguro de que quieres eliminar este item? Esta acción no se puede deshacer.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleConfirmClose}>Cancelar</Button>
<Button onClick={handleConfirmDelete} color="error" variant="contained">
Eliminar
</Button>
</DialogActions>
</Dialog>
</Box>
</Box>
);
};
export default ContextManager;