diff --git a/components/lancamentos/dialogs/mass-add-dialog.tsx b/components/lancamentos/dialogs/mass-add-dialog.tsx index 82fb122..a848958 100644 --- a/components/lancamentos/dialogs/mass-add-dialog.tsx +++ b/components/lancamentos/dialogs/mass-add-dialog.tsx @@ -3,7 +3,6 @@ import { RiAddLine, RiDeleteBinLine } from "@remixicon/react"; import { useMemo, useState } from "react"; import { toast } from "sonner"; -import { PeriodPicker } from "@/components/period-picker"; import { Button } from "@/components/ui/button"; import { CurrencyInput } from "@/components/ui/currency-input"; import { DatePicker } from "@/components/ui/date-picker"; @@ -16,6 +15,12 @@ import { DialogTitle, } from "@/components/ui/dialog"; import { Label } from "@/components/ui/label"; +import { MonthPicker } from "@/components/ui/monthpicker"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; import { Select, SelectContent, @@ -30,6 +35,7 @@ import { Spinner } from "@/components/ui/spinner"; import { groupAndSortCategorias } from "@/lib/lancamentos/categoria-helpers"; import { LANCAMENTO_PAYMENT_METHODS } from "@/lib/lancamentos/constants"; import { getTodayDateString } from "@/lib/utils/date"; +import { displayPeriod } from "@/lib/utils/period"; import type { SelectOption } from "../../types"; import { CategoriaSelectContent, @@ -40,6 +46,57 @@ import { } from "../select-items"; import { EstabelecimentoInput } from "../shared/estabelecimento-input"; +/** Payment methods sem Boleto para este modal */ +const MASS_ADD_PAYMENT_METHODS = LANCAMENTO_PAYMENT_METHODS.filter( + (m) => m !== "Boleto", +); + +function periodToDate(period: string): Date { + const [year, month] = period.split("-").map(Number); + return new Date(year, month - 1, 1); +} + +function dateToPeriod(date: Date): string { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, "0"); + return `${year}-${month}`; +} + +function InlinePeriodPicker({ + period, + onPeriodChange, +}: { + period: string; + onPeriodChange: (value: string) => void; +}) { + const [open, setOpen] = useState(false); + + return ( +
+ Fatura de + + + + + + { + onPeriodChange(dateToPeriod(date)); + setOpen(false); + }} + /> + + +
+ ); +} + interface MassAddDialogProps { open: boolean; onOpenChange: (open: boolean) => void; @@ -102,22 +159,15 @@ export function MassAddDialog({ LANCAMENTO_PAYMENT_METHODS[0], ); const [period, setPeriod] = useState(selectedPeriod); - // Formato: "conta:uuid" ou "cartao:uuid" - const [contaCartaoId, setContaCartaoId] = useState( - defaultCartaoId ? `cartao:${defaultCartaoId}` : undefined, + const [contaId, setContaId] = useState(undefined); + const [cartaoId, setCartaoId] = useState( + defaultCartaoId ?? undefined, ); // Quando defaultCartaoId está definido, exibe apenas o cartão específico const isLockedToCartao = !!defaultCartaoId; - // Deriva contaId e cartaoId do valor selecionado - const isCartaoSelected = contaCartaoId?.startsWith("cartao:"); - const contaId = contaCartaoId?.startsWith("conta:") - ? contaCartaoId.replace("conta:", "") - : undefined; - const cartaoId = contaCartaoId?.startsWith("cartao:") - ? contaCartaoId.replace("cartao:", "") - : undefined; + const isCartaoSelected = paymentMethod === "Cartão de crédito"; // Transaction rows const [transactions, setTransactions] = useState([ @@ -173,8 +223,12 @@ export function MassAddDialog({ const handleSubmit = async () => { // Validate conta/cartao selection - if (!contaCartaoId) { - toast.error("Selecione uma conta ou cartão para continuar"); + if (isCartaoSelected && !cartaoId) { + toast.error("Selecione um cartão para continuar"); + return; + } + if (!isCartaoSelected && !contaId) { + toast.error("Selecione uma conta para continuar"); return; } @@ -194,11 +248,11 @@ export function MassAddDialog({ const formData: MassAddFormData = { fixedFields: { transactionType, - paymentMethod: isCartaoSelected ? "Cartão de crédito" : paymentMethod, + paymentMethod, condition: "À vista", period, - contaId: contaId, - cartaoId: cartaoId, + contaId, + cartaoId, }, transactions: transactions.map((t) => ({ purchaseDate: t.purchaseDate, @@ -217,9 +271,8 @@ export function MassAddDialog({ setTransactionType("Despesa"); setPaymentMethod(LANCAMENTO_PAYMENT_METHODS[0]); setPeriod(selectedPeriod); - setContaCartaoId( - defaultCartaoId ? `cartao:${defaultCartaoId}` : undefined, - ); + setContaId(undefined); + setCartaoId(defaultCartaoId ?? undefined); setTransactions([ { id: crypto.randomUUID(), @@ -237,9 +290,6 @@ export function MassAddDialog({ } }; - // Show period picker only for credit card - const showPeriodPicker = isCartaoSelected; - return ( @@ -252,11 +302,11 @@ export function MassAddDialog({ -
+
{/* Fixed Fields Section */}

Valores Padrão

-
+
{/* Transaction Type */}
@@ -291,9 +341,9 @@ export function MassAddDialog({ setPaymentMethod(value); // Reset conta/cartao when changing payment method if (value === "Cartão de crédito") { - setContaCartaoId(undefined); + setContaId(undefined); } else { - setContaCartaoId(undefined); + setCartaoId(undefined); } }} > @@ -305,7 +355,7 @@ export function MassAddDialog({ - {LANCAMENTO_PAYMENT_METHODS.map((method) => ( + {MASS_ADD_PAYMENT_METHODS.map((method) => ( @@ -314,33 +364,19 @@ export function MassAddDialog({
- {/* Period - only for credit card */} - {showPeriodPicker ? ( + {/* Cartão (only for credit card) */} + {isCartaoSelected ? (
- - -
- ) : null} - - {/* Conta/Cartao */} -
- - + + + {cartaoId && + (() => { const selectedOption = cartaoOptions.find( (opt) => opt.value === cartaoId, ); @@ -351,7 +387,53 @@ export function MassAddDialog({ isCartao={true} /> ) : null; - } else { + })()} + + + + {cartaoOptions.length === 0 ? ( +
+

+ Nenhum cartão cadastrado +

+
+ ) : ( + cartaoOptions + .filter( + (option) => + !isLockedToCartao || + option.value === defaultCartaoId, + ) + .map((option) => ( + + + + )) + )} +
+ + {cartaoId ? ( + + ) : null} +
+ ) : null} + + {/* Conta (for non-credit-card methods) */} + {!isCartaoSelected ? ( +
+ + -
+ )) + )} + + +
+ ) : null}
@@ -428,7 +485,7 @@ export function MassAddDialog({ className="grid gap-2 border-b pb-3 border-dashed last:border-0" >
-
+