diff --git a/.env b/.env
index bae8a6f..6160c3f 100644
--- a/.env
+++ b/.env
@@ -1,4 +1,4 @@
-VITE_DEBUG_MODE=false
+DEBUG_MODE=true
-VITE_EFC_API_URL=http://192.168.1.195:8000/api/v1
-VITE_EFC_MICROSERVICE_URL=http://192.168.1.195:8001/api/v1
+VITE_EFC_API_URL=https://api.efc-aduanasoft.com/api/v1
+VITE_EFC_MICROSERVICE_URL=https://api.efc-aduanasoft.com/microservice/api/v1
diff --git a/src/pages/Vucem.jsx b/src/pages/Vucem.jsx
index 35b4013..bee9261 100644
--- a/src/pages/Vucem.jsx
+++ b/src/pages/Vucem.jsx
@@ -26,6 +26,74 @@ export default function Vucem() {
};
const [form, setForm] = useState(initialForm);
+ // Estados para controlar visibilidad de contraseñas y copiar
+ const [showPassword, setShowPassword] = useState({});
+ const [showEfirma, setShowEfirma] = useState({});
+ const [copySuccess, setCopySuccess] = useState('');
+
+ // Funciones para alternar visibilidad
+ const togglePasswordVisibility = (id) => {
+ setShowPassword(prev => ({
+ ...prev,
+ [id]: !prev[id]
+ }));
+ };
+
+ const toggleEfirmaVisibility = (id) => {
+ setShowEfirma(prev => ({
+ ...prev,
+ [id]: !prev[id]
+ }));
+ };
+
+ // Función para copiar al portapapeles
+ const copyToClipboard = async (text, fieldName) => {
+ try {
+ // Verificar si el texto existe
+ if (!text || text.trim() === '') {
+ setCopySuccess(`${fieldName} está vacío`);
+ setTimeout(() => setCopySuccess(''), 2000);
+ return;
+ }
+
+ // Intentar usar la Clipboard API moderna
+ if (navigator.clipboard && window.isSecureContext) {
+ await navigator.clipboard.writeText(text);
+ setCopySuccess(`${fieldName} copiado`);
+ setTimeout(() => setCopySuccess(''), 2000);
+ } else {
+ // Fallback para navegadores más antiguos o contextos no seguros
+ const textArea = document.createElement('textarea');
+ textArea.value = text;
+ textArea.style.position = 'fixed';
+ textArea.style.opacity = '0';
+ textArea.style.pointerEvents = 'none';
+ document.body.appendChild(textArea);
+ textArea.focus();
+ textArea.select();
+
+ try {
+ const successful = document.execCommand('copy');
+ if (successful) {
+ setCopySuccess(`${fieldName} copiado`);
+ } else {
+ setCopySuccess(`Error al copiar ${fieldName}`);
+ }
+ } catch (fallbackErr) {
+ console.error('Error en fallback:', fallbackErr);
+ setCopySuccess(`Error al copiar ${fieldName}`);
+ } finally {
+ document.body.removeChild(textArea);
+ setTimeout(() => setCopySuccess(''), 2000);
+ }
+ }
+ } catch (err) {
+ console.error('Error al copiar:', err);
+ setCopySuccess(`Error al copiar ${fieldName}`);
+ setTimeout(() => setCopySuccess(''), 2000);
+ }
+ };
+
// Handlers básicos para inputs
const handleInputChange = e => {
const { name, value, type, checked, files } = e.target;
@@ -64,6 +132,79 @@ export default function Vucem() {
setLoading(false);
};
+ // Funciones de descarga
+ const downloadCertificate = async (id, usuario) => {
+ try {
+ const token = localStorage.getItem('access');
+ const res = await fetch(`${API_URL}/vucem/vucem/${id}/download_cer/`, {
+ headers: token ? { 'Authorization': `Bearer ${token}` } : {},
+ });
+
+ if (!res.ok) {
+ if (res.status === 404) {
+ setCopySuccess('Certificado no encontrado');
+ setTimeout(() => setCopySuccess(''), 2000);
+ return;
+ }
+ throw new Error('Error al descargar certificado');
+ }
+
+ const blob = await res.blob();
+ const url = window.URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.style.display = 'none';
+ a.href = url;
+ a.download = `${usuario}_certificado.cer`;
+ document.body.appendChild(a);
+ a.click();
+ window.URL.revokeObjectURL(url);
+ document.body.removeChild(a);
+
+ setCopySuccess('Certificado descargado');
+ setTimeout(() => setCopySuccess(''), 2000);
+ } catch (err) {
+ console.error('Error al descargar certificado:', err);
+ setCopySuccess('Error al descargar certificado');
+ setTimeout(() => setCopySuccess(''), 2000);
+ }
+ };
+
+ const downloadKey = async (id, usuario) => {
+ try {
+ const token = localStorage.getItem('access');
+ const res = await fetch(`${API_URL}/vucem/vucem/${id}/download_key/`, {
+ headers: token ? { 'Authorization': `Bearer ${token}` } : {},
+ });
+
+ if (!res.ok) {
+ if (res.status === 404) {
+ setCopySuccess('Clave no encontrada');
+ setTimeout(() => setCopySuccess(''), 2000);
+ return;
+ }
+ throw new Error('Error al descargar clave');
+ }
+
+ const blob = await res.blob();
+ const url = window.URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.style.display = 'none';
+ a.href = url;
+ a.download = `${usuario}_clave.key`;
+ document.body.appendChild(a);
+ a.click();
+ window.URL.revokeObjectURL(url);
+ document.body.removeChild(a);
+
+ setCopySuccess('Clave descargada');
+ setTimeout(() => setCopySuccess(''), 2000);
+ } catch (err) {
+ console.error('Error al descargar clave:', err);
+ setCopySuccess('Error al descargar clave');
+ setTimeout(() => setCopySuccess(''), 2000);
+ }
+ };
+
useEffect(() => {
fetchVucem();
}, []);
@@ -90,9 +231,9 @@ export default function Vucem() {
if (editVucem) {
setForm({
usuario: editVucem.usuario || '',
- password: '', // No se rellena por seguridad
+ password: editVucem.password || '', // Mostrar el password actual para edición
patente: editVucem.patente || '',
- efirma: editVucem.efirma || '',
+ efirma: editVucem.efirma || '', // Ya estaba incluido
key: null, // No se rellena, solo se sube si el usuario selecciona
cer: null, // No se rellena, solo se sube si el usuario selecciona
is_importador: !!editVucem.is_importador,
@@ -168,6 +309,17 @@ export default function Vucem() {
opacity: 0;
}
`}
+
+ {/* Mensaje de éxito para copiar */}
+ {copySuccess && (
+
+ )}
+
{/* Controles de búsqueda y filtros mejorados */}
@@ -239,7 +391,8 @@ export default function Vucem() {
| Usuario |
- Patente |
+ Password |
+ e.firma |
Archivos |
Estado |
Acciones |
@@ -248,7 +401,7 @@ export default function Vucem() {
{loading ? (
- |
+ |
@@ -259,7 +412,7 @@ export default function Vucem() {
|
) : error ? (
- |
+ |
@@ -285,30 +438,96 @@ export default function Vucem() {
>
-
{vucem.usuario}
- ID: {vucem.id}
+ Patente: {vucem.patente}
|
- {vucem.patente}
- e.firma: {vucem.efirma}
+
+
+ {showPassword[vucem.id] ? vucem.password || '(vacío)' : '••••••••'}
+
+
+
+
+ |
+
+
+
+ {showEfirma[vucem.id] ? vucem.efirma || '(vacío)' : '••••••••'}
+
+
+
+
|
{vucem.key ? (
-
-
- Key
-
+
+
+
+ Key
+
+
+
) : (
)}
{vucem.cer ? (
-
-
- Cer
-
+
+
+
+ Cer
+
+
+
) : (
|
@@ -388,13 +618,13 @@ export default function Vucem() {
{/* Rellenar con filas vacías si hay menos de 8 */}
{paginatedList.length < 8 && !loading && !error && Array.from({ length: 8 - paginatedList.length }).map((_, idx) => (
- | |
+ |
))}
>
) : (
- |
+ |
@@ -437,42 +667,98 @@ export default function Vucem() {
-
{vucem.usuario}
Patente: {vucem.patente}
- ID: {vucem.id}
+
+ Password:
+
+
+ {showPassword[vucem.id] ? vucem.password || '(vacío)' : '••••••••'}
+
+
+
+
+
e.firma:
- {vucem.efirma}
+
+
+ {showEfirma[vucem.id] ? vucem.efirma || '(vacío)' : '••••••••'}
+
+
+
+
Estado:
@@ -504,14 +790,25 @@ export default function Vucem() {
Archivos:
-
+
{vucem.key ? (
-
-
-
-
- Key
-
+
+
+
+
+
+ Key
+
+
+
) : (
@@ -521,12 +818,23 @@ export default function Vucem() {
)}
{vucem.cer ? (
-
-
-
-
- Cer
-
+
+
+
+
+
+ Cer
+
+
+
) : (
@@ -651,7 +959,46 @@ export default function Vucem() {
-
+
+
+
+
+
+
+
@@ -659,7 +1006,46 @@ export default function Vucem() {
-
+
+
+
+
+
+
+
@@ -741,8 +1127,46 @@ export default function Vucem() {
-
-
+
+
+
+
+
+
+
+
@@ -750,7 +1174,46 @@ export default function Vucem() {
-
+
+
+
+
+
+
+
| |