import { useEffect, useRef, useState } from 'react';
import { toast, toastAfterReload } from '@/lib/toast';
type Prestamo = {
id: number;
cantidad: number;
material: { nombre: string; cantidad_disponible: number } | null;
alumno: { nombre: string | null; email: string } | null;
};
const hoy = () => new Date().toISOString().split('T')[0];
const enDias = (d: number) => new Date(Date.now() + d * 86400000).toISOString().split('T')[0];
export default function AccionesSolicitud({ prestamo }: { prestamo: Prestamo }) {
return (
);
}
function useDialog() {
const ref = useRef(null);
const open = () => ref.current?.showModal();
const close = () => ref.current?.close();
// Cerrar al hacer click en backdrop
useEffect(() => {
const d = ref.current;
if (!d) return;
const onClick = (e: MouseEvent) => {
if (e.target === d) d.close();
};
d.addEventListener('click', onClick);
return () => d.removeEventListener('click', onClick);
}, []);
return { ref, open, close };
}
function AprobarDialog({ prestamo }: { prestamo: Prestamo }) {
const dlg = useDialog();
const [fecha, setFecha] = useState(enDias(7));
const [notas, setNotas] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const stockInsuficiente = (prestamo.material?.cantidad_disponible ?? 0) < prestamo.cantidad;
const submit = async (e: React.FormEvent) => {
e.preventDefault();
setError(null);
if (!fecha || fecha < hoy()) {
setError('La fecha de devolución debe ser hoy o posterior.');
return;
}
setLoading(true);
try {
const res = await fetch(`/api/admin/prestamos/${prestamo.id}/aprobar`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ fecha_devolucion_estimada: fecha, notas: notas.trim() || undefined }),
});
if (!res.ok) {
const body = await res.json().catch(() => ({}));
throw new Error(body?.error ?? `Error ${res.status}`);
}
toastAfterReload({
kind: 'success',
title: 'Solicitud aprobada',
description: `${prestamo.material?.nombre ?? 'Material'} · ${prestamo.alumno?.nombre ?? prestamo.alumno?.email ?? ''}`,
});
location.reload();
} catch (err: any) {
const msg = err.message ?? 'Error al aprobar.';
setError(msg);
toast({ kind: 'error', title: 'No se pudo aprobar', description: msg });
setLoading(false);
}
};
return (
<>
>
);
}
function RechazarDialog({ prestamo }: { prestamo: Prestamo }) {
const dlg = useDialog();
const [motivo, setMotivo] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const submit = async (e: React.FormEvent) => {
e.preventDefault();
setError(null);
if (motivo.trim().length < 5) {
setError('El motivo debe tener al menos 5 caracteres.');
return;
}
setLoading(true);
try {
const res = await fetch(`/api/admin/prestamos/${prestamo.id}/rechazar`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ motivo: motivo.trim() }),
});
if (!res.ok) {
const body = await res.json().catch(() => ({}));
throw new Error(body?.error ?? `Error ${res.status}`);
}
toastAfterReload({
kind: 'info',
title: 'Solicitud rechazada',
description: `${prestamo.material?.nombre ?? 'Material'} · ${prestamo.alumno?.nombre ?? prestamo.alumno?.email ?? ''}`,
});
location.reload();
} catch (err: any) {
const msg = err.message ?? 'Error al rechazar.';
setError(msg);
toast({ kind: 'error', title: 'No se pudo rechazar', description: msg });
setLoading(false);
}
};
return (
<>
>
);
}