Compare commits

..

2 commits

Author SHA1 Message Date
rever-tecnologia
993bd3890a 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>
2025-12-18 11:31:17 -03:00
rever-tecnologia
a9feea9b78 style(companies): centraliza itens na tabela de empresas
- Adiciona text-center em todos os TableCell
- Centraliza conteudo interno com justify-center
- Mantem texto a esquerda dentro dos cards de contrato/contato

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 11:29:29 -03:00
2 changed files with 49 additions and 21 deletions

View file

@ -814,13 +814,13 @@ function TableView({ companies, machineCountsBySlug, onEdit, onDelete }: TableVi
return ( return (
<TableRow key={company.id} className="hover:bg-muted/40"> <TableRow key={company.id} className="hover:bg-muted/40">
<TableCell className="align-middle"> <TableCell className="text-center align-middle">
<div className="flex min-h-[3.5rem] flex-col justify-center gap-1"> <div className="flex min-h-[3.5rem] flex-col items-center justify-center gap-1">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<p className="font-semibold text-foreground">{company.name}</p> <p className="font-semibold text-foreground">{company.name}</p>
{company.isAvulso ? <Badge variant="outline">Avulso</Badge> : null} {company.isAvulso ? <Badge variant="outline">Avulso</Badge> : null}
</div> </div>
<div className="flex flex-wrap gap-1 text-xs text-muted-foreground"> <div className="flex flex-wrap justify-center gap-1 text-xs text-muted-foreground">
{company.domain ? <span>{company.domain}</span> : null} {company.domain ? <span>{company.domain}</span> : null}
{company.phone ? ( {company.phone ? (
<span className="inline-flex items-center gap-1"> <span className="inline-flex items-center gap-1">
@ -829,7 +829,7 @@ function TableView({ companies, machineCountsBySlug, onEdit, onDelete }: TableVi
</span> </span>
) : null} ) : null}
</div> </div>
<div className="flex flex-wrap gap-1"> <div className="flex flex-wrap justify-center gap-1">
{company.tags.map((tag) => ( {company.tags.map((tag) => (
<Badge key={tag} variant="secondary" className="text-[11px] uppercase"> <Badge key={tag} variant="secondary" className="text-[11px] uppercase">
{tag} {tag}
@ -838,13 +838,13 @@ function TableView({ companies, machineCountsBySlug, onEdit, onDelete }: TableVi
</div> </div>
</div> </div>
</TableCell> </TableCell>
<TableCell className="align-middle text-sm"> <TableCell className="text-center align-middle text-sm">
{contracts.length === 0 ? ( {contracts.length === 0 ? (
<p className="text-muted-foreground">Nenhum contrato registrado.</p> <p className="text-muted-foreground">Nenhum contrato registrado.</p>
) : ( ) : (
<ul className="space-y-1 text-xs"> <ul className="space-y-1 text-xs">
{contracts.map((contract) => ( {contracts.map((contract) => (
<li key={contract.id} className="rounded-md border border-border/60 px-2 py-1"> <li key={contract.id} className="rounded-md border border-border/60 px-2 py-1 text-left">
<p className="font-semibold capitalize">{contract.contractType}</p> <p className="font-semibold capitalize">{contract.contractType}</p>
<p className="text-muted-foreground"> <p className="text-muted-foreground">
{contract.scope.length ? contract.scope.join(", ") : "Escopo base"} {contract.scope.length ? contract.scope.join(", ") : "Escopo base"}
@ -860,13 +860,13 @@ function TableView({ companies, machineCountsBySlug, onEdit, onDelete }: TableVi
</ul> </ul>
)} )}
</TableCell> </TableCell>
<TableCell className="align-middle text-sm"> <TableCell className="text-center align-middle text-sm">
{contacts.length === 0 ? ( {contacts.length === 0 ? (
<p className="text-muted-foreground">Nenhum contato cadastrado.</p> <p className="text-muted-foreground">Nenhum contato cadastrado.</p>
) : ( ) : (
<ul className="space-y-1 text-xs"> <ul className="space-y-1 text-xs">
{contacts.map((contact) => ( {contacts.map((contact) => (
<li key={contact.id} className="rounded-md border border-border/60 px-2 py-1"> <li key={contact.id} className="rounded-md border border-border/60 px-2 py-1 text-left">
<p className="font-semibold">{contact.fullName}</p> <p className="font-semibold">{contact.fullName}</p>
<p className="text-muted-foreground">{contact.email}</p> <p className="text-muted-foreground">{contact.email}</p>
<p className="text-muted-foreground capitalize">{contact.role.replace("_", " ")}</p> <p className="text-muted-foreground capitalize">{contact.role.replace("_", " ")}</p>
@ -880,11 +880,11 @@ function TableView({ companies, machineCountsBySlug, onEdit, onDelete }: TableVi
</ul> </ul>
)} )}
</TableCell> </TableCell>
<TableCell className="align-middle text-sm"> <TableCell className="text-center align-middle text-sm">
<Badge variant="outline">{machineCount}</Badge> <Badge variant="outline">{machineCount}</Badge>
</TableCell> </TableCell>
<TableCell className="align-middle text-right text-sm"> <TableCell className="text-center align-middle text-sm">
<div className="flex flex-wrap items-center justify-end gap-1.5"> <div className="flex flex-wrap items-center justify-center gap-1.5">
<Button <Button
size="sm" size="sm"
variant="outline" variant="outline"

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>
) )
} }