Replace spinner with skeleton loading in emprestimos page
- Remove initial spinner and show skeleton layout immediately - Add skeleton to stats cards during loading - Show skeleton rows in table while data loads - Provides better visual feedback with layout structure 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
b5b74a674d
commit
ff90f16cef
1 changed files with 24 additions and 15 deletions
|
|
@ -47,7 +47,6 @@ import {
|
||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table"
|
} from "@/components/ui/table"
|
||||||
import { Spinner } from "@/components/ui/spinner"
|
|
||||||
import { Skeleton } from "@/components/ui/skeleton"
|
import { Skeleton } from "@/components/ui/skeleton"
|
||||||
import { SearchableCombobox, type SearchableComboboxOption } from "@/components/ui/searchable-combobox"
|
import { SearchableCombobox, type SearchableComboboxOption } from "@/components/ui/searchable-combobox"
|
||||||
import { DateRangeButton, type DateRangeValue } from "@/components/date-range-button"
|
import { DateRangeButton, type DateRangeValue } from "@/components/date-range-button"
|
||||||
|
|
@ -388,13 +387,7 @@ export function EmprestimosPageClient() {
|
||||||
setDateRange({ from: null, to: null })
|
setDateRange({ from: null, to: null })
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
if (!tenantId || !convexUserId) {
|
const isLoading = !tenantId || !convexUserId
|
||||||
return (
|
|
||||||
<div className="flex items-center justify-center py-20">
|
|
||||||
<Spinner className="size-8" />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const fieldWrap = "min-w-[180px] flex-1"
|
const fieldWrap = "min-w-[180px] flex-1"
|
||||||
const fieldTrigger =
|
const fieldTrigger =
|
||||||
|
|
@ -410,21 +403,37 @@ export function EmprestimosPageClient() {
|
||||||
<div className="grid gap-4 md:grid-cols-4">
|
<div className="grid gap-4 md:grid-cols-4">
|
||||||
<div className="rounded-2xl border border-slate-200 bg-white/90 p-4 shadow-sm transition-colors hover:border-cyan-200/60 hover:bg-cyan-50/30">
|
<div className="rounded-2xl border border-slate-200 bg-white/90 p-4 shadow-sm transition-colors hover:border-cyan-200/60 hover:bg-cyan-50/30">
|
||||||
<p className="text-xs font-medium uppercase tracking-wide text-neutral-500">Total</p>
|
<p className="text-xs font-medium uppercase tracking-wide text-neutral-500">Total</p>
|
||||||
<p className="mt-1 text-2xl font-bold text-neutral-900">{stats?.total ?? 0}</p>
|
{isLoading || stats === undefined ? (
|
||||||
|
<Skeleton className="mt-2 h-7 w-12" />
|
||||||
|
) : (
|
||||||
|
<p className="mt-1 text-2xl font-bold text-neutral-900">{stats.total}</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="rounded-2xl border border-cyan-200/60 bg-cyan-50/40 p-4 shadow-sm">
|
<div className="rounded-2xl border border-cyan-200/60 bg-cyan-50/40 p-4 shadow-sm">
|
||||||
<p className="text-xs font-medium uppercase tracking-wide text-cyan-600">Ativos</p>
|
<p className="text-xs font-medium uppercase tracking-wide text-cyan-600">Ativos</p>
|
||||||
<p className="mt-1 text-2xl font-bold text-cyan-700">{stats?.ativos ?? 0}</p>
|
{isLoading || stats === undefined ? (
|
||||||
|
<Skeleton className="mt-2 h-7 w-10" />
|
||||||
|
) : (
|
||||||
|
<p className="mt-1 text-2xl font-bold text-cyan-700">{stats.ativos}</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="rounded-2xl border border-red-200/60 bg-red-50/40 p-4 shadow-sm">
|
<div className="rounded-2xl border border-red-200/60 bg-red-50/40 p-4 shadow-sm">
|
||||||
<p className="text-xs font-medium uppercase tracking-wide text-red-600">Atrasados</p>
|
<p className="text-xs font-medium uppercase tracking-wide text-red-600">Atrasados</p>
|
||||||
<p className="mt-1 text-2xl font-bold text-red-700">{stats?.atrasados ?? 0}</p>
|
{isLoading || stats === undefined ? (
|
||||||
|
<Skeleton className="mt-2 h-7 w-8" />
|
||||||
|
) : (
|
||||||
|
<p className="mt-1 text-2xl font-bold text-red-700">{stats.atrasados}</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="rounded-2xl border border-emerald-200/60 bg-emerald-50/40 p-4 shadow-sm">
|
<div className="rounded-2xl border border-emerald-200/60 bg-emerald-50/40 p-4 shadow-sm">
|
||||||
<p className="text-xs font-medium uppercase tracking-wide text-emerald-600">Valor ativo</p>
|
<p className="text-xs font-medium uppercase tracking-wide text-emerald-600">Valor ativo</p>
|
||||||
<p className="mt-1 text-2xl font-bold text-emerald-700">
|
{isLoading || stats === undefined ? (
|
||||||
R$ {(stats?.valorTotalAtivo ?? 0).toLocaleString("pt-BR", { minimumFractionDigits: 2 })}
|
<Skeleton className="mt-2 h-7 w-24" />
|
||||||
</p>
|
) : (
|
||||||
|
<p className="mt-1 text-2xl font-bold text-emerald-700">
|
||||||
|
R$ {stats.valorTotalAtivo.toLocaleString("pt-BR", { minimumFractionDigits: 2 })}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -535,7 +544,7 @@ export function EmprestimosPageClient() {
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{!emprestimos ? (
|
{isLoading || !emprestimos ? (
|
||||||
// Skeleton rows durante o loading
|
// Skeleton rows durante o loading
|
||||||
Array.from({ length: 5 }).map((_, idx) => (
|
Array.from({ length: 5 }).map((_, idx) => (
|
||||||
<TableRow key={`skeleton-${idx}`} className="animate-pulse">
|
<TableRow key={`skeleton-${idx}`} className="animate-pulse">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue