Improve emprestimos UX with skeleton loading and optimistic devolver

- Replace spinner with skeleton table rows during loading
- Apply optimistic closing for devolver dialog (instant feedback)
- Use toast.promise for background mutation with loading state
- Remove unnecessary isSubmitting state from devolver button
- Maintain table layout during filter changes (no layout shift)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
rever-tecnologia 2025-12-05 10:24:53 -03:00
parent b7e7f99f99
commit 0054b93d3c

View file

@ -343,27 +343,31 @@ export function EmprestimosPageClient() {
const handleDevolver = useCallback(async () => {
if (!selectedEmprestimoId || !convexUserId) return
setIsSubmitting(true)
try {
const result = await devolverEmprestimo({
id: selectedEmprestimoId as Id<"emprestimos">,
updatedBy: convexUserId as Id<"users">,
observacoes: formObservacoes || undefined,
})
if (result.multaCalculada) {
toast.success(`Empréstimo devolvido com multa de R$ ${result.multaCalculada.toFixed(2)}.`)
} else {
toast.success("Empréstimo devolvido com sucesso.")
}
// Fechamento otimista - fecha dialog imediatamente
const emprestimoId = selectedEmprestimoId
const observacoes = formObservacoes
setIsDevolverDialogOpen(false)
setSelectedEmprestimoId(null)
setFormObservacoes("")
} catch (error) {
console.error("[emprestimos] Falha ao devolver", error)
toast.error("Falha ao registrar devolução.")
} finally {
setIsSubmitting(false)
// Executa mutacao em background com toast de loading
toast.promise(
devolverEmprestimo({
id: emprestimoId as Id<"emprestimos">,
updatedBy: convexUserId as Id<"users">,
observacoes: observacoes || undefined,
}),
{
loading: "Registrando devolucao...",
success: (result) => {
if (result.multaCalculada) {
return `Emprestimo devolvido com multa de R$ ${result.multaCalculada.toFixed(2)}.`
}
return "Emprestimo devolvido com sucesso."
},
error: "Falha ao registrar devolucao.",
}
)
}, [selectedEmprestimoId, convexUserId, formObservacoes, devolverEmprestimo])
const openDevolverDialog = useCallback((id: string) => {
@ -823,18 +827,9 @@ export function EmprestimosPageClient() {
<Button variant="outline" onClick={() => setIsDevolverDialogOpen(false)}>
Cancelar
</Button>
<Button onClick={handleDevolver} disabled={isSubmitting}>
{isSubmitting ? (
<>
<Spinner className="size-4" />
Registrando...
</>
) : (
<>
<Button onClick={handleDevolver}>
<IconCircleCheck className="size-4" />
Confirmar devolução
</>
)}
Confirmar devolucao
</Button>
</DialogFooter>
</DialogContent>