Init Commit
This commit is contained in:
101
frontend/src/components/Dashboard/EjecucionManual.tsx
Normal file
101
frontend/src/components/Dashboard/EjecucionManual.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import { useState } from 'react';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { Calendar, PlayCircle, Loader2 } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { operacionesApi } from '../../services/api';
|
||||
|
||||
interface EjecucionManualProps {
|
||||
onExecute: () => void;
|
||||
}
|
||||
|
||||
export default function EjecucionManual({ onExecute }: EjecucionManualProps) {
|
||||
const [fechaDesde, setFechaDesde] = useState<string>(
|
||||
new Date().toISOString().split('T')[0]
|
||||
);
|
||||
|
||||
const ejecutarMutation = useMutation({
|
||||
mutationFn: () => operacionesApi.ejecutarManual({ fechaDesde }),
|
||||
onSuccess: () => {
|
||||
toast.success('✓ Proceso iniciado correctamente');
|
||||
toast.info('Revisa los eventos para ver el progreso');
|
||||
onExecute();
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(`Error al ejecutar: ${error.message}`);
|
||||
},
|
||||
});
|
||||
|
||||
const handleEjecutar = () => {
|
||||
if (!fechaDesde) {
|
||||
toast.error('Debes seleccionar una fecha');
|
||||
return;
|
||||
}
|
||||
|
||||
ejecutarMutation.mutate();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="card">
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-4">
|
||||
Ejecución Manual
|
||||
</h3>
|
||||
|
||||
<p className="text-sm text-gray-600 mb-6">
|
||||
Ejecuta el proceso inmediatamente sin esperar al cronograma programado.
|
||||
Selecciona la fecha desde la cual buscar facturas.
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
{/* Selector de fecha */}
|
||||
<div>
|
||||
<label htmlFor="fechaDesde" className="label-text">
|
||||
Fecha desde:
|
||||
</label>
|
||||
<div className="relative">
|
||||
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<Calendar className="w-5 h-5 text-gray-400" />
|
||||
</div>
|
||||
<input
|
||||
type="date"
|
||||
id="fechaDesde"
|
||||
value={fechaDesde}
|
||||
onChange={(e) => setFechaDesde(e.target.value)}
|
||||
max={new Date().toISOString().split('T')[0]}
|
||||
className="input-field pl-10"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
Se procesarán todas las facturas desde esta fecha hasta hoy
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Botón de ejecución */}
|
||||
<button
|
||||
onClick={handleEjecutar}
|
||||
disabled={ejecutarMutation.isPending || !fechaDesde}
|
||||
className="w-full btn-primary flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{ejecutarMutation.isPending ? (
|
||||
<>
|
||||
<Loader2 className="w-5 h-5 animate-spin" />
|
||||
Ejecutando proceso...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<PlayCircle className="w-5 h-5" />
|
||||
Ejecutar Ahora
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
|
||||
{/* Información adicional */}
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||||
<p className="text-sm text-blue-800">
|
||||
<strong>Nota:</strong> El proceso se ejecutará en segundo plano. Los resultados
|
||||
aparecerán en la tabla de eventos más abajo.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user