Files
openmonetis/app/(dashboard)/orcamentos/page.tsx
Felipe Coutinho 4237062bde feat: implementar relatórios de categorias e substituir seleção de período por picker visual
BREAKING CHANGE: Remove feature de seleção de período das preferências do usuário

  Alterações principais:

  - Adiciona sistema completo de relatórios por categoria
    - Cria página /relatorios/categorias com filtros e visualizações
    - Implementa tabela e gráfico de evolução mensal
    - Adiciona funcionalidade de exportação de dados
    - Cria skeleton otimizado para melhor UX de loading

  - Remove feature de seleção de período das preferências
    - Deleta lib/user-preferences/period.ts
    - Remove colunas periodMonthsBefore e periodMonthsAfter do schema
    - Remove todas as referências em 16+ arquivos
    - Atualiza database schema via Drizzle

  - Substitui Select de período por MonthPicker visual
    - Implementa componente PeriodPicker reutilizável
    - Integra shadcn MonthPicker customizado (português, Remix icons)
    - Substitui createMonthOptions em todos os formulários
    - Mantém formato "YYYY-MM" no banco de dados

  - Melhora design da tabela de relatórios
    - Mescla colunas Categoria e Tipo em uma única coluna
    - Substitui badge de tipo por dot colorido discreto
    - Reduz largura da tabela em ~120px
    - Atualiza skeleton para refletir nova estrutura

  - Melhorias gerais de UI
    - Reduz espaçamento entre títulos da sidebar (p-2 → px-2 py-1)
    - Adiciona MonthNavigation para navegação entre períodos
    - Otimiza loading states com skeletons detalhados
2026-01-04 03:03:09 +00:00

52 lines
1.5 KiB
TypeScript

import MonthNavigation from "@/components/month-picker/month-navigation";
import { BudgetsPage } from "@/components/orcamentos/budgets-page";
import { getUserId } from "@/lib/auth/server";
import { parsePeriodParam } from "@/lib/utils/period";
import { fetchBudgetsForUser } from "./data";
type PageSearchParams = Promise<Record<string, string | string[] | undefined>>;
type PageProps = {
searchParams?: PageSearchParams;
};
const getSingleParam = (
params: Record<string, string | string[] | undefined> | undefined,
key: string
) => {
const value = params?.[key];
if (!value) return null;
return Array.isArray(value) ? value[0] ?? null : value;
};
const capitalize = (value: string) =>
value.length === 0 ? value : value[0]?.toUpperCase() + value.slice(1);
export default async function Page({ searchParams }: PageProps) {
const userId = await getUserId();
const resolvedSearchParams = searchParams ? await searchParams : undefined;
const periodoParam = getSingleParam(resolvedSearchParams, "periodo");
const {
period: selectedPeriod,
monthName: rawMonthName,
year,
} = parsePeriodParam(periodoParam);
const periodLabel = `${capitalize(rawMonthName)} ${year}`;
const { budgets, categoriesOptions } = await fetchBudgetsForUser(userId, selectedPeriod);
return (
<main className="flex flex-col gap-6">
<MonthNavigation />
<BudgetsPage
budgets={budgets}
categories={categoriesOptions}
selectedPeriod={selectedPeriod}
periodLabel={periodLabel}
/>
</main>
);
}