refactor: simplificar lancamento-dialog e mass-add-dialog

Substitui FaturaWarningDialog por deriveCreditCardPeriod() que calcula
o período da fatura automaticamente a partir da data de compra +
dia de fechamento/vencimento do cartão.

lancamento-dialog: remove periodDirty state, adiciona seção colapsável
"Condições e anotações", propaga closingDay/dueDay via cardInfo.

mass-add-dialog: unifica contaId/cartaoId em contaCartaoId com
parsing por prefixo, period picker apenas para cartão de crédito.

basic-fields-section: remove PeriodPicker (período agora auto-derivado),
move Estabelecimento para topo.

payment-method-section: adiciona InlinePeriodPicker como link
"Fatura de [mês]" com popover MonthPicker.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-02-26 17:23:23 +00:00
parent 96118d85e4
commit ac2ea63dbd
10 changed files with 693 additions and 677 deletions

View File

@@ -7,7 +7,6 @@ import {
cartoes,
categorias,
contas,
faturas,
lancamentos,
pagadores,
} from "@/db/schema";
@@ -33,7 +32,6 @@ import {
import { noteSchema, uuidSchema } from "@/lib/schemas/common";
import { formatDecimalForDbRequired } from "@/lib/utils/currency";
import { getTodayDate, parseLocalDateString } from "@/lib/utils/date";
import { getNextPeriod } from "@/lib/utils/period";
// ============================================================================
// Authorization Validation Functions
@@ -1641,59 +1639,6 @@ export async function deleteMultipleLancamentosAction(
}
}
// Check fatura payment status and card closing day for the given period
export async function checkFaturaStatusAction(
cartaoId: string,
period: string,
): Promise<{
shouldSuggestNext: boolean;
isPaid: boolean;
isAfterClosing: boolean;
closingDay: string | null;
cardName: string;
nextPeriod: string;
} | null> {
try {
const user = await getUser();
const cartao = await db.query.cartoes.findFirst({
where: and(eq(cartoes.id, cartaoId), eq(cartoes.userId, user.id)),
columns: { id: true, name: true, closingDay: true },
});
if (!cartao) return null;
const fatura = await db.query.faturas.findFirst({
where: and(
eq(faturas.cartaoId, cartaoId),
eq(faturas.userId, user.id),
eq(faturas.period, period),
),
columns: { paymentStatus: true },
});
const isPaid = fatura?.paymentStatus === "pago";
const today = new Date();
const currentPeriod = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, "0")}`;
const closingDayNum = Number.parseInt(cartao.closingDay ?? "", 10);
const isAfterClosing =
period === currentPeriod &&
!Number.isNaN(closingDayNum) &&
today.getDate() > closingDayNum;
return {
shouldSuggestNext: isPaid || isAfterClosing,
isPaid,
isAfterClosing,
closingDay: cartao.closingDay,
cardName: cartao.name,
nextPeriod: getNextPeriod(period),
};
} catch {
return null;
}
}
// Get unique establishment names from the last 3 months
export async function getRecentEstablishmentsAction(): Promise<string[]> {
try {