Dashboard
Painel de visão geral que combina quatro Stat Cards, filtro de período e uma Data Table de contatos.
Visão geral
Desempenho do site e dos contatos da Clínica Sorriso.
Visitas ao site
12.847
Alta de+38%vs. mês anterior
Leads no mês
184
Alta de+22,4%vs. mês anterior
Taxa de conversão
3,8%
Queda de-0,4%vs. mês anterior
Faturamento
R$ 48.320,00
Alta de+15%vs. mês anterior
Contatos recentes
Leads recebidos pelo site, WhatsApp e anúncios.
14 contatos
| Contato | Origem | Status | Valor estimado | Recebido em | |
|---|---|---|---|---|---|
Mariana Costamariana@clinicasorriso.com.br | Google Ads | Novo | R$ 4.800,00 | 27 de set. de 2026 | |
Rafael Oliveirarafael@padariapaodeouro.com.br | Formulário do site | Em atendimento | R$ 2.500,00 | 26 de set. de 2026 | |
Juliana Martinsjuliana@studiojm.com.br | Convertido | R$ 7.200,00 | 25 de set. de 2026 | ||
Carlos Eduardo Limacarlos@limaadvocacia.adv.br | Indicação | Convertido | R$ 12.900,00 | 24 de set. de 2026 | |
Fernanda Souzafernanda@petshopamigo.com.br | Novo | R$ 3.100,00 | 24 de set. de 2026 |
Mostrando 1–5 de 14
'use client';
import { getLocalTimeZone, today } from '@internationalized/date';
import { DollarSign, Eye, Percent, Users } from 'lucide-react';
import { I18nProvider } from 'react-aria-components';
import { DataTable } from '@/components/data-table';
import { StatCard } from '@/components/stat-card';
import { DateRangePicker } from '@/components/ui/date-picker';
export default function DashboardDemo() {
const now = today(getLocalTimeZone());
return (
<I18nProvider locale="pt-BR">
<div className="flex w-full flex-col gap-6 p-4 sm:p-6">
<header className="flex flex-wrap items-end justify-between gap-4">
<div className="flex flex-col gap-1">
<h1 className="font-heading text-2xl font-semibold tracking-tight">Visão geral</h1>
<p className="text-sm text-muted-foreground">Desempenho do site e dos contatos da Clínica Sorriso.</p>
</div>
<DateRangePicker
aria-label="Período"
className="w-full sm:w-72"
defaultValue={{ start: now.subtract({ days: 29 }), end: now }}
maxValue={now}
/>
</header>
<section aria-label="Indicadores" className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
<StatCard
label="Visitas ao site"
value="12.847"
delta={38}
deltaLabel="vs. mês anterior"
icon={<Eye />}
sparkline={[320, 380, 360, 420, 410, 480, 530, 510, 590, 640, 620, 710]}
sparklineColor={1}
/>
<StatCard
label="Leads no mês"
value="184"
delta={22.4}
deltaLabel="vs. mês anterior"
icon={<Users />}
sparkline={[8, 12, 10, 14, 13, 17, 16, 21, 19, 24]}
sparklineColor={2}
/>
<StatCard
label="Taxa de conversão"
value="3,8%"
delta={-0.4}
deltaLabel="vs. mês anterior"
icon={<Percent />}
sparkline={[4.1, 4.3, 4.0, 4.2, 3.9, 3.7, 3.9, 3.8]}
sparklineColor={3}
/>
<StatCard
label="Faturamento"
value="R$ 48.320,00"
delta={15}
deltaLabel="vs. mês anterior"
icon={<DollarSign />}
sparkline={[31, 34, 33, 38, 36, 41, 44, 48]}
sparklineColor={4}
/>
</section>
<section
aria-labelledby="contatos-recentes"
className="flex flex-col gap-4 rounded-xl border bg-card p-5 text-card-foreground shadow-xs"
>
<div className="flex flex-col gap-1">
<h2 id="contatos-recentes" className="font-heading text-lg font-semibold">
Contatos recentes
</h2>
<p className="text-sm text-muted-foreground">Leads recebidos pelo site, WhatsApp e anúncios.</p>
</div>
<DataTable aria-label="Contatos recentes" pageSize={5} />
</section>
</div>
</I18nProvider>
);
}Instalação
O Dashboard não é um item do registry: é uma composição de blocos e componentes. Instale as peças e copie a página.
npx shadcn@latest add @lenstech/stat-card @lenstech/data-table @lenstech/date-pickerCódigo
'use client';
import { getLocalTimeZone, today } from '@internationalized/date';
import { DollarSign, Eye, Percent, Users } from 'lucide-react';
import { I18nProvider } from 'react-aria-components';
import { DataTable } from '@/components/data-table';
import { StatCard } from '@/components/stat-card';
import { DateRangePicker } from '@/components/ui/date-picker';
export default function DashboardDemo() {
const now = today(getLocalTimeZone());
return (
<I18nProvider locale="pt-BR">
<div className="flex w-full flex-col gap-6 p-4 sm:p-6">
<header className="flex flex-wrap items-end justify-between gap-4">
<div className="flex flex-col gap-1">
<h1 className="font-heading text-2xl font-semibold tracking-tight">Visão geral</h1>
<p className="text-sm text-muted-foreground">Desempenho do site e dos contatos da Clínica Sorriso.</p>
</div>
<DateRangePicker
aria-label="Período"
className="w-full sm:w-72"
defaultValue={{ start: now.subtract({ days: 29 }), end: now }}
maxValue={now}
/>
</header>
<section aria-label="Indicadores" className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
<StatCard
label="Visitas ao site"
value="12.847"
delta={38}
deltaLabel="vs. mês anterior"
icon={<Eye />}
sparkline={[320, 380, 360, 420, 410, 480, 530, 510, 590, 640, 620, 710]}
sparklineColor={1}
/>
<StatCard
label="Leads no mês"
value="184"
delta={22.4}
deltaLabel="vs. mês anterior"
icon={<Users />}
sparkline={[8, 12, 10, 14, 13, 17, 16, 21, 19, 24]}
sparklineColor={2}
/>
<StatCard
label="Taxa de conversão"
value="3,8%"
delta={-0.4}
deltaLabel="vs. mês anterior"
icon={<Percent />}
sparkline={[4.1, 4.3, 4.0, 4.2, 3.9, 3.7, 3.9, 3.8]}
sparklineColor={3}
/>
<StatCard
label="Faturamento"
value="R$ 48.320,00"
delta={15}
deltaLabel="vs. mês anterior"
icon={<DollarSign />}
sparkline={[31, 34, 33, 38, 36, 41, 44, 48]}
sparklineColor={4}
/>
</section>
<section
aria-labelledby="contatos-recentes"
className="flex flex-col gap-4 rounded-xl border bg-card p-5 text-card-foreground shadow-xs"
>
<div className="flex flex-col gap-1">
<h2 id="contatos-recentes" className="font-heading text-lg font-semibold">
Contatos recentes
</h2>
<p className="text-sm text-muted-foreground">Leads recebidos pelo site, WhatsApp e anúncios.</p>
</div>
<DataTable aria-label="Contatos recentes" pageSize={5} />
</section>
</div>
</I18nProvider>
);
}Como está montado
- Cabeçalho: título da página (
font-heading) e umDateRangePickercom os últimos 30 dias emaxValueem hoje. - Indicadores: 4
StatCardnuma gradesm:grid-cols-2 xl:grid-cols-4— cada um com cor de gráfico própria (chart-1..4). - Contatos recentes: a
DataTabledentro de um cartão (bg-card,shadow-xs). - Idioma: tudo envolvido em
<I18nProvider locale="pt-BR">, para datas em português.
Conectando aos seus dados
Os valores do exemplo são fixos. Na prática, busque os indicadores e os contatos pelo período escolhido:
guarde o valor do DateRangePicker em estado (value/onChange) e envie start.toString() e
end.toString() (datas ISO) para a sua API.
Quando usar
- Use como tela inicial de painéis de clientes: visão rápida dos números e dos contatos mais recentes.
- Não use como relatório detalhado — crie páginas próprias com gráficos completos e filtros.
- Mantenha poucos indicadores (até 4–6) e escolha os que levam a uma ação.