From 8de22b9930af54e78e9c9ea4c442988a2a9fc513 Mon Sep 17 00:00:00 2001 From: Felipe Coutinho Date: Thu, 26 Feb 2026 17:19:33 +0000 Subject: [PATCH] =?UTF-8?q?refactor:=20remover=20c=C3=B3digo=20morto=20e?= =?UTF-8?q?=20exports=20n=C3=A3o=20utilizados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove 6 componentes não utilizados (dashboard-grid, expenses/income by category widgets, installment analysis panels, fatura-warning-dialog). Remove funções/tipos não utilizados: successResult, generateApiToken, validateApiToken, getTodayUTC/Local, formatDateForDb, getDateInfo, calculatePercentage, roundToDecimals, safeParseInt/Float, isPeriodValid, getLastPeriods, normalizeWhitespace, formatCurrency wrapper, InboxItemInput, InboxBatchInput, ProcessInboxInput, DiscardInboxInput, LancamentosColumnId, 5 funções de anticipation-helpers. Redireciona imports de formatCurrency para lib/lancamentos/formatting-helpers. Co-Authored-By: Claude Opus 4.6 --- components/dashboard/dashboard-grid.tsx | 26 --- .../dashboard/expenses-by-category-widget.tsx | 173 ----------------- .../dashboard/income-by-category-widget.tsx | 178 ------------------ .../analysis-summary-panel.tsx | 52 ----- .../pending-invoice-card.tsx | 177 ----------------- .../dialogs/fatura-warning-dialog.tsx | 84 --------- components/pre-lancamentos/types.ts | 17 -- components/relatorios/category-cell.tsx | 3 +- .../relatorios/category-report-cards.tsx | 3 +- .../relatorios/category-report-export.tsx | 2 +- components/relatorios/category-table.tsx | 3 +- lib/actions/types.ts | 10 - lib/auth/api-token.ts | 20 -- lib/installments/anticipation-helpers.ts | 77 +------- lib/lancamentos/column-order.ts | 2 - lib/relatorios/utils.ts | 12 -- lib/schemas/inbox.ts | 3 - lib/utils/date.ts | 73 ------- lib/utils/math.ts | 25 --- lib/utils/number.ts | 41 ---- lib/utils/period/index.ts | 32 ---- lib/utils/string.ts | 9 - 22 files changed, 8 insertions(+), 1014 deletions(-) delete mode 100644 components/dashboard/dashboard-grid.tsx delete mode 100644 components/dashboard/expenses-by-category-widget.tsx delete mode 100644 components/dashboard/income-by-category-widget.tsx delete mode 100644 components/dashboard/installment-analysis/analysis-summary-panel.tsx delete mode 100644 components/dashboard/installment-analysis/pending-invoice-card.tsx delete mode 100644 components/lancamentos/dialogs/fatura-warning-dialog.tsx diff --git a/components/dashboard/dashboard-grid.tsx b/components/dashboard/dashboard-grid.tsx deleted file mode 100644 index 685ae0b..0000000 --- a/components/dashboard/dashboard-grid.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import WidgetCard from "@/components/widget-card"; -import type { DashboardData } from "@/lib/dashboard/fetch-dashboard-data"; -import { widgetsConfig } from "@/lib/dashboard/widgets/widgets-config"; - -type DashboardGridProps = { - data: DashboardData; - period: string; -}; - -export function DashboardGrid({ data, period }: DashboardGridProps) { - return ( -
- {widgetsConfig.map((widget) => ( - - {widget.component({ data, period })} - - ))} -
- ); -} diff --git a/components/dashboard/expenses-by-category-widget.tsx b/components/dashboard/expenses-by-category-widget.tsx deleted file mode 100644 index 577f884..0000000 --- a/components/dashboard/expenses-by-category-widget.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import { - RiArrowDownSFill, - RiArrowUpSFill, - RiExternalLinkLine, - RiPieChartLine, - RiWallet3Line, -} from "@remixicon/react"; -import Link from "next/link"; -import MoneyValues from "@/components/money-values"; -import type { ExpensesByCategoryData } from "@/lib/dashboard/categories/expenses-by-category"; -import { getIconComponent } from "@/lib/utils/icons"; -import { formatPeriodForUrl } from "@/lib/utils/period"; -import { WidgetEmptyState } from "../widget-empty-state"; - -type ExpensesByCategoryWidgetProps = { - data: ExpensesByCategoryData; - period: string; -}; - -const buildInitials = (value: string) => { - const parts = value.trim().split(/\s+/).filter(Boolean); - if (parts.length === 0) { - return "CT"; - } - if (parts.length === 1) { - const firstPart = parts[0]; - return firstPart ? firstPart.slice(0, 2).toUpperCase() : "CT"; - } - const firstChar = parts[0]?.[0] ?? ""; - const secondChar = parts[1]?.[0] ?? ""; - return `${firstChar}${secondChar}`.toUpperCase() || "CT"; -}; - -const formatPercentage = (value: number) => { - return `${Math.abs(value).toFixed(0)}%`; -}; - -export function ExpensesByCategoryWidget({ - data, - period, -}: ExpensesByCategoryWidgetProps) { - const periodParam = formatPeriodForUrl(period); - - if (data.categories.length === 0) { - return ( - } - title="Nenhuma despesa encontrada" - description="Quando houver despesas registradas, elas aparecerão aqui." - /> - ); - } - - return ( -
- {data.categories.map((category) => { - const IconComponent = category.categoryIcon - ? getIconComponent(category.categoryIcon) - : null; - const initials = buildInitials(category.categoryName); - const hasIncrease = - category.percentageChange !== null && category.percentageChange > 0; - const hasDecrease = - category.percentageChange !== null && category.percentageChange < 0; - const hasBudget = category.budgetAmount !== null; - const budgetExceeded = - hasBudget && - category.budgetUsedPercentage !== null && - category.budgetUsedPercentage > 100; - - const formatCurrency = (value: number) => - new Intl.NumberFormat("pt-BR", { - style: "currency", - currency: "BRL", - }).format(value); - - const exceededAmount = - budgetExceeded && category.budgetAmount - ? category.currentAmount - category.budgetAmount - : 0; - - return ( -
-
-
-
- {IconComponent ? ( - - ) : ( - - {initials} - - )} -
- -
-
- - {category.categoryName} - - -
-
- - {formatPercentage(category.percentageOfTotal)} da despesa - total - -
-
-
- -
- - {category.percentageChange !== null && ( - - {hasIncrease && } - {hasDecrease && } - {formatPercentage(category.percentageChange)} - - )} -
-
- - {hasBudget && category.budgetUsedPercentage !== null && ( -
- - - {budgetExceeded ? ( - <> - {formatPercentage(category.budgetUsedPercentage)} do - limite - excedeu em {formatCurrency(exceededAmount)} - - ) : ( - <> - {formatPercentage(category.budgetUsedPercentage)} do - limite - - )} - -
- )} -
- ); - })} -
- ); -} diff --git a/components/dashboard/income-by-category-widget.tsx b/components/dashboard/income-by-category-widget.tsx deleted file mode 100644 index a4591e5..0000000 --- a/components/dashboard/income-by-category-widget.tsx +++ /dev/null @@ -1,178 +0,0 @@ -import { - RiArrowDownSFill, - RiArrowUpSFill, - RiExternalLinkLine, - RiPieChartLine, - RiWallet3Line, -} from "@remixicon/react"; -import Link from "next/link"; -import MoneyValues from "@/components/money-values"; -import type { IncomeByCategoryData } from "@/lib/dashboard/categories/income-by-category"; -import { getIconComponent } from "@/lib/utils/icons"; -import { formatPeriodForUrl } from "@/lib/utils/period"; -import { WidgetEmptyState } from "../widget-empty-state"; - -type IncomeByCategoryWidgetProps = { - data: IncomeByCategoryData; - period: string; -}; - -const buildInitials = (value: string) => { - const parts = value.trim().split(/\s+/).filter(Boolean); - if (parts.length === 0) { - return "CT"; - } - if (parts.length === 1) { - const firstPart = parts[0]; - return firstPart ? firstPart.slice(0, 2).toUpperCase() : "CT"; - } - const firstChar = parts[0]?.[0] ?? ""; - const secondChar = parts[1]?.[0] ?? ""; - return `${firstChar}${secondChar}`.toUpperCase() || "CT"; -}; - -const formatPercentage = (value: number) => { - return `${Math.abs(value).toFixed(1)}%`; -}; - -export function IncomeByCategoryWidget({ - data, - period, -}: IncomeByCategoryWidgetProps) { - const periodParam = formatPeriodForUrl(period); - - if (data.categories.length === 0) { - return ( - } - title="Nenhuma receita encontrada" - description="Quando houver receitas registradas, elas aparecerão aqui." - /> - ); - } - - return ( -
- {data.categories.map((category) => { - const IconComponent = category.categoryIcon - ? getIconComponent(category.categoryIcon) - : null; - const initials = buildInitials(category.categoryName); - const hasIncrease = - category.percentageChange !== null && category.percentageChange > 0; - const hasDecrease = - category.percentageChange !== null && category.percentageChange < 0; - const hasBudget = category.budgetAmount !== null; - const budgetExceeded = - hasBudget && - category.budgetUsedPercentage !== null && - category.budgetUsedPercentage > 100; - - const formatCurrency = (value: number) => - new Intl.NumberFormat("pt-BR", { - style: "currency", - currency: "BRL", - }).format(value); - - const exceededAmount = - budgetExceeded && category.budgetAmount - ? category.currentAmount - category.budgetAmount - : 0; - - return ( -
-
-
-
- {IconComponent ? ( - - ) : ( - - {initials} - - )} -
- -
-
- - {category.categoryName} - - -
-
- - {formatPercentage(category.percentageOfTotal)} da receita - total - -
-
-
- -
- - {category.percentageChange !== null && ( - - {hasIncrease && } - {hasDecrease && } - {formatPercentage(category.percentageChange)} - - )} -
-
- - {hasBudget && - category.budgetUsedPercentage !== null && - category.budgetAmount !== null && ( -
- - - {budgetExceeded ? ( - <> - {formatPercentage(category.budgetUsedPercentage)} do - limite {formatCurrency(category.budgetAmount)} - excedeu - em {formatCurrency(exceededAmount)} - - ) : ( - <> - {formatPercentage(category.budgetUsedPercentage)} do - limite {formatCurrency(category.budgetAmount)} - - )} - -
- )} -
- ); - })} -
- ); -} diff --git a/components/dashboard/installment-analysis/analysis-summary-panel.tsx b/components/dashboard/installment-analysis/analysis-summary-panel.tsx deleted file mode 100644 index 3aedaca..0000000 --- a/components/dashboard/installment-analysis/analysis-summary-panel.tsx +++ /dev/null @@ -1,52 +0,0 @@ -"use client"; - -import { RiPieChartLine } from "@remixicon/react"; -import MoneyValues from "@/components/money-values"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; - -type AnalysisSummaryPanelProps = { - totalInstallments: number; - grandTotal: number; - selectedCount: number; -}; - -export function AnalysisSummaryPanel({ - totalInstallments, - grandTotal, - selectedCount, -}: AnalysisSummaryPanelProps) { - return ( - - -
- - Resumo -
-
- - {/* Total geral */} -
-

- Total Selecionado -

- -

- {selectedCount} {selectedCount === 1 ? "parcela" : "parcelas"} -

-
- - {/* Mensagem quando nada está selecionado */} - {selectedCount === 0 && ( -
-

- Selecione parcelas para ver o resumo -

-
- )} -
-
- ); -} diff --git a/components/dashboard/installment-analysis/pending-invoice-card.tsx b/components/dashboard/installment-analysis/pending-invoice-card.tsx deleted file mode 100644 index 2060f18..0000000 --- a/components/dashboard/installment-analysis/pending-invoice-card.tsx +++ /dev/null @@ -1,177 +0,0 @@ -"use client"; - -import { - RiArrowDownSLine, - RiArrowRightSLine, - RiBillLine, -} from "@remixicon/react"; -import { format, parse } from "date-fns"; -import { ptBR } from "date-fns/locale"; -import Image from "next/image"; -import { useState } from "react"; -import MoneyValues from "@/components/money-values"; -import { Badge } from "@/components/ui/badge"; -import { Card, CardContent } from "@/components/ui/card"; -import { Checkbox } from "@/components/ui/checkbox"; -import { cn } from "@/lib/utils/ui"; -import type { PendingInvoice } from "./types"; - -type PendingInvoiceCardProps = { - invoice: PendingInvoice; - isSelected: boolean; - onToggle: () => void; -}; - -export function PendingInvoiceCard({ - invoice, - isSelected, - onToggle, -}: PendingInvoiceCardProps) { - const [isExpanded, setIsExpanded] = useState(false); - - // Formatar período (YYYY-MM) para texto legível - const periodDate = parse(invoice.period, "yyyy-MM", new Date()); - const periodText = format(periodDate, "MMMM 'de' yyyy", { locale: ptBR }); - - // Calcular data de vencimento aproximada - const dueDay = parseInt(invoice.dueDay, 10); - const dueDate = new Date(periodDate); - dueDate.setDate(dueDay); - const dueDateText = format(dueDate, "dd/MM/yyyy", { locale: ptBR }); - - return ( - - - {/* Header do card */} -
- - -
-
-
-
- {invoice.cartaoLogo ? ( - {invoice.cartaoName} - ) : ( -
- -
- )} -

{invoice.cartaoName}

-
-
- {periodText} - - - Vencimento: {dueDateText} -
-
- - -
- - {/* Badge de status */} -
- - Pendente - - - {invoice.lancamentos.length}{" "} - {invoice.lancamentos.length === 1 - ? "lançamento" - : "lançamentos"} - -
- - {/* Botão de expandir */} - -
-
- - {/* Lista de lançamentos expandida */} - {isExpanded && ( -
- {invoice.lancamentos.map((lancamento) => { - const purchaseDate = format( - lancamento.purchaseDate, - "dd/MM/yyyy", - { locale: ptBR }, - ); - - const installmentLabel = - lancamento.condition === "Parcelado" && - lancamento.currentInstallment && - lancamento.installmentCount - ? `${lancamento.currentInstallment}/${lancamento.installmentCount}` - : null; - - return ( -
-
-
-

- {lancamento.name} -

-
- {purchaseDate} - {installmentLabel && ( - <> - - - Parcela {installmentLabel} - - )} - {lancamento.condition !== "Parcelado" && ( - <> - - - {lancamento.condition} - - )} -
-
- - -
-
- ); - })} -
- )} -
-
- ); -} diff --git a/components/lancamentos/dialogs/fatura-warning-dialog.tsx b/components/lancamentos/dialogs/fatura-warning-dialog.tsx deleted file mode 100644 index 266ed2b..0000000 --- a/components/lancamentos/dialogs/fatura-warning-dialog.tsx +++ /dev/null @@ -1,84 +0,0 @@ -"use client"; - -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, -} from "@/components/ui/alert-dialog"; -import { MONTH_NAMES } from "@/lib/utils/period"; - -export type FaturaWarning = { - nextPeriod: string; - cardName: string; - isPaid: boolean; - isAfterClosing: boolean; - closingDay: string | null; - currentPeriod: string; -}; - -export function formatPeriodDisplay(period: string): string { - const [yearStr, monthStr] = period.split("-"); - const monthIndex = Number.parseInt(monthStr ?? "1", 10) - 1; - const monthName = MONTH_NAMES[monthIndex] ?? monthStr; - return `${monthName}/${yearStr}`; -} - -function buildWarningMessage(warning: FaturaWarning): string { - const currentDisplay = formatPeriodDisplay(warning.currentPeriod); - if (warning.isPaid && warning.isAfterClosing) { - return `A fatura do ${warning.cardName} em ${currentDisplay} já está paga e fechou no dia ${warning.closingDay}.`; - } - if (warning.isPaid) { - return `A fatura do ${warning.cardName} em ${currentDisplay} já está paga.`; - } - return `A fatura do ${warning.cardName} fechou no dia ${warning.closingDay}.`; -} - -interface FaturaWarningDialogProps { - warning: FaturaWarning | null; - onConfirm: (nextPeriod: string) => void; - onCancel: () => void; -} - -export function FaturaWarningDialog({ - warning, - onConfirm, - onCancel, -}: FaturaWarningDialogProps) { - if (!warning) return null; - - return ( - { - if (!open) onCancel(); - }} - > - - - Fatura indisponível - - {buildWarningMessage(warning)} Deseja registrá-lo em{" "} - - {formatPeriodDisplay(warning.nextPeriod)} - - ? - - - - onConfirm(warning.nextPeriod)}> - Mover para {formatPeriodDisplay(warning.nextPeriod)} - - - Manter em {formatPeriodDisplay(warning.currentPeriod)} - - - - - ); -} diff --git a/components/pre-lancamentos/types.ts b/components/pre-lancamentos/types.ts index d5064d0..ebf25f3 100644 --- a/components/pre-lancamentos/types.ts +++ b/components/pre-lancamentos/types.ts @@ -17,22 +17,5 @@ export interface InboxItem { updatedAt: Date; } -export interface ProcessInboxInput { - inboxItemId: string; - name: string; - amount: number; - purchaseDate: string; - condition: string; - paymentMethod: string; - categoriaId: string; - contaId?: string; - cartaoId?: string; - note?: string; -} - -export interface DiscardInboxInput { - inboxItemId: string; -} - // Re-export the lancamentos SelectOption for use in inbox components export type SelectOption = LancamentoSelectOption; diff --git a/components/relatorios/category-cell.tsx b/components/relatorios/category-cell.tsx index 229d39c..82f9d44 100644 --- a/components/relatorios/category-cell.tsx +++ b/components/relatorios/category-cell.tsx @@ -6,7 +6,8 @@ import { TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; -import { formatCurrency, formatPercentageChange } from "@/lib/relatorios/utils"; +import { formatCurrency } from "@/lib/lancamentos/formatting-helpers"; +import { formatPercentageChange } from "@/lib/relatorios/utils"; import { cn } from "@/lib/utils/ui"; interface CategoryCellProps { diff --git a/components/relatorios/category-report-cards.tsx b/components/relatorios/category-report-cards.tsx index af37930..b2de966 100644 --- a/components/relatorios/category-report-cards.tsx +++ b/components/relatorios/category-report-cards.tsx @@ -4,11 +4,12 @@ import Link from "next/link"; import { useMemo } from "react"; import { CategoryIconBadge } from "@/components/categorias/category-icon-badge"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { formatCurrency } from "@/lib/lancamentos/formatting-helpers"; import type { CategoryReportData, CategoryReportItem, } from "@/lib/relatorios/types"; -import { formatCurrency, formatPeriodLabel } from "@/lib/relatorios/utils"; +import { formatPeriodLabel } from "@/lib/relatorios/utils"; import { formatPeriodForUrl } from "@/lib/utils/period"; import { CategoryCell } from "./category-cell"; diff --git a/components/relatorios/category-report-export.tsx b/components/relatorios/category-report-export.tsx index 9f3085b..be0b00c 100644 --- a/components/relatorios/category-report-export.tsx +++ b/components/relatorios/category-report-export.tsx @@ -18,9 +18,9 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; +import { formatCurrency } from "@/lib/lancamentos/formatting-helpers"; import type { CategoryReportData } from "@/lib/relatorios/types"; import { - formatCurrency, formatPercentageChange, formatPeriodLabel, } from "@/lib/relatorios/utils"; diff --git a/components/relatorios/category-table.tsx b/components/relatorios/category-table.tsx index b154dcb..b270082 100644 --- a/components/relatorios/category-table.tsx +++ b/components/relatorios/category-table.tsx @@ -12,8 +12,9 @@ import { TableHeader, TableRow, } from "@/components/ui/table"; +import { formatCurrency } from "@/lib/lancamentos/formatting-helpers"; import type { CategoryReportItem } from "@/lib/relatorios/types"; -import { formatCurrency, formatPeriodLabel } from "@/lib/relatorios/utils"; +import { formatPeriodLabel } from "@/lib/relatorios/utils"; import { formatPeriodForUrl } from "@/lib/utils/period"; import DotIcon from "../dot-icon"; import { Card } from "../ui/card"; diff --git a/lib/actions/types.ts b/lib/actions/types.ts index 7945d19..b947c67 100644 --- a/lib/actions/types.ts +++ b/lib/actions/types.ts @@ -5,16 +5,6 @@ export type ActionResult = | { success: true; message: string; data?: TData } | { success: false; error: string }; -/** - * Success result helper - */ -export function successResult( - message: string, - data?: TData, -): ActionResult { - return { success: true, message, data }; -} - /** * Error result helper */ diff --git a/lib/auth/api-token.ts b/lib/auth/api-token.ts index 4460e28..92a3812 100644 --- a/lib/auth/api-token.ts +++ b/lib/auth/api-token.ts @@ -144,14 +144,6 @@ export function generateTokenId(): string { return crypto.randomUUID(); } -/** - * Generate a random API token with prefix - */ -export function generateApiToken(): string { - const randomPart = crypto.randomBytes(32).toString("base64url"); - return `os_${randomPart}`; -} - /** * Hash a token using SHA-256 */ @@ -236,18 +228,6 @@ export function extractBearerToken(authHeader: string | null): string | null { return match ? match[1] : null; } -/** - * Validate an API token and return the payload - * @deprecated Use validateHashToken for os_xxx tokens - */ -export function validateApiToken(token: string): JwtPayload | null { - const payload = verifyJwt(token); - if (!payload || payload.type !== "api_access") { - return null; - } - return payload; -} - /** * Validate a hash-based API token (os_xxx format) * Returns the token hash for database lookup diff --git a/lib/installments/anticipation-helpers.ts b/lib/installments/anticipation-helpers.ts index 1eccc42..7bb00a1 100644 --- a/lib/installments/anticipation-helpers.ts +++ b/lib/installments/anticipation-helpers.ts @@ -1,47 +1,5 @@ -import type { Lancamento } from "@/db/schema"; import type { EligibleInstallment } from "./anticipation-types"; -/** - * Calcula o valor total de antecipação baseado nas parcelas selecionadas - */ -export function calculateTotalAnticipationAmount( - installments: EligibleInstallment[], -): number { - return installments.reduce((sum, inst) => sum + Number(inst.amount), 0); -} - -/** - * Valida se o período de antecipação é válido - * O período não pode ser anterior ao período da primeira parcela selecionada - */ -export function validateAnticipationPeriod( - period: string, - installments: EligibleInstallment[], -): boolean { - if (installments.length === 0) return false; - - const earliestPeriod = installments.reduce((earliest, inst) => { - return inst.period < earliest ? inst.period : earliest; - }, installments[0].period); - - return period >= earliestPeriod; -} - -/** - * Formata os números das parcelas antecipadas em uma string legível - * Exemplo: "1, 2, 3" ou "5, 6, 7, 8" - */ -export function getAnticipatedInstallmentNumbers( - installments: EligibleInstallment[], -): string { - const numbers = installments - .map((inst) => inst.currentInstallment) - .filter((num): num is number => num !== null) - .sort((a, b) => a - b) - .join(", "); - return numbers; -} - /** * Formata o resumo de parcelas antecipadas * Exemplo: "Parcelas 1-3 de 12" ou "Parcela 5 de 12" @@ -67,7 +25,7 @@ export function formatAnticipatedInstallmentsRange( // Se as parcelas são consecutivas const isConsecutive = numbers.every((num, i) => { if (i === 0) return true; - return num === numbers[i - 1]! + 1; + return num === (numbers[i - 1] ?? 0) + 1; }); if (isConsecutive) { @@ -77,27 +35,6 @@ export function formatAnticipatedInstallmentsRange( } } -/** - * Verifica se uma antecipação pode ser cancelada - * Só pode cancelar se o lançamento de antecipação não foi pago - */ -export function canCancelAnticipation(lancamento: Lancamento): boolean { - return lancamento.isSettled !== true; -} - -/** - * Ordena parcelas por número da parcela atual - */ -export function sortInstallmentsByNumber( - installments: EligibleInstallment[], -): EligibleInstallment[] { - return [...installments].sort((a, b) => { - const aNum = a.currentInstallment ?? 0; - const bNum = b.currentInstallment ?? 0; - return aNum - bNum; - }); -} - /** * Calcula quantas parcelas restam após uma antecipação */ @@ -108,18 +45,6 @@ export function calculateRemainingInstallments( return Math.max(0, totalInstallments - anticipatedCount); } -/** - * Valida se as parcelas selecionadas pertencem à mesma série - */ -export function validateInstallmentsSameSeries( - installments: EligibleInstallment[], - _seriesId: string, -): boolean { - // Esta validação será feita no servidor com os dados completos - // Aqui apenas retorna true como placeholder - return installments.length > 0; -} - /** * Gera descrição automática para o lançamento de antecipação */ diff --git a/lib/lancamentos/column-order.ts b/lib/lancamentos/column-order.ts index 9413235..d22b317 100644 --- a/lib/lancamentos/column-order.ts +++ b/lib/lancamentos/column-order.ts @@ -14,8 +14,6 @@ export const LANCAMENTOS_REORDERABLE_COLUMN_IDS = [ "contaCartao", ] as const; -export type LancamentosColumnId = (typeof LANCAMENTOS_REORDERABLE_COLUMN_IDS)[number]; - export const LANCAMENTOS_COLUMN_LABELS: Record = { name: "Estabelecimento", transactionType: "Transação", diff --git a/lib/relatorios/utils.ts b/lib/relatorios/utils.ts index aee0927..9dae8d8 100644 --- a/lib/relatorios/utils.ts +++ b/lib/relatorios/utils.ts @@ -1,4 +1,3 @@ -import { currencyFormatter } from "@/lib/lancamentos/formatting-helpers"; import { calculatePercentageChange } from "@/lib/utils/math"; import { buildPeriodRange, MONTH_NAMES, parsePeriod } from "@/lib/utils/period"; import type { DateRangeValidation } from "./types"; @@ -95,17 +94,6 @@ export function validateDateRange( } } -/** - * Formats a number as Brazilian currency (R$ X.XXX,XX) - * Uses the shared currencyFormatter from formatting-helpers - * - * @param value - Numeric value to format - * @returns Formatted currency string - */ -export function formatCurrency(value: number): string { - return currencyFormatter.format(value); -} - /** * Formats percentage change for display * Format: "±X%" or "±X.X%" (one decimal if < 10%) diff --git a/lib/schemas/inbox.ts b/lib/schemas/inbox.ts index 1caea65..1c66c34 100644 --- a/lib/schemas/inbox.ts +++ b/lib/schemas/inbox.ts @@ -14,6 +14,3 @@ export const inboxItemSchema = z.object({ export const inboxBatchSchema = z.object({ items: z.array(inboxItemSchema).min(1).max(50), }); - -export type InboxItemInput = z.infer; -export type InboxBatchInput = z.infer; diff --git a/lib/utils/date.ts b/lib/utils/date.ts index f4f4bd6..a9f6aaa 100644 --- a/lib/utils/date.ts +++ b/lib/utils/date.ts @@ -61,57 +61,6 @@ export function parseLocalDateString(dateString: string): Date { ); } -/** - * Gets today's date in UTC - * @returns Date object set to today at midnight UTC - */ -export function getTodayUTC(): Date { - const now = new Date(); - const year = now.getUTCFullYear(); - const month = now.getUTCMonth(); - const day = now.getUTCDate(); - - return new Date(Date.UTC(year, month, day)); -} - -/** - * Gets today's date in local timezone - * @returns Date object set to today at midnight local time - */ -export function getTodayLocal(): Date { - const now = new Date(); - const year = now.getFullYear(); - const month = now.getMonth(); - const day = now.getDate(); - - return new Date(year, month, day); -} - -/** - * Gets today's period in YYYY-MM format (UTC) - * @returns Period string - */ -export function getTodayPeriodUTC(): string { - const now = new Date(); - const year = now.getUTCFullYear(); - const month = now.getUTCMonth(); - - return `${year}-${String(month + 1).padStart(2, "0")}`; -} - -/** - * Formats date as YYYY-MM-DD string - * @param date - Date to format - * @returns Formatted date string - */ -export function formatDateForDb(date: Date): string { - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, "0"); - const day = String(date.getDate()).padStart(2, "0"); - - return `${year}-${month}-${day}`; -} - /** * Gets today's date as YYYY-MM-DD string * @returns Formatted date string @@ -224,27 +173,5 @@ export function getGreeting(date: Date = new Date()): string { return "Boa noite"; } -// ============================================================================ -// DATE INFORMATION -// ============================================================================ - -/** - * Gets information about a date - * @param date - Date to analyze (defaults to now) - * @returns Object with date information - */ -export function getDateInfo(date: Date = new Date()) { - return { - date, - year: date.getFullYear(), - month: date.getMonth() + 1, - monthName: MONTH_NAMES[date.getMonth()], - day: date.getDate(), - weekday: WEEKDAY_NAMES[date.getDay()], - friendlyDisplay: friendlyDate(date), - greeting: getGreeting(date), - }; -} - // Re-export MONTH_NAMES for convenience export { MONTH_NAMES }; diff --git a/lib/utils/math.ts b/lib/utils/math.ts index a201ce6..27b85b2 100644 --- a/lib/utils/math.ts +++ b/lib/utils/math.ts @@ -24,28 +24,3 @@ export function calculatePercentageChange( // Protege contra valores absurdos (retorna null se > 1 milhão %) return Number.isFinite(change) && Math.abs(change) < 1000000 ? change : null; } - -/** - * Calculates percentage of part relative to total - * @param part - Part value - * @param total - Total value - * @returns Percentage (0-100) - */ -export function calculatePercentage(part: number, total: number): number { - if (total === 0) { - return 0; - } - - return (part / total) * 100; -} - -/** - * Rounds number to specified decimal places - * @param value - Value to round - * @param decimals - Number of decimal places (default 2) - * @returns Rounded number - */ -export function roundToDecimals(value: number, decimals: number = 2): number { - const multiplier = 10 ** decimals; - return Math.round(value * multiplier) / multiplier; -} diff --git a/lib/utils/number.ts b/lib/utils/number.ts index 367b195..710e193 100644 --- a/lib/utils/number.ts +++ b/lib/utils/number.ts @@ -25,44 +25,3 @@ export function safeToNumber(value: unknown, defaultValue: number = 0): number { const parsed = Number(value); return Number.isNaN(parsed) ? defaultValue : parsed; } - -/** - * Safely parses integer from unknown value - * @param value - Value to parse - * @param defaultValue - Default value if parsing fails - * @returns Parsed integer or default value - */ -export function safeParseInt(value: unknown, defaultValue: number = 0): number { - if (typeof value === "number") { - return Math.trunc(value); - } - - if (typeof value === "string") { - const parsed = Number.parseInt(value, 10); - return Number.isNaN(parsed) ? defaultValue : parsed; - } - - return defaultValue; -} - -/** - * Safely parses float from unknown value - * @param value - Value to parse - * @param defaultValue - Default value if parsing fails - * @returns Parsed float or default value - */ -export function safeParseFloat( - value: unknown, - defaultValue: number = 0, -): number { - if (typeof value === "number") { - return value; - } - - if (typeof value === "string") { - const parsed = Number.parseFloat(value); - return Number.isNaN(parsed) ? defaultValue : parsed; - } - - return defaultValue; -} diff --git a/lib/utils/period/index.ts b/lib/utils/period/index.ts index 633ce0a..e861191 100644 --- a/lib/utils/period/index.ts +++ b/lib/utils/period/index.ts @@ -29,8 +29,6 @@ export const MONTH_NAMES = [ "dezembro", ] as const; -export type MonthName = (typeof MONTH_NAMES)[number]; - // ============================================================================ // CORE PARSING & FORMATTING (YYYY-MM format) // ============================================================================ @@ -63,20 +61,6 @@ export function formatPeriod(year: number, month: number): string { return `${year}-${String(month).padStart(2, "0")}`; } -/** - * Validates if period string is valid - * @param period - Period string to validate - * @returns True if valid, false otherwise - */ -export function isPeriodValid(period: string): boolean { - try { - parsePeriod(period); - return true; - } catch { - return false; - } -} - // ============================================================================ // PERIOD NAVIGATION // ============================================================================ @@ -139,22 +123,6 @@ export function addMonthsToPeriod(period: string, offset: number): string { return formatPeriod(nextYear, nextMonth); } -/** - * Gets the last N periods including the current one - * @param current - Current period in YYYY-MM format - * @param length - Number of periods to return - * @returns Array of period strings - */ -export function getLastPeriods(current: string, length: number): string[] { - const periods: string[] = []; - - for (let offset = length - 1; offset >= 0; offset -= 1) { - periods.push(addMonthsToPeriod(current, -offset)); - } - - return periods; -} - // ============================================================================ // PERIOD COMPARISON & RANGES // ============================================================================ diff --git a/lib/utils/string.ts b/lib/utils/string.ts index 8152521..48c9840 100644 --- a/lib/utils/string.ts +++ b/lib/utils/string.ts @@ -23,15 +23,6 @@ export function normalizeFilePath(path: string | null | undefined): string { return path?.split("/").filter(Boolean).pop() ?? ""; } -/** - * Normalizes whitespace in string (replaces multiple spaces with single space) - * @param value - String to normalize - * @returns String with normalized whitespace - */ -export function normalizeWhitespace(value: string): string { - return value.replace(/\s+/g, " ").trim(); -} - /** * Normalizes icon input - trims and returns null if empty * @param icon - Icon string to normalize