diff --git a/packages/webapp/src/components/DialogsContainer.tsx b/packages/webapp/src/components/DialogsContainer.tsx index 7f7d2729a..3789a974e 100644 --- a/packages/webapp/src/components/DialogsContainer.tsx +++ b/packages/webapp/src/components/DialogsContainer.tsx @@ -50,6 +50,16 @@ import { DisconnectBankAccountDialog } from '@/containers/CashFlow/AccountTransa import { SharePaymentLinkDialog } from '@/containers/PaymentLink/dialogs/SharePaymentLinkDialog/SharePaymentLinkDialog'; import { SelectPaymentMethodsDialog } from '@/containers/PaymentLink/dialogs/SelectPaymentMethodsDialog/SelectPaymentMethodsDialog'; import ApiKeysGenerateDialog from '@/containers/Dialogs/ApiKeysGenerateDialog'; +import InvoiceBulkDeleteDialog from '@/containers/Dialogs/Invoices/InvoiceBulkDeleteDialog'; +import EstimateBulkDeleteDialog from '@/containers/Dialogs/Estimates/EstimateBulkDeleteDialog'; +import ReceiptBulkDeleteDialog from '@/containers/Dialogs/Receipts/ReceiptBulkDeleteDialog'; +import CreditNoteBulkDeleteDialog from '@/containers/Dialogs/CreditNotes/CreditNoteBulkDeleteDialog'; +import PaymentReceivedBulkDeleteDialog from '@/containers/Dialogs/PaymentsReceived/PaymentReceivedBulkDeleteDialog'; +import BillBulkDeleteDialog from '@/containers/Dialogs/Bills/BillBulkDeleteDialog'; +import VendorCreditBulkDeleteDialog from '@/containers/Dialogs/VendorCredits/VendorCreditBulkDeleteDialog'; +import ManualJournalBulkDeleteDialog from '@/containers/Dialogs/ManualJournals/ManualJournalBulkDeleteDialog'; +import ExpenseBulkDeleteDialog from '@/containers/Dialogs/Expenses/ExpenseBulkDeleteDialog'; +import AccountBulkDeleteDialog from '@/containers/Dialogs/Accounts/AccountBulkDeleteDialog'; /** * Dialogs container. @@ -139,6 +149,24 @@ export default function DialogsContainer() { + + + + + + + + + + { history.push('/make-journal-entry'); }; - // Handle delete button click. + const { + openBulkDeleteDialog, + isValidatingBulkDeleteManualJournals, + } = useBulkDeleteManualJournalsDialog(); + const handleBulkDelete = () => { - openAlert('journals-bulk-delete', { - journalsIds: manualJournalsSelectedRows, - }); + openBulkDeleteDialog(manualJournalsSelectedRows); }; // Handle tab change. @@ -120,6 +119,7 @@ function ManualJournalActionsBar({ text={} intent={Intent.DANGER} onClick={handleBulkDelete} + disabled={isValidatingBulkDeleteManualJournals} /> @@ -208,7 +208,6 @@ function ManualJournalActionsBar({ export default compose( withDialogActions, - withAlertActions, withManualJournalsActions, withSettingsActions, withManualJournals(({ manualJournalsTableState, manualJournalsSelectedRows }) => ({ diff --git a/packages/webapp/src/containers/Accounting/JournalsLanding/ManualJournalsAlerts.tsx b/packages/webapp/src/containers/Accounting/JournalsLanding/ManualJournalsAlerts.tsx index fe4a242e2..d45132c5a 100644 --- a/packages/webapp/src/containers/Accounting/JournalsLanding/ManualJournalsAlerts.tsx +++ b/packages/webapp/src/containers/Accounting/JournalsLanding/ManualJournalsAlerts.tsx @@ -8,10 +8,6 @@ const JournalPublishAlert = React.lazy( () => import('@/containers/Alerts/ManualJournals/JournalPublishAlert'), ); -const JournalBulkDeleteAlert = React.lazy( - () => import('@/containers/Alerts/ManualJournals/JournalBulkDeleteAlert'), -); - /** * Manual journals alerts. */ @@ -19,5 +15,4 @@ const JournalBulkDeleteAlert = React.lazy( export default [ { name: 'journal-delete', component: JournalDeleteAlert }, { name: 'journal-publish', component: JournalPublishAlert }, - { name: 'journals-bulk-delete', component: JournalBulkDeleteAlert }, ]; diff --git a/packages/webapp/src/containers/Accounting/JournalsLanding/hooks/use-bulk-delete-manual-journals-dialog.ts b/packages/webapp/src/containers/Accounting/JournalsLanding/hooks/use-bulk-delete-manual-journals-dialog.ts new file mode 100644 index 000000000..7a507e0fc --- /dev/null +++ b/packages/webapp/src/containers/Accounting/JournalsLanding/hooks/use-bulk-delete-manual-journals-dialog.ts @@ -0,0 +1,20 @@ +// @ts-nocheck +import { DialogsName } from '@/constants/dialogs'; +import { useValidateBulkDeleteManualJournals } from '@/hooks/query/manualJournals'; +import { useBulkDeleteDialog } from '@/hooks/dialogs/useBulkDeleteDialog'; + +export const useBulkDeleteManualJournalsDialog = () => { + const validateBulkDeleteMutation = useValidateBulkDeleteManualJournals(); + const { + openBulkDeleteDialog, + closeBulkDeleteDialog, + isValidatingBulkDelete, + } = useBulkDeleteDialog(DialogsName.ManualJournalBulkDelete, validateBulkDeleteMutation); + + return { + openBulkDeleteDialog, + closeBulkDeleteDialog, + isValidatingBulkDeleteManualJournals: isValidatingBulkDelete, + }; +}; + diff --git a/packages/webapp/src/containers/Accounts/AccountsActionsBar.tsx b/packages/webapp/src/containers/Accounts/AccountsActionsBar.tsx index 67c316ba2..0859368e1 100644 --- a/packages/webapp/src/containers/Accounts/AccountsActionsBar.tsx +++ b/packages/webapp/src/containers/Accounts/AccountsActionsBar.tsx @@ -34,6 +34,7 @@ import { useHistory } from 'react-router-dom'; import { useRefreshAccounts } from '@/hooks/query/accounts'; import { useAccountsChartContext } from './AccountsChartProvider'; import { useDownloadExportPdf } from '@/hooks/query/FinancialReports/use-export-pdf'; +import { useBulkDeleteAccountsDialog } from './hooks/use-bulk-delete-accounts-dialog'; import withAccounts from './withAccounts'; import withAccountsTableActions from './withAccountsTableActions'; @@ -78,9 +79,15 @@ function AccountsActionsBar({ // Accounts refresh action. const { refresh } = useRefreshAccounts(); + // Bulk delete accounts dialog. + const { + openBulkDeleteDialog, + isValidatingBulkDeleteAccounts, + } = useBulkDeleteAccountsDialog(); + // Handle bulk accounts delete. const handleBulkDelete = () => { - openAlert('accounts-bulk-delete', { accountsIds: accountsSelectedRows }); + openBulkDeleteDialog(accountsSelectedRows); }; // Handle bulk accounts activate. const handelBulkActivate = () => { @@ -148,6 +155,7 @@ function AccountsActionsBar({ text={} intent={Intent.DANGER} onClick={handleBulkDelete} + disabled={isValidatingBulkDeleteAccounts} /> diff --git a/packages/webapp/src/containers/Accounts/AccountsAlerts.tsx b/packages/webapp/src/containers/Accounts/AccountsAlerts.tsx index 8d6d24cc5..4f6f1cfaa 100644 --- a/packages/webapp/src/containers/Accounts/AccountsAlerts.tsx +++ b/packages/webapp/src/containers/Accounts/AccountsAlerts.tsx @@ -10,9 +10,6 @@ const AccountInactivateAlert = React.lazy( const AccountActivateAlert = React.lazy( () => import('@/containers/Alerts/Accounts/AccountActivateAlert'), ); -const AccountBulkDeleteAlert = React.lazy( - () => import('@/containers/Alerts/Accounts/AccountBulkDeleteAlert'), -); const AccountBulkActivateAlert = React.lazy( () => import('@/containers/Alerts/Accounts/AccountBulkActivateAlert'), ); @@ -24,7 +21,6 @@ export default [ { name: 'account-delete', component: AccountDeleteAlert }, { name: 'account-inactivate', component: AccountInactivateAlert }, { name: 'account-activate', component: AccountActivateAlert }, - { name: 'accounts-bulk-delete', component: AccountBulkDeleteAlert }, { name: 'accounts-bulk-activate', component: AccountBulkActivateAlert }, { name: 'accounts-bulk-inactivate', component: AccountBulkInactivateAlert }, ]; diff --git a/packages/webapp/src/containers/Accounts/hooks/use-bulk-delete-accounts-dialog.ts b/packages/webapp/src/containers/Accounts/hooks/use-bulk-delete-accounts-dialog.ts new file mode 100644 index 000000000..2c69d8180 --- /dev/null +++ b/packages/webapp/src/containers/Accounts/hooks/use-bulk-delete-accounts-dialog.ts @@ -0,0 +1,20 @@ +// @ts-nocheck +import { DialogsName } from '@/constants/dialogs'; +import { useValidateBulkDeleteAccounts } from '@/hooks/query/accounts'; +import { useBulkDeleteDialog } from '@/hooks/dialogs/useBulkDeleteDialog'; + +export const useBulkDeleteAccountsDialog = () => { + const validateBulkDeleteMutation = useValidateBulkDeleteAccounts(); + const { + openBulkDeleteDialog, + closeBulkDeleteDialog, + isValidatingBulkDelete, + } = useBulkDeleteDialog(DialogsName.AccountBulkDelete, validateBulkDeleteMutation); + + return { + openBulkDeleteDialog, + closeBulkDeleteDialog, + isValidatingBulkDeleteAccounts: isValidatingBulkDelete, + }; +}; + diff --git a/packages/webapp/src/containers/Alerts/Accounts/AccountBulkDeleteAlert.tsx b/packages/webapp/src/containers/Alerts/Accounts/AccountBulkDeleteAlert.tsx deleted file mode 100644 index dc889c115..000000000 --- a/packages/webapp/src/containers/Alerts/Accounts/AccountBulkDeleteAlert.tsx +++ /dev/null @@ -1,75 +0,0 @@ -// @ts-nocheck -import React from 'react'; -import { FormattedMessage as T } from '@/components'; -import intl from 'react-intl-universal'; -import { Intent, Alert } from '@blueprintjs/core'; -import { queryCache } from 'react-query'; -import { AppToaster } from '@/components'; - -import { handleDeleteErrors } from '@/containers/Accounts/utils'; -import { useBulkDeleteAccounts } from '@/hooks/query/accounts'; - -import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect'; -import withAlertActions from '@/containers/Alert/withAlertActions'; - -import { compose } from '@/utils'; - -/** - * Account bulk delete alert. - */ -function AccountBulkDeleteAlert({ - // #ownProps - name, - - // #withAlertStoreConnect - isOpen, - payload: { accountsIds }, - - // #withAlertActions - closeAlert, -}) { - const { mutateAsync: bulkDeleteAccounts, isLoading } = useBulkDeleteAccounts(); - - const handleCancel = () => { - closeAlert(name); - }; - // Handle confirm accounts bulk delete. - const handleConfirmBulkDelete = () => { - bulkDeleteAccounts(accountsIds) - .then(() => { - AppToaster.show({ - message: intl.get('the_accounts_has_been_successfully_deleted'), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('accounts-table'); - closeAlert(name); - }) - .catch((errors) => { - handleDeleteErrors(errors); - }); - }; - - return ( - } - confirmButtonText={ - - } - icon="trash" - intent={Intent.DANGER} - isOpen={isOpen} - onCancel={handleCancel} - onConfirm={handleConfirmBulkDelete} - loading={isLoading} - > -

- -

-
- ); -} - -export default compose( - withAlertStoreConnect(), - withAlertActions, -)(AccountBulkDeleteAlert); diff --git a/packages/webapp/src/containers/Alerts/Bills/BillBulkDeleteAlert.tsx b/packages/webapp/src/containers/Alerts/Bills/BillBulkDeleteAlert.tsx deleted file mode 100644 index 8ba15d370..000000000 --- a/packages/webapp/src/containers/Alerts/Bills/BillBulkDeleteAlert.tsx +++ /dev/null @@ -1,69 +0,0 @@ -// @ts-nocheck -import React from 'react'; -import { FormattedMessage as T } from '@/components'; -import intl from 'react-intl-universal'; -import { Intent, Alert } from '@blueprintjs/core'; -import { queryCache } from 'react-query'; -import { AppToaster } from '@/components'; - -import { useBulkDeleteBills } from '@/hooks/query/bills'; -import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect'; -import withAlertActions from '@/containers/Alert/withAlertActions'; - -import { compose } from '@/utils'; - -/** - * Bill bulk delete alert. - */ -function BillBulkDeleteAlert({ - name, - isOpen, - payload: { billsIds }, - closeAlert, -}) { - const { mutateAsync: bulkDeleteBills, isLoading } = useBulkDeleteBills(); - - const handleCancel = () => { - closeAlert(name); - }; - - const handleConfirmBulkDelete = () => { - bulkDeleteBills(billsIds) - .then(() => { - AppToaster.show({ - message: intl.get('the_bills_has_been_deleted_successfully'), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('bills-table'); - closeAlert(name); - }) - .catch((errors) => { - // Handle errors - }); - }; - - return ( - } - confirmButtonText={ - - } - icon="trash" - intent={Intent.DANGER} - isOpen={isOpen} - onCancel={handleCancel} - onConfirm={handleConfirmBulkDelete} - loading={isLoading} - > -

- -

-
- ); -} - -export default compose( - withAlertStoreConnect(), - withAlertActions, -)(BillBulkDeleteAlert); - diff --git a/packages/webapp/src/containers/Alerts/CreditNotes/CreditNoteBulkDeleteAlert.tsx b/packages/webapp/src/containers/Alerts/CreditNotes/CreditNoteBulkDeleteAlert.tsx deleted file mode 100644 index 3366ed108..000000000 --- a/packages/webapp/src/containers/Alerts/CreditNotes/CreditNoteBulkDeleteAlert.tsx +++ /dev/null @@ -1,69 +0,0 @@ -// @ts-nocheck -import React from 'react'; -import { FormattedMessage as T } from '@/components'; -import intl from 'react-intl-universal'; -import { Intent, Alert } from '@blueprintjs/core'; -import { queryCache } from 'react-query'; -import { AppToaster } from '@/components'; - -import { useBulkDeleteCreditNotes } from '@/hooks/query/creditNote'; -import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect'; -import withAlertActions from '@/containers/Alert/withAlertActions'; - -import { compose } from '@/utils'; - -/** - * Credit note bulk delete alert. - */ -function CreditNoteBulkDeleteAlert({ - name, - isOpen, - payload: { creditNotesIds }, - closeAlert, -}) { - const { mutateAsync: bulkDeleteCreditNotes, isLoading } = useBulkDeleteCreditNotes(); - - const handleCancel = () => { - closeAlert(name); - }; - - const handleConfirmBulkDelete = () => { - bulkDeleteCreditNotes(creditNotesIds) - .then(() => { - AppToaster.show({ - message: intl.get('the_credit_notes_has_been_deleted_successfully'), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('credit-notes-table'); - closeAlert(name); - }) - .catch((errors) => { - // Handle errors - }); - }; - - return ( - } - confirmButtonText={ - - } - icon="trash" - intent={Intent.DANGER} - isOpen={isOpen} - onCancel={handleCancel} - onConfirm={handleConfirmBulkDelete} - loading={isLoading} - > -

- -

-
- ); -} - -export default compose( - withAlertStoreConnect(), - withAlertActions, -)(CreditNoteBulkDeleteAlert); - diff --git a/packages/webapp/src/containers/Alerts/Estimates/EstimateBulkDeleteAlert.tsx b/packages/webapp/src/containers/Alerts/Estimates/EstimateBulkDeleteAlert.tsx deleted file mode 100644 index 797cf19d7..000000000 --- a/packages/webapp/src/containers/Alerts/Estimates/EstimateBulkDeleteAlert.tsx +++ /dev/null @@ -1,69 +0,0 @@ -// @ts-nocheck -import React from 'react'; -import { FormattedMessage as T } from '@/components'; -import intl from 'react-intl-universal'; -import { Intent, Alert } from '@blueprintjs/core'; -import { queryCache } from 'react-query'; -import { AppToaster } from '@/components'; - -import { useBulkDeleteEstimates } from '@/hooks/query/estimates'; -import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect'; -import withAlertActions from '@/containers/Alert/withAlertActions'; - -import { compose } from '@/utils'; - -/** - * Estimate bulk delete alert. - */ -function EstimateBulkDeleteAlert({ - name, - isOpen, - payload: { estimatesIds }, - closeAlert, -}) { - const { mutateAsync: bulkDeleteEstimates, isLoading } = useBulkDeleteEstimates(); - - const handleCancel = () => { - closeAlert(name); - }; - - const handleConfirmBulkDelete = () => { - bulkDeleteEstimates(estimatesIds) - .then(() => { - AppToaster.show({ - message: intl.get('the_estimates_has_been_deleted_successfully'), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('estimates-table'); - closeAlert(name); - }) - .catch((errors) => { - // Handle errors - }); - }; - - return ( - } - confirmButtonText={ - - } - icon="trash" - intent={Intent.DANGER} - isOpen={isOpen} - onCancel={handleCancel} - onConfirm={handleConfirmBulkDelete} - loading={isLoading} - > -

- -

-
- ); -} - -export default compose( - withAlertStoreConnect(), - withAlertActions, -)(EstimateBulkDeleteAlert); - diff --git a/packages/webapp/src/containers/Alerts/Expenses/ExpenseBulkDeleteAlert.tsx b/packages/webapp/src/containers/Alerts/Expenses/ExpenseBulkDeleteAlert.tsx deleted file mode 100644 index 625d352da..000000000 --- a/packages/webapp/src/containers/Alerts/Expenses/ExpenseBulkDeleteAlert.tsx +++ /dev/null @@ -1,68 +0,0 @@ -// @ts-nocheck -import React from 'react'; -import { FormattedMessage as T } from '@/components'; -import intl from 'react-intl-universal'; -import { Intent, Alert } from '@blueprintjs/core'; -import { queryCache } from 'react-query'; -import { AppToaster } from '@/components'; - -import { useBulkDeleteExpenses } from '@/hooks/query/expenses'; -import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect'; -import withAlertActions from '@/containers/Alert/withAlertActions'; - -import { compose } from '@/utils'; - -/** - * Expense bulk delete alert. - */ -function ExpenseBulkDeleteAlert({ - closeAlert, - name, - payload: { expensesIds }, - isOpen, -}) { - const { mutateAsync: bulkDeleteExpenses, isLoading } = useBulkDeleteExpenses(); - - const handleCancel = () => { - closeAlert(name); - }; - - const handleConfirmBulkDelete = () => { - bulkDeleteExpenses(expensesIds) - .then(() => { - AppToaster.show({ - message: intl.get('the_expenses_have_been_deleted_successfully'), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('expenses-table'); - closeAlert(name); - }) - .catch((errors) => { - // Handle errors - }); - }; - - return ( - } - confirmButtonText={ - - } - icon="trash" - intent={Intent.DANGER} - isOpen={isOpen} - onCancel={handleCancel} - onConfirm={handleConfirmBulkDelete} - loading={isLoading} - > -

- -

-
- ); -} - -export default compose( - withAlertStoreConnect(), - withAlertActions, -)(ExpenseBulkDeleteAlert); diff --git a/packages/webapp/src/containers/Alerts/Invoices/InvoiceBulkDeleteAlert.tsx b/packages/webapp/src/containers/Alerts/Invoices/InvoiceBulkDeleteAlert.tsx deleted file mode 100644 index 80038bd3e..000000000 --- a/packages/webapp/src/containers/Alerts/Invoices/InvoiceBulkDeleteAlert.tsx +++ /dev/null @@ -1,69 +0,0 @@ -// @ts-nocheck -import React from 'react'; -import { FormattedMessage as T } from '@/components'; -import intl from 'react-intl-universal'; -import { Intent, Alert } from '@blueprintjs/core'; -import { queryCache } from 'react-query'; - -import { AppToaster } from '@/components'; -import { useBulkDeleteInvoices } from '@/hooks/query/invoices'; -import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect'; -import withAlertActions from '@/containers/Alert/withAlertActions'; - -import { compose } from '@/utils'; - -/** - * Invoice bulk delete alert. - */ -function InvoiceBulkDeleteAlert({ - name, - isOpen, - payload: { invoicesIds }, - closeAlert, -}) { - const { mutateAsync: bulkDeleteInvoices, isLoading } = useBulkDeleteInvoices(); - - const handleCancel = () => { - closeAlert(name); - }; - - const handleConfirmBulkDelete = () => { - bulkDeleteInvoices(invoicesIds) - .then(() => { - AppToaster.show({ - message: intl.get('the_invoices_has_been_deleted_successfully'), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('invoices-table'); - closeAlert(name); - }) - .catch((errors) => { - // Handle errors - }); - }; - - return ( - } - confirmButtonText={ - - } - icon="trash" - intent={Intent.DANGER} - isOpen={isOpen} - onCancel={handleCancel} - onConfirm={handleConfirmBulkDelete} - loading={isLoading} - > -

- -

-
- ); -} - -export default compose( - withAlertStoreConnect(), - withAlertActions, -)(InvoiceBulkDeleteAlert); - diff --git a/packages/webapp/src/containers/Alerts/ManualJournals/JournalBulkDeleteAlert.tsx b/packages/webapp/src/containers/Alerts/ManualJournals/JournalBulkDeleteAlert.tsx deleted file mode 100644 index e7371dde6..000000000 --- a/packages/webapp/src/containers/Alerts/ManualJournals/JournalBulkDeleteAlert.tsx +++ /dev/null @@ -1,68 +0,0 @@ -// @ts-nocheck -import React from 'react'; -import { FormattedMessage as T } from '@/components'; -import intl from 'react-intl-universal'; -import { Intent, Alert } from '@blueprintjs/core'; -import { queryCache } from 'react-query'; -import { AppToaster } from '@/components'; - -import { useBulkDeleteManualJournals } from '@/hooks/query/manualJournals'; -import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect'; -import withAlertActions from '@/containers/Alert/withAlertActions'; - -import { compose } from '@/utils'; - -/** - * Manual journal bulk delete alert. - */ -function JournalBulkDeleteAlert({ - name, - isOpen, - payload: { journalsIds }, - closeAlert, -}) { - const { mutateAsync: bulkDeleteManualJournals, isLoading } = useBulkDeleteManualJournals(); - - const handleCancel = () => { - closeAlert(name); - }; - - const handleConfirmBulkDelete = () => { - bulkDeleteManualJournals(journalsIds) - .then(() => { - AppToaster.show({ - message: intl.get('the_journals_has_been_deleted_successfully'), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('manual-journals-table'); - closeAlert(name); - }) - .catch((errors) => { - // Handle errors - }); - }; - - return ( - } - confirmButtonText={ - - } - icon="trash" - intent={Intent.DANGER} - isOpen={isOpen} - onCancel={handleCancel} - onConfirm={handleConfirmBulkDelete} - loading={isLoading} - > -

- -

-
- ); -} - -export default compose( - withAlertStoreConnect(), - withAlertActions, -)(JournalBulkDeleteAlert); diff --git a/packages/webapp/src/containers/Alerts/PaymentReceived/PaymentReceivedBulkDeleteAlert.tsx b/packages/webapp/src/containers/Alerts/PaymentReceived/PaymentReceivedBulkDeleteAlert.tsx deleted file mode 100644 index d65227ece..000000000 --- a/packages/webapp/src/containers/Alerts/PaymentReceived/PaymentReceivedBulkDeleteAlert.tsx +++ /dev/null @@ -1,68 +0,0 @@ -// @ts-nocheck -import React from 'react'; -import { FormattedMessage as T } from '@/components'; -import intl from 'react-intl-universal'; -import { Intent, Alert } from '@blueprintjs/core'; -import { queryCache } from 'react-query'; -import { AppToaster } from '@/components'; - -import { useBulkDeletePaymentReceives } from '@/hooks/query/paymentReceives'; -import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect'; -import withAlertActions from '@/containers/Alert/withAlertActions'; - -import { compose } from '@/utils'; - -/** - * Payment received bulk delete alert. - */ -function PaymentReceivedBulkDeleteAlert({ - name, - isOpen, - payload: { paymentsReceivedIds }, - closeAlert, -}) { - const { mutateAsync: bulkDeletePaymentReceives, isLoading } = useBulkDeletePaymentReceives(); - - const handleCancel = () => { - closeAlert(name); - }; - const handleConfirmBulkDelete = () => { - bulkDeletePaymentReceives(paymentsReceivedIds) - .then(() => { - AppToaster.show({ - message: intl.get('the_payments_received_has_been_deleted_successfully'), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('payments-received-table'); - closeAlert(name); - }) - .catch((errors) => { - // Handle errors - }); - }; - - return ( - } - confirmButtonText={ - - } - icon="trash" - intent={Intent.DANGER} - isOpen={isOpen} - onCancel={handleCancel} - onConfirm={handleConfirmBulkDelete} - loading={isLoading} - > -

- -

-
- ); -} - -export default compose( - withAlertStoreConnect(), - withAlertActions, -)(PaymentReceivedBulkDeleteAlert); - diff --git a/packages/webapp/src/containers/Alerts/Receipts/ReceiptBulkDeleteAlert.tsx b/packages/webapp/src/containers/Alerts/Receipts/ReceiptBulkDeleteAlert.tsx deleted file mode 100644 index 3a6d02c66..000000000 --- a/packages/webapp/src/containers/Alerts/Receipts/ReceiptBulkDeleteAlert.tsx +++ /dev/null @@ -1,68 +0,0 @@ -// @ts-nocheck -import React from 'react'; -import { FormattedMessage as T } from '@/components'; -import intl from 'react-intl-universal'; -import { Intent, Alert } from '@blueprintjs/core'; -import { queryCache } from 'react-query'; -import { AppToaster } from '@/components'; - -import { useBulkDeleteReceipts } from '@/hooks/query/receipts'; -import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect'; -import withAlertActions from '@/containers/Alert/withAlertActions'; - -import { compose } from '@/utils'; - -/** - * Receipt bulk delete alert. - */ -function ReceiptBulkDeleteAlert({ - name, - isOpen, - payload: { receiptsIds }, - closeAlert, -}) { - const { mutateAsync: bulkDeleteReceipts, isLoading } = useBulkDeleteReceipts(); - - const handleCancel = () => { - closeAlert(name); - }; - const handleConfirmBulkDelete = () => { - bulkDeleteReceipts(receiptsIds) - .then(() => { - AppToaster.show({ - message: intl.get('the_receipts_has_been_deleted_successfully'), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('sale-receipts-table'); - closeAlert(name); - }) - .catch((errors) => { - // Handle errors - }); - }; - - return ( - } - confirmButtonText={ - - } - icon="trash" - intent={Intent.DANGER} - isOpen={isOpen} - onCancel={handleCancel} - onConfirm={handleConfirmBulkDelete} - loading={isLoading} - > -

- -

-
- ); -} - -export default compose( - withAlertStoreConnect(), - withAlertActions, -)(ReceiptBulkDeleteAlert); - diff --git a/packages/webapp/src/containers/Alerts/VendorCeditNotes/VendorCreditBulkDeleteAlert.tsx b/packages/webapp/src/containers/Alerts/VendorCeditNotes/VendorCreditBulkDeleteAlert.tsx deleted file mode 100644 index 0f860bb0e..000000000 --- a/packages/webapp/src/containers/Alerts/VendorCeditNotes/VendorCreditBulkDeleteAlert.tsx +++ /dev/null @@ -1,69 +0,0 @@ -// @ts-nocheck -import React from 'react'; -import { FormattedMessage as T } from '@/components'; -import intl from 'react-intl-universal'; -import { Intent, Alert } from '@blueprintjs/core'; -import { queryCache } from 'react-query'; -import { AppToaster } from '@/components'; - -import { useBulkDeleteVendorCredits } from '@/hooks/query/vendorCredit'; -import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect'; -import withAlertActions from '@/containers/Alert/withAlertActions'; - -import { compose } from '@/utils'; - -/** - * Vendor credit bulk delete alert. - */ -function VendorCreditBulkDeleteAlert({ - name, - isOpen, - payload: { vendorCreditsIds }, - closeAlert, -}) { - const { mutateAsync: bulkDeleteVendorCredits, isLoading } = useBulkDeleteVendorCredits(); - - const handleCancel = () => { - closeAlert(name); - }; - - const handleConfirmBulkDelete = () => { - bulkDeleteVendorCredits(vendorCreditsIds) - .then(() => { - AppToaster.show({ - message: intl.get('the_vendor_credits_has_been_deleted_successfully'), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('vendor-credits-table'); - closeAlert(name); - }) - .catch((errors) => { - // Handle errors - }); - }; - - return ( - } - confirmButtonText={ - - } - icon="trash" - intent={Intent.DANGER} - isOpen={isOpen} - onCancel={handleCancel} - onConfirm={handleConfirmBulkDelete} - loading={isLoading} - > -

- -

-
- ); -} - -export default compose( - withAlertStoreConnect(), - withAlertActions, -)(VendorCreditBulkDeleteAlert); - diff --git a/packages/webapp/src/containers/Dialogs/Accounts/AccountBulkDeleteDialog.tsx b/packages/webapp/src/containers/Dialogs/Accounts/AccountBulkDeleteDialog.tsx new file mode 100644 index 000000000..0111f9eb3 --- /dev/null +++ b/packages/webapp/src/containers/Dialogs/Accounts/AccountBulkDeleteDialog.tsx @@ -0,0 +1,103 @@ +// @ts-nocheck +import React from 'react'; +import { Button, Classes, Dialog, Intent } from '@blueprintjs/core'; +import { FormattedMessage as T, AppToaster } from '@/components'; +import intl from 'react-intl-universal'; +import { queryCache } from 'react-query'; + +import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent'; +import { useBulkDeleteAccounts } from '@/hooks/query/accounts'; +import withDialogRedux from '@/components/DialogReduxConnect'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import withAccountsTableActions from '@/containers/Accounts/withAccountsTableActions'; +import { compose } from '@/utils'; +import { handleDeleteErrors } from '@/containers/Accounts/utils'; + +function AccountBulkDeleteDialog({ + dialogName, + isOpen, + payload: { + ids = [], + deletableCount = 0, + undeletableCount = 0, + totalSelected = ids.length, + } = {}, + + // #withAccountsTableActions + setAccountsSelectedRows, + + // #withDialogActions + closeDialog, +}) { + const { mutateAsync: bulkDeleteAccounts, isLoading } = useBulkDeleteAccounts(); + + const handleCancel = () => { + closeDialog(dialogName); + }; + + const handleConfirmBulkDelete = () => { + bulkDeleteAccounts({ + ids, + skipUndeletable: true, + }) + .then(() => { + AppToaster.show({ + message: intl.get('the_accounts_has_been_successfully_deleted'), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('accounts-table'); + closeDialog(dialogName); + setAccountsSelectedRows([]); + }) + .catch((errors) => { + handleDeleteErrors(errors); + }); + }; + + return ( + + } + isOpen={isOpen} + onClose={handleCancel} + canEscapeKeyClose={!isLoading} + canOutsideClickClose={!isLoading} + > + + +
+
+ + + +
+
+
+ ); +} + +export default compose( + withDialogRedux(), + withDialogActions, + withAccountsTableActions, +)(AccountBulkDeleteDialog); + diff --git a/packages/webapp/src/containers/Dialogs/Bills/BillBulkDeleteDialog.tsx b/packages/webapp/src/containers/Dialogs/Bills/BillBulkDeleteDialog.tsx new file mode 100644 index 000000000..a484cb8a9 --- /dev/null +++ b/packages/webapp/src/containers/Dialogs/Bills/BillBulkDeleteDialog.tsx @@ -0,0 +1,105 @@ +// @ts-nocheck +import React from 'react'; +import { Button, Classes, Dialog, Intent } from '@blueprintjs/core'; +import { FormattedMessage as T, AppToaster } from '@/components'; +import intl from 'react-intl-universal'; +import { queryCache } from 'react-query'; + +import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent'; +import { useBulkDeleteBills } from '@/hooks/query/bills'; +import withDialogRedux from '@/components/DialogReduxConnect'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import withBillsActions from '@/containers/Purchases/Bills/BillsLanding/withBillsActions'; +import { compose } from '@/utils'; + +function BillBulkDeleteDialog({ + dialogName, + isOpen, + payload: { + ids = [], + deletableCount = 0, + undeletableCount = 0, + totalSelected = ids.length, + } = {}, + + // #withBillsActions + setBillsSelectedRows, + + // #withDialogActions + closeDialog, +}) { + const { mutateAsync: bulkDeleteBills, isLoading } = useBulkDeleteBills(); + + const handleCancel = () => { + closeDialog(dialogName); + }; + + const handleConfirmBulkDelete = () => { + bulkDeleteBills({ + ids, + skipUndeletable: true, + }) + .then(() => { + AppToaster.show({ + message: intl.get('the_bills_has_been_deleted_successfully'), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('bills-table'); + closeDialog(dialogName); + setBillsSelectedRows([]); + }) + .catch(() => { + AppToaster.show({ + message: intl.get('something_went_wrong'), + intent: Intent.DANGER, + }); + }); + }; + + return ( + + } + isOpen={isOpen} + onClose={handleCancel} + canEscapeKeyClose={!isLoading} + canOutsideClickClose={!isLoading} + > + + +
+
+ + + +
+
+
+ ); +} + +export default compose( + withDialogRedux(), + withDialogActions, + withBillsActions, +)(BillBulkDeleteDialog); + diff --git a/packages/webapp/src/containers/Dialogs/CreditNotes/CreditNoteBulkDeleteDialog.tsx b/packages/webapp/src/containers/Dialogs/CreditNotes/CreditNoteBulkDeleteDialog.tsx new file mode 100644 index 000000000..731cbcd8e --- /dev/null +++ b/packages/webapp/src/containers/Dialogs/CreditNotes/CreditNoteBulkDeleteDialog.tsx @@ -0,0 +1,106 @@ +// @ts-nocheck +import React from 'react'; +import { Button, Classes, Dialog, Intent } from '@blueprintjs/core'; +import { FormattedMessage as T, AppToaster } from '@/components'; +import intl from 'react-intl-universal'; +import { queryCache } from 'react-query'; + +import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent'; +import { useBulkDeleteCreditNotes } from '@/hooks/query/creditNote'; +import withDialogRedux from '@/components/DialogReduxConnect'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import withCreditNotesActions from '@/containers/Sales/CreditNotes/CreditNotesLanding/withCreditNotesActions'; +import { compose } from '@/utils'; + +function CreditNoteBulkDeleteDialog({ + dialogName, + isOpen, + payload: { + ids = [], + deletableCount = 0, + undeletableCount = 0, + totalSelected = ids.length, + } = {}, + + // #withCreditNotesActions + setCreditNotesSelectedRows, + + // #withDialogActions + closeDialog, +}) { + const { mutateAsync: bulkDeleteCreditNotes, isLoading } = + useBulkDeleteCreditNotes(); + + const handleCancel = () => { + closeDialog(dialogName); + }; + + const handleConfirmBulkDelete = () => { + bulkDeleteCreditNotes({ + ids, + skipUndeletable: true, + }) + .then(() => { + AppToaster.show({ + message: intl.get('the_credit_notes_has_been_deleted_successfully'), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('credit-notes-table'); + closeDialog(dialogName); + setCreditNotesSelectedRows([]); + }) + .catch(() => { + AppToaster.show({ + message: intl.get('something_went_wrong'), + intent: Intent.DANGER, + }); + }); + }; + + return ( + + } + isOpen={isOpen} + onClose={handleCancel} + canEscapeKeyClose={!isLoading} + canOutsideClickClose={!isLoading} + > + + +
+
+ + + +
+
+
+ ); +} + +export default compose( + withDialogRedux(), + withDialogActions, + withCreditNotesActions, +)(CreditNoteBulkDeleteDialog); + diff --git a/packages/webapp/src/containers/Dialogs/Estimates/EstimateBulkDeleteDialog.tsx b/packages/webapp/src/containers/Dialogs/Estimates/EstimateBulkDeleteDialog.tsx new file mode 100644 index 000000000..95aa299f4 --- /dev/null +++ b/packages/webapp/src/containers/Dialogs/Estimates/EstimateBulkDeleteDialog.tsx @@ -0,0 +1,106 @@ +// @ts-nocheck +import React from 'react'; +import { Button, Classes, Dialog, Intent } from '@blueprintjs/core'; +import { FormattedMessage as T, AppToaster } from '@/components'; +import intl from 'react-intl-universal'; +import { queryCache } from 'react-query'; + +import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent'; +import { useBulkDeleteEstimates } from '@/hooks/query/estimates'; +import withDialogRedux from '@/components/DialogReduxConnect'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import withEstimatesActions from '@/containers/Sales/Estimates/EstimatesLanding/withEstimatesActions'; +import { compose } from '@/utils'; + +function EstimateBulkDeleteDialog({ + dialogName, + isOpen, + payload: { + ids = [], + deletableCount = 0, + undeletableCount = 0, + totalSelected = ids.length, + } = {}, + + // #withEstimatesActions + setEstimatesSelectedRows, + + // #withDialogActions + closeDialog, +}) { + const { mutateAsync: bulkDeleteEstimates, isLoading } = + useBulkDeleteEstimates(); + + const handleCancel = () => { + closeDialog(dialogName); + }; + + const handleConfirmBulkDelete = () => { + bulkDeleteEstimates({ + ids, + skipUndeletable: true, + }) + .then(() => { + AppToaster.show({ + message: intl.get('the_estimates_has_been_deleted_successfully'), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('estimates-table'); + closeDialog(dialogName); + setEstimatesSelectedRows([]); + }) + .catch(() => { + AppToaster.show({ + message: intl.get('something_went_wrong'), + intent: Intent.DANGER, + }); + }); + }; + + return ( + + } + isOpen={isOpen} + onClose={handleCancel} + canEscapeKeyClose={!isLoading} + canOutsideClickClose={!isLoading} + > + + +
+
+ + + +
+
+
+ ); +} + +export default compose( + withDialogRedux(), + withDialogActions, + withEstimatesActions, +)(EstimateBulkDeleteDialog); + diff --git a/packages/webapp/src/containers/Dialogs/Expenses/ExpenseBulkDeleteDialog.tsx b/packages/webapp/src/containers/Dialogs/Expenses/ExpenseBulkDeleteDialog.tsx new file mode 100644 index 000000000..c8c3d22fe --- /dev/null +++ b/packages/webapp/src/containers/Dialogs/Expenses/ExpenseBulkDeleteDialog.tsx @@ -0,0 +1,106 @@ +// @ts-nocheck +import React from 'react'; +import { Button, Classes, Dialog, Intent } from '@blueprintjs/core'; +import { FormattedMessage as T, AppToaster } from '@/components'; +import intl from 'react-intl-universal'; +import { queryCache } from 'react-query'; + +import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent'; +import { useBulkDeleteExpenses } from '@/hooks/query/expenses'; +import withDialogRedux from '@/components/DialogReduxConnect'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import withExpensesActions from '@/containers/Expenses/ExpensesLanding/withExpensesActions'; +import { compose } from '@/utils'; + +function ExpenseBulkDeleteDialog({ + dialogName, + isOpen, + payload: { + ids = [], + deletableCount = 0, + undeletableCount = 0, + totalSelected = ids.length, + } = {}, + + // #withExpensesActions + setExpensesSelectedRows, + + // #withDialogActions + closeDialog, +}) { + const { mutateAsync: bulkDeleteExpenses, isLoading } = + useBulkDeleteExpenses(); + + const handleCancel = () => { + closeDialog(dialogName); + }; + + const handleConfirmBulkDelete = () => { + bulkDeleteExpenses({ + ids, + skipUndeletable: true, + }) + .then(() => { + AppToaster.show({ + message: intl.get('the_expenses_has_been_deleted_successfully'), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('expenses-table'); + closeDialog(dialogName); + setExpensesSelectedRows([]); + }) + .catch(() => { + AppToaster.show({ + message: intl.get('something_went_wrong'), + intent: Intent.DANGER, + }); + }); + }; + + return ( + + } + isOpen={isOpen} + onClose={handleCancel} + canEscapeKeyClose={!isLoading} + canOutsideClickClose={!isLoading} + > + + +
+
+ + + +
+
+
+ ); +} + +export default compose( + withDialogRedux(), + withDialogActions, + withExpensesActions, +)(ExpenseBulkDeleteDialog); + diff --git a/packages/webapp/src/containers/Dialogs/Invoices/InvoiceBulkDeleteDialog.tsx b/packages/webapp/src/containers/Dialogs/Invoices/InvoiceBulkDeleteDialog.tsx new file mode 100644 index 000000000..9b13c394b --- /dev/null +++ b/packages/webapp/src/containers/Dialogs/Invoices/InvoiceBulkDeleteDialog.tsx @@ -0,0 +1,110 @@ +// @ts-nocheck +import React from 'react'; +import { FormattedMessage as T } from '@/components'; +import intl from 'react-intl-universal'; +import { Button, Classes, Dialog, Intent } from '@blueprintjs/core'; +import { queryCache } from 'react-query'; + +import withDialogRedux from '@/components/DialogReduxConnect'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import withInvoiceActions from '@/containers/Sales/Invoices/InvoicesLanding/withInvoiceActions'; +import { useBulkDeleteInvoices } from '@/hooks/query/invoices'; +import { AppToaster } from '@/components'; +import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent'; + +import { compose } from '@/utils'; + +/** + * Invoice bulk delete dialog. + */ +function InvoiceBulkDeleteDialog({ + dialogName, + isOpen, + payload: { + ids = [], + deletableCount = 0, + undeletableCount = 0, + totalSelected = ids.length, + } = {}, + + // #withInvoiceActions + resetInvoicesSelectedRows, + + // #withDialogActions + closeDialog, +}) { + const { mutateAsync: bulkDeleteInvoices, isLoading } = + useBulkDeleteInvoices(); + + const handleCancel = () => { + closeDialog(dialogName); + }; + + const handleConfirmBulkDelete = () => { + bulkDeleteInvoices({ + ids, + skipUndeletable: true, + }) + .then(() => { + AppToaster.show({ + message: intl.get('the_invoices_has_been_deleted_successfully'), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('invoices-table'); + closeDialog(dialogName); + resetInvoicesSelectedRows(); + }) + .catch((errors) => { + AppToaster.show({ + message: intl.get('something_went_wrong'), + intent: Intent.DANGER, + }); + }); + }; + + return ( + + } + isOpen={isOpen} + onClose={handleCancel} + canEscapeKeyClose={!isLoading} + canOutsideClickClose={!isLoading} + > + + +
+
+ + + +
+
+
+ ); +} + +export default compose( + withDialogRedux(), + withDialogActions, + withInvoiceActions, +)(InvoiceBulkDeleteDialog); diff --git a/packages/webapp/src/containers/Dialogs/ManualJournals/ManualJournalBulkDeleteDialog.tsx b/packages/webapp/src/containers/Dialogs/ManualJournals/ManualJournalBulkDeleteDialog.tsx new file mode 100644 index 000000000..643333069 --- /dev/null +++ b/packages/webapp/src/containers/Dialogs/ManualJournals/ManualJournalBulkDeleteDialog.tsx @@ -0,0 +1,108 @@ +// @ts-nocheck +import React from 'react'; +import { Button, Classes, Dialog, Intent } from '@blueprintjs/core'; +import { FormattedMessage as T, AppToaster } from '@/components'; +import intl from 'react-intl-universal'; +import { queryCache } from 'react-query'; + +import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent'; +import { useBulkDeleteManualJournals } from '@/hooks/query/manualJournals'; +import withDialogRedux from '@/components/DialogReduxConnect'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import withManualJournalsActions from '@/containers/Accounting/JournalsLanding/withManualJournalsActions'; +import { compose } from '@/utils'; + +function ManualJournalBulkDeleteDialog({ + dialogName, + isOpen, + payload: { + ids = [], + deletableCount = 0, + undeletableCount = 0, + totalSelected = ids.length, + } = {}, + + // #withManualJournalsActions + setManualJournalsSelectedRows, + + // #withDialogActions + closeDialog, +}) { + const { mutateAsync: bulkDeleteManualJournals, isLoading } = + useBulkDeleteManualJournals(); + + const handleCancel = () => { + closeDialog(dialogName); + }; + + const handleConfirmBulkDelete = () => { + bulkDeleteManualJournals({ + ids, + skipUndeletable: true, + }) + .then(() => { + AppToaster.show({ + message: intl.get('the_journals_has_been_deleted_successfully'), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('manual-journals-table'); + closeDialog(dialogName); + setManualJournalsSelectedRows([]); + }) + .catch(() => { + AppToaster.show({ + message: intl.get('something_went_wrong'), + intent: Intent.DANGER, + }); + }); + }; + + return ( + + } + isOpen={isOpen} + onClose={handleCancel} + canEscapeKeyClose={!isLoading} + canOutsideClickClose={!isLoading} + > + + +
+
+ + + +
+
+
+ ); +} + +export default compose( + withDialogRedux(), + withDialogActions, + withManualJournalsActions, +)(ManualJournalBulkDeleteDialog); + diff --git a/packages/webapp/src/containers/Dialogs/PaymentsReceived/PaymentReceivedBulkDeleteDialog.tsx b/packages/webapp/src/containers/Dialogs/PaymentsReceived/PaymentReceivedBulkDeleteDialog.tsx new file mode 100644 index 000000000..7ef6743e1 --- /dev/null +++ b/packages/webapp/src/containers/Dialogs/PaymentsReceived/PaymentReceivedBulkDeleteDialog.tsx @@ -0,0 +1,110 @@ +// @ts-nocheck +import React from 'react'; +import { Button, Classes, Dialog, Intent } from '@blueprintjs/core'; +import { FormattedMessage as T, AppToaster } from '@/components'; +import intl from 'react-intl-universal'; +import { queryCache } from 'react-query'; + +import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent'; +import { useBulkDeletePaymentReceives } from '@/hooks/query/paymentReceives'; +import withDialogRedux from '@/components/DialogReduxConnect'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import withPaymentsReceivedActions from '@/containers/Sales/PaymentsReceived/PaymentsLanding/withPaymentsReceivedActions'; +import { compose } from '@/utils'; + +function PaymentReceivedBulkDeleteDialog({ + dialogName, + isOpen, + payload: { + ids = [], + deletableCount = 0, + undeletableCount = 0, + totalSelected = ids.length, + } = {}, + + // #withPaymentsReceivedActions + setPaymentReceivesSelectedRows, + + // #withDialogActions + closeDialog, +}) { + const { mutateAsync: bulkDeletePaymentReceives, isLoading } = + useBulkDeletePaymentReceives(); + + const handleCancel = () => { + closeDialog(dialogName); + }; + + const handleConfirmBulkDelete = () => { + bulkDeletePaymentReceives({ + ids, + skipUndeletable: true, + }) + .then(() => { + AppToaster.show({ + message: intl.get( + 'the_payments_received_has_been_deleted_successfully', + ), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('payments-received-table'); + closeDialog(dialogName); + setPaymentReceivesSelectedRows([]); + }) + .catch(() => { + AppToaster.show({ + message: intl.get('something_went_wrong'), + intent: Intent.DANGER, + }); + }); + }; + + return ( + + } + isOpen={isOpen} + onClose={handleCancel} + canEscapeKeyClose={!isLoading} + canOutsideClickClose={!isLoading} + > + + +
+
+ + + +
+
+
+ ); +} + +export default compose( + withDialogRedux(), + withDialogActions, + withPaymentsReceivedActions, +)(PaymentReceivedBulkDeleteDialog); + diff --git a/packages/webapp/src/containers/Dialogs/Receipts/ReceiptBulkDeleteDialog.tsx b/packages/webapp/src/containers/Dialogs/Receipts/ReceiptBulkDeleteDialog.tsx new file mode 100644 index 000000000..e5db5ab96 --- /dev/null +++ b/packages/webapp/src/containers/Dialogs/Receipts/ReceiptBulkDeleteDialog.tsx @@ -0,0 +1,106 @@ +// @ts-nocheck +import React from 'react'; +import { Button, Classes, Dialog, Intent } from '@blueprintjs/core'; +import { FormattedMessage as T, AppToaster } from '@/components'; +import intl from 'react-intl-universal'; +import { queryCache } from 'react-query'; + +import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent'; +import { useBulkDeleteReceipts } from '@/hooks/query/receipts'; +import withDialogRedux from '@/components/DialogReduxConnect'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import withReceiptsActions from '@/containers/Sales/Receipts/ReceiptsLanding/withReceiptsActions'; +import { compose } from '@/utils'; + +function ReceiptBulkDeleteDialog({ + dialogName, + isOpen, + payload: { + ids = [], + deletableCount = 0, + undeletableCount = 0, + totalSelected = ids.length, + } = {}, + + // #withReceiptsActions + setReceiptsSelectedRows, + + // #withDialogActions + closeDialog, +}) { + const { mutateAsync: bulkDeleteReceipts, isLoading } = + useBulkDeleteReceipts(); + + const handleCancel = () => { + closeDialog(dialogName); + }; + + const handleConfirmBulkDelete = () => { + bulkDeleteReceipts({ + ids, + skipUndeletable: true, + }) + .then(() => { + AppToaster.show({ + message: intl.get('the_receipts_has_been_deleted_successfully'), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('sale-receipts-table'); + closeDialog(dialogName); + setReceiptsSelectedRows([]); + }) + .catch(() => { + AppToaster.show({ + message: intl.get('something_went_wrong'), + intent: Intent.DANGER, + }); + }); + }; + + return ( + + } + isOpen={isOpen} + onClose={handleCancel} + canEscapeKeyClose={!isLoading} + canOutsideClickClose={!isLoading} + > + + +
+
+ + + +
+
+
+ ); +} + +export default compose( + withDialogRedux(), + withDialogActions, + withReceiptsActions, +)(ReceiptBulkDeleteDialog); + diff --git a/packages/webapp/src/containers/Dialogs/VendorCredits/VendorCreditBulkDeleteDialog.tsx b/packages/webapp/src/containers/Dialogs/VendorCredits/VendorCreditBulkDeleteDialog.tsx new file mode 100644 index 000000000..27decd9ee --- /dev/null +++ b/packages/webapp/src/containers/Dialogs/VendorCredits/VendorCreditBulkDeleteDialog.tsx @@ -0,0 +1,108 @@ +// @ts-nocheck +import React from 'react'; +import { Button, Classes, Dialog, Intent } from '@blueprintjs/core'; +import { FormattedMessage as T, AppToaster } from '@/components'; +import intl from 'react-intl-universal'; +import { queryCache } from 'react-query'; + +import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent'; +import { useBulkDeleteVendorCredits } from '@/hooks/query/vendorCredit'; +import withDialogRedux from '@/components/DialogReduxConnect'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import withVendorsCreditNotesActions from '@/containers/Purchases/CreditNotes/CreditNotesLanding/withVendorsCreditNotesActions'; +import { compose } from '@/utils'; + +function VendorCreditBulkDeleteDialog({ + dialogName, + isOpen, + payload: { + ids = [], + deletableCount = 0, + undeletableCount = 0, + totalSelected = ids.length, + } = {}, + + // #withVendorsCreditNotesActions + setVendorsCreditNoteSelectedRows, + + // #withDialogActions + closeDialog, +}) { + const { mutateAsync: bulkDeleteVendorCredits, isLoading } = + useBulkDeleteVendorCredits(); + + const handleCancel = () => { + closeDialog(dialogName); + }; + + const handleConfirmBulkDelete = () => { + bulkDeleteVendorCredits({ + ids, + skipUndeletable: true, + }) + .then(() => { + AppToaster.show({ + message: intl.get( + 'the_vendor_credits_has_been_deleted_successfully', + ), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('vendor-credits-table'); + closeDialog(dialogName); + setVendorsCreditNoteSelectedRows([]); + }) + .catch(() => { + AppToaster.show({ + message: intl.get('something_went_wrong'), + intent: Intent.DANGER, + }); + }); + }; + + return ( + + } + isOpen={isOpen} + onClose={handleCancel} + canEscapeKeyClose={!isLoading} + canOutsideClickClose={!isLoading} + > + + +
+
+ + + +
+
+
+ ); +} + +export default compose( + withDialogRedux(), + withDialogActions, + withVendorsCreditNotesActions, +)(VendorCreditBulkDeleteDialog); + diff --git a/packages/webapp/src/containers/Dialogs/components/BulkDeleteDialogContent.tsx b/packages/webapp/src/containers/Dialogs/components/BulkDeleteDialogContent.tsx new file mode 100644 index 000000000..6f3068abd --- /dev/null +++ b/packages/webapp/src/containers/Dialogs/components/BulkDeleteDialogContent.tsx @@ -0,0 +1,89 @@ +// @ts-nocheck +import React from 'react'; +import { Classes, Intent, Tag } from '@blueprintjs/core'; +import { FormattedMessage as T } from '@/components'; +import { x } from '@xstyled/emotion'; + +interface BulkDeleteDialogContentProps { + totalSelected: number; + deletableCount: number; + undeletableCount: number; + resourceSingularLabel: string; + resourcePluralLabel: string; +} + +function BulkDeleteDialogContent({ + totalSelected, + deletableCount, + undeletableCount, + resourceSingularLabel, + resourcePluralLabel, +}: BulkDeleteDialogContentProps) { + return ( +
+ + + + + + + {deletableCount} + + + {' '} + + + + + + + + + {undeletableCount} + + + {' '} + + + + + + + + + + + + + + {':'} + + + + + +
+ ); +} + +export default BulkDeleteDialogContent; + diff --git a/packages/webapp/src/containers/Expenses/ExpensesAlerts.tsx b/packages/webapp/src/containers/Expenses/ExpensesAlerts.tsx index 9283f2725..5b772b42c 100644 --- a/packages/webapp/src/containers/Expenses/ExpensesAlerts.tsx +++ b/packages/webapp/src/containers/Expenses/ExpensesAlerts.tsx @@ -8,15 +8,10 @@ const ExpensePublishAlert = React.lazy( () => import('@/containers/Alerts/Expenses/ExpensePublishAlert'), ); -const ExpenseBulkDeleteAlert = React.lazy( - () => import('@/containers/Alerts/Expenses/ExpenseBulkDeleteAlert'), -); - /** * Accounts alert. */ export default [ { name: 'expense-delete', component: ExpenseDeleteAlert }, { name: 'expense-publish', component: ExpensePublishAlert }, - { name: 'expenses-bulk-delete', component: ExpenseBulkDeleteAlert }, ]; diff --git a/packages/webapp/src/containers/Expenses/ExpensesLanding/ExpenseActionsBar.tsx b/packages/webapp/src/containers/Expenses/ExpensesLanding/ExpenseActionsBar.tsx index faa460978..3aaa86217 100644 --- a/packages/webapp/src/containers/Expenses/ExpensesLanding/ExpenseActionsBar.tsx +++ b/packages/webapp/src/containers/Expenses/ExpensesLanding/ExpenseActionsBar.tsx @@ -34,10 +34,10 @@ import withExpensesActions from './withExpensesActions'; import withSettingsActions from '@/containers/Settings/withSettingsActions'; import withDialogActions from '@/containers/Dialog/withDialogActions'; import withSettings from '@/containers/Settings/withSettings'; -import withAlertActions from '@/containers/Alert/withAlertActions'; import { compose } from '@/utils'; import { isEmpty } from 'lodash'; +import { useBulkDeleteExpensesDialog } from './hooks/use-bulk-delete-expenses-dialog'; /** * Expenses actions bar. @@ -58,9 +58,6 @@ function ExpensesActionsBar({ // #withDialogActions openDialog, - - // #withAlertActions - openAlert, }) { // History context. const history = useHistory(); @@ -78,11 +75,14 @@ function ExpensesActionsBar({ const onClickNewExpense = () => { history.push('/expenses/new'); }; + const { + openBulkDeleteDialog, + isValidatingBulkDeleteExpenses, + } = useBulkDeleteExpensesDialog(); + // Handle delete button click. const handleBulkDelete = () => { - openAlert('expenses-bulk-delete', { - expensesIds: expensesSelectedRows, - }); + openBulkDeleteDialog(expensesSelectedRows); }; // Handles the tab chaning. @@ -122,6 +122,7 @@ function ExpensesActionsBar({ text={} intent={Intent.DANGER} onClick={handleBulkDelete} + disabled={isValidatingBulkDeleteExpenses} /> @@ -209,7 +210,6 @@ function ExpensesActionsBar({ export default compose( withDialogActions, - withAlertActions, withExpensesActions, withSettingsActions, withExpenses(({ expensesTableState, expensesSelectedRows }) => ({ diff --git a/packages/webapp/src/containers/Expenses/ExpensesLanding/hooks/use-bulk-delete-expenses-dialog.ts b/packages/webapp/src/containers/Expenses/ExpensesLanding/hooks/use-bulk-delete-expenses-dialog.ts new file mode 100644 index 000000000..dcb7c18b2 --- /dev/null +++ b/packages/webapp/src/containers/Expenses/ExpensesLanding/hooks/use-bulk-delete-expenses-dialog.ts @@ -0,0 +1,20 @@ +// @ts-nocheck +import { DialogsName } from '@/constants/dialogs'; +import { useValidateBulkDeleteExpenses } from '@/hooks/query/expenses'; +import { useBulkDeleteDialog } from '@/hooks/dialogs/useBulkDeleteDialog'; + +export const useBulkDeleteExpensesDialog = () => { + const validateBulkDeleteMutation = useValidateBulkDeleteExpenses(); + const { + openBulkDeleteDialog, + closeBulkDeleteDialog, + isValidatingBulkDelete, + } = useBulkDeleteDialog(DialogsName.ExpenseBulkDelete, validateBulkDeleteMutation); + + return { + openBulkDeleteDialog, + closeBulkDeleteDialog, + isValidatingBulkDeleteExpenses: isValidatingBulkDelete, + }; +}; + diff --git a/packages/webapp/src/containers/Purchases/Bills/BillsLanding/BillsActionsBar.tsx b/packages/webapp/src/containers/Purchases/Bills/BillsLanding/BillsActionsBar.tsx index 94bdd7bea..3e7e39193 100644 --- a/packages/webapp/src/containers/Purchases/Bills/BillsLanding/BillsActionsBar.tsx +++ b/packages/webapp/src/containers/Purchases/Bills/BillsLanding/BillsActionsBar.tsx @@ -29,11 +29,13 @@ import withBillsActions from './withBillsActions'; import withSettings from '@/containers/Settings/withSettings'; import withSettingsActions from '@/containers/Settings/withSettingsActions'; import withDialogActions from '@/containers/Dialog/withDialogActions'; -import withAlertActions from '@/containers/Alert/withAlertActions'; import { useBillsListContext } from './BillsListProvider'; -import { useRefreshBills } from '@/hooks/query/bills'; +import { + useRefreshBills, +} from '@/hooks/query/bills'; import { useDownloadExportPdf } from '@/hooks/query/FinancialReports/use-export-pdf'; +import { useBulkDeleteBillsDialog } from './hooks/use-bulk-delete-bills-dialog'; import { compose } from '@/utils'; import { DialogsName } from '@/constants/dialogs'; @@ -58,9 +60,6 @@ function BillActionsBar({ // #withDialogActions openDialog, - - // #withAlertActions - openAlert, }) { const history = useHistory(); @@ -103,9 +102,14 @@ function BillActionsBar({ const handlePrintBtnClick = () => { downloadExportPdf({ resource: 'Bill' }); }; + const { + openBulkDeleteDialog, + isValidatingBulkDeleteBills, + } = useBulkDeleteBillsDialog(); + // Handle bulk delete. const handleBulkDelete = () => { - openAlert('bills-bulk-delete', { billsIds: billsSelectedRows }); + openBulkDeleteDialog(billsSelectedRows); }; if (!isEmpty(billsSelectedRows)) { @@ -118,6 +122,7 @@ function BillActionsBar({ text={} intent={Intent.DANGER} onClick={handleBulkDelete} + disabled={isValidatingBulkDeleteBills} /> @@ -214,5 +219,4 @@ export default compose( billsTableSize: billsettings?.tableSize, })), withDialogActions, - withAlertActions, )(BillActionsBar); diff --git a/packages/webapp/src/containers/Purchases/Bills/BillsLanding/BillsAlerts.tsx b/packages/webapp/src/containers/Purchases/Bills/BillsLanding/BillsAlerts.tsx index 791cb5cb4..266075f52 100644 --- a/packages/webapp/src/containers/Purchases/Bills/BillsLanding/BillsAlerts.tsx +++ b/packages/webapp/src/containers/Purchases/Bills/BillsLanding/BillsAlerts.tsx @@ -12,10 +12,6 @@ const BillLocatedLandedCostDeleteAlert = React.lazy( () => import('@/containers/Alerts/Bills/BillLocatedLandedCostDeleteAlert'), ); -const BillBulkDeleteAlert = React.lazy( - () => import('@/containers/Alerts/Bills/BillBulkDeleteAlert'), -); - export default [ { name: 'bill-delete', component: BillDeleteAlert }, { name: 'bill-open', component: BillOpenAlert }, @@ -23,5 +19,4 @@ export default [ name: 'bill-located-cost-delete', component: BillLocatedLandedCostDeleteAlert, }, - { name: 'bills-bulk-delete', component: BillBulkDeleteAlert }, ]; diff --git a/packages/webapp/src/containers/Purchases/Bills/BillsLanding/hooks/use-bulk-delete-bills-dialog.ts b/packages/webapp/src/containers/Purchases/Bills/BillsLanding/hooks/use-bulk-delete-bills-dialog.ts new file mode 100644 index 000000000..80008c167 --- /dev/null +++ b/packages/webapp/src/containers/Purchases/Bills/BillsLanding/hooks/use-bulk-delete-bills-dialog.ts @@ -0,0 +1,20 @@ +// @ts-nocheck +import { DialogsName } from '@/constants/dialogs'; +import { useValidateBulkDeleteBills } from '@/hooks/query/bills'; +import { useBulkDeleteDialog } from '@/hooks/dialogs/useBulkDeleteDialog'; + +export const useBulkDeleteBillsDialog = () => { + const validateBulkDeleteMutation = useValidateBulkDeleteBills(); + const { + openBulkDeleteDialog, + closeBulkDeleteDialog, + isValidatingBulkDelete, + } = useBulkDeleteDialog(DialogsName.BillBulkDelete, validateBulkDeleteMutation); + + return { + openBulkDeleteDialog, + closeBulkDeleteDialog, + isValidatingBulkDeleteBills: isValidatingBulkDelete, + }; +}; + diff --git a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.tsx b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.tsx index 75bbcacd6..9978092cd 100644 --- a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.tsx +++ b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.tsx @@ -1,6 +1,7 @@ // @ts-nocheck import React from 'react'; import { useHistory } from 'react-router-dom'; +import { isEmpty } from 'lodash'; import { Button, Classes, @@ -32,7 +33,6 @@ import { VendorCreditAction, AbilitySubject } from '@/constants/abilityOption'; import withVendorsCreditNotesActions from './withVendorsCreditNotesActions'; import withSettings from '@/containers/Settings/withSettings'; import withSettingsActions from '@/containers/Settings/withSettingsActions'; -import withVendorsCreditNotes from './withVendorsCreditNotes'; import withDialogActions from '@/containers/Dialog/withDialogActions'; import withVendorActions from './withVendorActions'; import withDrawerActions from '@/containers/Drawer/withDrawerActions'; @@ -40,6 +40,8 @@ import withDrawerActions from '@/containers/Drawer/withDrawerActions'; import { compose } from '@/utils'; import { DialogsName } from '@/constants/dialogs'; import { DRAWERS } from '@/constants/drawers'; +import withVendorsCreditNotes from './withVendorsCreditNotes'; +import { useBulkDeleteVendorCreditsDialog } from './hooks/use-bulk-delete-vendor-credits-dialog'; /** * Vendors Credit note table actions bar. @@ -49,6 +51,7 @@ function VendorsCreditNoteActionsBar({ // #withVendorsCreditNotes vendorCreditFilterRoles, + vendorsCreditNoteSelectedRows, // #withVendorsCreditNotesActions setVendorsCreditNoteTableState, @@ -107,6 +110,32 @@ function VendorsCreditNoteActionsBar({ openDrawer(DRAWERS.CREDIT_NOTE_DETAILS); }; + const { + openBulkDeleteDialog, + isValidatingBulkDeleteVendorCredits, + } = useBulkDeleteVendorCreditsDialog(); + + if (!isEmpty(vendorsCreditNoteSelectedRows)) { + const handleBulkDelete = () => { + openBulkDeleteDialog(vendorsCreditNoteSelectedRows); + }; + + return ( + + +