refactor: faxina arquitetural — código morto, identificadores em inglês e estrutura padronizada

Refatoração estrutural sem mudanças funcionais. Saldo líquido: −428 linhas.

Removido:
- 14 funções/constantes mortas verificadas via grep no repo todo: validateCategoriaOwnership,
  getInstallmentAnticipationsAction, getAnticipationDetailsAction, formatDecimalForDb,
  currencyFormatterNoCents, optionalDecimalSchema, formatMonthLabel,
  getGoalProgressStatusColorClass, MONTH_PERIOD_PARAM, calculateRemainingInstallments,
  e 5 funções fetch* não usadas em inbox/queries.ts.
- 1 tipo morto (ImportRow) + 2 órfãos consequentes (InstallmentAnticipationWithRelations,
  GoalProgressStatus convertido em interno).
- ~30 export keywords desnecessários (símbolos usados apenas no próprio arquivo).
- Re-exports mortos em barrels: EstablishmentLogoPicker, CategoryReportSkeleton,
  WidgetSkeleton, toNameKey.
- Arquivo features/reports/types.ts (barrel inteiro era órfão).

Padronizado (PT-BR→EN em identificadores expostos):
- 4 constantes globais (LANCAMENTOS_* → TRANSACTIONS_*).
- 12 tipos/interfaces (Lancamento*/Pagador*/Estabelecimento* → equivalentes EN).
- 13 funções/components exportados (fetchPagador*, EstabelecimentoInput, PagadorInfoCard, etc.).
- 5 props cross-file (preLancamentosCount → inboxPendingCount, pagadorAvatarUrl → payerAvatarUrl, etc.).
- Mantidas em PT-BR conforme exceção do CLAUDE.md: variáveis locais (pagador, categoria,
  lancamento), accessor key pagadorName (persistida em preferências), strings de UI.

Reorganizado:
- transactions/: 14 helpers soltos na raiz movidos para lib/; barrel actions.ts reduzido
  de 76 linhas de wrappers para 14 linhas de re-exports puros; anticipation-actions.ts
  movido para actions/anticipation.ts.
- dashboard/: 8 helpers soltos consolidados em dashboard/lib/.
- reports/: 5 query files na raiz consolidados em reports/lib/.
- payers/: detail-actions.ts (21KB) e detail-queries.ts movidos para payers/lib/.
- shared/components/: 9 dos 16 componentes soltos agrupados em brand/, widgets/, feedback/.
- shared/lib/fetch-json.ts movido para shared/utils/fetch-json.ts.

Validação: pnpm exec tsc --noEmit (0 erros), biome check (0 issues), knip (sem unused).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-05-06 18:42:54 +00:00
parent b9b843b9db
commit 7d0781b035
229 changed files with 415 additions and 872 deletions

View File

@@ -12,8 +12,10 @@
], ],
// PostCSS is inferred from the config file, but the project only depends on // PostCSS is inferred from the config file, but the project only depends on
// the Tailwind PostCSS plugin directly. // the Tailwind PostCSS plugin directly.
// `server-only` is provided implicitly by Next.js — no install needed.
"ignoreDependencies": [ "ignoreDependencies": [
"postcss" "postcss",
"server-only"
], ],
"next": true, "next": true,
"postcss": true, "postcss": true,

View File

@@ -21,6 +21,7 @@ const nextConfig: NextConfig = {
experimental: { experimental: {
prefetchInlining: true, prefetchInlining: true,
turbopackFileSystemCacheForDev: true, turbopackFileSystemCacheForDev: true,
optimizePackageImports: ["@remixicon/react"],
}, },
// Headers for Safari compatibility // Headers for Safari compatibility

View File

@@ -21,7 +21,7 @@ import type {
PAYMENT_METHODS, PAYMENT_METHODS,
TRANSACTION_CONDITIONS, TRANSACTION_CONDITIONS,
TRANSACTION_TYPES, TRANSACTION_TYPES,
} from "@/features/transactions/constants"; } from "@/features/transactions/lib/constants";
import { import {
buildInvoicePaymentNote, buildInvoicePaymentNote,
INITIAL_BALANCE_CATEGORY_NAME, INITIAL_BALANCE_CATEGORY_NAME,

View File

@@ -1,4 +1,4 @@
import { Logo } from "@/shared/components/logo"; import { Logo } from "@/shared/components/brand/logo";
export default function AuthLayout({ export default function AuthLayout({
children, children,

View File

@@ -7,8 +7,8 @@ import { AdjustBalanceDialog } from "@/features/accounts/components/adjust-balan
import type { Account } from "@/features/accounts/components/types"; import type { Account } from "@/features/accounts/components/types";
import { import {
fetchAccountData, fetchAccountData,
fetchAccountLancamentosPage,
fetchAccountSummary, fetchAccountSummary,
fetchAccountTransactionsPage,
} from "@/features/accounts/statement-queries"; } from "@/features/accounts/statement-queries";
import { fetchUserPreferences } from "@/features/settings/queries"; import { fetchUserPreferences } from "@/features/settings/queries";
import { TransactionsPage as LancamentosSection } from "@/features/transactions/components/page/transactions-page"; import { TransactionsPage as LancamentosSection } from "@/features/transactions/components/page/transactions-page";
@@ -22,7 +22,7 @@ import {
mapTransactionsData, mapTransactionsData,
type ResolvedSearchParams, type ResolvedSearchParams,
resolveTransactionPagination, resolveTransactionPagination,
} from "@/features/transactions/page-helpers"; } from "@/features/transactions/lib/page-helpers";
import { import {
fetchRecentEstablishments, fetchRecentEstablishments,
fetchTransactionFilterSources, fetchTransactionFilterSources,
@@ -89,7 +89,7 @@ export default async function Page({ params, searchParams }: PageProps) {
accountId: account.id, accountId: account.id,
}); });
const transactionsPage = await fetchAccountLancamentosPage( const transactionsPage = await fetchAccountTransactionsPage(
filters, filters,
pagination, pagination,
); );

View File

@@ -4,7 +4,7 @@ import { fetchCalendarData } from "@/features/calendar/queries";
import { import {
getSingleParam, getSingleParam,
type ResolvedSearchParams, type ResolvedSearchParams,
} from "@/features/transactions/page-helpers"; } from "@/features/transactions/lib/page-helpers";
import MonthNavigation from "@/shared/components/month-picker/month-navigation"; import MonthNavigation from "@/shared/components/month-picker/month-navigation";
import { getUserId } from "@/shared/lib/auth/server"; import { getUserId } from "@/shared/lib/auth/server";
import type { CalendarPeriod } from "@/shared/lib/types/calendar"; import type { CalendarPeriod } from "@/shared/lib/types/calendar";

View File

@@ -21,7 +21,7 @@ import {
getSingleParam, getSingleParam,
mapTransactionsData, mapTransactionsData,
type ResolvedSearchParams, type ResolvedSearchParams,
} from "@/features/transactions/page-helpers"; } from "@/features/transactions/lib/page-helpers";
import { import {
fetchRecentEstablishments, fetchRecentEstablishments,
fetchTransactionFilterSources, fetchTransactionFilterSources,

View File

@@ -7,7 +7,7 @@ import { TransactionsPage } from "@/features/transactions/components/page/transa
import { import {
buildOptionSets, buildOptionSets,
buildSluggedFilters, buildSluggedFilters,
} from "@/features/transactions/page-helpers"; } from "@/features/transactions/lib/page-helpers";
import { import {
fetchRecentEstablishments, fetchRecentEstablishments,
fetchTransactionFilterSources, fetchTransactionFilterSources,

View File

@@ -2,9 +2,9 @@ import { connection } from "next/server";
import { DashboardGridEditable } from "@/features/dashboard/components/dashboard-grid-editable"; import { DashboardGridEditable } from "@/features/dashboard/components/dashboard-grid-editable";
import { DashboardMetricsCards } from "@/features/dashboard/components/dashboard-metrics-cards"; import { DashboardMetricsCards } from "@/features/dashboard/components/dashboard-metrics-cards";
import { DashboardWelcome } from "@/features/dashboard/components/dashboard-welcome"; import { DashboardWelcome } from "@/features/dashboard/components/dashboard-welcome";
import { extractDashboardLogoNames } from "@/features/dashboard/extract-logo-names"; import { extractDashboardLogoNames } from "@/features/dashboard/lib/extract-logo-names";
import { fetchDashboardPageData } from "@/features/dashboard/page-data-queries"; import { fetchDashboardPageData } from "@/features/dashboard/page-data-queries";
import { getSingleParam } from "@/features/transactions/page-helpers"; import { getSingleParam } from "@/features/transactions/lib/page-helpers";
import { LogoPrefetchProvider } from "@/shared/components/entity-avatar"; import { LogoPrefetchProvider } from "@/shared/components/entity-avatar";
import MonthNavigation from "@/shared/components/month-picker/month-navigation"; import MonthNavigation from "@/shared/components/month-picker/month-navigation";
import { getUser } from "@/shared/lib/auth/server"; import { getUser } from "@/shared/lib/auth/server";

View File

@@ -1,5 +1,5 @@
import { connection } from "next/server"; import { connection } from "next/server";
import { fetchDashboardNavbarData } from "@/features/dashboard/navbar-queries"; import { fetchDashboardNavbarData } from "@/features/dashboard/lib/navbar-queries";
import { AppNavbar } from "@/shared/components/navigation/navbar/app-navbar"; import { AppNavbar } from "@/shared/components/navigation/navbar/app-navbar";
import { LogoDevProvider } from "@/shared/components/providers/logo-dev-provider"; import { LogoDevProvider } from "@/shared/components/providers/logo-dev-provider";
import { PrivacyProvider } from "@/shared/components/providers/privacy-provider"; import { PrivacyProvider } from "@/shared/components/providers/privacy-provider";
@@ -21,8 +21,8 @@ export default async function DashboardLayout({
<PrivacyProvider> <PrivacyProvider>
<AppNavbar <AppNavbar
user={{ ...session.user, image: session.user.image ?? null }} user={{ ...session.user, image: session.user.image ?? null }}
pagadorAvatarUrl={navbarData.pagadorAvatarUrl} payerAvatarUrl={navbarData.payerAvatarUrl}
preLancamentosCount={navbarData.preLancamentosCount} inboxPendingCount={navbarData.inboxPendingCount}
notificationsSnapshot={navbarData.notificationsSnapshot} notificationsSnapshot={navbarData.notificationsSnapshot}
/> />
<div className="relative flex flex-1 flex-col pt-16"> <div className="relative flex flex-1 flex-col pt-16">

View File

@@ -4,7 +4,7 @@ import { Skeleton } from "@/shared/components/ui/skeleton";
* Loading state para a página de detalhes do pagador. * Loading state para a página de detalhes do pagador.
* Layout: navegação mensal + tabs com card compartilhado do pagador. * Layout: navegação mensal + tabs com card compartilhado do pagador.
*/ */
export default function PagadorDetailsLoading() { export default function PayerDetailsLoading() {
return ( return (
<main className="flex flex-col gap-6"> <main className="flex flex-col gap-6">
<div className="h-[60px] animate-pulse rounded-md bg-foreground/10" /> <div className="h-[60px] animate-pulse rounded-md bg-foreground/10" />

View File

@@ -8,7 +8,7 @@ import { connection } from "next/server";
import { PayerCardUsageCard } from "@/features/payers/components/details/payer-card-usage-card"; import { PayerCardUsageCard } from "@/features/payers/components/details/payer-card-usage-card";
import { PayerHeaderCard } from "@/features/payers/components/details/payer-header-card"; import { PayerHeaderCard } from "@/features/payers/components/details/payer-header-card";
import { PayerHistoryCard } from "@/features/payers/components/details/payer-history-card"; import { PayerHistoryCard } from "@/features/payers/components/details/payer-history-card";
import { PagadorInfoCard } from "@/features/payers/components/details/payer-info-card"; import { PayerInfoCard } from "@/features/payers/components/details/payer-info-card";
import { PayerLeaveShareCard } from "@/features/payers/components/details/payer-leave-share-card"; import { PayerLeaveShareCard } from "@/features/payers/components/details/payer-leave-share-card";
import { PayerMonthlySummaryCard } from "@/features/payers/components/details/payer-monthly-summary-card"; import { PayerMonthlySummaryCard } from "@/features/payers/components/details/payer-monthly-summary-card";
import { import {
@@ -16,12 +16,12 @@ import {
PayerPaymentStatusCard, PayerPaymentStatusCard,
} from "@/features/payers/components/details/payer-payment-method-cards"; } from "@/features/payers/components/details/payer-payment-method-cards";
import { PayerSharingCard } from "@/features/payers/components/details/payer-sharing-card"; import { PayerSharingCard } from "@/features/payers/components/details/payer-sharing-card";
import { buildReadOnlyOptionSets } from "@/features/payers/lib/build-readonly-option-sets";
import { import {
fetchCurrentUserShare, fetchCurrentUserShare,
fetchPagadorLancamentos,
fetchPayerShares, fetchPayerShares,
} from "@/features/payers/detail-queries"; fetchPayerTransactions,
import { buildReadOnlyOptionSets } from "@/features/payers/lib/build-readonly-option-sets"; } from "@/features/payers/lib/detail-queries";
import { fetchUserPreferences } from "@/features/settings/queries"; import { fetchUserPreferences } from "@/features/settings/queries";
import { TransactionsPage as LancamentosSection } from "@/features/transactions/components/page/transactions-page"; import { TransactionsPage as LancamentosSection } from "@/features/transactions/components/page/transactions-page";
import { import {
@@ -36,13 +36,12 @@ import {
type SluggedFilters, type SluggedFilters,
type SlugMaps, type SlugMaps,
type TransactionSearchFilters, type TransactionSearchFilters,
} from "@/features/transactions/page-helpers"; } from "@/features/transactions/lib/page-helpers";
import { import {
fetchRecentEstablishments, fetchRecentEstablishments,
fetchTransactionFilterSources, fetchTransactionFilterSources,
} from "@/features/transactions/queries"; } from "@/features/transactions/queries";
import { LogoPrefetchProvider } from "@/shared/components/entity-avatar"; import { LogoPrefetchProvider } from "@/shared/components/entity-avatar";
import { ExpandableWidgetCard } from "@/shared/components/expandable-widget-card";
import MonthNavigation from "@/shared/components/month-picker/month-navigation"; import MonthNavigation from "@/shared/components/month-picker/month-navigation";
import { import {
Tabs, Tabs,
@@ -50,16 +49,17 @@ import {
TabsList, TabsList,
TabsTrigger, TabsTrigger,
} from "@/shared/components/ui/tabs"; } from "@/shared/components/ui/tabs";
import { ExpandableWidgetCard } from "@/shared/components/widgets/expandable-widget-card";
import { getUserId } from "@/shared/lib/auth/server"; import { getUserId } from "@/shared/lib/auth/server";
import { prefetchLogoMappings } from "@/shared/lib/logo/prefetch-server"; import { prefetchLogoMappings } from "@/shared/lib/logo/prefetch-server";
import { getPayerAccess } from "@/shared/lib/payers/access"; import { getPayerAccess } from "@/shared/lib/payers/access";
import { import {
fetchPagadorBoletoItems, fetchPayerBoletoItems,
fetchPagadorBoletoStats, fetchPayerBoletoStats,
fetchPagadorCardUsage, fetchPayerCardUsage,
fetchPagadorPaymentStatus,
fetchPayerHistory, fetchPayerHistory,
fetchPayerMonthlyBreakdown, fetchPayerMonthlyBreakdown,
fetchPayerPaymentStatus,
type PayerCardUsageItem, type PayerCardUsageItem,
} from "@/shared/lib/payers/details"; } from "@/shared/lib/payers/details";
import { parsePeriodParam } from "@/shared/utils/period"; import { parsePeriodParam } from "@/shared/utils/period";
@@ -182,7 +182,7 @@ export default async function Page({ params, searchParams }: PageProps) {
estabelecimentos, estabelecimentos,
userPreferences, userPreferences,
] = await Promise.all([ ] = await Promise.all([
fetchPagadorLancamentos(filters), fetchPayerTransactions(filters),
fetchPayerMonthlyBreakdown({ fetchPayerMonthlyBreakdown({
userId: dataOwnerId, userId: dataOwnerId,
payerId: pagador.id, payerId: pagador.id,
@@ -193,22 +193,22 @@ export default async function Page({ params, searchParams }: PageProps) {
payerId: pagador.id, payerId: pagador.id,
period: selectedPeriod, period: selectedPeriod,
}), }),
fetchPagadorCardUsage({ fetchPayerCardUsage({
userId: dataOwnerId, userId: dataOwnerId,
payerId: pagador.id, payerId: pagador.id,
period: selectedPeriod, period: selectedPeriod,
}), }),
fetchPagadorBoletoStats({ fetchPayerBoletoStats({
userId: dataOwnerId, userId: dataOwnerId,
payerId: pagador.id, payerId: pagador.id,
period: selectedPeriod, period: selectedPeriod,
}), }),
fetchPagadorBoletoItems({ fetchPayerBoletoItems({
userId: dataOwnerId, userId: dataOwnerId,
payerId: pagador.id, payerId: pagador.id,
period: selectedPeriod, period: selectedPeriod,
}), }),
fetchPagadorPaymentStatus({ fetchPayerPaymentStatus({
userId: dataOwnerId, userId: dataOwnerId,
payerId: pagador.id, payerId: pagador.id,
period: selectedPeriod, period: selectedPeriod,
@@ -333,7 +333,7 @@ export default async function Page({ params, searchParams }: PageProps) {
/> />
<TabsContent value="profile" className="space-y-4"> <TabsContent value="profile" className="space-y-4">
<PagadorInfoCard payer={payerData} /> <PayerInfoCard payer={payerData} />
{canEdit && payerData.shareCode ? ( {canEdit && payerData.shareCode ? (
<PayerSharingCard <PayerSharingCard
payerId={pagador.id} payerId={pagador.id}

View File

@@ -4,7 +4,7 @@ import { Skeleton } from "@/shared/components/ui/skeleton";
* Loading state para a página de pessoas * Loading state para a página de pessoas
* Layout: Header + Input de compartilhamento + Grid de cards * Layout: Header + Input de compartilhamento + Grid de cards
*/ */
export default function PagadoresLoading() { export default function PayersLoading() {
return ( return (
<main className="flex flex-col items-start gap-6"> <main className="flex flex-col items-start gap-6">
<div className="w-full space-y-6"> <div className="w-full space-y-6">

View File

@@ -1,11 +1,11 @@
import { RiBankCard2Line } from "@remixicon/react"; import { RiBankCard2Line } from "@remixicon/react";
import { connection } from "next/server"; import { connection } from "next/server";
import { fetchCartoesReportData } from "@/features/reports/cards-report-queries";
import { CardCategoryBreakdown } from "@/features/reports/components/cards/card-category-breakdown"; import { CardCategoryBreakdown } from "@/features/reports/components/cards/card-category-breakdown";
import { CardInvoiceStatus } from "@/features/reports/components/cards/card-invoice-status"; import { CardInvoiceStatus } from "@/features/reports/components/cards/card-invoice-status";
import { CardTopExpenses } from "@/features/reports/components/cards/card-top-expenses"; import { CardTopExpenses } from "@/features/reports/components/cards/card-top-expenses";
import { CardUsageChart } from "@/features/reports/components/cards/card-usage-chart"; import { CardUsageChart } from "@/features/reports/components/cards/card-usage-chart";
import { CardsOverview } from "@/features/reports/components/cards/cards-overview"; import { CardsOverview } from "@/features/reports/components/cards/cards-overview";
import { fetchCartoesReportData } from "@/features/reports/lib/cards-report-queries";
import MonthNavigation from "@/shared/components/month-picker/month-navigation"; import MonthNavigation from "@/shared/components/month-picker/month-navigation";
import { Card } from "@/shared/components/ui/card"; import { Card } from "@/shared/components/ui/card";
import { getUser } from "@/shared/lib/auth/server"; import { getUser } from "@/shared/lib/auth/server";

View File

@@ -1,15 +1,15 @@
import { redirect } from "next/navigation"; import { redirect } from "next/navigation";
import { connection } from "next/server"; import { connection } from "next/server";
import type { Category } from "@/db/schema"; import type { Category } from "@/db/schema";
import { fetchCategoryChartData } from "@/features/reports/category-chart-queries";
import { fetchCategoryReport } from "@/features/reports/category-report-queries";
import { fetchUserCategories } from "@/features/reports/category-trends-queries";
import { CategoryReportPage } from "@/features/reports/components/category-report-page"; import { CategoryReportPage } from "@/features/reports/components/category-report-page";
import type { import type {
CategoryOption, CategoryOption,
FilterState, FilterState,
} from "@/features/reports/components/types"; } from "@/features/reports/components/types";
import { validateDateRange } from "@/features/reports/utils"; import { fetchCategoryChartData } from "@/features/reports/lib/category-chart-queries";
import { fetchCategoryReport } from "@/features/reports/lib/category-report-queries";
import { fetchUserCategories } from "@/features/reports/lib/category-trends-queries";
import { validateDateRange } from "@/features/reports/lib/utils";
import { getUserId } from "@/shared/lib/auth/server"; import { getUserId } from "@/shared/lib/auth/server";
import type { CategoryReportFilters } from "@/shared/lib/types/reports"; import type { CategoryReportFilters } from "@/shared/lib/types/reports";
import { addMonthsToPeriod, getCurrentPeriod } from "@/shared/utils/period"; import { addMonthsToPeriod, getCurrentPeriod } from "@/shared/utils/period";

View File

@@ -34,7 +34,7 @@ const validatePeriodFilter = (value: string | null): PeriodFilter => {
return "6"; return "6";
}; };
export default async function TopEstabelecimentosPage({ export default async function TopEstablishmentsPage({
searchParams, searchParams,
}: PageProps) { }: PageProps) {
await connection(); await connection();

View File

@@ -3,7 +3,7 @@ import { ImportPage } from "@/features/transactions/components/import/import-pag
import { import {
buildOptionSets, buildOptionSets,
buildSluggedFilters, buildSluggedFilters,
} from "@/features/transactions/page-helpers"; } from "@/features/transactions/lib/page-helpers";
import { fetchTransactionFilterSources } from "@/features/transactions/queries"; import { fetchTransactionFilterSources } from "@/features/transactions/queries";
import { getUserId } from "@/shared/lib/auth/server"; import { getUserId } from "@/shared/lib/auth/server";

View File

@@ -8,7 +8,7 @@ import { Skeleton } from "@/shared/components/ui/skeleton";
* Loading state para a página de lançamentos * Loading state para a página de lançamentos
* Mantém o mesmo layout da página final * Mantém o mesmo layout da página final
*/ */
export default function LancamentosLoading() { export default function TransactionsLoading() {
return ( return (
<main className="flex flex-col gap-6"> <main className="flex flex-col gap-6">
{/* Month Picker placeholder */} {/* Month Picker placeholder */}

View File

@@ -11,7 +11,7 @@ import {
mapTransactionsData, mapTransactionsData,
type ResolvedSearchParams, type ResolvedSearchParams,
resolveTransactionPagination, resolveTransactionPagination,
} from "@/features/transactions/page-helpers"; } from "@/features/transactions/lib/page-helpers";
import { import {
fetchRecentEstablishments, fetchRecentEstablishments,
fetchTransactionFilterSources, fetchTransactionFilterSources,

View File

@@ -24,7 +24,7 @@ import {
import { landingImages } from "@/features/landing/images"; import { landingImages } from "@/features/landing/images";
import { fetchGitHubStats } from "@/features/landing/queries"; import { fetchGitHubStats } from "@/features/landing/queries";
import { AnimatedThemeToggler } from "@/shared/components/animated-theme-toggler"; import { AnimatedThemeToggler } from "@/shared/components/animated-theme-toggler";
import { Logo } from "@/shared/components/logo"; import { Logo } from "@/shared/components/brand/logo";
import { NavbarShell } from "@/shared/components/navigation/navbar/navbar-shell"; import { NavbarShell } from "@/shared/components/navigation/navbar/navbar-shell";
import { Badge } from "@/shared/components/ui/badge"; import { Badge } from "@/shared/components/ui/badge";
import { Button } from "@/shared/components/ui/button"; import { Button } from "@/shared/components/ui/button";

View File

@@ -1,5 +1,5 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { fetchTransactionAttachments } from "@/features/transactions/attachment-queries"; import { fetchTransactionAttachments } from "@/features/transactions/lib/attachment-queries";
import { getOptionalUserSession } from "@/shared/lib/auth/server"; import { getOptionalUserSession } from "@/shared/lib/auth/server";
const PRIVATE_RESPONSE_HEADERS = { const PRIVATE_RESPONSE_HEADERS = {

View File

@@ -1,5 +1,5 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { fetchInstallmentAnticipations } from "@/features/transactions/anticipation-queries"; import { fetchInstallmentAnticipations } from "@/features/transactions/lib/anticipation-queries";
import { getOptionalUserSession } from "@/shared/lib/auth/server"; import { getOptionalUserSession } from "@/shared/lib/auth/server";
const PRIVATE_RESPONSE_HEADERS = { const PRIVATE_RESPONSE_HEADERS = {

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import StatusDot from "@/shared/components/status-dot"; import StatusDot from "@/shared/components/feedback/status-dot";
import { getAccountTypeIcon } from "@/shared/utils/icons"; import { getAccountTypeIcon } from "@/shared/utils/icons";
export function AccountTypeSelectContent({ label }: { label: string }) { export function AccountTypeSelectContent({ label }: { label: string }) {

View File

@@ -8,7 +8,7 @@ import { toast } from "sonner";
import { deleteAccountAction } from "@/features/accounts/actions"; import { deleteAccountAction } from "@/features/accounts/actions";
import { AccountCard } from "@/features/accounts/components/account-card"; import { AccountCard } from "@/features/accounts/components/account-card";
import { ConfirmActionDialog } from "@/shared/components/confirm-action-dialog"; import { ConfirmActionDialog } from "@/shared/components/confirm-action-dialog";
import { EmptyState } from "@/shared/components/empty-state"; import { EmptyState } from "@/shared/components/feedback/empty-state";
import { Button } from "@/shared/components/ui/button"; import { Button } from "@/shared/components/ui/button";
import { Card } from "@/shared/components/ui/card"; import { Card } from "@/shared/components/ui/card";
import { import {

View File

@@ -99,13 +99,13 @@ async function fetchAccountsByStatus(
return { accounts, logoOptions }; return { accounts, logoOptions };
} }
export async function fetchAccountsForUser( async function fetchAccountsForUser(
userId: string, userId: string,
): Promise<{ accounts: AccountData[]; logoOptions: string[] }> { ): Promise<{ accounts: AccountData[]; logoOptions: string[] }> {
return fetchAccountsByStatus(userId, false); return fetchAccountsByStatus(userId, false);
} }
export async function fetchInactiveForUser( async function fetchInactiveForUser(
userId: string, userId: string,
): Promise<{ accounts: AccountData[]; logoOptions: string[] }> { ): Promise<{ accounts: AccountData[]; logoOptions: string[] }> {
return fetchAccountsByStatus(userId, true); return fetchAccountsByStatus(userId, true);

View File

@@ -154,7 +154,7 @@ export async function fetchAccountSummary(
}; };
} }
export async function fetchAccountLancamentos( export async function fetchAccountTransactions(
filters: SQL[], filters: SQL[],
settledOnly = true, settledOnly = true,
) { ) {
@@ -167,7 +167,7 @@ export async function fetchAccountLancamentos(
}); });
} }
export async function fetchAccountLancamentosPage( export async function fetchAccountTransactionsPage(
filters: SQL[], filters: SQL[],
{ {
page, page,

View File

@@ -18,7 +18,7 @@ import { fetchTransactionDialogOptionsAction } from "@/features/transactions/act
import { TransactionDetailsDialog } from "@/features/transactions/components/dialogs/transaction-details-dialog"; import { TransactionDetailsDialog } from "@/features/transactions/components/dialogs/transaction-details-dialog";
import { TransactionDialog } from "@/features/transactions/components/dialogs/transaction-dialog/transaction-dialog"; import { TransactionDialog } from "@/features/transactions/components/dialogs/transaction-dialog/transaction-dialog";
import type { TransactionItem } from "@/features/transactions/components/types"; import type { TransactionItem } from "@/features/transactions/components/types";
import { EmptyState } from "@/shared/components/empty-state"; import { EmptyState } from "@/shared/components/feedback/empty-state";
import { Card, CardContent } from "@/shared/components/ui/card"; import { Card, CardContent } from "@/shared/components/ui/card";
import { cn } from "@/shared/utils/ui"; import { cn } from "@/shared/utils/ui";

View File

@@ -2,11 +2,11 @@
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { fetchJson } from "@/shared/lib/fetch-json"; import { fetchJson } from "@/shared/utils/fetch-json";
const ATTACHMENT_URL_STALE_TIME = 4 * 60 * 1000; const ATTACHMENT_URL_STALE_TIME = 4 * 60 * 1000;
export const attachmentUrlQueryKey = (attachmentId: string) => const attachmentUrlQueryKey = (attachmentId: string) =>
["attachments", "url", attachmentId] as const; ["attachments", "url", attachmentId] as const;
export function useAttachmentUrlQuery(attachmentId: string, enabled: boolean) { export function useAttachmentUrlQuery(attachmentId: string, enabled: boolean) {

View File

@@ -3,7 +3,7 @@ import {
RiBarChart2Line, RiBarChart2Line,
RiShieldCheckLine, RiShieldCheckLine,
} from "@remixicon/react"; } from "@remixicon/react";
import { Logo } from "@/shared/components/logo"; import { Logo } from "@/shared/components/brand/logo";
import { DotPattern } from "@/shared/components/ui/dot-pattern"; import { DotPattern } from "@/shared/components/ui/dot-pattern";
import { AuthSidebarInvoicesMock } from "./auth-sidebar-invoices-mock"; import { AuthSidebarInvoicesMock } from "./auth-sidebar-invoices-mock";

View File

@@ -8,7 +8,7 @@ import {
duplicatePreviousMonthBudgetsAction, duplicatePreviousMonthBudgetsAction,
} from "@/features/budgets/actions"; } from "@/features/budgets/actions";
import { ConfirmActionDialog } from "@/shared/components/confirm-action-dialog"; import { ConfirmActionDialog } from "@/shared/components/confirm-action-dialog";
import { EmptyState } from "@/shared/components/empty-state"; import { EmptyState } from "@/shared/components/feedback/empty-state";
import { Button } from "@/shared/components/ui/button"; import { Button } from "@/shared/components/ui/button";
import { Card } from "@/shared/components/ui/card"; import { Card } from "@/shared/components/ui/card";
import { BudgetCard } from "./budget-card"; import { BudgetCard } from "./budget-card";

View File

@@ -26,7 +26,7 @@ type BudgetData = {
} | null; } | null;
}; };
export type CategoryOption = { type CategoryOption = {
id: string; id: string;
name: string; name: string;
icon: string | null; icon: string | null;

View File

@@ -4,7 +4,7 @@ import {
buildOptionSets, buildOptionSets,
buildSluggedFilters, buildSluggedFilters,
mapTransactionsData, mapTransactionsData,
} from "@/features/transactions/page-helpers"; } from "@/features/transactions/lib/page-helpers";
import { import {
fetchRecentEstablishments, fetchRecentEstablishments,
fetchTransactionFilterSources, fetchTransactionFilterSources,

View File

@@ -2,7 +2,7 @@
import { RiBankLine } from "@remixicon/react"; import { RiBankLine } from "@remixicon/react";
import Image from "next/image"; import Image from "next/image";
import StatusDot from "@/shared/components/status-dot"; import StatusDot from "@/shared/components/feedback/status-dot";
import { resolveCardBrandLogoSrc } from "@/shared/lib/cards/brand-assets"; import { resolveCardBrandLogoSrc } from "@/shared/lib/cards/brand-assets";
import { resolveLogoSrc } from "@/shared/lib/logo"; import { resolveLogoSrc } from "@/shared/lib/logo";

View File

@@ -6,7 +6,7 @@ import { useMemo, useState } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import { deleteCardAction } from "@/features/cards/actions"; import { deleteCardAction } from "@/features/cards/actions";
import { ConfirmActionDialog } from "@/shared/components/confirm-action-dialog"; import { ConfirmActionDialog } from "@/shared/components/confirm-action-dialog";
import { EmptyState } from "@/shared/components/empty-state"; import { EmptyState } from "@/shared/components/feedback/empty-state";
import { Button } from "@/shared/components/ui/button"; import { Button } from "@/shared/components/ui/button";
import { Card as UiCard } from "@/shared/components/ui/card"; import { Card as UiCard } from "@/shared/components/ui/card";
import { import {

View File

@@ -19,7 +19,7 @@ type CardData = {
accountName: string; accountName: string;
}; };
export type AccountSimple = { type AccountSimple = {
id: string; id: string;
name: string; name: string;
logo: string | null; logo: string | null;
@@ -121,7 +121,7 @@ async function fetchCardsByStatus(
return { cards: cardList, accounts, logoOptions }; return { cards: cardList, accounts, logoOptions };
} }
export async function fetchCardsForUser(userId: string): Promise<{ async function fetchCardsForUser(userId: string): Promise<{
cards: CardData[]; cards: CardData[];
accounts: AccountSimple[]; accounts: AccountSimple[];
logoOptions: string[]; logoOptions: string[];
@@ -129,7 +129,7 @@ export async function fetchCardsForUser(userId: string): Promise<{
return fetchCardsByStatus(userId, false); return fetchCardsByStatus(userId, false);
} }
export async function fetchInactiveForUser(userId: string): Promise<{ async function fetchInactiveForUser(userId: string): Promise<{
cards: CardData[]; cards: CardData[];
accounts: AccountSimple[]; accounts: AccountSimple[];
logoOptions: string[]; logoOptions: string[];

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import StatusDot from "@/shared/components/status-dot"; import StatusDot from "@/shared/components/feedback/status-dot";
export function TypeSelectContent({ label }: { label: string }) { export function TypeSelectContent({ label }: { label: string }) {
const isReceita = label === "Receita"; const isReceita = label === "Receita";

View File

@@ -3,7 +3,7 @@ import { type Category, categories } from "@/db/schema";
import type { CategoryType } from "@/shared/lib/categories/constants"; import type { CategoryType } from "@/shared/lib/categories/constants";
import { db } from "@/shared/lib/db"; import { db } from "@/shared/lib/db";
export type CategoryData = { type CategoryData = {
id: string; id: string;
name: string; name: string;
type: CategoryType; type: CategoryType;

View File

@@ -8,7 +8,7 @@ import {
} from "@/shared/utils/financial-dates"; } from "@/shared/utils/financial-dates";
export type BillDialogState = PaymentDialogState; export type BillDialogState = PaymentDialogState;
export type BillStatusDateItem = Pick< type BillStatusDateItem = Pick<
DashboardBill, DashboardBill,
"dueDate" | "boletoPaymentDate" | "isSettled" "dueDate" | "boletoPaymentDate" | "isSettled"
>; >;

View File

@@ -1,6 +1,6 @@
import { and, desc, eq, isNull, ne, or, sql } from "drizzle-orm"; import { and, desc, eq, isNull, ne, or, sql } from "drizzle-orm";
import { categories, financialAccounts, transactions } from "@/db/schema"; import { categories, financialAccounts, transactions } from "@/db/schema";
import { mapTransactionsData } from "@/features/transactions/page-helpers"; import { mapTransactionsData } from "@/features/transactions/lib/page-helpers";
import { import {
ACCOUNT_AUTO_INVOICE_NOTE_PREFIX, ACCOUNT_AUTO_INVOICE_NOTE_PREFIX,
INITIAL_BALANCE_NOTE, INITIAL_BALANCE_NOTE,
@@ -17,7 +17,7 @@ import { getPreviousPeriod } from "@/shared/utils/period";
type MappedLancamentos = ReturnType<typeof mapTransactionsData>; type MappedLancamentos = ReturnType<typeof mapTransactionsData>;
export type CategoryDetailData = { type CategoryDetailData = {
category: { category: {
id: string; id: string;
name: string; name: string;

View File

@@ -11,14 +11,14 @@ import {
formatPeriodMonthShort, formatPeriodMonthShort,
} from "@/shared/utils/period"; } from "@/shared/utils/period";
export type CategoryOption = { type CategoryOption = {
id: string; id: string;
name: string; name: string;
icon: string | null; icon: string | null;
type: "receita" | "despesa"; type: "receita" | "despesa";
}; };
export type CategoryHistoryItem = { type CategoryHistoryItem = {
id: string; id: string;
name: string; name: string;
icon: string | null; icon: string | null;

View File

@@ -22,7 +22,7 @@ import {
excludeInitialBalanceWhenConfigured, excludeInitialBalanceWhenConfigured,
excludeRefundEntries, excludeRefundEntries,
excludeTransactionsFromExcludedAccounts, excludeTransactionsFromExcludedAccounts,
} from "@/features/dashboard/transaction-filters"; } from "@/features/dashboard/lib/transaction-filters";
import { db } from "@/shared/lib/db"; import { db } from "@/shared/lib/db";
import { getAdminPayerId } from "@/shared/lib/payers/get-admin-id"; import { getAdminPayerId } from "@/shared/lib/payers/get-admin-id";
import { safeToNumber as toNumber } from "@/shared/utils/number"; import { safeToNumber as toNumber } from "@/shared/utils/number";

View File

@@ -1,10 +1,10 @@
export type CategoryOption = { type CategoryOption = {
id: string; id: string;
name: string; name: string;
type: string; type: string;
}; };
export type CategoryTransaction = { type CategoryTransaction = {
id: string; id: string;
name: string; name: string;
amount: number; amount: number;

View File

@@ -14,8 +14,8 @@ import type {
} from "@/features/dashboard/bills/bills-queries"; } from "@/features/dashboard/bills/bills-queries";
import { AccountCardSelectContent } from "@/features/transactions/components/select-items"; import { AccountCardSelectContent } from "@/features/transactions/components/select-items";
import { EstablishmentLogo } from "@/shared/components/entity-avatar"; import { EstablishmentLogo } from "@/shared/components/entity-avatar";
import { PaymentSuccess } from "@/shared/components/feedback/payment-success";
import MoneyValues from "@/shared/components/money-values"; import MoneyValues from "@/shared/components/money-values";
import { PaymentSuccess } from "@/shared/components/payment-success";
import { Badge } from "@/shared/components/ui/badge"; import { Badge } from "@/shared/components/ui/badge";
import { Button } from "@/shared/components/ui/button"; import { Button } from "@/shared/components/ui/button";
import { Card } from "@/shared/components/ui/card"; import { Card } from "@/shared/components/ui/card";

View File

@@ -1,6 +1,6 @@
import { RiBarcodeFill } from "@remixicon/react"; import { RiBarcodeFill } from "@remixicon/react";
import type { DashboardBill } from "@/features/dashboard/bills/bills-queries"; import type { DashboardBill } from "@/features/dashboard/bills/bills-queries";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { BillListItem } from "./bill-list-item"; import { BillListItem } from "./bill-list-item";
type BillsListProps = { type BillsListProps = {

View File

@@ -13,7 +13,7 @@ import {
TabsList, TabsList,
TabsTrigger, TabsTrigger,
} from "@/shared/components/ui/tabs"; } from "@/shared/components/ui/tabs";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { formatPeriodForUrl } from "@/shared/utils/period"; import { formatPeriodForUrl } from "@/shared/utils/period";
import { CategoryBreakdownChart } from "./category-breakdown-chart"; import { CategoryBreakdownChart } from "./category-breakdown-chart";
import { CategoryBreakdownList } from "./category-breakdown-list"; import { CategoryBreakdownList } from "./category-breakdown-list";

View File

@@ -40,8 +40,8 @@ import {
} from "@/features/dashboard/widget-registry/widget-config"; } from "@/features/dashboard/widget-registry/widget-config";
import { NoteDialog } from "@/features/notes/components/note-dialog"; import { NoteDialog } from "@/features/notes/components/note-dialog";
import { TransactionDialog } from "@/features/transactions/components/dialogs/transaction-dialog/transaction-dialog"; import { TransactionDialog } from "@/features/transactions/components/dialogs/transaction-dialog/transaction-dialog";
import { ExpandableWidgetCard } from "@/shared/components/expandable-widget-card";
import { Button } from "@/shared/components/ui/button"; import { Button } from "@/shared/components/ui/button";
import { ExpandableWidgetCard } from "@/shared/components/widgets/expandable-widget-card";
type DashboardGridEditableProps = { type DashboardGridEditableProps = {
data: DashboardData; data: DashboardData;

View File

@@ -1,6 +1,6 @@
import { RiFundsLine } from "@remixicon/react"; import { RiFundsLine } from "@remixicon/react";
import type { GoalProgressItem } from "@/features/dashboard/goals-progress/goals-progress-queries"; import type { GoalProgressItem } from "@/features/dashboard/goals-progress/goals-progress-queries";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { GoalProgressItem as GoalProgressListItem } from "./goals-progress-item"; import { GoalProgressItem as GoalProgressListItem } from "./goals-progress-item";
type GoalsProgressListProps = { type GoalsProgressListProps = {

View File

@@ -1,6 +1,6 @@
import { RiNumbersLine } from "@remixicon/react"; import { RiNumbersLine } from "@remixicon/react";
import type { InstallmentExpense } from "@/features/dashboard/expenses/installment-expenses-queries"; import type { InstallmentExpense } from "@/features/dashboard/expenses/installment-expenses-queries";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { InstallmentExpenseListItem } from "./installment-expense-list-item"; import { InstallmentExpenseListItem } from "./installment-expense-list-item";
type InstallmentExpensesListProps = { type InstallmentExpensesListProps = {

View File

@@ -14,8 +14,8 @@ import type {
InvoicePaymentAccountOption, InvoicePaymentAccountOption,
} from "@/features/dashboard/invoices/invoices-queries"; } from "@/features/dashboard/invoices/invoices-queries";
import { AccountCardSelectContent } from "@/features/transactions/components/select-items"; import { AccountCardSelectContent } from "@/features/transactions/components/select-items";
import { PaymentSuccess } from "@/shared/components/feedback/payment-success";
import MoneyValues from "@/shared/components/money-values"; import MoneyValues from "@/shared/components/money-values";
import { PaymentSuccess } from "@/shared/components/payment-success";
import { Badge } from "@/shared/components/ui/badge"; import { Badge } from "@/shared/components/ui/badge";
import { Button } from "@/shared/components/ui/button"; import { Button } from "@/shared/components/ui/button";
import { Card } from "@/shared/components/ui/card"; import { Card } from "@/shared/components/ui/card";

View File

@@ -1,6 +1,6 @@
import { RiBillLine } from "@remixicon/react"; import { RiBillLine } from "@remixicon/react";
import type { DashboardInvoice } from "@/features/dashboard/invoices/invoices-queries"; import type { DashboardInvoice } from "@/features/dashboard/invoices/invoices-queries";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { InvoiceListItem } from "./invoice-list-item"; import { InvoiceListItem } from "./invoice-list-item";
type InvoicesListProps = { type InvoicesListProps = {

View File

@@ -1,6 +1,6 @@
import { RiTodoLine } from "@remixicon/react"; import { RiTodoLine } from "@remixicon/react";
import type { Note } from "@/features/notes/components/types"; import type { Note } from "@/features/notes/components/types";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { NoteListItem } from "./note-list-item"; import { NoteListItem } from "./note-list-item";
type NotesListProps = { type NotesListProps = {

View File

@@ -1,5 +1,5 @@
import type { ReactNode } from "react"; import type { ReactNode } from "react";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { import {
PaymentBreakdownListItem, PaymentBreakdownListItem,
type PaymentBreakdownListItemData, type PaymentBreakdownListItemData,

View File

@@ -1,5 +1,5 @@
import StatusDot from "@/shared/components/feedback/status-dot";
import MoneyValues from "@/shared/components/money-values"; import MoneyValues from "@/shared/components/money-values";
import StatusDot from "@/shared/components/status-dot";
import { Progress } from "@/shared/components/ui/progress"; import { Progress } from "@/shared/components/ui/progress";
type PaymentStatusCategorySectionProps = { type PaymentStatusCategorySectionProps = {

View File

@@ -1,7 +1,7 @@
import { RiWallet3Line } from "@remixicon/react"; import { RiWallet3Line } from "@remixicon/react";
import type { PaymentStatusData } from "@/features/dashboard/payments/payment-status-queries"; import type { PaymentStatusData } from "@/features/dashboard/payments/payment-status-queries";
import { CardContent } from "@/shared/components/ui/card"; import { CardContent } from "@/shared/components/ui/card";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { PaymentStatusCategorySection } from "./payment-status-category-section"; import { PaymentStatusCategorySection } from "./payment-status-category-section";
type PaymentStatusWidgetViewProps = { type PaymentStatusWidgetViewProps = {

View File

@@ -6,7 +6,7 @@ import {
import { formatPercentage } from "@/shared/utils/percentage"; import { formatPercentage } from "@/shared/utils/percentage";
import { cn } from "@/shared/utils/ui"; import { cn } from "@/shared/utils/ui";
export type PercentageChangeTrend = "up" | "down" | "flat"; type PercentageChangeTrend = "up" | "down" | "flat";
type PercentageChangeIndicatorProps = { type PercentageChangeIndicatorProps = {
value?: number | null; value?: number | null;

View File

@@ -14,7 +14,7 @@ import {
TooltipContent, TooltipContent,
TooltipTrigger, TooltipTrigger,
} from "@/shared/components/ui/tooltip"; } from "@/shared/components/ui/tooltip";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { formatDateOnly } from "@/shared/utils/date"; import { formatDateOnly } from "@/shared/utils/date";
import { formatBytes } from "@/shared/utils/number"; import { formatBytes } from "@/shared/utils/number";

View File

@@ -26,7 +26,7 @@ import {
PopoverContent, PopoverContent,
PopoverTrigger, PopoverTrigger,
} from "@/shared/components/ui/popover"; } from "@/shared/components/ui/popover";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { CATEGORY_COLORS } from "@/shared/utils/category-colors"; import { CATEGORY_COLORS } from "@/shared/utils/category-colors";
import { formatCurrency, formatCurrencyCompact } from "@/shared/utils/currency"; import { formatCurrency, formatCurrencyCompact } from "@/shared/utils/currency";
import { getIconComponent } from "@/shared/utils/icons"; import { getIconComponent } from "@/shared/utils/icons";

View File

@@ -5,7 +5,7 @@ import type { DashboardCategoryBreakdownItem } from "@/features/dashboard/catego
import { PercentageChangeIndicator } from "@/features/dashboard/components/percentage-change-indicator"; import { PercentageChangeIndicator } from "@/features/dashboard/components/percentage-change-indicator";
import { CategoryIconBadge } from "@/shared/components/entity-avatar"; import { CategoryIconBadge } from "@/shared/components/entity-avatar";
import MoneyValues from "@/shared/components/money-values"; import MoneyValues from "@/shared/components/money-values";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { formatPercentage } from "@/shared/utils/percentage"; import { formatPercentage } from "@/shared/utils/percentage";
type CategoryTrendsWidgetProps = { type CategoryTrendsWidgetProps = {

View File

@@ -9,7 +9,7 @@ import Image from "next/image";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import type { DashboardInboxSnapshot } from "@/features/dashboard/inbox-snapshot-queries"; import type { DashboardInboxSnapshot } from "@/features/dashboard/lib/inbox-snapshot-queries";
import type { DashboardWidgetQuickActionOptions } from "@/features/dashboard/widget-registry/widget-config"; import type { DashboardWidgetQuickActionOptions } from "@/features/dashboard/widget-registry/widget-config";
import { import {
discardInboxItemAction, discardInboxItemAction,
@@ -19,7 +19,7 @@ import { TransactionDialog } from "@/features/transactions/components/dialogs/tr
import { ConfirmActionDialog } from "@/shared/components/confirm-action-dialog"; import { ConfirmActionDialog } from "@/shared/components/confirm-action-dialog";
import MoneyValues from "@/shared/components/money-values"; import MoneyValues from "@/shared/components/money-values";
import { Button } from "@/shared/components/ui/button"; import { Button } from "@/shared/components/ui/button";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { resolveLogoSrc } from "@/shared/lib/logo"; import { resolveLogoSrc } from "@/shared/lib/logo";
const DEFAULT_INBOX_APP_LOGO = "/avatars/default_icon.png"; const DEFAULT_INBOX_APP_LOGO = "/avatars/default_icon.png";

View File

@@ -9,7 +9,7 @@ import {
ChartContainer, ChartContainer,
ChartTooltip, ChartTooltip,
} from "@/shared/components/ui/chart"; } from "@/shared/components/ui/chart";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { formatCurrency } from "@/shared/utils/currency"; import { formatCurrency } from "@/shared/utils/currency";
type IncomeExpenseBalanceWidgetProps = { type IncomeExpenseBalanceWidgetProps = {

View File

@@ -10,7 +10,7 @@ import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import { useTransition } from "react"; import { useTransition } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import type { DashboardAccount } from "@/features/dashboard/accounts-queries"; import type { DashboardAccount } from "@/features/dashboard/lib/accounts-queries";
import { updateMyAccountsWidgetPreference } from "@/features/dashboard/widget-registry/widget-actions"; import { updateMyAccountsWidgetPreference } from "@/features/dashboard/widget-registry/widget-actions";
import MoneyValues from "@/shared/components/money-values"; import MoneyValues from "@/shared/components/money-values";
import { Badge } from "@/shared/components/ui/badge"; import { Badge } from "@/shared/components/ui/badge";
@@ -21,7 +21,7 @@ import {
TooltipContent, TooltipContent,
TooltipTrigger, TooltipTrigger,
} from "@/shared/components/ui/tooltip"; } from "@/shared/components/ui/tooltip";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { isAccountInactive } from "@/shared/lib/accounts/constants"; import { isAccountInactive } from "@/shared/lib/accounts/constants";
import { resolveLogoSrc } from "@/shared/lib/logo"; import { resolveLogoSrc } from "@/shared/lib/logo";
import { formatPeriodForUrl } from "@/shared/utils/period"; import { formatPeriodForUrl } from "@/shared/utils/period";

View File

@@ -7,14 +7,14 @@ import {
} from "@remixicon/react"; } from "@remixicon/react";
import Link from "next/link"; import Link from "next/link";
import { PercentageChangeIndicator } from "@/features/dashboard/components/percentage-change-indicator"; import { PercentageChangeIndicator } from "@/features/dashboard/components/percentage-change-indicator";
import type { DashboardPagador } from "@/features/dashboard/payers-queries"; import type { DashboardPagador } from "@/features/dashboard/lib/payers-queries";
import MoneyValues from "@/shared/components/money-values"; import MoneyValues from "@/shared/components/money-values";
import { import {
Avatar, Avatar,
AvatarFallback, AvatarFallback,
AvatarImage, AvatarImage,
} from "@/shared/components/ui/avatar"; } from "@/shared/components/ui/avatar";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { getAvatarSrc } from "@/shared/lib/payers/utils"; import { getAvatarSrc } from "@/shared/lib/payers/utils";
import { buildInitials } from "@/shared/utils/initials"; import { buildInitials } from "@/shared/utils/initials";

View File

@@ -12,7 +12,7 @@ import {
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from "@/shared/components/ui/select"; } from "@/shared/components/ui/select";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { CATEGORY_TYPE_LABEL } from "@/shared/lib/categories/constants"; import { CATEGORY_TYPE_LABEL } from "@/shared/lib/categories/constants";
import { formatTransactionDate } from "@/shared/utils/date"; import { formatTransactionDate } from "@/shared/utils/date";

View File

@@ -2,7 +2,7 @@ import { RiRefreshLine } from "@remixicon/react";
import type { RecurringExpensesData } from "@/features/dashboard/expenses/recurring-expenses-queries"; import type { RecurringExpensesData } from "@/features/dashboard/expenses/recurring-expenses-queries";
import { EstablishmentLogo } from "@/shared/components/entity-avatar"; import { EstablishmentLogo } from "@/shared/components/entity-avatar";
import MoneyValues from "@/shared/components/money-values"; import MoneyValues from "@/shared/components/money-values";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
type RecurringExpensesWidgetProps = { type RecurringExpensesWidgetProps = {
data: RecurringExpensesData; data: RecurringExpensesData;

View File

@@ -3,7 +3,7 @@
import { RiArrowUpDoubleLine, RiStore2Line } from "@remixicon/react"; import { RiArrowUpDoubleLine, RiStore2Line } from "@remixicon/react";
import { useState } from "react"; import { useState } from "react";
import type { TopExpensesData } from "@/features/dashboard/expenses/top-expenses-queries"; import type { TopExpensesData } from "@/features/dashboard/expenses/top-expenses-queries";
import type { TopEstablishmentsData } from "@/features/dashboard/top-establishments-queries"; import type { TopEstablishmentsData } from "@/features/dashboard/lib/top-establishments-queries";
import { import {
Tabs, Tabs,
TabsContent, TabsContent,

View File

@@ -1,8 +1,8 @@
import { RiStore2Line } from "@remixicon/react"; import { RiStore2Line } from "@remixicon/react";
import type { TopEstablishmentsData } from "@/features/dashboard/top-establishments-queries"; import type { TopEstablishmentsData } from "@/features/dashboard/lib/top-establishments-queries";
import { EstablishmentLogo } from "@/shared/components/entity-avatar"; import { EstablishmentLogo } from "@/shared/components/entity-avatar";
import MoneyValues from "@/shared/components/money-values"; import MoneyValues from "@/shared/components/money-values";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
type TopEstablishmentsWidgetProps = { type TopEstablishmentsWidgetProps = {
data: TopEstablishmentsData; data: TopEstablishmentsData;

View File

@@ -9,7 +9,7 @@ import type {
import { EstablishmentLogo } from "@/shared/components/entity-avatar"; import { EstablishmentLogo } from "@/shared/components/entity-avatar";
import MoneyValues from "@/shared/components/money-values"; import MoneyValues from "@/shared/components/money-values";
import { Switch } from "@/shared/components/ui/switch"; import { Switch } from "@/shared/components/ui/switch";
import { WidgetEmptyState } from "@/shared/components/widget-empty-state"; import { WidgetEmptyState } from "@/shared/components/widgets/widget-empty-state";
import { formatTransactionDate } from "@/shared/utils/date"; import { formatTransactionDate } from "@/shared/utils/date";
type TopExpensesWidgetProps = { type TopExpensesWidgetProps = {

View File

@@ -31,7 +31,7 @@ function calculateDueDate(period: string, dueDay: string | null): Date | null {
} }
} }
export type InstallmentDetail = { type InstallmentDetail = {
id: string; id: string;
currentInstallment: number; currentInstallment: number;
amount: number; amount: number;

View File

@@ -4,7 +4,7 @@ import {
formatLastInstallmentDate, formatLastInstallmentDate,
} from "@/shared/lib/installments/utils"; } from "@/shared/lib/installments/utils";
export type InstallmentExpenseDisplay = { type InstallmentExpenseDisplay = {
compactLabel: string | null; compactLabel: string | null;
isLast: boolean; isLast: boolean;
remainingInstallments: number; remainingInstallments: number;
@@ -13,7 +13,7 @@ export type InstallmentExpenseDisplay = {
progress: number; progress: number;
}; };
export const buildInstallmentCompactLabel = ( const buildInstallmentCompactLabel = (
currentInstallment: number | null, currentInstallment: number | null,
installmentCount: number | null, installmentCount: number | null,
) => { ) => {
@@ -24,7 +24,7 @@ export const buildInstallmentCompactLabel = (
return null; return null;
}; };
export const isInstallmentLast = ( const isInstallmentLast = (
currentInstallment: number | null, currentInstallment: number | null,
installmentCount: number | null, installmentCount: number | null,
) => { ) => {
@@ -35,7 +35,7 @@ export const isInstallmentLast = (
return currentInstallment === installmentCount && installmentCount > 1; return currentInstallment === installmentCount && installmentCount > 1;
}; };
export const calculateInstallmentRemainingCount = ( const calculateInstallmentRemainingCount = (
currentInstallment: number | null, currentInstallment: number | null,
installmentCount: number | null, installmentCount: number | null,
) => { ) => {
@@ -46,7 +46,7 @@ export const calculateInstallmentRemainingCount = (
return Math.max(0, installmentCount - currentInstallment); return Math.max(0, installmentCount - currentInstallment);
}; };
export const calculateInstallmentRemainingAmount = ( const calculateInstallmentRemainingAmount = (
amount: number, amount: number,
currentInstallment: number | null, currentInstallment: number | null,
installmentCount: number | null, installmentCount: number | null,
@@ -54,7 +54,7 @@ export const calculateInstallmentRemainingAmount = (
amount * amount *
calculateInstallmentRemainingCount(currentInstallment, installmentCount); calculateInstallmentRemainingCount(currentInstallment, installmentCount);
export const formatInstallmentEndDate = ( const formatInstallmentEndDate = (
period: string, period: string,
currentInstallment: number | null, currentInstallment: number | null,
installmentCount: number | null, installmentCount: number | null,
@@ -72,7 +72,7 @@ export const formatInstallmentEndDate = (
return formatLastInstallmentDate(lastDate); return formatLastInstallmentDate(lastDate);
}; };
export const buildInstallmentProgress = ( const buildInstallmentProgress = (
currentInstallment: number | null, currentInstallment: number | null,
installmentCount: number | null, installmentCount: number | null,
) => { ) => {

View File

@@ -1,4 +1,4 @@
export type RecurringExpense = { type RecurringExpense = {
id: string; id: string;
name: string; name: string;
amount: number; amount: number;

View File

@@ -1,13 +1,13 @@
import { cacheLife, cacheTag } from "next/cache"; import { cacheLife, cacheTag } from "next/cache";
import { fetchAttachmentsForPeriod } from "@/features/attachments/queries"; import { fetchAttachmentsForPeriod } from "@/features/attachments/queries";
import { fetchDashboardAccounts } from "./accounts-queries";
import { fetchDashboardCategoryOverview } from "./categories/category-overview-queries"; import { fetchDashboardCategoryOverview } from "./categories/category-overview-queries";
import { fetchDashboardInboxSnapshot } from "./inbox-snapshot-queries";
import { fetchDashboardInvoices } from "./invoices/invoices-queries"; import { fetchDashboardInvoices } from "./invoices/invoices-queries";
import { fetchDashboardAccounts } from "./lib/accounts-queries";
import { fetchDashboardInboxSnapshot } from "./lib/inbox-snapshot-queries";
import { fetchDashboardPayers } from "./lib/payers-queries";
import { fetchDashboardNotes } from "./notes/notes-queries"; import { fetchDashboardNotes } from "./notes/notes-queries";
import { fetchDashboardCurrentPeriodOverview } from "./overview/current-period-overview-queries"; import { fetchDashboardCurrentPeriodOverview } from "./overview/current-period-overview-queries";
import { fetchDashboardPeriodOverview } from "./overview/period-overview-queries"; import { fetchDashboardPeriodOverview } from "./overview/period-overview-queries";
import { fetchDashboardPayers } from "./payers-queries";
async function fetchDashboardDataInternal(userId: string, period: string) { async function fetchDashboardDataInternal(userId: string, period: string) {
const [ const [

View File

@@ -5,7 +5,6 @@ import type {
import type { import type {
GoalProgressCategory, GoalProgressCategory,
GoalProgressItem, GoalProgressItem,
GoalProgressStatus,
} from "@/features/dashboard/goals-progress/goals-progress-queries"; } from "@/features/dashboard/goals-progress/goals-progress-queries";
import { formatPercentage } from "@/shared/utils/percentage"; import { formatPercentage } from "@/shared/utils/percentage";
@@ -18,9 +17,6 @@ export const formatGoalProgressPercentage = (value: number, withSign = false) =>
signDisplay: withSign ? "always" : "auto", signDisplay: withSign ? "always" : "auto",
}); });
export const getGoalProgressStatusColorClass = (status: GoalProgressStatus) =>
status === "exceeded" ? "text-destructive" : "";
export const mapGoalProgressCategoriesToBudgetCategories = ( export const mapGoalProgressCategoriesToBudgetCategories = (
categories: GoalProgressCategory[], categories: GoalProgressCategory[],
): BudgetCategory[] => ): BudgetCategory[] =>

View File

@@ -1,4 +1,4 @@
export type GoalProgressStatus = "on-track" | "critical" | "exceeded"; type GoalProgressStatus = "on-track" | "critical" | "exceeded";
export type GoalProgressItem = { export type GoalProgressItem = {
id: string; id: string;

View File

@@ -55,7 +55,7 @@ type RawInvoiceBreakdownRow = {
amount: number | string | null; amount: number | string | null;
}; };
export type InvoicePagadorBreakdown = { type InvoicePagadorBreakdown = {
payerId: string | null; payerId: string | null;
pagadorName: string; pagadorName: string;
pagadorAvatar: string | null; pagadorAvatar: string | null;

View File

@@ -1,4 +1,4 @@
import type { DashboardData } from "./fetch-dashboard-data"; import type { DashboardData } from "../fetch-dashboard-data";
/** /**
* Coleta todos os nomes de estabelecimentos exibidos nos widgets do * Coleta todos os nomes de estabelecimentos exibidos nos widgets do

View File

@@ -3,7 +3,7 @@ import { cacheLife, cacheTag } from "next/cache";
import { cards, financialAccounts, inboxItems } from "@/db/schema"; import { cards, financialAccounts, inboxItems } from "@/db/schema";
import { db } from "@/shared/lib/db"; import { db } from "@/shared/lib/db";
export type DashboardInboxItem = { type DashboardInboxItem = {
id: string; id: string;
sourceAppName: string | null; sourceAppName: string | null;
parsedName: string | null; parsedName: string | null;

View File

@@ -8,11 +8,11 @@ import { getBusinessDateString } from "@/shared/utils/date";
import { import {
type DashboardNotificationsSnapshot, type DashboardNotificationsSnapshot,
fetchDashboardNotifications, fetchDashboardNotifications,
} from "./notifications/notifications-queries"; } from "../notifications/notifications-queries";
type DashboardNavbarData = { type DashboardNavbarData = {
pagadorAvatarUrl: string | null; payerAvatarUrl: string | null;
preLancamentosCount: number; inboxPendingCount: number;
notificationsSnapshot: DashboardNotificationsSnapshot; notificationsSnapshot: DashboardNotificationsSnapshot;
}; };
@@ -39,7 +39,7 @@ async function fetchDashboardNavbarDataInternal(
userId: string, userId: string,
): Promise<DashboardNavbarData> { ): Promise<DashboardNavbarData> {
const currentPeriod = getBusinessDateString().slice(0, 7); const currentPeriod = getBusinessDateString().slice(0, 7);
const [pagadorAvatarUrl, notificationsSnapshot, preLancamentosCount] = const [payerAvatarUrl, notificationsSnapshot, inboxPendingCount] =
await Promise.all([ await Promise.all([
fetchAdminPayerAvatarUrl(userId), fetchAdminPayerAvatarUrl(userId),
fetchDashboardNotifications(userId, currentPeriod), fetchDashboardNotifications(userId, currentPeriod),
@@ -47,8 +47,8 @@ async function fetchDashboardNavbarDataInternal(
]); ]);
return { return {
pagadorAvatarUrl, payerAvatarUrl,
preLancamentosCount, inboxPendingCount,
notificationsSnapshot, notificationsSnapshot,
}; };
} }

View File

@@ -1,6 +1,6 @@
import { and, desc, eq, inArray, isNull, or, sql } from "drizzle-orm"; import { and, desc, eq, inArray, isNull, or, sql } from "drizzle-orm";
import { financialAccounts, payers, transactions } from "@/db/schema"; import { financialAccounts, payers, transactions } from "@/db/schema";
import { excludeTransactionsFromExcludedAccounts } from "@/features/dashboard/transaction-filters"; import { excludeTransactionsFromExcludedAccounts } from "@/features/dashboard/lib/transaction-filters";
import { ACCOUNT_AUTO_INVOICE_NOTE_PREFIX } from "@/shared/lib/accounts/constants"; import { ACCOUNT_AUTO_INVOICE_NOTE_PREFIX } from "@/shared/lib/accounts/constants";
import { db } from "@/shared/lib/db"; import { db } from "@/shared/lib/db";
import { PAYER_ROLE_ADMIN } from "@/shared/lib/payers/constants"; import { PAYER_ROLE_ADMIN } from "@/shared/lib/payers/constants";

View File

@@ -1,4 +1,4 @@
export type TopEstablishment = { type TopEstablishment = {
id: string; id: string;
name: string; name: string;
amount: number; amount: number;

View File

@@ -1,7 +1,7 @@
import type { DashboardNote } from "@/features/dashboard/notes/notes-queries"; import type { DashboardNote } from "@/features/dashboard/notes/notes-queries";
import type { Note } from "@/features/notes/components/types"; import type { Note } from "@/features/notes/components/types";
export const mapDashboardNoteToNote = (note: DashboardNote): Note => ({ const mapDashboardNoteToNote = (note: DashboardNote): Note => ({
id: note.id, id: note.id,
title: note.title, title: note.title,
description: note.description, description: note.description,

View File

@@ -2,7 +2,7 @@ import { and, eq } from "drizzle-orm";
import { notes } from "@/db/schema"; import { notes } from "@/db/schema";
import { db } from "@/shared/lib/db"; import { db } from "@/shared/lib/db";
export type DashboardTask = { type DashboardTask = {
id: string; id: string;
text: string; text: string;
completed: boolean; completed: boolean;

View File

@@ -31,13 +31,7 @@ import {
getNextPeriod, getNextPeriod,
} from "@/shared/utils/period"; } from "@/shared/utils/period";
export type { export type { DashboardNotificationsSnapshot } from "@/shared/lib/types/notifications";
BudgetNotification,
BudgetStatus,
DashboardNotification,
DashboardNotificationsSnapshot,
NotificationType,
} from "@/shared/lib/types/notifications";
const PAYMENT_METHOD_BOLETO = "Boleto"; const PAYMENT_METHOD_BOLETO = "Boleto";
const BUDGET_CRITICAL_THRESHOLD = 80; const BUDGET_CRITICAL_THRESHOLD = 80;

View File

@@ -13,11 +13,11 @@ import type {
TopExpense, TopExpense,
TopExpensesData, TopExpensesData,
} from "@/features/dashboard/expenses/top-expenses-queries"; } from "@/features/dashboard/expenses/top-expenses-queries";
import type { TopEstablishmentsData } from "@/features/dashboard/lib/top-establishments-queries";
import { excludeTransactionsFromExcludedAccounts } from "@/features/dashboard/lib/transaction-filters";
import type { PaymentConditionsData } from "@/features/dashboard/payments/payment-conditions-queries"; import type { PaymentConditionsData } from "@/features/dashboard/payments/payment-conditions-queries";
import type { PaymentMethodsData } from "@/features/dashboard/payments/payment-methods-queries"; import type { PaymentMethodsData } from "@/features/dashboard/payments/payment-methods-queries";
import type { PaymentStatusData } from "@/features/dashboard/payments/payment-status-queries"; import type { PaymentStatusData } from "@/features/dashboard/payments/payment-status-queries";
import type { TopEstablishmentsData } from "@/features/dashboard/top-establishments-queries";
import { excludeTransactionsFromExcludedAccounts } from "@/features/dashboard/transaction-filters";
import { import {
ACCOUNT_AUTO_INVOICE_NOTE_PREFIX, ACCOUNT_AUTO_INVOICE_NOTE_PREFIX,
INITIAL_BALANCE_NOTE, INITIAL_BALANCE_NOTE,

View File

@@ -1,16 +1,16 @@
import { and, asc, eq, gte, inArray, lte, sql } from "drizzle-orm"; import { and, asc, eq, gte, inArray, lte, sql } from "drizzle-orm";
import { financialAccounts, transactions } from "@/db/schema"; import { financialAccounts, transactions } from "@/db/schema";
import type { DashboardCardMetrics } from "@/features/dashboard/overview/dashboard-metrics-queries";
import type {
IncomeExpenseBalanceData,
MonthData,
} from "@/features/dashboard/overview/income-expense-balance-queries";
import { import {
buildDashboardAdminFilters, buildDashboardAdminFilters,
excludeAutoInvoiceEntries, excludeAutoInvoiceEntries,
excludeInitialBalanceWhenConfigured, excludeInitialBalanceWhenConfigured,
excludeTransactionsFromExcludedAccounts, excludeTransactionsFromExcludedAccounts,
} from "@/features/dashboard/transaction-filters"; } from "@/features/dashboard/lib/transaction-filters";
import type { DashboardCardMetrics } from "@/features/dashboard/overview/dashboard-metrics-queries";
import type {
IncomeExpenseBalanceData,
MonthData,
} from "@/features/dashboard/overview/income-expense-balance-queries";
import { REFUND_NOTE_PREFIX } from "@/shared/lib/accounts/constants"; import { REFUND_NOTE_PREFIX } from "@/shared/lib/accounts/constants";
import { db } from "@/shared/lib/db"; import { db } from "@/shared/lib/db";
import { getAdminPayerId } from "@/shared/lib/payers/get-admin-id"; import { getAdminPayerId } from "@/shared/lib/payers/get-admin-id";

View File

@@ -1,10 +1,10 @@
import { cacheLife, cacheTag } from "next/cache"; import { cacheLife, cacheTag } from "next/cache";
import { fetchDashboardData } from "@/features/dashboard/fetch-dashboard-data"; import { fetchDashboardData } from "@/features/dashboard/fetch-dashboard-data";
import { fetchUserDashboardPreferences } from "@/features/dashboard/preferences-queries"; import { fetchUserDashboardPreferences } from "@/features/dashboard/lib/preferences-queries";
import { import {
buildOptionSets, buildOptionSets,
buildSluggedFilters, buildSluggedFilters,
} from "@/features/transactions/page-helpers"; } from "@/features/transactions/lib/page-helpers";
import { import {
fetchRecentEstablishments, fetchRecentEstablishments,
fetchTransactionFilterSources, fetchTransactionFilterSources,
@@ -52,7 +52,7 @@ async function fetchDashboardQuickActionOptionsInternal(
}; };
} }
export async function fetchDashboardQuickActionOptions(userId: string) { async function fetchDashboardQuickActionOptions(userId: string) {
"use cache"; "use cache";
cacheTag(`dashboard-${userId}`); cacheTag(`dashboard-${userId}`);
cacheLife({ revalidate: 3 }); cacheLife({ revalidate: 3 });

View File

@@ -1,4 +1,4 @@
export type PaymentConditionSummary = { type PaymentConditionSummary = {
condition: string; condition: string;
amount: number; amount: number;
percentage: number; percentage: number;

View File

@@ -1,4 +1,4 @@
export type PaymentMethodSummary = { type PaymentMethodSummary = {
paymentMethod: string; paymentMethod: string;
amount: number; amount: number;
percentage: number; percentage: number;

View File

@@ -1,4 +1,4 @@
export type PaymentStatusCategory = { type PaymentStatusCategory = {
total: number; total: number;
confirmed: number; confirmed: number;
pending: number; pending: number;

View File

@@ -1,7 +1,7 @@
import { RiAtLine, RiCalendarEventLine } from "@remixicon/react"; import { RiAtLine, RiCalendarEventLine } from "@remixicon/react";
import { format } from "date-fns"; import { format } from "date-fns";
import { ptBR } from "date-fns/locale"; import { ptBR } from "date-fns/locale";
import { EmptyState } from "@/shared/components/empty-state"; import { EmptyState } from "@/shared/components/feedback/empty-state";
import { Card } from "@/shared/components/ui/card"; import { Card } from "@/shared/components/ui/card";
import { InboxCard } from "./inbox-card"; import { InboxCard } from "./inbox-card";
import type { InboxItem } from "./types"; import type { InboxItem } from "./types";

View File

@@ -4,10 +4,7 @@ import {
RiArrowRightDoubleLine, RiArrowRightDoubleLine,
RiArrowRightSLine, RiArrowRightSLine,
} from "@remixicon/react"; } from "@remixicon/react";
import { import { INBOX_PAGE_SIZE_OPTIONS } from "@/features/inbox/page-helpers";
INBOX_DEFAULT_PAGE_SIZE,
INBOX_PAGE_SIZE_OPTIONS,
} from "@/features/inbox/page-helpers";
import { Button } from "@/shared/components/ui/button"; import { Button } from "@/shared/components/ui/button";
import { import {
Select, Select,
@@ -117,6 +114,3 @@ export function InboxPagination({
</div> </div>
); );
} }
// Re-export para facilitar uso externo
export { INBOX_DEFAULT_PAGE_SIZE };

View File

@@ -1,5 +1,5 @@
import { TabsList, TabsTrigger } from "@/shared/components/ui/tabs"; import { TabsList, TabsTrigger } from "@/shared/components/ui/tabs";
import type { InboxStatus, InboxStatusCounts } from "./types"; import type { InboxStatusCounts } from "./types";
type InboxTabsProps = { type InboxTabsProps = {
counts: InboxStatusCounts; counts: InboxStatusCounts;
@@ -36,5 +36,3 @@ export function InboxTabs({ counts, isPending }: InboxTabsProps) {
</TabsList> </TabsList>
); );
} }
export type { InboxStatus, InboxStatusCounts };

View File

@@ -1,4 +1,4 @@
import type { SelectOption as LancamentoSelectOption } from "@/features/transactions/components/types"; import type { SelectOption as TransactionSelectOption } from "@/features/transactions/components/types";
export type InboxStatus = "pending" | "processed" | "discarded"; export type InboxStatus = "pending" | "processed" | "discarded";
@@ -29,4 +29,4 @@ export type InboxPaginationState = {
}; };
// Re-export the lancamentos SelectOption for use in inbox components // Re-export the lancamentos SelectOption for use in inbox components
export type SelectOption = LancamentoSelectOption; export type SelectOption = TransactionSelectOption;

View File

@@ -7,9 +7,9 @@ export type ResolvedInboxSearchParams =
export const INBOX_DEFAULT_PAGE_SIZE = 12; export const INBOX_DEFAULT_PAGE_SIZE = 12;
export const INBOX_PAGE_SIZE_OPTIONS = [12, 24, 48]; export const INBOX_PAGE_SIZE_OPTIONS = [12, 24, 48];
export const INBOX_STATUSES = ["pending", "processed", "discarded"] as const; const INBOX_STATUSES = ["pending", "processed", "discarded"] as const;
export const getSingleParam = ( const getSingleParam = (
params: ResolvedInboxSearchParams, params: ResolvedInboxSearchParams,
key: string, key: string,
): string | null => { ): string | null => {

View File

@@ -1,5 +1,5 @@
import { and, count, desc, eq } from "drizzle-orm"; import { and, count, desc, eq } from "drizzle-orm";
import { cards, categories, financialAccounts, inboxItems } from "@/db/schema"; import { cards, financialAccounts, inboxItems } from "@/db/schema";
import type { import type {
InboxItem, InboxItem,
InboxPaginationState, InboxPaginationState,
@@ -10,29 +10,13 @@ import type {
import { import {
buildOptionSets, buildOptionSets,
buildSluggedFilters, buildSluggedFilters,
} from "@/features/transactions/page-helpers"; } from "@/features/transactions/lib/page-helpers";
import { import {
fetchRecentEstablishments, fetchRecentEstablishments,
fetchTransactionFilterSources, fetchTransactionFilterSources,
} from "@/features/transactions/queries"; } from "@/features/transactions/queries";
import { db } from "@/shared/lib/db"; import { db } from "@/shared/lib/db";
export async function fetchInboxItems(
userId: string,
status: InboxStatus = "pending",
): Promise<InboxItem[]> {
const items = await db
.select()
.from(inboxItems)
.where(and(eq(inboxItems.userId, userId), eq(inboxItems.status, status)))
.orderBy(
desc(inboxItems.notificationTimestamp),
desc(inboxItems.createdAt),
);
return items;
}
export async function fetchInboxItemsPage( export async function fetchInboxItemsPage(
userId: string, userId: string,
status: InboxStatus, status: InboxStatus,
@@ -126,65 +110,6 @@ export async function fetchInboxStatusCounts(
return counts; return counts;
} }
export async function fetchInboxItemById(
userId: string,
itemId: string,
): Promise<InboxItem | null> {
const [item] = await db
.select()
.from(inboxItems)
.where(and(eq(inboxItems.id, itemId), eq(inboxItems.userId, userId)))
.limit(1);
return item ?? null;
}
export async function fetchCategoriesForSelect(
userId: string,
type?: string,
): Promise<SelectOption[]> {
const rows = await db
.select({ id: categories.id, name: categories.name })
.from(categories)
.where(
type
? and(eq(categories.userId, userId), eq(categories.type, type))
: eq(categories.userId, userId),
)
.orderBy(categories.name);
return rows.map((row) => ({ value: row.id, label: row.name }));
}
export async function fetchAccountsForSelect(
userId: string,
): Promise<SelectOption[]> {
const rows = await db
.select({ id: financialAccounts.id, name: financialAccounts.name })
.from(financialAccounts)
.where(
and(
eq(financialAccounts.userId, userId),
eq(financialAccounts.status, "ativo"),
),
)
.orderBy(financialAccounts.name);
return rows.map((row) => ({ value: row.id, label: row.name }));
}
export async function fetchCardsForSelect(
userId: string,
): Promise<(SelectOption & { lastDigits?: string })[]> {
const rows = await db
.select({ id: cards.id, name: cards.name })
.from(cards)
.where(and(eq(cards.userId, userId), eq(cards.status, "ativo")))
.orderBy(cards.name);
return rows.map((row) => ({ value: row.id, label: row.name }));
}
export async function fetchAppLogoMap( export async function fetchAppLogoMap(
userId: string, userId: string,
): Promise<Record<string, string>> { ): Promise<Record<string, string>> {

View File

@@ -1,32 +1,5 @@
"use server"; export { generateInsightsAction } from "./actions/generate";
export {
import { generateInsightsAction as generateInsightsActionImpl } from "./actions/generate"; deleteSavedInsightsAction,
import { saveInsightsAction,
deleteSavedInsightsAction as deleteSavedInsightsActionImpl,
loadSavedInsightsAction as loadSavedInsightsActionImpl,
saveInsightsAction as saveInsightsActionImpl,
} from "./actions/storage"; } from "./actions/storage";
export async function generateInsightsAction(
...args: Parameters<typeof generateInsightsActionImpl>
): ReturnType<typeof generateInsightsActionImpl> {
return generateInsightsActionImpl(...args);
}
export async function saveInsightsAction(
...args: Parameters<typeof saveInsightsActionImpl>
): ReturnType<typeof saveInsightsActionImpl> {
return saveInsightsActionImpl(...args);
}
export async function loadSavedInsightsAction(
...args: Parameters<typeof loadSavedInsightsActionImpl>
): ReturnType<typeof loadSavedInsightsActionImpl> {
return loadSavedInsightsActionImpl(...args);
}
export async function deleteSavedInsightsAction(
...args: Parameters<typeof deleteSavedInsightsActionImpl>
): ReturnType<typeof deleteSavedInsightsActionImpl> {
return deleteSavedInsightsActionImpl(...args);
}

View File

@@ -5,10 +5,7 @@ import { z } from "zod";
import { savedInsights } from "@/db/schema"; import { savedInsights } from "@/db/schema";
import { getUser } from "@/shared/lib/auth/server"; import { getUser } from "@/shared/lib/auth/server";
import { db } from "@/shared/lib/db"; import { db } from "@/shared/lib/db";
import { import type { InsightsResponse } from "@/shared/lib/schemas/insights";
type InsightsResponse,
InsightsResponseSchema,
} from "@/shared/lib/schemas/insights";
import type { ActionResult } from "./types"; import type { ActionResult } from "./types";
const periodSchema = z const periodSchema = z
@@ -115,62 +112,6 @@ export async function saveInsightsAction(
} }
} }
export async function loadSavedInsightsAction(period: string): Promise<
ActionResult<{
insights: InsightsResponse;
modelId: string;
createdAt: Date;
} | null>
> {
try {
const user = await getUser();
const validatedPeriod = periodSchema.safeParse(period);
if (!validatedPeriod.success) {
return {
success: false,
error: validatedPeriod.error.issues[0]?.message ?? "Período inválido",
};
}
period = validatedPeriod.data;
const result = await db
.select()
.from(savedInsights)
.where(
and(
eq(savedInsights.userId, user.id),
eq(savedInsights.period, period),
),
)
.limit(1);
if (result.length === 0) {
return {
success: true,
data: null,
};
}
const saved = result[0];
const insights = InsightsResponseSchema.parse(JSON.parse(saved.data));
return {
success: true,
data: {
insights,
modelId: saved.modelId,
createdAt: saved.createdAt,
},
};
} catch (error) {
console.error("Error loading saved insights:", error);
return {
success: false,
error: "Erro ao carregar análise salva. Tente novamente.",
};
}
}
export async function deleteSavedInsightsAction( export async function deleteSavedInsightsAction(
period: string, period: string,
): Promise<ActionResult<void>> { ): Promise<ActionResult<void>> {

View File

@@ -21,7 +21,7 @@ import {
savedInsightsQueryKey, savedInsightsQueryKey,
useSavedInsights, useSavedInsights,
} from "@/features/insights/hooks/use-saved-insights"; } from "@/features/insights/hooks/use-saved-insights";
import { EmptyState } from "@/shared/components/empty-state"; import { EmptyState } from "@/shared/components/feedback/empty-state";
import { Alert, AlertDescription } from "@/shared/components/ui/alert"; import { Alert, AlertDescription } from "@/shared/components/ui/alert";
import { Button } from "@/shared/components/ui/button"; import { Button } from "@/shared/components/ui/button";
import { Card, CardContent, CardHeader } from "@/shared/components/ui/card"; import { Card, CardContent, CardHeader } from "@/shared/components/ui/card";

Some files were not shown because too many files have changed in this diff Show More