feature/rbac y perfiles implementados

This commit is contained in:
2026-05-21 08:00:43 -06:00
parent 546a411df8
commit dc5f9fd6ce
29 changed files with 2007 additions and 977 deletions

View File

@@ -2,6 +2,7 @@
function RelacionarImportadoresModal({ open, onClose, vucem }) {
const [importadoresDisponibles, setImportadoresDisponibles] = React.useState([]);
const [importadoresSeleccionados, setImportadoresSeleccionados] = React.useState([]);
const { showMessage } = useNotification();
React.useEffect(() => {
if (!open || !vucem) return;
@@ -50,7 +51,10 @@ function RelacionarImportadoresModal({ open, onClose, vucem }) {
body: JSON.stringify(body)
}
);
if (!res.ok) throw new Error('Error al relacionar importador');
if (!res.ok) {
const errMsg = await extractApiError(res);
throw new Error(errMsg);
}
const data = await res.json();
// Guardar el id de la relación en el importador seleccionado
const impConRelacion = {
@@ -61,7 +65,7 @@ function RelacionarImportadoresModal({ open, onClose, vucem }) {
setImportadoresDisponibles(importadoresDisponibles.filter(i => i.rfc !== imp.rfc));
setImportadoresSeleccionados([...importadoresSeleccionados, impConRelacion]);
} catch (err) {
alert('No se pudo relacionar el importador.');
showMessage(err.message || 'No se pudo relacionar el importador', 'error');
}
};
// Mover importador de seleccionados a disponibles
@@ -71,16 +75,19 @@ function RelacionarImportadoresModal({ open, onClose, vucem }) {
// Buscar el id de la relación usuario-importador en el objeto importador
const relacionId = imp.usuario_importador_id || imp.id_relacion || imp.id;
if (!relacionId) {
alert('No se encontró el id de la relación usuario-importador.');
showMessage('No se encontró el ID de la relación usuario-importador', 'warning');
return;
}
const url = `${import.meta.env.VITE_EFC_API_URL}/vucem/usuario-importador/${relacionId}/`;
const res = await fetchWithAuth(url, { method: 'DELETE' });
if (!res.ok) throw new Error('Error al eliminar relación');
if (!res.ok) {
const errMsg = await extractApiError(res);
throw new Error(errMsg);
}
setImportadoresSeleccionados(importadoresSeleccionados.filter(i => i.rfc !== imp.rfc));
setImportadoresDisponibles([...importadoresDisponibles, imp]);
} catch (err) {
alert('No se pudo eliminar la relación del importador.');
showMessage(err.message || 'No se pudo eliminar la relación del importador', 'error');
}
};
@@ -203,11 +210,12 @@ function RelacionarImportadoresModal({ open, onClose, vucem }) {
import React, { useEffect, useState } from 'react';
import { fetchWithAuth, postWithAuth, putWithAuth, deleteWithAuth, putFormDataWithAuth, postFormDataWithAuth, patchWithAuth } from '../fetchWithAuth';
import { useUser } from '../context/UserContext';
import { useNotification } from '../context/NotificationContext';
import { extractApiError } from '../api/apiError';
const API_URL = import.meta.env.VITE_EFC_API_URL;
export default function Vucem() {
// Estado para modal de relacionar importadores
const { showMessage } = useNotification();
const isDebugMode = import.meta.env.VITE_DEBUG_MODE === 'true';
const [showRelacionarModal, setShowRelacionarModal] = useState(false);
const [selectedVucem, setSelectedVucem] = useState(null);
@@ -378,13 +386,15 @@ export default function Vucem() {
setLoading(true);
try {
const res = await fetchWithAuth(`${API_URL}/vucem/vucem/`);
if (!res.ok) throw new Error('Error al cargar Ventanilla Unica');
if (!res.ok) {
const errMsg = await extractApiError(res);
throw new Error(errMsg);
}
const data = await res.json();
// console.log('data > ', data);
setVucemList(data);
setError(null);
} catch (err) {
setError('Error al cargar Ventanilla Unica');
setError(err.message);
}
setLoading(false);
};
@@ -464,14 +474,15 @@ export default function Vucem() {
});
if (!response.ok) {
throw new Error('Error al cambiar el estado');
const errMsg = await extractApiError(response);
throw new Error(errMsg);
}
// Recargar la lista para reflejar los cambios
await fetchVucem();
} catch (err) {
alert('Error al cambiar el estado de la credencial');
showMessage(err.message || 'Error al cambiar el estado de la credencial', 'error');
}
};
@@ -1304,11 +1315,14 @@ export default function Vucem() {
if (form.cer) formData.append('cer', form.cer);
try {
const res = await postFormDataWithAuth(`${API_URL}/vucem/vucem/`, formData);
if (!res.ok) throw new Error('Error al crear');
if (!res.ok) {
const errMsg = await extractApiError(res);
throw new Error(errMsg);
}
await fetchVucem();
closeModals();
} catch (err) {
alert('Error al crear');
showMessage(err.message || 'Error al crear la credencial', 'error');
}
}}>
@@ -1697,11 +1711,14 @@ export default function Vucem() {
formData.append('is_active', form.is_active);
try {
const res = await putFormDataWithAuth(`${API_URL}/vucem/vucem/${editVucem.id}/`, formData);
if (!res.ok) throw new Error('Error al actualizar');
if (!res.ok) {
const errMsg = await extractApiError(res);
throw new Error(errMsg);
}
await fetchVucem();
closeModals();
} catch (err) {
alert('Error al actualizar');
showMessage(err.message || 'Error al actualizar la credencial', 'error');
}
}}>
@@ -2018,11 +2035,14 @@ export default function Vucem() {
if (!deleteVucem) return;
try {
const res = await deleteWithAuth(`${API_URL}/vucem/vucem/${deleteVucem.id}/`);
if (!res.ok) throw new Error('Error al eliminar');
if (!res.ok) {
const errMsg = await extractApiError(res);
throw new Error(errMsg);
}
await fetchVucem();
closeModals();
} catch (err) {
alert('Error al eliminar');
showMessage(err.message || 'Error al eliminar la credencial', 'error');
}
}} className="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 transition-colors disabled:opacity-50 flex items-center">Eliminar</button>
</div>