mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-06-09 14:56:00 +00:00
feat(transactions): adiciona dialogo de confirmacao ao descartar lancamentos massivos
Quando o usuario tenta fechar ou cancelar o dialogo de multiplos lancamentos com dados ainda nao salvos, agora exibe um ConfirmActionDialog pedindo confirmacao. Evita perda acidental de dados preenchidos. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
PAYMENT_METHODS,
|
||||
type TRANSACTION_TYPES,
|
||||
} from "@/features/transactions/lib/constants";
|
||||
import { ConfirmActionDialog } from "@/shared/components/confirm-action-dialog";
|
||||
import { Button } from "@/shared/components/ui/button";
|
||||
import { CurrencyInput } from "@/shared/components/ui/currency-input";
|
||||
import { DatePicker } from "@/shared/components/ui/date-picker";
|
||||
@@ -148,6 +149,9 @@ export function MassAddDialog({
|
||||
defaultCardId,
|
||||
}: MassAddDialogProps) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [isDirty, setIsDirty] = useState(false);
|
||||
const [confirmCloseOpen, setConfirmCloseOpen] = useState(false);
|
||||
const [cancelConfirmOpen, setCancelConfirmOpen] = useState(false);
|
||||
|
||||
// Fixed fields state (sempre ativos, sem checkboxes)
|
||||
const [transactionType, setTransactionType] =
|
||||
@@ -179,11 +183,22 @@ export function MassAddDialog({
|
||||
return groupAndSortCategories(filtered);
|
||||
}, [categoryOptions, transactionType]);
|
||||
|
||||
const resetForm = () => {
|
||||
setTransactionType("Despesa");
|
||||
setPaymentMethod(PAYMENT_METHODS[0]);
|
||||
setPeriod(selectedPeriod);
|
||||
setContaId(undefined);
|
||||
setCartaoId(defaultCardId ?? undefined);
|
||||
setTransactions([createEmptyTransactionRow(defaultPayerId)]);
|
||||
setIsDirty(false);
|
||||
};
|
||||
|
||||
const addTransaction = () => {
|
||||
setTransactions([
|
||||
...transactions,
|
||||
createEmptyTransactionRow(defaultPayerId),
|
||||
]);
|
||||
setIsDirty(true);
|
||||
};
|
||||
|
||||
const removeTransaction = (id: string) => {
|
||||
@@ -192,6 +207,7 @@ export function MassAddDialog({
|
||||
return;
|
||||
}
|
||||
setTransactions(transactions.filter((t) => t.id !== id));
|
||||
setIsDirty(true);
|
||||
};
|
||||
|
||||
const updateTransaction = (
|
||||
@@ -202,6 +218,7 @@ export function MassAddDialog({
|
||||
setTransactions(
|
||||
transactions.map((t) => (t.id === id ? { ...t, [field]: value } : t)),
|
||||
);
|
||||
setIsDirty(true);
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
@@ -250,13 +267,7 @@ export function MassAddDialog({
|
||||
try {
|
||||
await onSubmit(formData);
|
||||
onOpenChange(false);
|
||||
// Reset form
|
||||
setTransactionType("Despesa");
|
||||
setPaymentMethod(PAYMENT_METHODS[0]);
|
||||
setPeriod(selectedPeriod);
|
||||
setContaId(undefined);
|
||||
setCartaoId(defaultCardId ?? undefined);
|
||||
setTransactions([createEmptyTransactionRow(defaultPayerId)]);
|
||||
resetForm();
|
||||
} catch (_error) {
|
||||
// Error is handled by the onSubmit function
|
||||
} finally {
|
||||
@@ -265,7 +276,19 @@ export function MassAddDialog({
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<Dialog
|
||||
open={open}
|
||||
onOpenChange={(newOpen) => {
|
||||
if (!newOpen && isDirty) {
|
||||
setConfirmCloseOpen(true);
|
||||
} else {
|
||||
onOpenChange(newOpen);
|
||||
if (newOpen === false) {
|
||||
resetForm();
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogContent className="sm:max-w-3xl max-h-[90vh] overflow-y-auto p-6 sm:px-8">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Adicionar múltiplos lançamentos</DialogTitle>
|
||||
@@ -286,9 +309,10 @@ export function MassAddDialog({
|
||||
<Label htmlFor="transaction-type">Tipo de Transação</Label>
|
||||
<Select
|
||||
value={transactionType}
|
||||
onValueChange={(value) =>
|
||||
setTransactionType(value as MassAddTransactionType)
|
||||
}
|
||||
onValueChange={(value) => {
|
||||
setTransactionType(value as MassAddTransactionType);
|
||||
setIsDirty(true);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger id="transaction-type" className="w-full">
|
||||
<SelectValue>
|
||||
@@ -315,6 +339,7 @@ export function MassAddDialog({
|
||||
value={paymentMethod}
|
||||
onValueChange={(value) => {
|
||||
setPaymentMethod(value as MassAddPaymentMethod);
|
||||
setIsDirty(true);
|
||||
// Reset conta/cartao when changing payment method
|
||||
if (value === "Cartão de crédito") {
|
||||
setContaId(undefined);
|
||||
@@ -346,7 +371,10 @@ export function MassAddDialog({
|
||||
<Label htmlFor="cartao">Cartão</Label>
|
||||
<Select
|
||||
value={cardId}
|
||||
onValueChange={setCartaoId}
|
||||
onValueChange={(value) => {
|
||||
setCartaoId(value);
|
||||
setIsDirty(true);
|
||||
}}
|
||||
disabled={isLockedToCartao}
|
||||
>
|
||||
<SelectTrigger id="cartao" className="w-full">
|
||||
@@ -395,7 +423,10 @@ export function MassAddDialog({
|
||||
{cardId ? (
|
||||
<InlinePeriodPicker
|
||||
period={period}
|
||||
onPeriodChange={setPeriod}
|
||||
onPeriodChange={(value) => {
|
||||
setPeriod(value);
|
||||
setIsDirty(true);
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -405,7 +436,13 @@ export function MassAddDialog({
|
||||
{!isCartaoSelected ? (
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="conta">Conta</Label>
|
||||
<Select value={accountId} onValueChange={setContaId}>
|
||||
<Select
|
||||
value={accountId}
|
||||
onValueChange={(value) => {
|
||||
setContaId(value);
|
||||
setIsDirty(true);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger id="conta" className="w-full">
|
||||
<SelectValue placeholder="Selecione">
|
||||
{accountId &&
|
||||
@@ -635,7 +672,13 @@ export function MassAddDialog({
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => onOpenChange(false)}
|
||||
onClick={() => {
|
||||
if (isDirty) {
|
||||
setCancelConfirmOpen(true);
|
||||
} else {
|
||||
onOpenChange(false);
|
||||
}
|
||||
}}
|
||||
disabled={loading}
|
||||
>
|
||||
Cancelar
|
||||
@@ -646,6 +689,36 @@ export function MassAddDialog({
|
||||
{transactions.length === 1 ? "lançamento" : "lançamentos"}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
<ConfirmActionDialog
|
||||
open={confirmCloseOpen}
|
||||
onOpenChange={setConfirmCloseOpen}
|
||||
title="Descartar alterações?"
|
||||
description="Há lançamentos não salvos. Se fechar agora, todos os dados serão perdidos."
|
||||
confirmLabel="Descartar"
|
||||
cancelLabel="Continuar editando"
|
||||
confirmVariant="destructive"
|
||||
onConfirm={() => {
|
||||
setConfirmCloseOpen(false);
|
||||
onOpenChange(false);
|
||||
resetForm();
|
||||
}}
|
||||
/>
|
||||
|
||||
<ConfirmActionDialog
|
||||
open={cancelConfirmOpen}
|
||||
onOpenChange={setCancelConfirmOpen}
|
||||
title="Cancelar adição de lançamentos?"
|
||||
description="Há lançamentos não salvos. Se cancelar, todos os dados serão perdidos."
|
||||
confirmLabel="Cancelar"
|
||||
cancelLabel="Continuar editando"
|
||||
confirmVariant="destructive"
|
||||
onConfirm={() => {
|
||||
setCancelConfirmOpen(false);
|
||||
onOpenChange(false);
|
||||
resetForm();
|
||||
}}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user