mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-03-10 04:51:47 +00:00
refactor: migrate from ESLint to Biome and extract SQL queries to data.ts
- Replace ESLint with Biome for linting and formatting - Configure Biome with tabs, double quotes, and organized imports - Move all SQL/Drizzle queries from page.tsx files to data.ts files - Create new data.ts files for: ajustes, dashboard, relatorios/categorias - Update existing data.ts files: extrato, fatura (add lancamentos queries) - Remove all drizzle-orm imports from page.tsx files - Update README.md with new tooling info Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,39 +5,39 @@ import { Skeleton } from "@/components/ui/skeleton";
|
||||
* Reflete fielmente o layout: logo + nome + tipo + badge + métricas
|
||||
*/
|
||||
export function AccountStatementCardSkeleton() {
|
||||
return (
|
||||
<div className="rounded-2xl border p-6 space-y-6">
|
||||
{/* Header com logo, nome, tipo e badge */}
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-start gap-4">
|
||||
{/* Logo */}
|
||||
<Skeleton className="size-12 rounded-2xl bg-foreground/10" />
|
||||
return (
|
||||
<div className="rounded-2xl border p-6 space-y-6">
|
||||
{/* Header com logo, nome, tipo e badge */}
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-start gap-4">
|
||||
{/* Logo */}
|
||||
<Skeleton className="size-12 rounded-2xl bg-foreground/10" />
|
||||
|
||||
<div className="space-y-2">
|
||||
{/* Nome da conta */}
|
||||
<Skeleton className="h-6 w-48 rounded-2xl bg-foreground/10" />
|
||||
{/* Tipo de conta */}
|
||||
<Skeleton className="h-4 w-32 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{/* Nome da conta */}
|
||||
<Skeleton className="h-6 w-48 rounded-2xl bg-foreground/10" />
|
||||
{/* Tipo de conta */}
|
||||
<Skeleton className="h-4 w-32 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Badge de status */}
|
||||
<Skeleton className="h-6 w-16 rounded-2xl bg-foreground/10" />
|
||||
{/* Botão de editar */}
|
||||
<Skeleton className="size-8 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Badge de status */}
|
||||
<Skeleton className="h-6 w-16 rounded-2xl bg-foreground/10" />
|
||||
{/* Botão de editar */}
|
||||
<Skeleton className="size-8 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Métricas em grid */}
|
||||
<div className="grid grid-cols-2 gap-4 pt-4 border-t md:grid-cols-4">
|
||||
{Array.from({ length: 4 }).map((_, i) => (
|
||||
<div key={i} className="space-y-2">
|
||||
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-6 w-32 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
{/* Métricas em grid */}
|
||||
<div className="grid grid-cols-2 gap-4 pt-4 border-t md:grid-cols-4">
|
||||
{Array.from({ length: 4 }).map((_, i) => (
|
||||
<div key={i} className="space-y-2">
|
||||
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-6 w-32 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,112 +1,112 @@
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableFooter,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableFooter,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
|
||||
import { Tabs, TabsContent, TabsList } from "@/components/ui/tabs";
|
||||
|
||||
/**
|
||||
* Skeleton para a página de relatórios de categorias
|
||||
* Mantém a mesma estrutura de filtros, tabs e conteúdo
|
||||
*/
|
||||
export function CategoryReportSkeleton() {
|
||||
return (
|
||||
<div className="flex flex-col gap-6">
|
||||
{/* Filters Skeleton */}
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{/* Category MultiSelect */}
|
||||
<Skeleton className="h-10 w-[200px] rounded-2xl bg-foreground/10" />
|
||||
{/* Start Period */}
|
||||
<Skeleton className="h-10 w-[150px] rounded-2xl bg-foreground/10" />
|
||||
{/* End Period */}
|
||||
<Skeleton className="h-10 w-[150px] rounded-2xl bg-foreground/10" />
|
||||
{/* Clear Button */}
|
||||
<Skeleton className="h-8 w-16 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
{/* Export Button */}
|
||||
<Skeleton className="h-10 w-[120px] rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
return (
|
||||
<div className="flex flex-col gap-6">
|
||||
{/* Filters Skeleton */}
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{/* Category MultiSelect */}
|
||||
<Skeleton className="h-10 w-[200px] rounded-2xl bg-foreground/10" />
|
||||
{/* Start Period */}
|
||||
<Skeleton className="h-10 w-[150px] rounded-2xl bg-foreground/10" />
|
||||
{/* End Period */}
|
||||
<Skeleton className="h-10 w-[150px] rounded-2xl bg-foreground/10" />
|
||||
{/* Clear Button */}
|
||||
<Skeleton className="h-8 w-16 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
{/* Export Button */}
|
||||
<Skeleton className="h-10 w-[120px] rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tabs Skeleton */}
|
||||
<Tabs value="table" className="w-full">
|
||||
<TabsList>
|
||||
<div className="flex gap-1">
|
||||
<Skeleton className="h-10 w-[100px] rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-10 w-[100px] rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</TabsList>
|
||||
{/* Tabs Skeleton */}
|
||||
<Tabs value="table" className="w-full">
|
||||
<TabsList>
|
||||
<div className="flex gap-1">
|
||||
<Skeleton className="h-10 w-[100px] rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-10 w-[100px] rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="table" className="mt-4">
|
||||
{/* Desktop Table Skeleton */}
|
||||
<div className="hidden md:block">
|
||||
<CategoryReportTableSkeleton />
|
||||
</div>
|
||||
<TabsContent value="table" className="mt-4">
|
||||
{/* Desktop Table Skeleton */}
|
||||
<div className="hidden md:block">
|
||||
<CategoryReportTableSkeleton />
|
||||
</div>
|
||||
|
||||
{/* Mobile Cards Skeleton */}
|
||||
<div className="md:hidden space-y-3">
|
||||
{Array.from({ length: 5 }).map((_, i) => (
|
||||
<Card key={i} className="p-4">
|
||||
<div className="space-y-3">
|
||||
{/* Category name with icon */}
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-5 w-32 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
{/* Type badge */}
|
||||
<Skeleton className="h-6 w-20 rounded-2xl bg-foreground/10" />
|
||||
{/* Values */}
|
||||
<div className="space-y-2">
|
||||
{Array.from({ length: 3 }).map((_, j) => (
|
||||
<div
|
||||
key={j}
|
||||
className="flex items-center justify-between"
|
||||
>
|
||||
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</TabsContent>
|
||||
{/* Mobile Cards Skeleton */}
|
||||
<div className="md:hidden space-y-3">
|
||||
{Array.from({ length: 5 }).map((_, i) => (
|
||||
<Card key={i} className="p-4">
|
||||
<div className="space-y-3">
|
||||
{/* Category name with icon */}
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-5 w-32 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
{/* Type badge */}
|
||||
<Skeleton className="h-6 w-20 rounded-2xl bg-foreground/10" />
|
||||
{/* Values */}
|
||||
<div className="space-y-2">
|
||||
{Array.from({ length: 3 }).map((_, j) => (
|
||||
<div
|
||||
key={j}
|
||||
className="flex items-center justify-between"
|
||||
>
|
||||
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="chart" className="mt-4">
|
||||
{/* Chart Skeleton */}
|
||||
<Card className="p-6">
|
||||
<div className="space-y-4">
|
||||
{/* Chart title area */}
|
||||
<div className="flex items-center justify-between">
|
||||
<Skeleton className="h-6 w-48 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-8 w-32 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
{/* Chart area */}
|
||||
<Skeleton className="h-[400px] w-full rounded-2xl bg-foreground/10" />
|
||||
{/* Legend */}
|
||||
<div className="flex flex-wrap gap-4 justify-center">
|
||||
{Array.from({ length: 6 }).map((_, i) => (
|
||||
<div key={i} className="flex items-center gap-2">
|
||||
<Skeleton className="size-3 rounded-full bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
<TabsContent value="chart" className="mt-4">
|
||||
{/* Chart Skeleton */}
|
||||
<Card className="p-6">
|
||||
<div className="space-y-4">
|
||||
{/* Chart title area */}
|
||||
<div className="flex items-center justify-between">
|
||||
<Skeleton className="h-6 w-48 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-8 w-32 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
{/* Chart area */}
|
||||
<Skeleton className="h-[400px] w-full rounded-2xl bg-foreground/10" />
|
||||
{/* Legend */}
|
||||
<div className="flex flex-wrap gap-4 justify-center">
|
||||
{Array.from({ length: 6 }).map((_, i) => (
|
||||
<div key={i} className="flex items-center gap-2">
|
||||
<Skeleton className="size-3 rounded-full bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,80 +114,80 @@ export function CategoryReportSkeleton() {
|
||||
* Mantém a estrutura de colunas: Categoria, Tipo, múltiplos períodos, Total
|
||||
*/
|
||||
function CategoryReportTableSkeleton() {
|
||||
// Simula 6 períodos (colunas)
|
||||
const periodColumns = 6;
|
||||
// Simula 6 períodos (colunas)
|
||||
const periodColumns = 6;
|
||||
|
||||
return (
|
||||
<Card className="px-6 py-4">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{/* Categoria */}
|
||||
<TableHead className="w-[280px] min-w-[280px]">
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
</TableHead>
|
||||
{/* Period columns */}
|
||||
{Array.from({ length: periodColumns }).map((_, i) => (
|
||||
<TableHead key={i} className="text-right min-w-[120px]">
|
||||
<Skeleton className="h-4 w-16 rounded-2xl bg-foreground/10 ml-auto" />
|
||||
</TableHead>
|
||||
))}
|
||||
{/* Total */}
|
||||
<TableHead className="text-right min-w-[120px]">
|
||||
<Skeleton className="h-4 w-10 rounded-2xl bg-foreground/10 ml-auto" />
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
return (
|
||||
<Card className="px-6 py-4">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{/* Categoria */}
|
||||
<TableHead className="w-[280px] min-w-[280px]">
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
</TableHead>
|
||||
{/* Period columns */}
|
||||
{Array.from({ length: periodColumns }).map((_, i) => (
|
||||
<TableHead key={i} className="text-right min-w-[120px]">
|
||||
<Skeleton className="h-4 w-16 rounded-2xl bg-foreground/10 ml-auto" />
|
||||
</TableHead>
|
||||
))}
|
||||
{/* Total */}
|
||||
<TableHead className="text-right min-w-[120px]">
|
||||
<Skeleton className="h-4 w-10 rounded-2xl bg-foreground/10 ml-auto" />
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{Array.from({ length: 8 }).map((_, rowIndex) => (
|
||||
<TableRow key={rowIndex}>
|
||||
{/* Category name with dot and icon */}
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="size-2 rounded-full bg-foreground/10" />
|
||||
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-32 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</TableCell>
|
||||
{/* Period values */}
|
||||
{Array.from({ length: periodColumns }).map((_, colIndex) => (
|
||||
<TableCell key={colIndex} className="text-right">
|
||||
<div className="flex flex-col items-end gap-1">
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
{colIndex > 0 && (
|
||||
<Skeleton className="h-3 w-16 rounded-2xl bg-foreground/10" />
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
))}
|
||||
{/* Total */}
|
||||
<TableCell className="text-right">
|
||||
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
<TableBody>
|
||||
{Array.from({ length: 8 }).map((_, rowIndex) => (
|
||||
<TableRow key={rowIndex}>
|
||||
{/* Category name with dot and icon */}
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="size-2 rounded-full bg-foreground/10" />
|
||||
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-32 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</TableCell>
|
||||
{/* Period values */}
|
||||
{Array.from({ length: periodColumns }).map((_, colIndex) => (
|
||||
<TableCell key={colIndex} className="text-right">
|
||||
<div className="flex flex-col items-end gap-1">
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
{colIndex > 0 && (
|
||||
<Skeleton className="h-3 w-16 rounded-2xl bg-foreground/10" />
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
))}
|
||||
{/* Total */}
|
||||
<TableCell className="text-right">
|
||||
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
|
||||
<TableFooter>
|
||||
<TableRow>
|
||||
{/* Total label */}
|
||||
<TableCell className="font-bold">
|
||||
<Skeleton className="h-5 w-16 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
{/* Period totals */}
|
||||
{Array.from({ length: periodColumns }).map((_, i) => (
|
||||
<TableCell key={i} className="text-right">
|
||||
<Skeleton className="h-5 w-24 rounded-2xl bg-foreground/10 ml-auto" />
|
||||
</TableCell>
|
||||
))}
|
||||
{/* Grand total */}
|
||||
<TableCell className="text-right">
|
||||
<Skeleton className="h-5 w-28 rounded-2xl bg-foreground/10 ml-auto" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableFooter>
|
||||
</Table>
|
||||
</Card>
|
||||
);
|
||||
<TableFooter>
|
||||
<TableRow>
|
||||
{/* Total label */}
|
||||
<TableCell className="font-bold">
|
||||
<Skeleton className="h-5 w-16 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
{/* Period totals */}
|
||||
{Array.from({ length: periodColumns }).map((_, i) => (
|
||||
<TableCell key={i} className="text-right">
|
||||
<Skeleton className="h-5 w-24 rounded-2xl bg-foreground/10 ml-auto" />
|
||||
</TableCell>
|
||||
))}
|
||||
{/* Grand total */}
|
||||
<TableCell className="text-right">
|
||||
<Skeleton className="h-5 w-28 rounded-2xl bg-foreground/10 ml-auto" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableFooter>
|
||||
</Table>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,17 +6,17 @@ import { WidgetSkeleton } from "./widget-skeleton";
|
||||
* Mantém a mesma estrutura de layout do dashboard real
|
||||
*/
|
||||
export function DashboardGridSkeleton() {
|
||||
return (
|
||||
<div className="@container/main space-y-4">
|
||||
{/* Section Cards no topo */}
|
||||
<SectionCardsSkeleton />
|
||||
return (
|
||||
<div className="@container/main space-y-4">
|
||||
{/* Section Cards no topo */}
|
||||
<SectionCardsSkeleton />
|
||||
|
||||
{/* Grid de widgets */}
|
||||
<div className="grid grid-cols-1 gap-4 @3xl/main:grid-cols-2 @7xl/main:grid-cols-3">
|
||||
{Array.from({ length: 12 }).map((_, i) => (
|
||||
<WidgetSkeleton key={i} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
{/* Grid de widgets */}
|
||||
<div className="grid grid-cols-1 gap-4 @3xl/main:grid-cols-2 @7xl/main:grid-cols-3">
|
||||
{Array.from({ length: 12 }).map((_, i) => (
|
||||
<WidgetSkeleton key={i} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,16 +5,16 @@ import { Skeleton } from "@/components/ui/skeleton";
|
||||
* Mantém o layout horizontal com múltiplos selects
|
||||
*/
|
||||
export function FilterSkeleton() {
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{Array.from({ length: 6 }).map((_, i) => (
|
||||
<Skeleton
|
||||
key={i}
|
||||
className="h-10 w-[130px] rounded-2xl bg-foreground/10"
|
||||
/>
|
||||
))}
|
||||
<Skeleton className="h-10 w-[150px] rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-8 w-16 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{Array.from({ length: 6 }).map((_, i) => (
|
||||
<Skeleton
|
||||
key={i}
|
||||
className="h-10 w-[130px] rounded-2xl bg-foreground/10"
|
||||
/>
|
||||
))}
|
||||
<Skeleton className="h-10 w-[150px] rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-8 w-16 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,60 +5,60 @@ import { Skeleton } from "@/components/ui/skeleton";
|
||||
* Reflete fielmente o layout: logo + nome + bandeira + badges + total + limite + ações
|
||||
*/
|
||||
export function InvoiceSummaryCardSkeleton() {
|
||||
return (
|
||||
<div className="rounded-2xl border p-6 space-y-6">
|
||||
{/* Header com logo, nome, bandeira e badges */}
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-start gap-4">
|
||||
{/* Logo do cartão */}
|
||||
<Skeleton className="size-12 rounded-2xl bg-foreground/10" />
|
||||
return (
|
||||
<div className="rounded-2xl border p-6 space-y-6">
|
||||
{/* Header com logo, nome, bandeira e badges */}
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-start gap-4">
|
||||
{/* Logo do cartão */}
|
||||
<Skeleton className="size-12 rounded-2xl bg-foreground/10" />
|
||||
|
||||
<div className="space-y-2">
|
||||
{/* Nome do cartão */}
|
||||
<Skeleton className="h-6 w-48 rounded-2xl bg-foreground/10" />
|
||||
<div className="space-y-2">
|
||||
{/* Nome do cartão */}
|
||||
<Skeleton className="h-6 w-48 rounded-2xl bg-foreground/10" />
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Bandeira */}
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
{/* Badge de status */}
|
||||
<Skeleton className="h-6 w-16 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Bandeira */}
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
{/* Badge de status */}
|
||||
<Skeleton className="h-6 w-16 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Botão de editar */}
|
||||
<Skeleton className="size-8 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
{/* Botão de editar */}
|
||||
<Skeleton className="size-8 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
|
||||
{/* Informações da fatura */}
|
||||
<div className="space-y-4 pt-4 border-t">
|
||||
{/* Período e status */}
|
||||
<div className="flex items-center justify-between">
|
||||
<Skeleton className="h-5 w-32 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-6 w-24 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
{/* Informações da fatura */}
|
||||
<div className="space-y-4 pt-4 border-t">
|
||||
{/* Período e status */}
|
||||
<div className="flex items-center justify-between">
|
||||
<Skeleton className="h-5 w-32 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-6 w-24 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
|
||||
{/* Total da fatura */}
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-28 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-8 w-40 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
{/* Total da fatura */}
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-28 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-8 w-40 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
|
||||
{/* Limite e utilização */}
|
||||
<div className="grid grid-cols-2 gap-4 pt-4">
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-6 w-28 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-6 w-28 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
{/* Limite e utilização */}
|
||||
<div className="grid grid-cols-2 gap-4 pt-4">
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-6 w-28 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-6 w-28 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Botão de ação */}
|
||||
<Skeleton className="h-10 w-full rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
{/* Botão de ação */}
|
||||
<Skeleton className="h-10 w-full rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,32 +6,32 @@ import { Skeleton } from "@/components/ui/skeleton";
|
||||
* Mantém o mesmo layout de 4 colunas responsivo
|
||||
*/
|
||||
export function SectionCardsSkeleton() {
|
||||
return (
|
||||
<div className="*:data-[slot=card]:from-primary/5 *:data-[slot=card]:to-card dark:*:data-[slot=card]:bg-card grid grid-cols-1 gap-3 @xl/main:grid-cols-2 @5xl/main:grid-cols-4">
|
||||
{Array.from({ length: 4 }).map((_, index) => (
|
||||
<Card key={index} className="@container/card gap-2">
|
||||
<CardHeader>
|
||||
<div className="space-y-3">
|
||||
{/* Título com ícone */}
|
||||
<div className="flex items-center gap-1">
|
||||
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-5 w-20 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
return (
|
||||
<div className="*:data-[slot=card]:from-primary/5 *:data-[slot=card]:to-card dark:*:data-[slot=card]:bg-card grid grid-cols-1 gap-3 @xl/main:grid-cols-2 @5xl/main:grid-cols-4">
|
||||
{Array.from({ length: 4 }).map((_, index) => (
|
||||
<Card key={index} className="@container/card gap-2">
|
||||
<CardHeader>
|
||||
<div className="space-y-3">
|
||||
{/* Título com ícone */}
|
||||
<div className="flex items-center gap-1">
|
||||
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-5 w-20 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
|
||||
{/* Valor principal */}
|
||||
<Skeleton className="h-8 w-32 rounded-2xl bg-foreground/10" />
|
||||
{/* Valor principal */}
|
||||
<Skeleton className="h-8 w-32 rounded-2xl bg-foreground/10" />
|
||||
|
||||
{/* Badge de tendência */}
|
||||
<Skeleton className="h-6 w-16 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</CardHeader>
|
||||
{/* Badge de tendência */}
|
||||
<Skeleton className="h-6 w-16 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
<CardFooter className="flex-col items-start gap-1.5 text-sm">
|
||||
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
</CardFooter>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
<CardFooter className="flex-col items-start gap-1.5 text-sm">
|
||||
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
</CardFooter>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
|
||||
/**
|
||||
@@ -13,72 +13,72 @@ import {
|
||||
* Mantém a mesma estrutura de colunas
|
||||
*/
|
||||
export function TransactionsTableSkeleton() {
|
||||
return (
|
||||
<div className="rounded-2xl border">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[180px]">Nome</TableHead>
|
||||
<TableHead className="w-[100px]">Data</TableHead>
|
||||
<TableHead className="w-[120px]">Tipo</TableHead>
|
||||
<TableHead className="w-[120px]">Valor</TableHead>
|
||||
<TableHead className="w-[120px]">Condição</TableHead>
|
||||
<TableHead className="w-[120px]">Pagamento</TableHead>
|
||||
<TableHead className="w-[140px]">Pagador</TableHead>
|
||||
<TableHead className="w-[140px]">Categoria</TableHead>
|
||||
<TableHead className="w-[140px]">Conta/Cartão</TableHead>
|
||||
<TableHead className="w-[80px]">Ações</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{Array.from({ length: 8 }).map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4 w-full rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4 w-16 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-6 w-20 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-6 w-16 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-6 w-20 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="size-6 rounded-full bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-16 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-16 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="size-6 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex gap-1">
|
||||
<Skeleton className="size-8 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="size-8 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className="rounded-2xl border">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[180px]">Nome</TableHead>
|
||||
<TableHead className="w-[100px]">Data</TableHead>
|
||||
<TableHead className="w-[120px]">Tipo</TableHead>
|
||||
<TableHead className="w-[120px]">Valor</TableHead>
|
||||
<TableHead className="w-[120px]">Condição</TableHead>
|
||||
<TableHead className="w-[120px]">Pagamento</TableHead>
|
||||
<TableHead className="w-[140px]">Pagador</TableHead>
|
||||
<TableHead className="w-[140px]">Categoria</TableHead>
|
||||
<TableHead className="w-[140px]">Conta/Cartão</TableHead>
|
||||
<TableHead className="w-[80px]">Ações</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{Array.from({ length: 8 }).map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4 w-full rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4 w-16 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-6 w-20 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-6 w-16 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-6 w-20 rounded-2xl bg-foreground/10" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="size-6 rounded-full bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-16 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-16 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="size-6 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex gap-1">
|
||||
<Skeleton className="size-8 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="size-8 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,39 +6,39 @@ import { Skeleton } from "@/components/ui/skeleton";
|
||||
* Usado enquanto widgets do dashboard estão carregando
|
||||
*/
|
||||
export function WidgetSkeleton() {
|
||||
return (
|
||||
<Card className="md:h-custom-height-1 relative h-auto md:overflow-hidden">
|
||||
<CardHeader className="border-b [.border-b]:pb-2">
|
||||
<div className="flex w-full items-start justify-between">
|
||||
<div className="space-y-2">
|
||||
{/* Title com ícone */}
|
||||
<div className="flex items-center gap-1">
|
||||
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-5 w-32 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
{/* Subtitle */}
|
||||
<Skeleton className="h-4 w-48 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
return (
|
||||
<Card className="md:h-custom-height-1 relative h-auto md:overflow-hidden">
|
||||
<CardHeader className="border-b [.border-b]:pb-2">
|
||||
<div className="flex w-full items-start justify-between">
|
||||
<div className="space-y-2">
|
||||
{/* Title com ícone */}
|
||||
<div className="flex items-center gap-1">
|
||||
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-5 w-32 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
{/* Subtitle */}
|
||||
<Skeleton className="h-4 w-48 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent className="max-h-[calc(var(--spacing-custom-height-1)-5rem)] overflow-hidden md:max-h-[calc(100%-5rem)]">
|
||||
<div className="flex flex-col gap-3 py-4">
|
||||
{/* Simula 5 linhas de conteúdo */}
|
||||
{Array.from({ length: 5 }).map((_, i) => (
|
||||
<div key={i} className="flex items-center justify-between gap-3">
|
||||
<div className="flex flex-1 items-center gap-3">
|
||||
<Skeleton className="size-10 rounded-2xl bg-foreground/10" />
|
||||
<div className="flex-1 space-y-2">
|
||||
<Skeleton className="h-4 w-full rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-3 w-24 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
<Skeleton className="h-6 w-20 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
<CardContent className="max-h-[calc(var(--spacing-custom-height-1)-5rem)] overflow-hidden md:max-h-[calc(100%-5rem)]">
|
||||
<div className="flex flex-col gap-3 py-4">
|
||||
{/* Simula 5 linhas de conteúdo */}
|
||||
{Array.from({ length: 5 }).map((_, i) => (
|
||||
<div key={i} className="flex items-center justify-between gap-3">
|
||||
<div className="flex flex-1 items-center gap-3">
|
||||
<Skeleton className="size-10 rounded-2xl bg-foreground/10" />
|
||||
<div className="flex-1 space-y-2">
|
||||
<Skeleton className="h-4 w-full rounded-2xl bg-foreground/10" />
|
||||
<Skeleton className="h-3 w-24 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
</div>
|
||||
<Skeleton className="h-6 w-20 rounded-2xl bg-foreground/10" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user