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

@@ -1,76 +1,14 @@
"use server";
import {
createMassTransactionsAction as createMassTransactionsActionImpl,
deleteMultipleTransactionsAction as deleteMultipleTransactionsActionImpl,
deleteTransactionBulkAction as deleteTransactionBulkActionImpl,
updateTransactionBulkAction as updateTransactionBulkActionImpl,
export {
createMassTransactionsAction,
deleteMultipleTransactionsAction,
deleteTransactionBulkAction,
updateTransactionBulkAction,
} from "./actions/bulk-actions";
import { exportTransactionsDataAction as exportTransactionsDataActionImpl } from "./actions/export-actions";
import {
createTransactionAction as createTransactionActionImpl,
deleteTransactionAction as deleteTransactionActionImpl,
toggleTransactionSettlementAction as toggleTransactionSettlementActionImpl,
updateTransactionAction as updateTransactionActionImpl,
updateTransactionSplitPairAction as updateTransactionSplitPairActionImpl,
export { exportTransactionsDataAction } from "./actions/export-actions";
export {
createTransactionAction,
deleteTransactionAction,
toggleTransactionSettlementAction,
updateTransactionAction,
updateTransactionSplitPairAction,
} from "./actions/single-actions";
export async function createTransactionAction(
...args: Parameters<typeof createTransactionActionImpl>
): ReturnType<typeof createTransactionActionImpl> {
return createTransactionActionImpl(...args);
}
export async function updateTransactionAction(
...args: Parameters<typeof updateTransactionActionImpl>
): ReturnType<typeof updateTransactionActionImpl> {
return updateTransactionActionImpl(...args);
}
export async function deleteTransactionAction(
...args: Parameters<typeof deleteTransactionActionImpl>
): ReturnType<typeof deleteTransactionActionImpl> {
return deleteTransactionActionImpl(...args);
}
export async function toggleTransactionSettlementAction(
...args: Parameters<typeof toggleTransactionSettlementActionImpl>
): ReturnType<typeof toggleTransactionSettlementActionImpl> {
return toggleTransactionSettlementActionImpl(...args);
}
export async function deleteTransactionBulkAction(
...args: Parameters<typeof deleteTransactionBulkActionImpl>
): ReturnType<typeof deleteTransactionBulkActionImpl> {
return deleteTransactionBulkActionImpl(...args);
}
export async function updateTransactionBulkAction(
...args: Parameters<typeof updateTransactionBulkActionImpl>
): ReturnType<typeof updateTransactionBulkActionImpl> {
return updateTransactionBulkActionImpl(...args);
}
export async function createMassTransactionsAction(
...args: Parameters<typeof createMassTransactionsActionImpl>
): ReturnType<typeof createMassTransactionsActionImpl> {
return createMassTransactionsActionImpl(...args);
}
export async function deleteMultipleTransactionsAction(
...args: Parameters<typeof deleteMultipleTransactionsActionImpl>
): ReturnType<typeof deleteMultipleTransactionsActionImpl> {
return deleteMultipleTransactionsActionImpl(...args);
}
export async function updateTransactionSplitPairAction(
...args: Parameters<typeof updateTransactionSplitPairActionImpl>
): ReturnType<typeof updateTransactionSplitPairActionImpl> {
return updateTransactionSplitPairActionImpl(...args);
}
export async function exportTransactionsDataAction(
...args: Parameters<typeof exportTransactionsDataActionImpl>
): ReturnType<typeof exportTransactionsDataActionImpl> {
return exportTransactionsDataActionImpl(...args);
}

View File

@@ -1,6 +1,6 @@
"use server";
import { and, asc, desc, eq, inArray, isNull, or } from "drizzle-orm";
import { and, asc, eq, inArray, isNull, or } from "drizzle-orm";
import { z } from "zod";
import {
categories,
@@ -22,7 +22,6 @@ import type {
CancelAnticipationInput,
CreateAnticipationInput,
EligibleInstallment,
InstallmentAnticipationWithRelations,
} from "@/shared/lib/installments/anticipation-types";
import { uuidSchema } from "@/shared/lib/schemas/common";
import type { ActionResult } from "@/shared/lib/types/actions";
@@ -326,71 +325,6 @@ export async function createInstallmentAnticipationAction(
}
}
/**
* Busca histórico de antecipações de uma série
*/
export async function getInstallmentAnticipationsAction(
seriesId: string,
): Promise<ActionResult<InstallmentAnticipationWithRelations[]>> {
try {
const user = await getUser();
// Validar seriesId
const validatedSeriesId = uuidSchema("Série").parse(seriesId);
// Usar query builder ao invés de db.query para evitar problemas de tipagem
const anticipations = await db
.select({
id: installmentAnticipations.id,
seriesId: installmentAnticipations.seriesId,
anticipationPeriod: installmentAnticipations.anticipationPeriod,
anticipationDate: installmentAnticipations.anticipationDate,
anticipatedInstallmentIds:
installmentAnticipations.anticipatedInstallmentIds,
totalAmount: installmentAnticipations.totalAmount,
installmentCount: installmentAnticipations.installmentCount,
discount: installmentAnticipations.discount,
transactionId: installmentAnticipations.transactionId,
payerId: installmentAnticipations.payerId,
categoryId: installmentAnticipations.categoryId,
note: installmentAnticipations.note,
userId: installmentAnticipations.userId,
createdAt: installmentAnticipations.createdAt,
// Joins
transaction: transactions,
payer: payers,
category: categories,
})
.from(installmentAnticipations)
.leftJoin(
transactions,
eq(installmentAnticipations.transactionId, transactions.id),
)
.leftJoin(payers, eq(installmentAnticipations.payerId, payers.id))
.leftJoin(
categories,
eq(installmentAnticipations.categoryId, categories.id),
)
.where(
and(
eq(installmentAnticipations.seriesId, validatedSeriesId),
eq(installmentAnticipations.userId, user.id),
),
)
.orderBy(desc(installmentAnticipations.createdAt));
return {
success: true,
message: "Antecipações carregadas.",
data: anticipations,
};
} catch (error) {
return handleActionError(error) as ActionResult<
InstallmentAnticipationWithRelations[]
>;
}
}
/**
* Cancela uma antecipação de parcelas
* Remove o lançamento de antecipação e restaura as parcelas originais
@@ -503,46 +437,3 @@ export async function cancelInstallmentAnticipationAction(
return handleActionError(error);
}
}
/**
* Busca detalhes de uma antecipação específica
*/
export async function getAnticipationDetailsAction(
anticipationId: string,
): Promise<ActionResult<InstallmentAnticipationWithRelations>> {
try {
const user = await getUser();
// Validar anticipationId
const validatedId = uuidSchema("Antecipação").parse(anticipationId);
const anticipation = await db.query.installmentAnticipations.findFirst({
where: and(
eq(installmentAnticipations.id, validatedId),
eq(installmentAnticipations.userId, user.id),
),
with: {
transaction: true,
payer: true,
category: true,
},
});
if (!anticipation) {
return {
success: false,
error: "Antecipação não encontrada.",
};
}
return {
success: true,
message: "Detalhes da antecipação carregados.",
data: anticipation,
};
} catch (error) {
return handleActionError(
error,
) as ActionResult<InstallmentAnticipationWithRelations>;
}
}

View File

@@ -7,7 +7,7 @@ import { attachments, transactionAttachments, transactions } from "@/db/schema";
import {
ALLOWED_MIME_TYPES,
MAX_FILE_SIZE,
} from "@/features/transactions/attachments-config";
} from "@/features/transactions/lib/attachments-config";
import {
handleActionError,
revalidateForEntity,

View File

@@ -6,7 +6,7 @@ import {
PAYMENT_METHODS,
TRANSACTION_CONDITIONS,
TRANSACTION_TYPES,
} from "@/features/transactions/constants";
} from "@/features/transactions/lib/constants";
import { handleActionError } from "@/shared/lib/actions/helpers";
import { getUser } from "@/shared/lib/auth/server";
import { db } from "@/shared/lib/db";
@@ -705,7 +705,7 @@ export async function createMassTransactionsAction(
await sendPayerAutoEmails({
userLabel: resolveUserLabel(user),
action: "created",
entriesByPagador: notificationEntries,
entriesByPayer: notificationEntries,
});
}
@@ -799,7 +799,7 @@ export async function deleteMultipleTransactionsAction(
await sendPayerAutoEmails({
userLabel: resolveUserLabel(user),
action: "deleted",
entriesByPagador: notificationEntries,
entriesByPayer: notificationEntries,
});
}

View File

@@ -13,7 +13,7 @@ import {
PAYMENT_METHODS,
TRANSACTION_CONDITIONS,
TRANSACTION_TYPES,
} from "@/features/transactions/constants";
} from "@/features/transactions/lib/constants";
import {
INITIAL_BALANCE_CONDITION,
INITIAL_BALANCE_NOTE,
@@ -31,7 +31,7 @@ import { addMonthsToPeriod, MONTH_NAMES } from "@/shared/utils/period";
// Authorization Validation Functions
// ============================================================================
export async function validatePagadorOwnership(
export async function validatePayerOwnership(
userId: string,
payerId: string | null | undefined,
): Promise<boolean> {
@@ -65,19 +65,6 @@ export async function fetchOwnedPayerIds(
return new Set(rows.map((row) => row.id));
}
export async function validateCategoriaOwnership(
userId: string,
categoryId: string | null | undefined,
): Promise<boolean> {
if (!categoryId) return true;
const categoria = await db.query.categories.findFirst({
where: and(eq(categories.id, categoryId), eq(categories.userId, userId)),
});
return !!categoria;
}
export async function fetchOwnedCategoryIds(
userId: string,
categoryIds: Array<string | null | undefined>,
@@ -298,10 +285,10 @@ export const resolvePeriod = (purchaseDate: string, period?: string | null) => {
return `${year}-${month}`;
};
export const isValidDateInput = (value: string) =>
const isValidDateInput = (value: string) =>
!Number.isNaN(parseLocalDateString(value).getTime());
export const baseFields = z.object({
const baseFields = z.object({
purchaseDate: z
.string({ message: "Informe a data da transação." })
.trim()
@@ -498,7 +485,7 @@ export const toggleSettlementSchema = z.object({
.optional(),
});
export type BaseInput = z.infer<typeof baseFields>;
type BaseInput = z.infer<typeof baseFields>;
export type CreateInput = z.infer<typeof createSchema>;
export type UpdateInput = z.infer<typeof updateSchema>;
export type DeleteInput = z.infer<typeof deleteSchema>;
@@ -527,7 +514,7 @@ type InitialCandidate = {
paymentMethod: string | null;
};
export const isInitialBalanceLancamento = (record?: InitialCandidate | null) =>
export const isInitialBalanceTransaction = (record?: InitialCandidate | null) =>
!!record &&
record.note === INITIAL_BALANCE_NOTE &&
record.transactionType === INITIAL_BALANCE_TRANSACTION_TYPE &&
@@ -554,7 +541,7 @@ const splitAmount = (totalCents: number, parts: number) => {
);
};
export type Share = {
type Share = {
payerId: string | null;
amountCents: number;
};
@@ -617,7 +604,7 @@ type BuildTransactionRecordsParams = {
export type TransactionInsert = typeof transactions.$inferInsert;
export const buildLancamentoRecords = ({
export const buildTransactionRecords = ({
data,
userId,
period,
@@ -859,7 +846,7 @@ export const updateBulkSchema = z.object({
export type UpdateBulkInput = z.infer<typeof updateBulkSchema>;
export const massAddTransactionSchema = z.object({
const massAddTransactionSchema = z.object({
purchaseDate: z
.string({ message: "Informe a data da transação." })
.trim()

View File

@@ -1,14 +1,14 @@
"use server";
import { z } from "zod";
import { fetchAccountLancamentos } from "@/features/accounts/statement-queries";
import type { TransactionsExportContext } from "@/features/transactions/export-types";
import { fetchAccountTransactions } from "@/features/accounts/statement-queries";
import type { TransactionsExportContext } from "@/features/transactions/lib/export-types";
import {
buildSluggedFilters,
buildSlugMaps,
buildTransactionWhere,
mapTransactionsData,
} from "@/features/transactions/page-helpers";
} from "@/features/transactions/lib/page-helpers";
import {
fetchTransactionFilterSources,
fetchTransactions,
@@ -66,7 +66,7 @@ export async function exportTransactionsDataAction(
const rows =
validated.source === "account-statement"
? await fetchAccountLancamentos(filters, validated.settledOnly ?? true)
? await fetchAccountTransactions(filters, validated.settledOnly ?? true)
: await fetchTransactions(filters);
return {

View File

@@ -2,7 +2,7 @@
import { eq } from "drizzle-orm";
import { transactions } from "@/db/schema";
import { mapTransactionsData } from "@/features/transactions/page-helpers";
import { mapTransactionsData } from "@/features/transactions/lib/page-helpers";
import { fetchTransactionsWithRelations } from "@/features/transactions/queries";
import { getUser } from "@/shared/lib/auth/server";
import type { TransactionItem } from "../components/types";

View File

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

View File

@@ -6,7 +6,7 @@ import { transactions } from "@/db/schema";
import {
validateCartaoOwnership,
validateContaOwnership,
validatePagadorOwnership,
validatePayerOwnership,
} from "@/features/transactions/actions/core";
import { revalidateForEntity } from "@/shared/lib/actions/helpers";
import { getUserId } from "@/shared/lib/auth/server";
@@ -36,8 +36,7 @@ const importSchema = z.object({
.optional(),
});
export type ImportRow = z.infer<typeof importRowSchema>;
export type ImportInput = z.infer<typeof importSchema>;
type ImportInput = z.infer<typeof importSchema>;
type ImportResult =
| { success: true; imported: number; skipped: number; importBatchId: string }
@@ -79,7 +78,7 @@ export async function importTransactionsAction(
// Valida ownership
const [payerOk, accountOk, cardOk] = await Promise.all([
validatePagadorOwnership(userId, payerId),
validatePayerOwnership(userId, payerId),
validateContaOwnership(userId, accountId),
validateCartaoOwnership(userId, cardId),
]);

View File

@@ -21,11 +21,11 @@ import {
getBusinessTodayDate,
parseLocalDateString,
} from "@/shared/utils/date";
import { copyAttachmentsForImport } from "../attachment-copy";
import { copyAttachmentsForImport } from "../lib/attachment-copy";
import { cleanupAttachmentsAfterTransactionDelete } from "./attachments";
import {
buildLancamentoRecords,
buildShares,
buildTransactionRecords,
type CreateInput,
centsToDecimalString,
createSchema,
@@ -33,7 +33,7 @@ import {
deleteSchema,
formatPaidInvoicePeriods,
getPaidInvoicePeriods,
isInitialBalanceLancamento,
isInitialBalanceTransaction,
resolvePeriod,
resolveUserLabel,
revalidate,
@@ -95,7 +95,7 @@ export async function createTransactionAction(
data.condition === "Parcelado" || data.condition === "Recorrente";
const seriesId = isSeriesLancamento ? randomUUID() : null;
const records = buildLancamentoRecords({
const records = buildTransactionRecords({
data,
userId: user.id,
period,
@@ -180,7 +180,7 @@ export async function createTransactionAction(
await sendPayerAutoEmails({
userLabel: resolveUserLabel(user),
action: "created",
entriesByPagador: notificationEntries,
entriesByPayer: notificationEntries,
});
}
@@ -343,7 +343,7 @@ export async function updateTransactionAction(
and(eq(transactions.id, data.id), eq(transactions.userId, user.id)),
);
if (isInitialBalanceLancamento(existing) && existing.accountId) {
if (isInitialBalanceTransaction(existing) && existing.accountId) {
const updatedInitialBalance = formatDecimalForDbRequired(
Math.abs(data.amount ?? 0),
);
@@ -465,7 +465,7 @@ export async function deleteTransactionAction(
await sendPayerAutoEmails({
userLabel: resolveUserLabel(user),
action: "deleted",
entriesByPagador: notificationEntries,
entriesByPayer: notificationEntries,
});
}

View File

@@ -6,7 +6,7 @@ import { toast } from "sonner";
import {
ALLOWED_MIME_TYPES,
DEFAULT_MAX_FILE_SIZE_MB,
} from "@/features/transactions/attachments-config";
} from "@/features/transactions/lib/attachments-config";
import { Button } from "@/shared/components/ui/button";
interface AttachmentFilePickerProps {

View File

@@ -10,7 +10,7 @@ import {
import {
ALLOWED_MIME_TYPES,
DEFAULT_MAX_FILE_SIZE_MB,
} from "@/features/transactions/attachments-config";
} from "@/features/transactions/lib/attachments-config";
interface AttachmentUploadProps {
transactionId: string;

View File

@@ -7,7 +7,7 @@ import { CategoryIcon } from "@/features/categories/components/category-icon";
import {
createInstallmentAnticipationAction,
getEligibleInstallmentsAction,
} from "@/features/transactions/anticipation-actions";
} from "@/features/transactions/actions/anticipation";
import MoneyValues from "@/shared/components/money-values";
import { PeriodPicker } from "@/shared/components/period-picker";
import { Button } from "@/shared/components/ui/button";

View File

@@ -3,7 +3,7 @@
import { useMemo, useState, useTransition } from "react";
import { toast } from "sonner";
import { createTransactionAction } from "@/features/transactions/actions";
import { groupAndSortCategories } from "@/features/transactions/category-helpers";
import { groupAndSortCategories } from "@/features/transactions/lib/category-helpers";
import { Button } from "@/shared/components/ui/button";
import {
Dialog,

View File

@@ -3,11 +3,11 @@
import { RiAddLine, RiDeleteBinLine } from "@remixicon/react";
import { useMemo, useState } from "react";
import { toast } from "sonner";
import { groupAndSortCategories } from "@/features/transactions/category-helpers";
import { groupAndSortCategories } from "@/features/transactions/lib/category-helpers";
import {
PAYMENT_METHODS,
type TRANSACTION_TYPES,
} from "@/features/transactions/constants";
} from "@/features/transactions/lib/constants";
import { Button } from "@/shared/components/ui/button";
import { CurrencyInput } from "@/shared/components/ui/currency-input";
import { DatePicker } from "@/shared/components/ui/date-picker";
@@ -51,7 +51,7 @@ import {
PaymentMethodSelectContent,
TransactionTypeSelectContent,
} from "../select-items";
import { EstabelecimentoInput } from "../shared/establishment-input";
import { EstablishmentInput } from "../shared/establishment-input";
import type { SelectOption } from "../types";
/** Payment methods sem Boleto para este modal */
@@ -490,7 +490,7 @@ export function MassAddDialog({
>
Estabelecimento {index + 1}
</Label>
<EstabelecimentoInput
<EstablishmentInput
id={`name-${transaction.id}`}
placeholder="Local"
value={transaction.name}

View File

@@ -4,8 +4,8 @@ import { useRouter } from "next/navigation";
import { useEffect, useMemo, useState, useTransition } from "react";
import { toast } from "sonner";
import { refundTransactionAction } from "@/features/transactions/actions/refund-action";
import { deriveCreditCardPeriod } from "@/features/transactions/form-helpers";
import { formatDate } from "@/features/transactions/formatting-helpers";
import { deriveCreditCardPeriod } from "@/features/transactions/lib/form-helpers";
import { formatDate } from "@/features/transactions/lib/formatting-helpers";
import { PeriodPicker } from "@/shared/components/period-picker";
import { Button } from "@/shared/components/ui/button";
import { DatePicker } from "@/shared/components/ui/date-picker";

View File

@@ -12,7 +12,7 @@ import {
formatCondition,
formatDate,
formatPeriod,
} from "@/features/transactions/formatting-helpers";
} from "@/features/transactions/lib/formatting-helpers";
import { TransactionTypeBadge } from "@/shared/components/transaction-type-badge";
import {
Avatar,

View File

@@ -5,7 +5,7 @@ import { CalculatorDialogButton } from "@/shared/components/calculator/calculato
import { CurrencyInput } from "@/shared/components/ui/currency-input";
import { DatePicker } from "@/shared/components/ui/date-picker";
import { Label } from "@/shared/components/ui/label";
import { EstabelecimentoInput } from "../../shared/establishment-input";
import { EstablishmentInput } from "../../shared/establishment-input";
import type { BasicFieldsSectionProps } from "./transaction-dialog-types";
export function BasicFieldsSection({
@@ -17,7 +17,7 @@ export function BasicFieldsSection({
<div className="space-y-3">
<div className="space-y-1">
<Label htmlFor="name">Descrição</Label>
<EstabelecimentoInput
<EstablishmentInput
id="name"
value={formState.name}
onChange={(value) => onFieldChange("name", value)}

View File

@@ -1,6 +1,6 @@
"use client";
import { TRANSACTION_TYPES } from "@/features/transactions/constants";
import { TRANSACTION_TYPES } from "@/features/transactions/lib/constants";
import { Label } from "@/shared/components/ui/label";
import {
Select,

View File

@@ -1,6 +1,6 @@
"use client";
import { TRANSACTION_CONDITIONS } from "@/features/transactions/constants";
import { TRANSACTION_CONDITIONS } from "@/features/transactions/lib/constants";
import { Label } from "@/shared/components/ui/label";
import {
Select,

View File

@@ -5,7 +5,7 @@ import {
RiCheckboxCircleFill,
} from "@remixicon/react";
import { useState } from "react";
import { PAYMENT_METHODS } from "@/features/transactions/constants";
import { PAYMENT_METHODS } from "@/features/transactions/lib/constants";
import { Button } from "@/shared/components/ui/button";
import { Label } from "@/shared/components/ui/label";
import { MonthPicker } from "@/shared/components/ui/month-picker";

View File

@@ -1,4 +1,4 @@
import type { TransactionFormState } from "@/features/transactions/form-helpers";
import type { TransactionFormState } from "@/features/transactions/lib/form-helpers";
import type { SelectOption, TransactionItem } from "../../types";
export type FormState = TransactionFormState;
@@ -71,7 +71,7 @@ export interface TransactionDialogProps {
}) => void;
}
export interface BaseFieldSectionProps {
interface BaseFieldSectionProps {
formState: FormState;
onFieldChange: <Key extends keyof FormState>(
key: Key,

View File

@@ -14,12 +14,12 @@ import {
import {
filterSecondaryPayerOptions,
groupAndSortCategories,
} from "@/features/transactions/category-helpers";
} from "@/features/transactions/lib/category-helpers";
import {
applyFieldDependencies,
buildTransactionInitialState,
deriveCreditCardPeriod,
} from "@/features/transactions/form-helpers";
} from "@/features/transactions/lib/form-helpers";
import { Button } from "@/shared/components/ui/button";
import {
Collapsible,

View File

@@ -19,7 +19,7 @@ import {
SelectValue,
} from "@/shared/components/ui/select";
export type AccountCardValue = `card:${string}` | `account:${string}`;
type AccountCardValue = `card:${string}` | `account:${string}`;
export function encodeAccountCard(
type: "card" | "account",

View File

@@ -21,7 +21,7 @@ import { ConfirmActionDialog } from "@/shared/components/confirm-action-dialog";
import type {
TransactionsExportContext,
TransactionsPaginationState,
} from "../../export-types";
} from "../../lib/export-types";
import { AnticipateInstallmentsDialog } from "../dialogs/anticipate-installments-dialog/anticipate-installments-dialog";
import { AnticipationHistoryDialog } from "../dialogs/anticipate-installments-dialog/anticipation-history-dialog";
import {

View File

@@ -3,7 +3,7 @@
import { RiBankCard2Line, RiBankLine } from "@remixicon/react";
import Image from "next/image";
import { CategoryIcon } from "@/features/categories/components/category-icon";
import StatusDot from "@/shared/components/status-dot";
import StatusDot from "@/shared/components/feedback/status-dot";
import {
Avatar,
AvatarFallback,

View File

@@ -5,7 +5,7 @@ import { format } from "date-fns";
import { ptBR } from "date-fns/locale";
import { useTransition } from "react";
import { toast } from "sonner";
import { cancelInstallmentAnticipationAction } from "@/features/transactions/anticipation-actions";
import { cancelInstallmentAnticipationAction } from "@/features/transactions/actions/anticipation";
import type { InstallmentAnticipationListItem } from "@/features/transactions/hooks/use-installment-anticipations";
import { ConfirmActionDialog } from "@/shared/components/confirm-action-dialog";
import MoneyValues from "@/shared/components/money-values";

View File

@@ -17,7 +17,7 @@ import {
PopoverTrigger,
} from "@/shared/components/ui/popover";
export interface EstabelecimentoInputProps {
interface EstablishmentInputProps {
id?: string;
value: string;
onChange: (value: string) => void;
@@ -27,7 +27,7 @@ export interface EstabelecimentoInputProps {
maxLength?: number;
}
export function EstabelecimentoInput({
export function EstablishmentInput({
id,
value,
onChange,
@@ -35,7 +35,7 @@ export function EstabelecimentoInput({
placeholder = "Ex.: Padaria, Transferência, Saldo inicial",
required = false,
maxLength = 20,
}: EstabelecimentoInputProps) {
}: EstablishmentInputProps) {
const [open, setOpen] = React.useState(false);
const [searchValue, setSearchValue] = React.useState("");
const [width, setWidth] = React.useState<number | undefined>();

View File

@@ -18,11 +18,11 @@ import {
import type { ColumnDef } from "@tanstack/react-table";
import Image from "next/image";
import Link from "next/link";
import { DEFAULT_LANCAMENTOS_COLUMN_ORDER } from "@/features/transactions/column-order";
import { DEFAULT_TRANSACTIONS_COLUMN_ORDER } from "@/features/transactions/lib/column-order";
import {
CREDIT_CARD_PAYMENT_METHOD,
SETTLEABLE_PAYMENT_METHODS,
} from "@/features/transactions/constants";
} from "@/features/transactions/lib/constants";
import {
CategoryIconBadge,
EstablishmentLogo,
@@ -58,7 +58,7 @@ import { getConditionIcon, getPaymentMethodIcon } from "@/shared/utils/icons";
import { cn } from "@/shared/utils/ui";
import type { TransactionItem } from "../types";
export type BuildColumnsArgs = {
type BuildColumnsArgs = {
currentUserId: string;
noteAsColumn: boolean;
onEdit?: (item: TransactionItem) => void;
@@ -748,6 +748,6 @@ export function getTransactionColumns(
const built = buildColumns(args);
const order = args.columnOrder?.length
? args.columnOrder
: DEFAULT_LANCAMENTOS_COLUMN_ORDER;
: DEFAULT_TRANSACTIONS_COLUMN_ORDER;
return reorderColumnsByPreference(built, order);
}

View File

@@ -18,7 +18,7 @@ import {
SETTLED_FILTER_VALUES,
TRANSACTION_CONDITIONS,
TRANSACTION_TYPES,
} from "@/features/transactions/constants";
} from "@/features/transactions/lib/constants";
import { Button } from "@/shared/components/ui/button";
import {
Command,

View File

@@ -20,8 +20,8 @@ import { useMemo, useState } from "react";
import type {
TransactionsExportContext,
TransactionsPaginationState,
} from "@/features/transactions/export-types";
import { EmptyState } from "@/shared/components/empty-state";
} from "@/features/transactions/lib/export-types";
import { EmptyState } from "@/shared/components/feedback/empty-state";
import { Button } from "@/shared/components/ui/button";
import { Card, CardContent } from "@/shared/components/ui/card";
import {
@@ -50,7 +50,7 @@ import { getTransactionColumns } from "./transactions-columns";
import { TransactionsFilters } from "./transactions-filters";
import { TransactionsPagination } from "./transactions-pagination";
type LancamentosTableProps = {
type TransactionsTableProps = {
data: TransactionItem[];
currentUserId: string;
noteAsColumn?: boolean;
@@ -106,7 +106,7 @@ export function TransactionsTable({
isSettlementLoading,
showActions = true,
showFilters = true,
}: LancamentosTableProps) {
}: TransactionsTableProps) {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();

View File

@@ -9,8 +9,8 @@ import {
import { useState } from "react";
import { toast } from "sonner";
import { exportTransactionsDataAction } from "@/features/transactions/actions";
import type { TransactionsExportContext } from "@/features/transactions/export-types";
import { formatCurrency } from "@/features/transactions/formatting-helpers";
import type { TransactionsExportContext } from "@/features/transactions/lib/export-types";
import { formatCurrency } from "@/features/transactions/lib/formatting-helpers";
import { Button } from "@/shared/components/ui/button";
import {
DropdownMenu,
@@ -26,7 +26,7 @@ import {
import { displayPeriod } from "@/shared/utils/period";
import type { TransactionItem } from "./types";
interface LancamentosExportProps {
interface TransactionsExportProps {
lancamentos: TransactionItem[];
period: string;
exportContext?: TransactionsExportContext;
@@ -47,7 +47,7 @@ export function TransactionsExport({
lancamentos,
period,
exportContext,
}: LancamentosExportProps) {
}: TransactionsExportProps) {
const [isExporting, setIsExporting] = useState(false);
const getFileName = (extension: string) => {

View File

@@ -2,7 +2,7 @@
import { useQuery } from "@tanstack/react-query";
import { z } from "zod";
import { fetchJson } from "@/shared/lib/fetch-json";
import { fetchJson } from "@/shared/utils/fetch-json";
const anticipationItemSchema = z.object({
id: z.string().uuid(),

View File

@@ -1,8 +1,8 @@
"use client";
import { useQuery } from "@tanstack/react-query";
import type { TransactionAttachmentListItem } from "@/features/transactions/attachment-queries";
import { fetchJson } from "@/shared/lib/fetch-json";
import type { TransactionAttachmentListItem } from "@/features/transactions/lib/attachment-queries";
import { fetchJson } from "@/shared/utils/fetch-json";
export const transactionAttachmentsQueryKey = (transactionId: string) =>
["transactions", "attachments", transactionId] as const;

View File

@@ -8,7 +8,7 @@ import {
import { db } from "@/shared/lib/db";
import { uuidSchema } from "@/shared/lib/schemas/common";
export type InstallmentAnticipationListItem = {
type InstallmentAnticipationListItem = {
id: string;
anticipationPeriod: string;
anticipationDate: string;

View File

@@ -2,7 +2,7 @@
* Ids das colunas reordenáveis da tabela de lançamentos (extrato).
* select, purchaseDate e actions são fixos (início, oculto, fim).
*/
export const LANCAMENTOS_REORDERABLE_COLUMN_IDS = [
const TRANSACTIONS_REORDERABLE_COLUMN_IDS = [
"name",
"transactionType",
"amount",
@@ -14,7 +14,7 @@ export const LANCAMENTOS_REORDERABLE_COLUMN_IDS = [
"contaCartao",
] as const;
export const LANCAMENTOS_COLUMN_LABELS: Record<string, string> = {
export const TRANSACTIONS_COLUMN_LABELS: Record<string, string> = {
name: "Estabelecimento",
transactionType: "Transação",
amount: "Valor",
@@ -26,6 +26,6 @@ export const LANCAMENTOS_COLUMN_LABELS: Record<string, string> = {
contaCartao: "Conta/Cartão",
};
export const DEFAULT_LANCAMENTOS_COLUMN_ORDER: string[] = [
...LANCAMENTOS_REORDERABLE_COLUMN_IDS,
export const DEFAULT_TRANSACTIONS_COLUMN_ORDER: string[] = [
...TRANSACTIONS_REORDERABLE_COLUMN_IDS,
];

View File

@@ -1,4 +1,4 @@
export type TransactionExportFilters = {
type TransactionExportFilters = {
transactionFilter: string | null;
conditionFilter: string | null;
paymentFilter: string | null;

View File

@@ -90,7 +90,7 @@ export type TransactionFormState = {
/**
* Initial state overrides for lancamento form
*/
export type LancamentoFormOverrides = {
type TransactionFormOverrides = {
defaultCardId?: string | null;
defaultPaymentMethod?: string | null;
defaultPurchaseDate?: string | null;
@@ -107,7 +107,7 @@ export function buildTransactionInitialState(
transaction?: TransactionItem,
defaultPayerId?: string | null,
preferredPeriod?: string,
overrides?: LancamentoFormOverrides,
overrides?: TransactionFormOverrides,
): TransactionFormState {
const purchaseDate = transaction?.purchaseDate
? transaction.purchaseDate.slice(0, 10)

View File

@@ -14,7 +14,7 @@ import {
SETTLED_FILTER_VALUES,
TRANSACTION_CONDITIONS,
TRANSACTION_TYPES,
} from "@/features/transactions/constants";
} from "@/features/transactions/lib/constants";
import { ACCOUNT_AUTO_INVOICE_NOTE_PREFIX } from "@/shared/lib/accounts/constants";
import {
PAYER_ROLE_ADMIN,
@@ -32,8 +32,8 @@ export type ResolvedSearchParams =
| Record<string, string | string[] | undefined>
| undefined;
export const TRANSACTIONS_DEFAULT_PAGE_SIZE = 30;
export const TRANSACTIONS_PAGE_SIZE_OPTIONS = [5, 10, 20, 30, 40, 50, 100];
const TRANSACTIONS_DEFAULT_PAGE_SIZE = 30;
const TRANSACTIONS_PAGE_SIZE_OPTIONS = [5, 10, 20, 30, 40, 50, 100];
export type TransactionSearchFilters = {
transactionFilter: string | null;
@@ -91,16 +91,16 @@ export type SlugMaps = {
card: Map<string, string>;
};
export type FilterOption = {
type FilterOption = {
slug: string;
label: string;
};
export type AccountCardFilterOption = FilterOption & {
type AccountCardFilterOption = FilterOption & {
kind: "conta" | "cartao";
};
export type TransactionOptionSets = {
type TransactionOptionSets = {
payerOptions: SelectOption[];
splitPayerOptions: SelectOption[];
defaultPayerId: string | null;
@@ -186,7 +186,7 @@ const createSlugGenerator = () => {
};
};
export const toOption = (
const toOption = (
value: string,
label: string | null | undefined,
role?: string | null,

View File

@@ -32,7 +32,7 @@ type TransactionQueryInput = BaseTransactionQueryInput & {
offset?: number;
};
export type PaginatedTransactionsResult = {
type PaginatedTransactionsResult = {
rows: Awaited<ReturnType<typeof fetchTransactions>>;
totalItems: number;
page: number;