From 963f68a64088386a0c749412a51b60a3319c47ba Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Wed, 27 Jan 2021 14:54:08 +0200 Subject: [PATCH] refactor: Inovices alerts. --- .../Alerts/Invoices/InvoiceDeleteAlert.js | 89 ++++++++++++ .../Alerts/Invoices/InvoiceDeliverAlert.js | 78 +++++++++++ .../Sales/Invoice/InvoicesAlerts.js | 15 ++ .../containers/Sales/Invoice/InvoicesList.js | 131 +++--------------- .../containers/Sales/Invoice/components.js | 17 +++ 5 files changed, 221 insertions(+), 109 deletions(-) create mode 100644 client/src/containers/Alerts/Invoices/InvoiceDeleteAlert.js create mode 100644 client/src/containers/Alerts/Invoices/InvoiceDeliverAlert.js create mode 100644 client/src/containers/Sales/Invoice/InvoicesAlerts.js diff --git a/client/src/containers/Alerts/Invoices/InvoiceDeleteAlert.js b/client/src/containers/Alerts/Invoices/InvoiceDeleteAlert.js new file mode 100644 index 000000000..3aba617c8 --- /dev/null +++ b/client/src/containers/Alerts/Invoices/InvoiceDeleteAlert.js @@ -0,0 +1,89 @@ +import React, { useCallback, useState } from 'react'; +import { + FormattedMessage as T, + FormattedHTMLMessage, + useIntl, +} from 'react-intl'; +import { Intent, Alert } from '@blueprintjs/core'; +import { queryCache } from 'react-query'; +import { AppToaster } from 'components'; + +import { handleDeleteErrors } from 'containers/Sales/Invoice/components'; + +import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect'; +import withAlertActions from 'containers/Alert/withAlertActions'; +import withInvoiceActions from 'containers/Sales/Invoice/withInvoiceActions'; + +import { compose } from 'utils'; + +/** + * Invoice delete alert. + */ +function InvoiceDeleteAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { invoiceId }, + + // #withInvoiceActions + requestDeleteInvoice, + + // #withAlertActions + closeAlert, +}) { + const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); + + // handle cancel delete invoice alert. + const handleCancelDeleteAlert = () => { + closeAlert(name); + }; + + // handleConfirm delete invoice + const handleConfirmInvoiceDelete = useCallback(() => { + setLoading(true); + requestDeleteInvoice(invoiceId) + .then(() => { + AppToaster.show({ + message: formatMessage({ + id: 'the_invoice_has_been_deleted_successfully', + }), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('invoices-table'); + }) + .catch((errors) => { + handleDeleteErrors(errors); + }) + .finally(() => { + closeAlert(name); + setLoading(false); + }); + }, [invoiceId, requestDeleteInvoice, formatMessage]); + + return ( + } + confirmButtonText={} + icon="trash" + intent={Intent.DANGER} + isOpen={isOpen} + onCancel={handleCancelDeleteAlert} + onConfirm={handleConfirmInvoiceDelete} + loading={isLoading} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withInvoiceActions, +)(InvoiceDeleteAlert); diff --git a/client/src/containers/Alerts/Invoices/InvoiceDeliverAlert.js b/client/src/containers/Alerts/Invoices/InvoiceDeliverAlert.js new file mode 100644 index 000000000..d8f3f8263 --- /dev/null +++ b/client/src/containers/Alerts/Invoices/InvoiceDeliverAlert.js @@ -0,0 +1,78 @@ +import React, { useCallback, useState } from 'react'; +import { FormattedMessage as T, useIntl } from 'react-intl'; +import { Intent, Alert } from '@blueprintjs/core'; +import { queryCache } from 'react-query'; +import { AppToaster } from 'components'; + +import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect'; +import withAlertActions from 'containers/Alert/withAlertActions'; +import withInvoiceActions from 'containers/Sales/Invoice/withInvoiceActions'; + +import { compose } from 'utils'; + +/** + * Invoice alert. + */ +function InvoiceDeliverAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { invoiceId }, + + // #withInvoiceActions + requestDeliverInvoice, + + // #withAlertActions + closeAlert, +}) { + const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); + + // handle cancel delete deliver alert. + const handleCancelDeleteAlert = () => { + closeAlert(name); + }; + + // Handle confirm invoice deliver. + const handleConfirmInvoiceDeliver = useCallback(() => { + setLoading(true); + requestDeliverInvoice(invoiceId) + .then(() => { + AppToaster.show({ + message: formatMessage({ + id: 'the_invoice_has_been_delivered_successfully', + }), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('invoices-table'); + }) + .catch((error) => {}) + .finally(() => { + closeAlert(name); + setLoading(false); + }); + }, [invoiceId, requestDeliverInvoice, formatMessage]); + + return ( + } + confirmButtonText={} + intent={Intent.WARNING} + isOpen={isOpen} + onCancel={handleCancelDeleteAlert} + onConfirm={handleConfirmInvoiceDeliver} + loading={isLoading} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withInvoiceActions, +)(InvoiceDeliverAlert); diff --git a/client/src/containers/Sales/Invoice/InvoicesAlerts.js b/client/src/containers/Sales/Invoice/InvoicesAlerts.js new file mode 100644 index 000000000..024b4a819 --- /dev/null +++ b/client/src/containers/Sales/Invoice/InvoicesAlerts.js @@ -0,0 +1,15 @@ +import React from 'react'; +import InvoiceDeleteAlert from 'containers/Alerts/Invoices/InvoiceDeleteAlert'; +import InvoiceDeliverAlert from 'containers/Alerts/Invoices/InvoiceDeliverAlert'; + +/** + * Invoices alert. + */ +export default function ItemsAlerts() { + return ( +
+ + +
+ ); +} diff --git a/client/src/containers/Sales/Invoice/InvoicesList.js b/client/src/containers/Sales/Invoice/InvoicesList.js index cede77ee2..d20dee75f 100644 --- a/client/src/containers/Sales/Invoice/InvoicesList.js +++ b/client/src/containers/Sales/Invoice/InvoicesList.js @@ -1,25 +1,24 @@ import React, { useEffect, useCallback, useMemo, useState } from 'react'; import { Route, Switch, useHistory } from 'react-router-dom'; -import { useQuery, queryCache } from 'react-query'; -import { Alert, Intent } from '@blueprintjs/core'; +import { useQuery} from 'react-query'; import 'style/pages/SaleInvoice/List.scss'; -import AppToaster from 'components/AppToaster'; -import { FormattedMessage as T, useIntl } from 'react-intl' -; +import { FormattedMessage as T, useIntl } from 'react-intl'; import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; import DashboardInsider from 'components/Dashboard/DashboardInsider'; import InvoicesDataTable from './InvoicesDataTable'; import InvoiceActionsBar from './InvoiceActionsBar'; import InvoiceViewTabs from './InvoiceViewTabs'; +import InvoicesAlerts from './InvoicesAlerts'; import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withResourceActions from 'containers/Resources/withResourcesActions'; import withInvoices from './withInvoices'; -import withInvoiceActions from './withInvoiceActions'; +import withInvoiceActions from 'containers/Sales/Invoice/withInvoiceActions'; import withViewsActions from 'containers/Views/withViewsActions'; +import withAlertsActions from 'containers/Alert/withAlertActions'; import { compose } from 'utils'; @@ -38,17 +37,17 @@ function InvoicesList({ invoicesTableQuery, invoicesViews, + // #withAlertsActions. + openAlert, + //#withInvoiceActions requestFetchInvoiceTable, - requestDeleteInvoice, - requestDeliverInvoice, + addInvoiceTableQueries, }) { const history = useHistory(); const { formatMessage } = useIntl(); - const [deleteInvoice, setDeleteInvoice] = useState(false); - const [deliverInvoice, setDeliverInvoice] = useState(false); - const [selectedRows, setSelectedRows] = useState([]); + const [selectedRows, setSelectedRows] = useState([]); useEffect(() => { changePageTitle(formatMessage({ id: 'invoices_list' })); @@ -68,89 +67,27 @@ function InvoicesList({ ['invoices-table', invoicesTableQuery], (key, query) => requestFetchInvoiceTable({ ...query }), ); - //handle dalete Invoice + //handle delete Invoice const handleDeleteInvoice = useCallback( - (invoice) => { - setDeleteInvoice(invoice); + ({ id }) => { + openAlert('invoice-delete', { invoiceId: id }); }, - [setDeleteInvoice], + [openAlert], ); - // handle cancel Invoice - const handleCancelInvoiceDelete = useCallback(() => { - setDeleteInvoice(false); - }, [setDeleteInvoice]); - - const handleDeleteErrors = (errors) => { - if ( - errors.find( - (error) => error.type === 'INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES', - ) - ) { - AppToaster.show({ - message: formatMessage({ - id: 'the_invoice_cannot_be_deleted', - }), - intent: Intent.DANGER, - }); - } - }; - - // handleConfirm delete invoice - const handleConfirmInvoiceDelete = useCallback(() => { - requestDeleteInvoice(deleteInvoice.id) - .then(() => { - setDeleteInvoice(false); - AppToaster.show({ - message: formatMessage({ - id: 'the_invoice_has_been_deleted_successfully', - }), - intent: Intent.SUCCESS, - }); - }) - .catch((errors) => { - handleDeleteErrors(errors); - setDeleteInvoice(false); - }); - }, [deleteInvoice, requestDeleteInvoice, formatMessage]); - // Handle cancel/confirm invoice deliver. - const handleDeliverInvoice = useCallback((invoice) => { - setDeliverInvoice(invoice); - }, []); + const handleDeliverInvoice = useCallback( + ({id}) => { + openAlert('invoice-deliver', { invoiceId: id }); + }, + [openAlert], + ); - // Handle cancel deliver invoice alert. - const handleCancelDeliverInvoice = useCallback(() => { - setDeliverInvoice(false); - }, []); - - // Handle confirm invoiec deliver. - const handleConfirmInvoiceDeliver = useCallback(() => { - requestDeliverInvoice(deliverInvoice.id) - .then(() => { - setDeliverInvoice(false); - AppToaster.show({ - message: formatMessage({ - id: 'the_invoice_has_been_delivered_successfully', - }), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('invoices-table'); - }) - .catch((error) => { - // setDeliverInvoice(false); - }); - }, [deliverInvoice, requestDeliverInvoice, formatMessage]); const handleEditInvoice = useCallback((invoice) => { history.push(`/invoices/${invoice.id}/edit`); }); - // Calculates the selected rows count. - const selectedRowsCount = useMemo(() => Object.values(selectedRows).length, [ - selectedRows, - ]); - // Handle filter change to re-fetch data-table. const handleFilterChanged = useCallback(() => {}, []); @@ -167,7 +104,6 @@ function InvoicesList({ name={'sales-invoices-list'} > @@ -187,31 +123,7 @@ function InvoicesList({ - } - confirmButtonText={} - icon={'trash'} - intent={Intent.DANGER} - isOpen={deleteInvoice} - onCancel={handleCancelInvoiceDelete} - onConfirm={handleConfirmInvoiceDelete} - > -

- -

-
- } - confirmButtonText={} - intent={Intent.WARNING} - isOpen={deliverInvoice} - onCancel={handleCancelDeliverInvoice} - onConfirm={handleConfirmInvoiceDeliver} - > -

- -

-
+ ); @@ -225,4 +137,5 @@ export default compose( withInvoices(({ invoicesTableQuery }) => ({ invoicesTableQuery, })), + withAlertsActions, )(InvoicesList); diff --git a/client/src/containers/Sales/Invoice/components.js b/client/src/containers/Sales/Invoice/components.js index ade11fa9e..e4f31a5e4 100644 --- a/client/src/containers/Sales/Invoice/components.js +++ b/client/src/containers/Sales/Invoice/components.js @@ -2,6 +2,8 @@ import React from 'react'; import { Intent, Tag, ProgressBar } from '@blueprintjs/core'; import { Choose, If, Icon } from 'components'; import { FormattedMessage as T, useIntl } from 'react-intl'; +import { AppToaster } from 'components'; +import { formatMessage } from 'services/intl'; const calculateStatus = (paymentAmount, balanceAmount) => paymentAmount / balanceAmount; @@ -60,3 +62,18 @@ export const statusAccessor = (row) => { ); }; + +export const handleDeleteErrors = (errors) => { + if ( + errors.find( + (error) => error.type === 'INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES', + ) + ) { + AppToaster.show({ + message: formatMessage({ + id: 'the_invoice_cannot_be_deleted', + }), + intent: Intent.DANGER, + }); + } +};