From 3d58e16a8b643948afa6acb39b161d3d4834df6e Mon Sep 17 00:00:00 2001 From: Elliot Axel Noriega Date: Mon, 28 Oct 2024 18:45:56 -0600 Subject: [PATCH] =?UTF-8?q?Funcionalidad=20de=20edici=C3=B3n=20de=20campos?= =?UTF-8?q?=20de=20solicitudes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cosiap_frontend/src/api.js | 2 +- .../SolicitudesAdmin/MenuReportes.jsx | 0 .../SolicitudesAdmin/Solicitudes.jsx | 216 +++++++++++++++++- 3 files changed, 208 insertions(+), 10 deletions(-) create mode 100644 cosiap_frontend/src/components/SolicitudesAdmin/MenuReportes.jsx diff --git a/cosiap_frontend/src/api.js b/cosiap_frontend/src/api.js index 4b98370..c357def 100644 --- a/cosiap_frontend/src/api.js +++ b/cosiap_frontend/src/api.js @@ -119,7 +119,7 @@ const api = { get: () => ax.get('api/solicitudes'), post: (data) => ax.post('api/solicitudes/', data), getById: (id) => ax.get(`api/solicitudes/${id}`), - update: (id, data) => ax.put(`api/solicitudes/${id}`, data), + update: (id, data) => ax.put(`api/solicitudes/${id}/`, data), historial: { get: () => ax.get('api/solicitudes/historial'), getById: (id) => ax.get(`api/solicitudes/historial/${id}`), diff --git a/cosiap_frontend/src/components/SolicitudesAdmin/MenuReportes.jsx b/cosiap_frontend/src/components/SolicitudesAdmin/MenuReportes.jsx new file mode 100644 index 0000000..e69de29 diff --git a/cosiap_frontend/src/components/SolicitudesAdmin/Solicitudes.jsx b/cosiap_frontend/src/components/SolicitudesAdmin/Solicitudes.jsx index d0ec8f8..ab9022f 100644 --- a/cosiap_frontend/src/components/SolicitudesAdmin/Solicitudes.jsx +++ b/cosiap_frontend/src/components/SolicitudesAdmin/Solicitudes.jsx @@ -5,6 +5,7 @@ import api from "@/api"; import MenuColumnas from "./MenuColumnas"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import MenuFiltros from "./MenuFiltros"; +import Alert from "../common/ui/Alert"; export default function Solicitudes( {setViewPageLoader} ){ const [solicitudes, setSolicitudes] = useState([]); @@ -15,6 +16,19 @@ export default function Solicitudes( {setViewPageLoader} ){ const [filtrosAplicados, setFiltrosAplicados] = useState([]); const [searchTerm, setSearchTerm] = useState(''); + //Estados para la edición de campos + const [editingField, setEditingField] = useState(null); + const [editingValue, setEditingValue] = useState(""); + + //Los campos en las que se podran editar de manera fija + const AvailablesFieldsToEdit = [ + 'status', 'monto_aprobado', 'observacion' + ]; + + //Estados para alertas + const [showAlertSuccesful, setShowAlertSuccesful] = useState(false); + const [showAlertError, setShowAlertError] = useState(false); + //Vistas de columnas y filtros const [viewMenuColumnas, setViewMenuColumnas] = useState(false) const [viewMenuFiltros, setViewMenuFiltros] = useState(false) @@ -222,7 +236,7 @@ export default function Solicitudes( {setViewPageLoader} ){ ); case 'monto_aprobado': return ( - + ${value.toLocaleString('es-MX', { minimumFractionDigits: 2, // Número mínimo de decimales maximumFractionDigits: 2, // Número máximo de decimales @@ -251,23 +265,26 @@ export default function Solicitudes( {setViewPageLoader} ){ ); case 'solicitante__datos_bancarios__regimen': return Regimen(value) + + case 'observacion': + return ( + + {value} + + ); default: return value; } } - //Cada que el arreglo de filtros cambie, se aplicaran los filtros - useEffect(() => { - filtrarSolicitudes() - }, [filtros]) - + //Funcion para filtrar las solicitudes en base a los filtros const filtrarSolicitudes = () => { // Clonamos las solicitudes originales para no mutarlas let solicitudesFiltradas = [...solicitudesOriginales]; let nuevosFiltrosAplicados = []; - + // Iteramos sobre cada filtro disponible filtros.forEach(filtro => { @@ -348,8 +365,181 @@ export default function Solicitudes( {setViewPageLoader} ){ setFiltros(updatedFiltros); }; + // Función para manejar el doble clic en una celda + const handleDoubleClick = (id_solicitud, key, value) => { + setEditingField({ id_solicitud, key, value }); // Almacena el id y el nombre del campo en edición + setEditingValue(value); // Establece el valor actual del campo en edición + }; + + const handleResetEditing = () => { + setEditingField(null); // Reinicia el campo en edición + setEditingValue(""); // Reinicia el valor del campo en edición + } + + // Función para manejar el cambio en el input editable + const handleChange = (e) => { + setEditingValue(e.target.value); // Actualiza el valor en el input + }; + + const inputEditingField = (key) => { + switch (key) { + case 'status': + const choices = filtros.filter((filtro) => filtro.campo === 'status')[0].choices; + return ( + + ); + case 'monto_aprobado': + return ( + + ); + + case 'observacion': + return ( + + ); + default: + return ( + + ); + + } + } + + //Cada que el arreglo de filtros cambie, se aplicaran los filtros + //Añadi que tambien dependiera de las solicitudes originales para que se actualice de inmediato cuando se edita un campo y hay filtros aplicados + useEffect(() => { + filtrarSolicitudes() + }, [solicitudesOriginales,filtros]) + + // Evento de teclado para guardar cambios al presionar Enter + const handleKeyDown = (e) => { + if (e.key === "Enter") { + if (editingValue !== editingField.value) { // Si el valor original es diferente al cambiado + saveEdit(); //Guardamos + } + } + }; + + // Función para manejar el evento de blur o Enter para guardar cambios + const saveEdit = async () => { + // + try { + setViewPageLoader(true); + //Creamos un diccionario y agregamos como llave el valor editingField.key y como valor editingValue + const data = { + [editingField.key]: editingValue + }; + const response = await api.solicitudes.update(editingField.id_solicitud, {'field_updates': data}) + + console.log('Actualización exitosa', response) + + //Actualizamos las solicitudes + const responseSolicitudes = await api.solicitudes.get(); + + // Cambiamos en el arreglo de solicitudes, el registro + ChangeSolicitud(editingField.id_solicitud, editingField.key, editingValue) + + //Filtramos las solicitudes si es que hay filtros aplicados + filtrarSolicitudes() + + //Mostramos alerta de exito + setShowAlertSuccesful(true); + + // Resetea el estado de edición + setEditingField(null); + setEditingValue(""); + } catch (error) { + setShowAlertError(true); + } finally { + setViewPageLoader(false); + } + }; + + // Variable para cambiar el registro de una solicitud en ambos arreglos + const ChangeSolicitud = (id_solicitud, campo, newValue) => { + // Actualiza el arreglo de solicitudes + setSolicitudes((prevSolicitudes) => + prevSolicitudes.map((solicitud) => { + if (solicitud.id === id_solicitud) { + return { ...solicitud, [campo]: newValue }; + } + return solicitud; + }) + ); + + // Actualiza el arreglo de solicitudesOriginales + setSolicitudesOriginales((prevSolicitudesOriginales) => + prevSolicitudesOriginales.map((solicitud) => { + if (solicitud.id === id_solicitud) { + return { ...solicitud, [campo]: newValue }; + } + return solicitud; + }) + ); + }; + return ( <> + {showAlertSuccesful && ( + + )} + {showAlertError && ( + + )} {viewMenuColumnas && ( )} @@ -437,8 +627,16 @@ export default function Solicitudes( {setViewPageLoader} ){ {Object.entries(solicitud).map(([key, value], i) => ( !columnasOcultas.includes(key) && ( - - {getEstiloCampo(key, value)} + handleDoubleClick(solicitud.id, key, value) : null} //Le agregamos la funcion, solamente a los compos que se pueden editar + > + {editingField && editingField.id_solicitud === solicitud.id && editingField.key === key ? ( + inputEditingField(key) + ) : ( + getEstiloCampo(key, value) + )} ) ))} -- GitLab