Se agregaron cambios en vucem y settings
This commit is contained in:
@@ -243,13 +243,13 @@ const Settings = () => {
|
||||
|
||||
setSaving(true);
|
||||
try {
|
||||
// Preparar datos para enviar - NO incluir grupos para preservarlos
|
||||
// Preparar datos para enviar - NO incluir grupos ni RFC para preservarlos
|
||||
const updateData = {
|
||||
first_name: formData.first_name.trim(),
|
||||
last_name: formData.last_name.trim(),
|
||||
email: formData.email.trim(),
|
||||
// Username NO se incluye - no se puede modificar
|
||||
...(formData.rfc.trim() && { rfc: formData.rfc.trim() }), // Solo incluir RFC si existe
|
||||
// RFC NO se incluye - no se puede modificar
|
||||
is_importador: currentUser.is_importador, // Preservar estado actual
|
||||
is_active: currentUser.is_active // Preservar estado actual
|
||||
};
|
||||
@@ -336,9 +336,8 @@ const Settings = () => {
|
||||
return (
|
||||
formData.first_name !== (currentUser.first_name || '') ||
|
||||
formData.last_name !== (currentUser.last_name || '') ||
|
||||
formData.email !== (currentUser.email || '') ||
|
||||
// Username excluded from change detection - field is read-only
|
||||
formData.rfc !== (currentUser.rfc || '')
|
||||
formData.email !== (currentUser.email || '')
|
||||
// RFC excluded from change detection - field is read-only
|
||||
);
|
||||
};
|
||||
|
||||
@@ -543,10 +542,13 @@ const Settings = () => {
|
||||
type="text"
|
||||
name="rfc"
|
||||
value={formData.rfc}
|
||||
onChange={handleInputChange}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm transition-all duration-200 hover:border-gray-400"
|
||||
disabled
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-lg shadow-sm bg-gray-50 text-gray-500 cursor-not-allowed text-sm"
|
||||
placeholder="XXXX000000XXX"
|
||||
/>
|
||||
<p className="text-xs text-gray-500">
|
||||
El RFC no puede ser modificado por razones de seguridad
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -576,13 +578,13 @@ const Settings = () => {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
// Resetear formulario a los valores originales (username no se resetea porque no se puede cambiar)
|
||||
// Resetear formulario a los valores originales (username y RFC no se resetean porque no se pueden cambiar)
|
||||
setFormData({
|
||||
first_name: currentUser?.first_name || '',
|
||||
last_name: currentUser?.last_name || '',
|
||||
email: currentUser?.email || '',
|
||||
username: currentUser?.username || '', // Mantener valor original
|
||||
rfc: currentUser?.rfc || ''
|
||||
rfc: currentUser?.rfc || '' // Mantener valor original
|
||||
});
|
||||
}}
|
||||
disabled={saving}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { fetchWithAuth, postWithAuth, putWithAuth, deleteWithAuth, putFormDataWithAuth, postFormDataWithAuth } from '../fetchWithAuth';
|
||||
import { fetchWithAuth, postWithAuth, putWithAuth, deleteWithAuth, putFormDataWithAuth, postFormDataWithAuth, patchWithAuth } from '../fetchWithAuth';
|
||||
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
export default function Vucem() {
|
||||
@@ -32,6 +32,10 @@ export default function Vucem() {
|
||||
const [showEfirma, setShowEfirma] = useState({});
|
||||
const [copySuccess, setCopySuccess] = useState('');
|
||||
|
||||
// Estados específicos para modal de edición (siempre ocultos por defecto)
|
||||
const [showEditPassword, setShowEditPassword] = useState(false);
|
||||
const [showEditEfirma, setShowEditEfirma] = useState(false);
|
||||
|
||||
// Funciones para alternar visibilidad
|
||||
const togglePasswordVisibility = (id) => {
|
||||
setShowPassword(prev => ({
|
||||
@@ -47,6 +51,23 @@ export default function Vucem() {
|
||||
}));
|
||||
};
|
||||
|
||||
// Funciones para alternar visibilidad en modal de edición
|
||||
const toggleEditPasswordVisibility = () => {
|
||||
setShowEditPassword(!showEditPassword);
|
||||
};
|
||||
|
||||
const toggleEditEfirmaVisibility = () => {
|
||||
setShowEditEfirma(!showEditEfirma);
|
||||
};
|
||||
|
||||
// Función helper para truncar texto largo en la tabla
|
||||
const truncateForTable = (text, maxLength = 20) => {
|
||||
if (!text || text.length <= maxLength) return text;
|
||||
const start = text.substring(0, 6);
|
||||
const end = text.substring(text.length - 6);
|
||||
return `${start}...${end}`;
|
||||
};
|
||||
|
||||
// Función para copiar al portapapeles
|
||||
const copyToClipboard = async (text, fieldName) => {
|
||||
try {
|
||||
@@ -113,6 +134,9 @@ export default function Vucem() {
|
||||
setForm(initialForm);
|
||||
setEditVucem(null);
|
||||
setDeleteVucem(null);
|
||||
// Resetear estados de visibilidad del modal de edición
|
||||
setShowEditPassword(false);
|
||||
setShowEditEfirma(false);
|
||||
};
|
||||
|
||||
// Fetch list
|
||||
@@ -197,6 +221,25 @@ export default function Vucem() {
|
||||
}
|
||||
};
|
||||
|
||||
// Función para activar/desactivar credencial
|
||||
const toggleVucemStatus = async (id, currentStatus) => {
|
||||
try {
|
||||
const response = await patchWithAuth(`${API_URL}/vucem/vucem/${id}/`, {
|
||||
is_active: !currentStatus
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Error al cambiar el estado');
|
||||
}
|
||||
|
||||
// Recargar la lista para reflejar los cambios
|
||||
await fetchVucem();
|
||||
|
||||
} catch (err) {
|
||||
alert('Error al cambiar el estado de la credencial');
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchVucem();
|
||||
}, []);
|
||||
@@ -233,6 +276,9 @@ export default function Vucem() {
|
||||
acuseedocument: !!editVucem.acuseedocument,
|
||||
is_active: !!editVucem.is_active,
|
||||
});
|
||||
// Resetear visibilidad de campos sensibles cuando se abre el modal de edición
|
||||
setShowEditPassword(false);
|
||||
setShowEditEfirma(false);
|
||||
}
|
||||
}, [editVucem]);
|
||||
|
||||
@@ -439,7 +485,7 @@ export default function Vucem() {
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="text-sm text-gray-600 font-mono">
|
||||
{showPassword[vucem.id] ? vucem.password || '(vacío)' : '••••••••'}
|
||||
{showPassword[vucem.id] ? truncateForTable(vucem.password) || '(vacío)' : '••••••••'}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => togglePasswordVisibility(vucem.id)}
|
||||
@@ -471,7 +517,7 @@ export default function Vucem() {
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="text-sm text-gray-600 font-mono">
|
||||
{showEfirma[vucem.id] ? vucem.efirma || '(vacío)' : '••••••••'}
|
||||
{showEfirma[vucem.id] ? truncateForTable(vucem.efirma) || '(vacío)' : '••••••••'}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => toggleEfirmaVisibility(vucem.id)}
|
||||
@@ -594,6 +640,25 @@ export default function Vucem() {
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => toggleVucemStatus(vucem.id, vucem.is_active)}
|
||||
className={`inline-flex items-center p-2 border shadow-sm font-medium rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-offset-2 transition-all duration-200 transform hover:scale-105 ${
|
||||
vucem.is_active
|
||||
? 'border-orange-300 text-orange-700 hover:bg-orange-50 focus:ring-orange-500'
|
||||
: 'border-green-300 text-green-700 hover:bg-green-50 focus:ring-green-500'
|
||||
}`}
|
||||
title={vucem.is_active ? "Desactivar" : "Activar"}
|
||||
>
|
||||
{vucem.is_active ? (
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728L5.636 5.636m12.728 12.728L5.636 5.636" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { setDeleteVucem(vucem); setShowDeleteModal(true); }}
|
||||
className="inline-flex items-center p-2 border border-red-300 shadow-sm font-medium rounded-lg text-red-700 bg-white hover:bg-red-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 transition-all duration-200 transform hover:scale-105"
|
||||
@@ -674,6 +739,25 @@ export default function Vucem() {
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => toggleVucemStatus(vucem.id, vucem.is_active)}
|
||||
className={`inline-flex items-center justify-center p-2 border shadow-sm font-medium rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-offset-2 transition-all duration-200 ${
|
||||
vucem.is_active
|
||||
? 'border-orange-300 text-orange-700 hover:bg-orange-50 focus:ring-orange-500'
|
||||
: 'border-green-300 text-green-700 hover:bg-green-50 focus:ring-green-500'
|
||||
}`}
|
||||
title={vucem.is_active ? "Desactivar" : "Activar"}
|
||||
>
|
||||
{vucem.is_active ? (
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728L5.636 5.636m12.728 12.728L5.636 5.636" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { setDeleteVucem(vucem); setShowDeleteModal(true); }}
|
||||
className="inline-flex items-center justify-center p-2 border border-red-300 shadow-sm font-medium rounded-lg text-red-700 bg-white hover:bg-red-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 transition-all duration-200"
|
||||
@@ -690,7 +774,7 @@ export default function Vucem() {
|
||||
<span className="font-medium text-gray-500">Password:</span>
|
||||
<div className="mt-1 flex items-center space-x-2">
|
||||
<span className="text-gray-600 font-mono">
|
||||
{showPassword[vucem.id] ? vucem.password || '(vacío)' : '••••••••'}
|
||||
{showPassword[vucem.id] ? truncateForTable(vucem.password) || '(vacío)' : '••••••••'}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => togglePasswordVisibility(vucem.id)}
|
||||
@@ -723,7 +807,7 @@ export default function Vucem() {
|
||||
<span className="font-medium text-gray-500">e.firma:</span>
|
||||
<div className="mt-1 flex items-center space-x-2">
|
||||
<span className="text-gray-600 font-mono">
|
||||
{showEfirma[vucem.id] ? vucem.efirma || '(vacío)' : '••••••••'}
|
||||
{showEfirma[vucem.id] ? truncateForTable(vucem.efirma) || '(vacío)' : '••••••••'}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => toggleEfirmaVisibility(vucem.id)}
|
||||
@@ -1113,7 +1197,7 @@ export default function Vucem() {
|
||||
<div className="relative">
|
||||
<input
|
||||
name="password"
|
||||
type={showPassword ? "text" : "password"}
|
||||
type={showEditPassword ? "text" : "password"}
|
||||
value={form.password}
|
||||
onChange={handleInputChange}
|
||||
className="w-full px-3 py-2 pr-20 border border-gray-300 rounded-md shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
|
||||
@@ -1122,11 +1206,11 @@ export default function Vucem() {
|
||||
<div className="absolute inset-y-0 right-0 flex items-center">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
onClick={toggleEditPasswordVisibility}
|
||||
className="px-2 py-1 text-gray-400 hover:text-gray-600 focus:outline-none"
|
||||
title={showPassword ? "Ocultar password" : "Mostrar password"}
|
||||
title={showEditPassword ? "Ocultar password" : "Mostrar password"}
|
||||
>
|
||||
{showPassword ? (
|
||||
{showEditPassword ? (
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L8.464 8.464m1.414 1.414L21.536 21.536" />
|
||||
</svg>
|
||||
|
||||
Reference in New Issue
Block a user