style(devices): substitui spinner por skeleton cards no loading
Some checks failed
CI/CD Web + Desktop / Deploy Convex functions (push) Blocked by required conditions
CI/CD Web + Desktop / Detect changes (push) Successful in 5s
Quality Checks / Lint, Test and Build (push) Has been cancelled
CI/CD Web + Desktop / Deploy (VPS Linux) (push) Has been cancelled

- Cria DeviceCardSkeleton que simula a estrutura do DeviceCard
- Exibe grid de 6 skeletons durante carregamento
- Mantém mesmo layout responsivo dos cards reais

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rever-tecnologia 2025-12-18 11:31:17 -03:00
parent a9feea9b78
commit 993bd3890a

View file

@ -50,6 +50,7 @@ import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea" import { Textarea } from "@/components/ui/textarea"
import { Spinner } from "@/components/ui/spinner" import { Spinner } from "@/components/ui/spinner"
import { Skeleton } from "@/components/ui/skeleton"
import { Progress } from "@/components/ui/progress" import { Progress } from "@/components/ui/progress"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
@ -2719,18 +2720,45 @@ function EmptyState() {
) )
} }
function DeviceCardSkeleton() {
return (
<div className="rounded-xl border border-slate-200 bg-white p-4 shadow-sm">
<div className="flex items-start gap-3">
<Skeleton className="size-10 rounded-lg" />
<div className="flex-1 space-y-2">
<Skeleton className="h-4 w-32" />
<Skeleton className="h-3 w-24" />
</div>
<Skeleton className="h-5 w-16 rounded-full" />
</div>
<div className="mt-4 space-y-3">
<div className="flex items-center gap-2">
<Skeleton className="size-4 rounded" />
<Skeleton className="h-3 w-28" />
</div>
<div className="flex items-center gap-2">
<Skeleton className="size-4 rounded" />
<Skeleton className="h-3 w-36" />
</div>
<div className="flex items-center gap-2">
<Skeleton className="size-4 rounded" />
<Skeleton className="h-3 w-20" />
</div>
</div>
<div className="mt-4 flex gap-2">
<Skeleton className="h-2 flex-1 rounded-full" />
<Skeleton className="h-2 flex-1 rounded-full" />
</div>
</div>
)
}
function LoadingState() { function LoadingState() {
return ( return (
<div className="flex flex-col items-center gap-3 rounded-lg border border-dashed border-slate-300 bg-slate-50/50 py-12 text-center"> <div className="grid grid-cols-1 gap-3 [@supports(display:grid)]:grid-cols-[repeat(auto-fit,minmax(280px,1fr))]">
<div className="inline-flex size-12 items-center justify-center rounded-full border border-slate-200 bg-white shadow-sm"> {Array.from({ length: 6 }).map((_, i) => (
<Spinner className="size-6 text-slate-500" /> <DeviceCardSkeleton key={i} />
</div> ))}
<div className="space-y-1">
<p className="text-sm font-semibold text-slate-600">Carregando dispositivos...</p>
<p className="text-sm text-muted-foreground">
Sincronizando o inventário em tempo real. Isso leva apenas alguns instantes.
</p>
</div>
</div> </div>
) )
} }