Primera version para produccion
This commit is contained in:
@@ -9,6 +9,7 @@ const MICROSERVICE_URL = import.meta.env.VITE_EFC_MICROSERVICE_URL;
|
||||
|
||||
|
||||
|
||||
|
||||
export default function Procesos() {
|
||||
const [procesos, setProcesos] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -21,6 +22,10 @@ export default function Procesos() {
|
||||
const [estadoFilter, setEstadoFilter] = useState('');
|
||||
const [servicioFilter, setServicioFilter] = useState('');
|
||||
|
||||
// Sorting
|
||||
const [sortField, setSortField] = useState('');
|
||||
const [sortOrder, setSortOrder] = useState('asc'); // 'asc' | 'desc'
|
||||
|
||||
// Estado para loading de ejecución de servicio
|
||||
const [executingId, setExecutingId] = useState(null);
|
||||
|
||||
@@ -34,6 +39,9 @@ export default function Procesos() {
|
||||
let endpoint = '';
|
||||
// Determinar endpoint según el tipo de servicio
|
||||
switch (proc.servicio) {
|
||||
case 3:
|
||||
endpoint = '/services/pedimento_completo';
|
||||
break;
|
||||
case 4: // Partidas
|
||||
endpoint = '/services/partidas';
|
||||
break;
|
||||
@@ -43,7 +51,10 @@ export default function Procesos() {
|
||||
case 6: // Acuse
|
||||
endpoint = '/services/acuse';
|
||||
break;
|
||||
case 8: // Acuse Cove
|
||||
case 8: // Coves
|
||||
endpoint = '/services/Coves';
|
||||
break;
|
||||
case 9: // Acuse Cove
|
||||
endpoint = '/services/acuseCove';
|
||||
break;
|
||||
default:
|
||||
@@ -102,7 +113,9 @@ export default function Procesos() {
|
||||
if (pedimentoPedimentoFilter) params.append('pedimento__pedimento', pedimentoPedimentoFilter);
|
||||
if (estadoFilter) params.append('estado', estadoFilter);
|
||||
if (servicioFilter) params.append('servicio', servicioFilter);
|
||||
// ...existing code...
|
||||
if (sortField) {
|
||||
params.append('ordering', (sortOrder === 'desc' ? '-' : '') + sortField);
|
||||
}
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
const headers = token ? { 'Authorization': `Bearer ${token}` } : {};
|
||||
const res = await fetch(`${API_URL}/customs/procesamientopedimentos/?${params.toString()}`, { headers });
|
||||
@@ -117,7 +130,7 @@ export default function Procesos() {
|
||||
}
|
||||
}
|
||||
fetchProcesos();
|
||||
}, [page, itemsPerPage, pedimentoPedimentoFilter, estadoFilter, servicioFilter]);
|
||||
}, [page, itemsPerPage, pedimentoPedimentoFilter, estadoFilter, servicioFilter, sortField, sortOrder]);
|
||||
|
||||
return (
|
||||
<div className="p-6 bg-gray-50 min-h-screen">
|
||||
@@ -131,6 +144,9 @@ export default function Procesos() {
|
||||
<div>
|
||||
<h1 className="text-3xl font-extrabold text-blue-900 tracking-tight mb-1 flex items-center gap-2">
|
||||
Procesos del Sistema
|
||||
<span className="inline-block bg-blue-200 text-blue-800 text-xs font-semibold px-2 py-0.5 rounded-full ml-2 animate-fade-in" title="Total de procesos">
|
||||
{count}
|
||||
</span>
|
||||
</h1>
|
||||
<p className="text-lg text-blue-700/80 font-medium">Estado actual de los procesos de la agencia aduanal</p>
|
||||
</div>
|
||||
@@ -160,10 +176,19 @@ export default function Procesos() {
|
||||
.animate-fadein-slideup {
|
||||
animation: fadein-slideup 0.7s cubic-bezier(0.22,1,0.36,1) 0.05s forwards;
|
||||
}
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; transform: scale(0.9); }
|
||||
to { opacity: 1; transform: scale(1); }
|
||||
}
|
||||
.animate-fade-in {
|
||||
animation: fade-in 0.7s ease;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
<div className="bg-white rounded-xl shadow-lg border border-gray-200 p-8 animate-fadein-slideup opacity-0" style={{ animation: 'fadein-slideup 0.7s cubic-bezier(0.22,1,0.36,1) 0.15s forwards' }}>
|
||||
<h2 className="text-2xl font-bold text-blue-800 mb-6">Procesamiento de Pedimentos</h2>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h2 className="text-2xl font-bold text-blue-800">Procesamiento de Pedimentos</h2>
|
||||
</div>
|
||||
{/* Filtros */}
|
||||
<div className="mb-4 flex flex-wrap gap-4 items-end justify-between">
|
||||
<div className="flex flex-col flex-1 min-w-[150px]">
|
||||
@@ -206,9 +231,10 @@ export default function Procesos() {
|
||||
<option value="6">Acuse</option>
|
||||
<option value="7">EDocument</option>
|
||||
<option value="8">Cove</option>
|
||||
<option value="9">Acuse Cove</option>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
{/* ...filtros anteriores... */}
|
||||
</div>
|
||||
{loading ? (
|
||||
<div className="text-center text-gray-500 py-8">Cargando procesos...</div>
|
||||
@@ -220,14 +246,51 @@ export default function Procesos() {
|
||||
<table className="min-w-full divide-y divide-gray-200 rounded-lg overflow-hidden sticky text-xs">
|
||||
<thead className="bg-gradient-to-r from-gray-50 sticky top-0 z-20">
|
||||
<tr>
|
||||
<th className="px-2 py-2 text-center font-bold text-blue-700 uppercase tracking-wider border-b border-gray-200 whitespace-nowrap">ID</th>
|
||||
<th className="px-2 py-2 text-left font-bold uppercase tracking-wider border-b border-gray-200 whitespace-nowrap">Organización</th>
|
||||
<th className="px-2 py-2 text-left font-bold uppercase tracking-wider border-b border-gray-200 whitespace-nowrap">Estado</th>
|
||||
<th className="px-2 py-2 text-left font-bold uppercase tracking-wider border-b border-gray-200 whitespace-nowrap">Pedimento</th>
|
||||
<th className="px-2 py-2 text-left font-bold uppercase tracking-wider border-b border-gray-200 whitespace-nowrap">Servicio</th>
|
||||
<th className="px-2 py-2 text-center font-bold text-blue-700 uppercase tracking-wider border-b border-gray-200 whitespace-nowrap">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<th className="px-2 py-2 text-center font-bold text-blue-700 uppercase tracking-wider border-b border-gray-200 whitespace-nowrap cursor-pointer select-none"
|
||||
onClick={() => {
|
||||
setSortField('id');
|
||||
setSortOrder(sortField === 'id' && sortOrder === 'asc' ? 'desc' : 'asc');
|
||||
}}
|
||||
>
|
||||
ID {sortField === 'id' && (sortOrder === 'asc' ? '▲' : '▼')}
|
||||
</th>
|
||||
<th className="px-2 py-2 text-left font-bold uppercase tracking-wider border-b border-gray-200 whitespace-nowrap cursor-pointer select-none"
|
||||
onClick={() => {
|
||||
setSortField('organizacion_name');
|
||||
setSortOrder(sortField === 'organizacion_name' && sortOrder === 'asc' ? 'desc' : 'asc');
|
||||
}}
|
||||
>
|
||||
Organización {sortField === 'organizacion_name' && (sortOrder === 'asc' ? '▲' : '▼')}
|
||||
</th>
|
||||
<th className="px-2 py-2 text-left font-bold uppercase tracking-wider border-b border-gray-200 whitespace-nowrap cursor-pointer select-none"
|
||||
onClick={() => {
|
||||
setSortField('estado');
|
||||
setSortOrder(sortField === 'estado' && sortOrder === 'asc' ? 'desc' : 'asc');
|
||||
}}
|
||||
>
|
||||
Estado {sortField === 'estado' && (sortOrder === 'asc' ? '▲' : '▼')}
|
||||
</th>
|
||||
<th className="px-2 py-2 text-left font-bold uppercase tracking-wider border-b border-gray-200 whitespace-nowrap cursor-pointer select-none"
|
||||
onClick={() => {
|
||||
setSortField('pedimento');
|
||||
setSortOrder(sortField === 'pedimento' && sortOrder === 'asc' ? 'desc' : 'asc');
|
||||
}}
|
||||
>
|
||||
Pedimento {sortField === 'pedimento' && (sortOrder === 'asc' ? '▲' : '▼')}
|
||||
</th>
|
||||
<th className="px-2 py-2 text-left font-bold uppercase tracking-wider border-b border-gray-200 whitespace-nowrap cursor-pointer select-none"
|
||||
onClick={() => {
|
||||
setSortField('servicio');
|
||||
setSortOrder(sortField === 'servicio' && sortOrder === 'asc' ? 'desc' : 'asc');
|
||||
}}
|
||||
>
|
||||
Servicio {sortField === 'servicio' && (sortOrder === 'asc' ? '▲' : '▼')}
|
||||
</th>
|
||||
<th className="px-2 py-2 text-center font-bold text-blue-700 uppercase tracking-wider border-b border-gray-200 whitespace-nowrap">
|
||||
Acciones
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-100" style={{ position: 'relative', minHeight: 'calc(12 * 40px)' }}>
|
||||
{procesos.length === 0 ? (
|
||||
<tr>
|
||||
@@ -259,6 +322,7 @@ export default function Procesos() {
|
||||
: proc.servicio === 6 ? 'Acuse'
|
||||
: proc.servicio === 7 ? 'EDocument'
|
||||
: proc.servicio === 8 ? 'Cove'
|
||||
: proc.servicio === 9 ? 'Acuse Cove'
|
||||
: String(proc.servicio)
|
||||
}</td>
|
||||
<td className="px-2 py-2 text-center align-middle whitespace-nowrap">
|
||||
@@ -277,11 +341,21 @@ export default function Procesos() {
|
||||
<button
|
||||
className="block w-full text-left px-4 py-2 text-xs text-blue-700 hover:bg-blue-100 disabled:opacity-60"
|
||||
onClick={() => handleEjecutarServicio(proc)}
|
||||
disabled={executingId === proc.id}
|
||||
disabled={
|
||||
executingId === proc.id ||
|
||||
proc.estado === 2 || // Procesando
|
||||
proc.estado === 3 || // Finalizado
|
||||
proc.estado === 4 // Error
|
||||
}
|
||||
>
|
||||
{executingId === proc.id ? 'Ejecutando...' : 'Ejecutar Servicio'}
|
||||
</button>
|
||||
<button className="block w-full text-left px-4 py-2 text-xs text-gray-700 hover:bg-blue-100">Pasar a espera</button>
|
||||
<button
|
||||
className={`block w-full text-left px-4 py-2 text-xs text-gray-700 hover:bg-blue-100${(proc.estado === 2 || proc.estado === 4) ? '' : ' opacity-50 cursor-not-allowed'}`}
|
||||
disabled={!(proc.estado === 2 || proc.estado === 4)}
|
||||
>
|
||||
Pasar a espera
|
||||
</button>
|
||||
<button className="block w-full text-left px-4 py-2 text-xs text-gray-700 hover:bg-blue-100">Editar</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user