From 62fcbf7c02e77d892ce610adf3694fdd70d8a226 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Wed, 27 Jan 2021 13:04:32 +0200 Subject: [PATCH 1/8] refactor: esitmate alert. --- .../Alerts/Estimates/EstimateApproveAlert.js | 78 ++++++++ .../Alerts/Estimates/EstimateDeleteAlert.js | 85 +++++++++ .../Estimates/EstimateDeliveredAlert.js | 78 ++++++++ .../Alerts/Estimates/EstimateRejectAlert.js | 77 ++++++++ .../Sales/Estimate/EstimateFormPage.js | 4 +- .../Sales/Estimate/EstimatesAlerts.js | 19 ++ .../Sales/Estimate/EstimatesList.js | 179 +++--------------- .../Sales/Estimate/withEstimateActions.js | 15 +- .../Sales/Estimate/withEstimates.js | 3 +- .../src/store/Estimate/estimates.reducer.js | 5 + client/src/store/Estimate/estimates.types.js | 1 + 11 files changed, 386 insertions(+), 158 deletions(-) create mode 100644 client/src/containers/Alerts/Estimates/EstimateApproveAlert.js create mode 100644 client/src/containers/Alerts/Estimates/EstimateDeleteAlert.js create mode 100644 client/src/containers/Alerts/Estimates/EstimateDeliveredAlert.js create mode 100644 client/src/containers/Alerts/Estimates/EstimateRejectAlert.js create mode 100644 client/src/containers/Sales/Estimate/EstimatesAlerts.js diff --git a/client/src/containers/Alerts/Estimates/EstimateApproveAlert.js b/client/src/containers/Alerts/Estimates/EstimateApproveAlert.js new file mode 100644 index 000000000..33c819adf --- /dev/null +++ b/client/src/containers/Alerts/Estimates/EstimateApproveAlert.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 withEstimateActions from 'containers/Sales/Estimate/withEstimateActions'; + +import { compose } from 'utils'; + +/** + * Estimate Approve alert. + */ +function EstimateApproveAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { estimateId }, + + // #withEstimateActions + requestApproveEstimate, + + // #withAlertActions + closeAlert, +}) { + const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); + + // handle cancel approve alert. + const handleCancelApproveEstimate = () => { + closeAlert(name); + }; + // Handle confirm estimate approve. + const handleConfirmEstimateApprove = useCallback(() => { + setLoading(true); + requestApproveEstimate(estimateId) + .then(() => { + AppToaster.show({ + message: formatMessage({ + id: 'the_estimate_has_been_approved_successfully', + }), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('estimates-table'); + }) + .catch((error) => {}) + .finally(() => { + setLoading(false); + closeAlert(name); + }); + }, [estimateId, requestApproveEstimate, formatMessage]); + + return ( + } + confirmButtonText={} + icon="trash" + intent={Intent.WARNING} + isOpen={isOpen} + loading={isLoading} + onCancel={handleCancelApproveEstimate} + onConfirm={handleConfirmEstimateApprove} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withEstimateActions, +)(EstimateApproveAlert); diff --git a/client/src/containers/Alerts/Estimates/EstimateDeleteAlert.js b/client/src/containers/Alerts/Estimates/EstimateDeleteAlert.js new file mode 100644 index 000000000..0a1b55cf2 --- /dev/null +++ b/client/src/containers/Alerts/Estimates/EstimateDeleteAlert.js @@ -0,0 +1,85 @@ +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 withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect'; +import withAlertActions from 'containers/Alert/withAlertActions'; +import withEstimateActions from 'containers/Sales/Estimate/withEstimateActions'; + +import { compose } from 'utils'; + +/** + * Estimate delete alert. + */ +function EstimateDeleteAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { estimateId }, + + // #withEstimateActions + requestDeleteEstimate, + + // #withAlertActions + closeAlert, +}) { + const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); + + // handle cancel delete alert. + const handleCancelEstimateDelete = () => { + closeAlert(name); + }; + + // handle confirm delete estimate + const handleConfirmEstimateDelete = useCallback(() => { + setLoading(true); + requestDeleteEstimate(estimateId) + .then(() => { + AppToaster.show({ + message: formatMessage({ + id: 'the_estimate_has_been_deleted_successfully', + }), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('estimates-table'); + }) + .catch(({ errors }) => {}) + .finally(() => { + setLoading(false); + closeAlert(name); + }); + }, [requestDeleteEstimate, formatMessage, estimateId]); + + return ( + } + confirmButtonText={} + icon="trash" + intent={Intent.DANGER} + isOpen={isOpen} + loading={isLoading} + onCancel={handleCancelEstimateDelete} + onConfirm={handleConfirmEstimateDelete} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withEstimateActions, +)(EstimateDeleteAlert); diff --git a/client/src/containers/Alerts/Estimates/EstimateDeliveredAlert.js b/client/src/containers/Alerts/Estimates/EstimateDeliveredAlert.js new file mode 100644 index 000000000..6c78ff76d --- /dev/null +++ b/client/src/containers/Alerts/Estimates/EstimateDeliveredAlert.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 withEstimateActions from 'containers/Sales/Estimate/withEstimateActions'; + +import { compose } from 'utils'; + +/** + * Estimate delivered alert. + */ +function EstimateDeliveredAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { estimateId }, + + // #withEstimateActions + requestDeliveredEstimate, + + // #withAlertActions + closeAlert, +}) { + const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); + + // Handle cancel delivered estimate alert. + const handleCancelDeliveredEstimate = () => { + closeAlert(name); + }; + + // Handle confirm estimate delivered. + const handleConfirmEstimateDelivered = useCallback(() => { + setLoading(true); + requestDeliveredEstimate(estimateId) + .then(() => { + AppToaster.show({ + message: formatMessage({ + id: 'the_estimate_has_been_delivered_successfully', + }), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('estimates-table'); + }) + .catch((error) => {}) + .finally(() => { + closeAlert(name); + setLoading(false); + }); + }, [estimateId, requestDeliveredEstimate, formatMessage]); + + return ( + } + confirmButtonText={} + intent={Intent.WARNING} + isOpen={isOpen} + onCancel={handleCancelDeliveredEstimate} + onConfirm={handleConfirmEstimateDelivered} + loading={isLoading} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withEstimateActions, +)(EstimateDeliveredAlert); diff --git a/client/src/containers/Alerts/Estimates/EstimateRejectAlert.js b/client/src/containers/Alerts/Estimates/EstimateRejectAlert.js new file mode 100644 index 000000000..58a069752 --- /dev/null +++ b/client/src/containers/Alerts/Estimates/EstimateRejectAlert.js @@ -0,0 +1,77 @@ +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 withEstimateActions from 'containers/Sales/Estimate/withEstimateActions'; + +import { compose } from 'utils'; + +/** + * Estimate reject delete alerts. + */ +function EstimateRejectAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { estimateId }, + + // #withEstimateActions + requestRejectEstimate, + + // #withAlertActions + closeAlert, +}) { + const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); + // Handle cancel reject estimate alert. + const handleCancelRejectEstimate = () => { + closeAlert(name); + }; + + // Handle confirm estimate reject. + const handleConfirmEstimateReject = useCallback(() => { + setLoading(true); + requestRejectEstimate(estimateId) + .then(() => { + AppToaster.show({ + message: formatMessage({ + id: 'the_estimate_has_been_rejected_successfully', + }), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('estimates-table'); + }) + .catch((error) => {}) + .finally(() => { + setLoading(false); + closeAlert(name); + }); + }, [estimateId, requestRejectEstimate, formatMessage]); + + return ( + } + confirmButtonText={} + intent={Intent.WARNING} + isOpen={isOpen} + onCancel={handleCancelRejectEstimate} + onConfirm={handleConfirmEstimateReject} + loading={isLoading} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withEstimateActions, +)(EstimateRejectAlert); diff --git a/client/src/containers/Sales/Estimate/EstimateFormPage.js b/client/src/containers/Sales/Estimate/EstimateFormPage.js index 9dbb3ed63..0ff455427 100644 --- a/client/src/containers/Sales/Estimate/EstimateFormPage.js +++ b/client/src/containers/Sales/Estimate/EstimateFormPage.js @@ -23,7 +23,7 @@ function EstimateFormPage({ requestFetchItems, // #withEstimateActions - requsetFetchEstimate, + requestFetchEstimate, // #withSettingsActions requestFetchOptions, @@ -52,7 +52,7 @@ function EstimateFormPage({ const fetchEstimate = useQuery( ['estimate', id], - (key, _id) => requsetFetchEstimate(_id), + (key, _id) => requestFetchEstimate(_id), { enabled: !!id }, ); diff --git a/client/src/containers/Sales/Estimate/EstimatesAlerts.js b/client/src/containers/Sales/Estimate/EstimatesAlerts.js new file mode 100644 index 000000000..ec27875f9 --- /dev/null +++ b/client/src/containers/Sales/Estimate/EstimatesAlerts.js @@ -0,0 +1,19 @@ +import React from 'react'; +import EstimateDeleteAlert from 'containers/Alerts/Estimates/EstimateDeleteAlert'; +import EstimateDeliveredAlert from 'containers/Alerts/Estimates/EstimateDeliveredAlert'; +import EstimateApproveAlert from 'containers/Alerts/Estimates/EstimateApproveAlert'; +import EstimateRejectAlert from 'containers/Alerts/Estimates/EstimateRejectAlert'; + +/** + * Estimates alert. + */ +export default function EstimatesAlerts() { + return ( +
+ + + + +
+ ); +} diff --git a/client/src/containers/Sales/Estimate/EstimatesList.js b/client/src/containers/Sales/Estimate/EstimatesList.js index fbda147c1..dfaed428f 100644 --- a/client/src/containers/Sales/Estimate/EstimatesList.js +++ b/client/src/containers/Sales/Estimate/EstimatesList.js @@ -8,6 +8,7 @@ import { FormattedMessage as T, useIntl } from 'react-intl'; import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; import DashboardInsider from 'components/Dashboard/DashboardInsider'; +import EstimatesAlerts from './EstimatesAlerts'; import EstimatesDataTable from './EstimatesDataTable'; import EstimateActionsBar from './EstimateActionsBar'; import EstimateViewTabs from './EstimateViewTabs'; @@ -15,8 +16,9 @@ import EstimateViewTabs from './EstimateViewTabs'; import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withResourceActions from 'containers/Resources/withResourcesActions'; import withEstimates from './withEstimates'; -import withEstimateActions from './withEstimateActions'; +import withEstimateActions from 'containers/Sales/Estimate/withEstimateActions'; import withViewsActions from 'containers/Views/withViewsActions'; +import withAlertsActions from 'containers/Alert/withAlertActions'; import { compose } from 'utils'; @@ -32,9 +34,11 @@ function EstimatesList({ estimatesTableQuery, estimateViews, + // #withAlertsActions. + openAlert, + //#withEistimateActions requestFetchEstimatesTable, - requestDeleteEstimate, requestDeliverdEstimate, requestApproveEstimate, requestRejectEstimate, @@ -42,7 +46,6 @@ function EstimatesList({ }) { const history = useHistory(); const { formatMessage } = useIntl(); - const [deleteEstimate, setDeleteEstimate] = useState(false); const [deliverEstimate, setDeliverEstimate] = useState(false); const [approveEstimate, setApproveEstimate] = useState(false); const [rejectEstimate, setRejectEstimate] = useState(false); @@ -70,111 +73,35 @@ function EstimatesList({ // handle delete estimate click const handleDeleteEstimate = useCallback( - (estimate) => { - setDeleteEstimate(estimate); + ({ id }) => { + openAlert('estimate-delete', { estimateId: id }); }, - [setDeleteEstimate], + [openAlert], ); - // handle cancel estimate - const handleCancelEstimateDelete = useCallback(() => { - setDeleteEstimate(false); - }, [setDeleteEstimate]); - - // handle confirm delete estimate - const handleConfirmEstimateDelete = useCallback(() => { - requestDeleteEstimate(deleteEstimate.id).then(() => { - AppToaster.show({ - message: formatMessage({ - id: 'the_estimate_has_been_deleted_successfully', - }), - intent: Intent.SUCCESS, - }); - setDeleteEstimate(false); - }); - }, [deleteEstimate, requestDeleteEstimate, formatMessage]); - // Handle cancel/confirm estimate deliver. - const handleDeliverEstimate = useCallback((estimate) => { - setDeliverEstimate(estimate); - }, []); - - // Handle cancel deliver estimate alert. - const handleCancelDeliverEstimate = useCallback(() => { - setDeliverEstimate(false); - }, []); - - // Handle confirm estimate deliver. - const handleConfirmEstimateDeliver = useCallback(() => { - requestDeliverdEstimate(deliverEstimate.id) - .then(() => { - setDeliverEstimate(false); - AppToaster.show({ - message: formatMessage({ - id: 'the_estimate_has_been_delivered_successfully', - }), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('estimates-table'); - }) - .catch((error) => { - setDeliverEstimate(false); - }); - }, [deliverEstimate, requestDeliverdEstimate, formatMessage]); + const handleDeliverEstimate = useCallback( + ({ id }) => { + openAlert('estimate-deliver', { estimateId: id }); + }, + [openAlert], + ); // Handle cancel/confirm estimate approve. - const handleApproveEstimate = useCallback((estimate) => { - setApproveEstimate(estimate); - }, []); - - // Handle cancel approve estimate alert. - const handleCancelApproveEstimate = useCallback(() => { - setApproveEstimate(false); - }, []); - - // Handle confirm estimate approve. - const handleConfirmEstimateApprove = useCallback(() => { - requestApproveEstimate(approveEstimate.id) - .then(() => { - setApproveEstimate(false); - AppToaster.show({ - message: formatMessage({ - id: 'the_estimate_has_been_approved_successfully', - }), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('estimates-table'); - }) - .catch((error) => { - setApproveEstimate(false); - }); - }, [approveEstimate, requestApproveEstimate, formatMessage]); + const handleApproveEstimate = useCallback( + ({ id }) => { + openAlert('estimate-Approve', { estimateId: id }); + }, + [openAlert], + ); // Handle cancel/confirm estimate reject. - const handleRejectEstimate = useCallback((estimate) => { - setRejectEstimate(estimate); - }, []); - - // Handle cancel reject estimate alert. - const handleCancelRejectEstimate = useCallback(() => { - setRejectEstimate(false); - }, []); - - // Handle confirm estimate reject. - const handleConfirmEstimateReject = useCallback(() => { - requestRejectEstimate(rejectEstimate.id) - .then(() => { - setRejectEstimate(false); - AppToaster.show({ - message: formatMessage({ - id: 'the_estimate_has_been_rejected_successfully', - }), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('estimates-table'); - }) - .catch((error) => {}); - }, [rejectEstimate, requestRejectEstimate, formatMessage]); + const handleRejectEstimate = useCallback( + ({ id }) => { + openAlert('estimate-reject', { estimateId: id }); + }, + [openAlert], + ); // Handle filter change to re-fetch data-table. const handleFilterChanged = useCallback(() => {}, []); @@ -224,56 +151,7 @@ function EstimatesList({ /> - - } - confirmButtonText={} - icon={'trash'} - intent={Intent.DANGER} - isOpen={deleteEstimate} - onCancel={handleCancelEstimateDelete} - onConfirm={handleConfirmEstimateDelete} - > -

- -

-
- } - confirmButtonText={} - intent={Intent.WARNING} - isOpen={deliverEstimate} - onCancel={handleCancelDeliverEstimate} - onConfirm={handleConfirmEstimateDeliver} - > -

- -

-
- } - confirmButtonText={} - intent={Intent.WARNING} - isOpen={approveEstimate} - onCancel={handleCancelApproveEstimate} - onConfirm={handleConfirmEstimateApprove} - > -

- -

-
- } - confirmButtonText={} - intent={Intent.WARNING} - isOpen={rejectEstimate} - onCancel={handleCancelRejectEstimate} - onConfirm={handleConfirmEstimateReject} - > -

- -

-
+ ); @@ -288,4 +166,5 @@ export default compose( estimatesTableQuery, estimateViews, })), + withAlertsActions, )(EstimatesList); diff --git a/client/src/containers/Sales/Estimate/withEstimateActions.js b/client/src/containers/Sales/Estimate/withEstimateActions.js index 5c36a8fd2..cf54edf9c 100644 --- a/client/src/containers/Sales/Estimate/withEstimateActions.js +++ b/client/src/containers/Sales/Estimate/withEstimateActions.js @@ -7,18 +7,18 @@ import { fetchEstimatesTable, deliverEstimate, approveEstimate, - rejectEstimate + rejectEstimate, } from 'store/Estimate/estimates.actions'; import t from 'store/types'; -const mapDipatchToProps = (dispatch) => ({ +const mapDispatchToProps = (dispatch) => ({ requestSubmitEstimate: (form) => dispatch(submitEstimate({ form })), - requsetFetchEstimate: (id) => dispatch(fetchEstimate({ id })), + requestFetchEstimate: (id) => dispatch(fetchEstimate({ id })), requestEditEstimate: (id, form) => dispatch(editEstimate(id, form)), requestFetchEstimatesTable: (query = {}) => dispatch(fetchEstimatesTable({ query: { ...query } })), requestDeleteEstimate: (id) => dispatch(deleteEstimate({ id })), - requestDeliverdEstimate: (id) => dispatch(deliverEstimate({ id })), + requestDeliveredEstimate: (id) => dispatch(deliverEstimate({ id })), requestApproveEstimate: (id) => dispatch(approveEstimate({ id })), requestRejectEstimate: (id) => dispatch(rejectEstimate({ id })), @@ -38,6 +38,11 @@ const mapDipatchToProps = (dispatch) => ({ type: t.ESTIMATE_NUMBER_CHANGED, payload: { isChanged }, }), + setSelectedRowsEstimates: (selectedRows) => + dispatch({ + type: t.ESTIMATES_SELECTED_ROWS_SET, + payload: { selectedRows }, + }), }); -export default connect(null, mapDipatchToProps); +export default connect(null, mapDispatchToProps); diff --git a/client/src/containers/Sales/Estimate/withEstimates.js b/client/src/containers/Sales/Estimate/withEstimates.js index 36be9d88c..ee812c25b 100644 --- a/client/src/containers/Sales/Estimate/withEstimates.js +++ b/client/src/containers/Sales/Estimate/withEstimates.js @@ -22,7 +22,8 @@ export default (mapState) => { estimateViews: getResourceViews(state, props, 'sale_estimate'), estimateItems: state.salesEstimates.items, - + estimateSelectedRows: state.salesEstimates.selectedRows, + estimatesTableQuery: query, estimatesPageination: getEstimatesPaginationMeta(state, props, query), estimatesLoading: state.salesEstimates.loading, diff --git a/client/src/store/Estimate/estimates.reducer.js b/client/src/store/Estimate/estimates.reducer.js index 410b140e4..0ea564c6a 100644 --- a/client/src/store/Estimate/estimates.reducer.js +++ b/client/src/store/Estimate/estimates.reducer.js @@ -15,6 +15,7 @@ const initialState = { page: 1, }, currentViewId: -1, + selectedRows: [], }; const defaultEstimate = { @@ -101,6 +102,10 @@ export default createReducer(initialState, { }, }; }, + [t.ESTIMATES_SELECTED_ROWS_SET]: (state, action) => { + const { selectedRows } = action.payload; + state.selectedRows = selectedRows; + }, ...journalNumberChangedReducer(t.ESTIMATE_NUMBER_CHANGED), ...createTableQueryReducers('ESTIMATES'), diff --git a/client/src/store/Estimate/estimates.types.js b/client/src/store/Estimate/estimates.types.js index 5a8801081..5d958d24d 100644 --- a/client/src/store/Estimate/estimates.types.js +++ b/client/src/store/Estimate/estimates.types.js @@ -10,4 +10,5 @@ export default { ESTIMATES_PAGE_SET: 'ESTIMATES_PAGE_SET', ESTIMATES_ITEMS_SET: 'ESTIMATES_ITEMS_SET', ESTIMATE_NUMBER_CHANGED: 'ESTIMATE_NUMBER_CHANGED', + ESTIMATES_SELECTED_ROWS_SET: 'ESTIMATES_SELECTED_ROWS_SET', }; From 0e95c5cce105c26064ec3b76b73102a48ea52648 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Wed, 27 Jan 2021 13:20:15 +0200 Subject: [PATCH 2/8] refactor: items alert. --- client/package.json | 2 +- .../InventoryAdjustmentDeleteAlert.js | 10 +++++++--- .../Alerts/{Item => Items}/ItemActivateAlert.js | 17 +++++++++-------- .../{Item => Items}/ItemBulkDeleteAlert.js | 10 ++++++---- .../ItemCategoryBulkDeleteAlert.js | 10 +++++++--- .../{Item => Items}/ItemCategoryDeleteAlert.js | 10 +++++++--- .../Alerts/{Item => Items}/ItemDeleteAlert.js | 9 +++++++-- .../{Item => Items}/ItemInactivateAlert.js | 15 ++++++++------- client/src/containers/Items/ItemsAlerts.js | 14 +++++++------- 9 files changed, 59 insertions(+), 38 deletions(-) rename client/src/containers/Alerts/{Item => Items}/InventoryAdjustmentDeleteAlert.js (90%) rename client/src/containers/Alerts/{Item => Items}/ItemActivateAlert.js (85%) rename client/src/containers/Alerts/{Item => Items}/ItemBulkDeleteAlert.js (89%) rename client/src/containers/Alerts/{Item => Items}/ItemCategoryBulkDeleteAlert.js (89%) rename client/src/containers/Alerts/{Item => Items}/ItemCategoryDeleteAlert.js (90%) rename client/src/containers/Alerts/{Item => Items}/ItemDeleteAlert.js (90%) rename client/src/containers/Alerts/{Item => Items}/ItemInactivateAlert.js (85%) diff --git a/client/package.json b/client/package.json index a73054c21..87266a85b 100644 --- a/client/package.json +++ b/client/package.json @@ -4,7 +4,7 @@ "private": true, "dependencies": { "@babel/core": "7.8.4", - "@blueprintjs/core": "^3.23.1", + "@blueprintjs/core": "^3.38.1", "@blueprintjs/datetime": "^3.15.2", "@blueprintjs/select": "^3.11.2", "@blueprintjs/table": "^3.8.3", diff --git a/client/src/containers/Alerts/Item/InventoryAdjustmentDeleteAlert.js b/client/src/containers/Alerts/Items/InventoryAdjustmentDeleteAlert.js similarity index 90% rename from client/src/containers/Alerts/Item/InventoryAdjustmentDeleteAlert.js rename to client/src/containers/Alerts/Items/InventoryAdjustmentDeleteAlert.js index 57f862073..e538e095f 100644 --- a/client/src/containers/Alerts/Item/InventoryAdjustmentDeleteAlert.js +++ b/client/src/containers/Alerts/Items/InventoryAdjustmentDeleteAlert.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { FormattedMessage as T, FormattedHTMLMessage, @@ -30,6 +30,7 @@ function InventoryAdjustmentDeleteAlert({ closeAlert, }) { const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); // handle cancel delete alert. const handleCancelInventoryAdjustmentDelete = () => { @@ -37,9 +38,9 @@ function InventoryAdjustmentDeleteAlert({ }; const handleConfirmInventoryAdjustmentDelete = () => { + setLoading(true); requestDeleteInventoryAdjustment(inventoryId) .then(() => { - closeAlert(name); AppToaster.show({ message: formatMessage({ id: 'the_adjustment_has_been_deleted_successfully', @@ -48,7 +49,9 @@ function InventoryAdjustmentDeleteAlert({ }); queryCache.invalidateQueries('inventory-adjustment-list'); }) - .catch((errors) => { + .catch((errors) => {}) + .finally(() => { + setLoading(false); closeAlert(name); }); }; @@ -62,6 +65,7 @@ function InventoryAdjustmentDeleteAlert({ isOpen={isOpen} onCancel={handleCancelInventoryAdjustmentDelete} onConfirm={handleConfirmInventoryAdjustmentDelete} + loading={isLoading} >

{ closeAlert(name); @@ -38,9 +36,9 @@ function ItemActivateAlert({ // Handle confirm item activated. const handleConfirmItemActivate = () => { + setLoading(true); requestActivateItem(itemId) .then(() => { - closeAlert(name); AppToaster.show({ message: formatMessage({ id: 'the_item_has_been_activated_successfully', @@ -49,8 +47,10 @@ function ItemActivateAlert({ }); queryCache.invalidateQueries('items-table'); }) - .catch((error) => { + .catch((error) => {}) + .finally(() => { closeAlert(name); + setLoading(false); }); }; @@ -62,6 +62,7 @@ function ItemActivateAlert({ isOpen={isOpen} onCancel={handleCancelActivateItem} onConfirm={handleConfirmItemActivate} + loading={isLoading} >

diff --git a/client/src/containers/Alerts/Item/ItemBulkDeleteAlert.js b/client/src/containers/Alerts/Items/ItemBulkDeleteAlert.js similarity index 89% rename from client/src/containers/Alerts/Item/ItemBulkDeleteAlert.js rename to client/src/containers/Alerts/Items/ItemBulkDeleteAlert.js index 0aa178eb5..354fd43e4 100644 --- a/client/src/containers/Alerts/Item/ItemBulkDeleteAlert.js +++ b/client/src/containers/Alerts/Items/ItemBulkDeleteAlert.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { FormattedMessage as T, useIntl } from 'react-intl'; import { Intent, Alert } from '@blueprintjs/core'; import { AppToaster } from 'components'; @@ -26,16 +26,16 @@ function ItemBulkDeleteAlert({ closeAlert, }) { const { formatMessage } = useIntl(); - + const [isLoading, setLoading] = useState(false); // handle cancel item bulk delete alert. const handleCancelBulkDelete = () => { closeAlert(name); }; // Handle confirm items bulk delete. const handleConfirmBulkDelete = () => { + setLoading(true); requestDeleteBulkItems(itemsIds) .then(() => { - closeAlert(name); AppToaster.show({ message: formatMessage({ id: 'the_items_has_been_deleted_successfully', @@ -43,7 +43,9 @@ function ItemBulkDeleteAlert({ intent: Intent.SUCCESS, }); }) - .catch((errors) => { + .catch((errors) => {}) + .finally(() => { + setLoading(false); closeAlert(name); }); }; diff --git a/client/src/containers/Alerts/Item/ItemCategoryBulkDeleteAlert.js b/client/src/containers/Alerts/Items/ItemCategoryBulkDeleteAlert.js similarity index 89% rename from client/src/containers/Alerts/Item/ItemCategoryBulkDeleteAlert.js rename to client/src/containers/Alerts/Items/ItemCategoryBulkDeleteAlert.js index 644ca020d..3bdee7dc1 100644 --- a/client/src/containers/Alerts/Item/ItemCategoryBulkDeleteAlert.js +++ b/client/src/containers/Alerts/Items/ItemCategoryBulkDeleteAlert.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { FormattedMessage as T, FormattedHTMLMessage, @@ -30,6 +30,7 @@ function ItemCategoryBulkDeleteAlert({ closeAlert, }) { const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); // handle cancel bulk delete alert. const handleCancelBulkDelete = () => { @@ -38,9 +39,9 @@ function ItemCategoryBulkDeleteAlert({ // handle confirm itemCategories bulk delete. const handleConfirmBulkDelete = () => { + setLoading(true); requestDeleteBulkItemCategories(itemCategoriesIds) .then(() => { - closeAlert(name); AppToaster.show({ message: formatMessage({ id: 'the_item_categories_has_been_deleted_successfully', @@ -48,8 +49,10 @@ function ItemCategoryBulkDeleteAlert({ intent: Intent.SUCCESS, }); }) - .catch((errors) => { + .catch((errors) => {}) + .finally(() => { closeAlert(name); + setLoading(false); }); }; return ( @@ -63,6 +66,7 @@ function ItemCategoryBulkDeleteAlert({ isOpen={isOpen} onCancel={handleCancelBulkDelete} onConfirm={handleConfirmBulkDelete} + loading={isLoading} >

{ @@ -39,9 +40,9 @@ function ItemCategoryDeleteAlert({ // Handle alert confirm delete item category. const handleConfirmItemDelete = () => { + setLoading(true); requestDeleteItemCategory(itemCategoryId) .then(() => { - closeAlert(name); AppToaster.show({ message: formatMessage({ id: 'the_item_category_has_been_deleted_successfully', @@ -50,7 +51,9 @@ function ItemCategoryDeleteAlert({ }); queryCache.invalidateQueries('items-categories-list'); }) - .catch(() => { + .catch(() => {}) + .finally(() => { + setLoading(false); closeAlert(name); }); }; @@ -64,6 +67,7 @@ function ItemCategoryDeleteAlert({ isOpen={isOpen} onCancel={handleCancelItemCategoryDelete} onConfirm={handleConfirmItemDelete} + loading={isLoading} >

{ @@ -40,9 +41,9 @@ function ItemDeleteAlert({ }; const handleConfirmDeleteItem = () => { + setLoading(true); requestDeleteItem(itemId) .then(() => { - closeAlert(name); AppToaster.show({ message: formatMessage({ id: 'the_item_has_been_deleted_successfully', @@ -53,7 +54,10 @@ function ItemDeleteAlert({ }) .catch(({ errors }) => { handleDeleteErrors(errors); + }) + .finally(() => { closeAlert(name); + setLoading(false); }); }; @@ -66,6 +70,7 @@ function ItemDeleteAlert({ isOpen={isOpen} onCancel={handleCancelItemDelete} onConfirm={handleConfirmDeleteItem} + loading={isLoading} >

{ @@ -38,9 +36,9 @@ function ItemInactivateAlert({ // Handle confirm item Inactive. const handleConfirmItemInactive = () => { + setLoading(true); requestInactiveItem(itemId) .then(() => { - closeAlert(name); AppToaster.show({ message: formatMessage({ id: 'the_item_has_been_inactivated_successfully', @@ -49,7 +47,9 @@ function ItemInactivateAlert({ }); queryCache.invalidateQueries('items-table'); }) - .catch((error) => { + .catch((error) => {}) + .finally(() => { + setLoading(false); closeAlert(name); }); }; @@ -62,6 +62,7 @@ function ItemInactivateAlert({ isOpen={isOpen} onCancel={handleCancelInactivateItem} onConfirm={handleConfirmItemInactive} + loading={isLoading} >

diff --git a/client/src/containers/Items/ItemsAlerts.js b/client/src/containers/Items/ItemsAlerts.js index 26482550a..858340f8c 100644 --- a/client/src/containers/Items/ItemsAlerts.js +++ b/client/src/containers/Items/ItemsAlerts.js @@ -1,11 +1,11 @@ import React from 'react'; -import ItemDeleteAlert from 'containers/Alerts/Item/ItemDeleteAlert'; -import ItemInactivateAlert from 'containers/Alerts/Item/ItemInactivateAlert'; -import ItemActivateAlert from 'containers/Alerts/Item/ItemActivateAlert'; -import ItemBulkDeleteAlert from 'containers/Alerts/Item/ItemBulkDeleteAlert'; -import ItemCategoryDeleteAlert from 'containers/Alerts/Item/ItemCategoryDeleteAlert'; -import ItemCategoryBulkDeleteAlert from 'containers/Alerts/Item/ItemCategoryBulkDeleteAlert'; -import InventoryAdjustmentDeleteAlert from 'containers/Alerts/Item/InventoryAdjustmentDeleteAlert'; +import ItemDeleteAlert from 'containers/Alerts/Items/ItemDeleteAlert'; +import ItemInactivateAlert from 'containers/Alerts/Items/ItemInactivateAlert'; +import ItemActivateAlert from 'containers/Alerts/Items/ItemActivateAlert'; +import ItemBulkDeleteAlert from 'containers/Alerts/Items/ItemBulkDeleteAlert'; +import ItemCategoryDeleteAlert from 'containers/Alerts/Items/ItemCategoryDeleteAlert'; +import ItemCategoryBulkDeleteAlert from 'containers/Alerts/Items/ItemCategoryBulkDeleteAlert'; +import InventoryAdjustmentDeleteAlert from 'containers/Alerts/Items/InventoryAdjustmentDeleteAlert'; /** * Items alert. From 963f68a64088386a0c749412a51b60a3319c47ba Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Wed, 27 Jan 2021 14:54:08 +0200 Subject: [PATCH 3/8] 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, + }); + } +}; From 216eef889b3190b7207a4e01b8abc32894b0533a Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Wed, 27 Jan 2021 14:56:27 +0200 Subject: [PATCH 4/8] refactor: Payment Receives alerts. --- .../PaymentReceiveDeleteAlert.js | 85 +++++++++++++++++++ .../PaymentReceive/PaymentReceiveAlerts.js | 13 +++ .../PaymentReceive/PaymentReceivesList.js | 85 ++++--------------- 3 files changed, 113 insertions(+), 70 deletions(-) create mode 100644 client/src/containers/Alerts/PaymentReceives/PaymentReceiveDeleteAlert.js create mode 100644 client/src/containers/Sales/PaymentReceive/PaymentReceiveAlerts.js diff --git a/client/src/containers/Alerts/PaymentReceives/PaymentReceiveDeleteAlert.js b/client/src/containers/Alerts/PaymentReceives/PaymentReceiveDeleteAlert.js new file mode 100644 index 000000000..1a64ae5d1 --- /dev/null +++ b/client/src/containers/Alerts/PaymentReceives/PaymentReceiveDeleteAlert.js @@ -0,0 +1,85 @@ +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 withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect'; +import withAlertActions from 'containers/Alert/withAlertActions'; +import withPaymentReceivesActions from 'containers/Sales/PaymentReceive/withPaymentReceivesActions'; + +import { compose } from 'utils'; + +/** + * Payment receive delete alert. + */ +function PaymentReceiveDeleteAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { paymentReceiveId }, + + // #withPaymentReceivesActions + requestDeletePaymentReceive, + + // #withAlertActions + closeAlert, +}) { + const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); + + // Handle cancel payment Receive. + const handleCancelDeleteAlert = () => { + closeAlert(name); + }; + + // Handle confirm delete payment receive. + const handleConfirmPaymentReceiveDelete = useCallback(() => { + setLoading(true); + requestDeletePaymentReceive(paymentReceiveId) + .then(() => { + AppToaster.show({ + message: formatMessage({ + id: 'the_payment_receive_has_been_deleted_successfully', + }), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('paymentReceives-table'); + }) + .catch(() => {}) + .finally(() => { + closeAlert(name); + setLoading(false); + }); + }, [paymentReceiveId, requestDeletePaymentReceive, formatMessage]); + + return ( + } + confirmButtonText={} + icon="trash" + intent={Intent.DANGER} + isOpen={isOpen} + onCancel={handleCancelDeleteAlert} + onConfirm={handleConfirmPaymentReceiveDelete} + loading={isLoading} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withPaymentReceivesActions, +)(PaymentReceiveDeleteAlert); diff --git a/client/src/containers/Sales/PaymentReceive/PaymentReceiveAlerts.js b/client/src/containers/Sales/PaymentReceive/PaymentReceiveAlerts.js new file mode 100644 index 000000000..0d0bb0e1b --- /dev/null +++ b/client/src/containers/Sales/PaymentReceive/PaymentReceiveAlerts.js @@ -0,0 +1,13 @@ +import React from 'react'; +import PaymentReceiveDeleteAlert from 'containers/Alerts/PaymentReceives/PaymentReceiveDeleteAlert'; + +/** + * PaymentReceives alert. + */ +export default function EstimatesAlerts() { + return ( +
+ +
+ ); +} diff --git a/client/src/containers/Sales/PaymentReceive/PaymentReceivesList.js b/client/src/containers/Sales/PaymentReceive/PaymentReceivesList.js index 04c71192c..21d5093b0 100644 --- a/client/src/containers/Sales/PaymentReceive/PaymentReceivesList.js +++ b/client/src/containers/Sales/PaymentReceive/PaymentReceivesList.js @@ -1,9 +1,7 @@ -import React, { useEffect, useCallback, useMemo, useState } from 'react'; +import React, { useEffect, useCallback, 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 AppToaster from 'components/AppToaster'; import { FormattedMessage as T, useIntl } from 'react-intl'; import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; import DashboardInsider from 'components/Dashboard/DashboardInsider'; @@ -11,12 +9,12 @@ import DashboardInsider from 'components/Dashboard/DashboardInsider'; import PaymentReceivesDataTable from './PaymentReceivesDataTable'; import PaymentReceiveActionsBar from './PaymentReceiveActionsBar'; import PaymentReceiveViewTabs from './PaymentReceiveViewTabs'; - +import PaymentReceiveAlerts from './PaymentReceiveAlerts'; import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withResourceActions from 'containers/Resources/withResourcesActions'; import withPaymentReceives from './withPaymentReceives'; import withPaymentReceivesActions from './withPaymentReceivesActions'; -import withViewsActions from 'containers/Views/withViewsActions'; +import withAlertsActions from 'containers/Alert/withAlertActions'; import { compose } from 'utils'; @@ -24,77 +22,40 @@ function PaymentReceiveList({ // #withDashboardActions changePageTitle, - // #withViewsActions - requestFetchResourceViews, - requestFetchResourceFields, - //#withPaymentReceives paymentReceivesTableQuery, + // #withAlertsActions. + openAlert, + //#withPaymentReceivesActions requestFetchPaymentReceiveTable, - requestDeletePaymentReceive, - addPaymentReceivesTableQueries, }) { const history = useHistory(); const { formatMessage } = useIntl(); - const [deletePaymentReceive, setDeletePaymentReceive] = useState(false); const [selectedRows, setSelectedRows] = useState([]); useEffect(() => { changePageTitle(formatMessage({ id: 'payment_Receives_list' })); }, [changePageTitle, formatMessage]); - const fetchResourceViews = useQuery( - ['resource-views', 'payment_receives'], - (key, resourceName) => requestFetchResourceViews(resourceName), - ); - - const fetchResourceFields = useQuery( - ['resource-fields', 'payment_receives'], - (key, resourceName) => requestFetchResourceFields(resourceName), - ); - const fetchPaymentReceives = useQuery( - ['paymantReceives-table', paymentReceivesTableQuery], + ['paymentReceives-table', paymentReceivesTableQuery], () => requestFetchPaymentReceiveTable(), ); - // Handle dalete Payment Receive + // Handle delete Payment Receive const handleDeletePaymentReceive = useCallback( - (paymentReceive) => { - setDeletePaymentReceive(paymentReceive); + ({ id }) => { + openAlert('payment-receive-delete', { paymentReceiveId: id }); }, - [setDeletePaymentReceive], + [openAlert], ); - // Handle cancel payment Receive. - const handleCancelPaymentReceiveDelete = useCallback(() => { - setDeletePaymentReceive(false); - }, [setDeletePaymentReceive]); - - // Handle confirm delete payment receive. - const handleConfirmPaymentReceiveDelete = useCallback(() => { - requestDeletePaymentReceive(deletePaymentReceive.id).then(() => { - AppToaster.show({ - message: formatMessage({ - id: 'the_payment_receive_has_been_deleted_successfully', - }), - intent: Intent.SUCCESS, - }); - setDeletePaymentReceive(false); - }); - }, [deletePaymentReceive, requestDeletePaymentReceive, formatMessage]); - const handleEditPaymentReceive = useCallback((payment) => { history.push(`/payment-receives/${payment.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(() => {}, [fetchPaymentReceives]); @@ -107,12 +68,8 @@ function PaymentReceiveList({ ); return ( - + @@ -133,19 +90,7 @@ function PaymentReceiveList({ /> - } - confirmButtonText={} - icon={'trash'} - intent={Intent.DANGER} - isOpen={deletePaymentReceive} - onCancel={handleCancelPaymentReceiveDelete} - onConfirm={handleConfirmPaymentReceiveDelete} - > -

- -

-
+
); @@ -155,8 +100,8 @@ export default compose( withResourceActions, withPaymentReceivesActions, withDashboardActions, - withViewsActions, withPaymentReceives(({ paymentReceivesTableQuery }) => ({ paymentReceivesTableQuery, })), + withAlertsActions, )(PaymentReceiveList); From 29259f460dfa4524442c2d313a385b781a8faffa Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Wed, 27 Jan 2021 15:20:58 +0200 Subject: [PATCH 5/8] refactor: receipts alerts. --- .../Alerts/Receipts/ReceiptCloseAlert.js | 78 +++++++++++++ .../Alerts/Receipts/ReceiptDeleteAlert.js | 85 ++++++++++++++ .../Sales/Receipt/ReceiptsAlerts.js | 15 +++ .../containers/Sales/Receipt/ReceiptsList.js | 110 +++--------------- 4 files changed, 192 insertions(+), 96 deletions(-) create mode 100644 client/src/containers/Alerts/Receipts/ReceiptCloseAlert.js create mode 100644 client/src/containers/Alerts/Receipts/ReceiptDeleteAlert.js create mode 100644 client/src/containers/Sales/Receipt/ReceiptsAlerts.js diff --git a/client/src/containers/Alerts/Receipts/ReceiptCloseAlert.js b/client/src/containers/Alerts/Receipts/ReceiptCloseAlert.js new file mode 100644 index 000000000..4057942e3 --- /dev/null +++ b/client/src/containers/Alerts/Receipts/ReceiptCloseAlert.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 withReceiptActions from 'containers/Sales/Receipt/withReceiptActions'; + +import { compose } from 'utils'; + +/** + * Receipt close alert. + */ +function ReceiptCloseAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { receiptId }, + + // #withReceiptActions + requestCloseReceipt, + + // #withAlertActions + closeAlert, +}) { + const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); + + // handle cancel delete alert. + const handleCancelDeleteAlert = () => { + closeAlert(name); + }; + + // Handle confirm receipt close. + const handleConfirmReceiptClose = useCallback(() => { + setLoading(true); + requestCloseReceipt(receiptId) + .then(() => { + AppToaster.show({ + message: formatMessage({ + id: 'the_receipt_has_been_closed_successfully', + }), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('receipts-table'); + }) + .catch((error) => {}) + .finally(() => { + closeAlert(name); + setLoading(false); + }); + }, [receiptId, requestCloseReceipt, formatMessage]); + + return ( + } + confirmButtonText={} + intent={Intent.WARNING} + isOpen={isOpen} + onCancel={handleCancelDeleteAlert} + onConfirm={handleConfirmReceiptClose} + loading={isLoading} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withReceiptActions, +)(ReceiptCloseAlert); diff --git a/client/src/containers/Alerts/Receipts/ReceiptDeleteAlert.js b/client/src/containers/Alerts/Receipts/ReceiptDeleteAlert.js new file mode 100644 index 000000000..0aa3703b0 --- /dev/null +++ b/client/src/containers/Alerts/Receipts/ReceiptDeleteAlert.js @@ -0,0 +1,85 @@ +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 withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect'; +import withAlertActions from 'containers/Alert/withAlertActions'; +import withReceiptActions from 'containers/Sales/Receipt/withReceiptActions'; + +import { compose } from 'utils'; + +/** + * Invoice alert. + */ +function NameDeleteAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { receiptId }, + + // #withReceiptActions + requestDeleteReceipt, + + // #withAlertActions + closeAlert, +}) { + const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); + + // handle cancel delete alert. + const handleCancelDeleteAlert = () => { + closeAlert(name); + }; + + // handle confirm delete receipt + const handleConfirmReceiptDelete = useCallback(() => { + setLoading(true); + requestDeleteReceipt(receiptId) + .then(() => { + AppToaster.show({ + message: formatMessage({ + id: 'the_receipt_has_been_deleted_successfully', + }), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('receipts-table'); + }) + .catch(() => {}) + .finally(() => { + setLoading(false); + closeAlert(name); + }); + }, [receiptId, requestDeleteReceipt, formatMessage]); + + return ( + } + confirmButtonText={} + icon="trash" + intent={Intent.DANGER} + isOpen={isOpen} + onCancel={handleCancelDeleteAlert} + onConfirm={handleConfirmReceiptDelete} + loading={isLoading} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withReceiptActions, +)(NameDeleteAlert); diff --git a/client/src/containers/Sales/Receipt/ReceiptsAlerts.js b/client/src/containers/Sales/Receipt/ReceiptsAlerts.js new file mode 100644 index 000000000..a5e98e5e6 --- /dev/null +++ b/client/src/containers/Sales/Receipt/ReceiptsAlerts.js @@ -0,0 +1,15 @@ +import React from 'react'; +import ReceiptDeleteAlert from 'containers/Alerts/Receipts/ReceiptDeleteAlert'; +import ReceiptCloseAlert from 'containers/Alerts/Receipts/ReceiptCloseAlert'; + +/** + * Receipts alerts. + */ +export default function ReceiptsAlerts() { + return ( +
+ + +
+ ); +} diff --git a/client/src/containers/Sales/Receipt/ReceiptsList.js b/client/src/containers/Sales/Receipt/ReceiptsList.js index 4a9e74853..0d0aae47f 100644 --- a/client/src/containers/Sales/Receipt/ReceiptsList.js +++ b/client/src/containers/Sales/Receipt/ReceiptsList.js @@ -1,9 +1,7 @@ -import React, { useEffect, useCallback, useMemo, useState } from 'react'; +import React, { useEffect, useCallback, 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 AppToaster from 'components/AppToaster'; import { FormattedMessage as T, useIntl } from 'react-intl'; import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; import DashboardInsider from 'components/Dashboard/DashboardInsider'; @@ -11,12 +9,14 @@ import DashboardInsider from 'components/Dashboard/DashboardInsider'; import ReceiptsDataTable from './ReceiptsDataTable'; import ReceiptActionsBar from './ReceiptActionsBar'; import ReceiptViewTabs from './ReceiptViewTabs'; +import ReceiptsAlerts from './ReceiptsAlerts'; import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withResourceActions from 'containers/Resources/withResourcesActions'; import withReceipts from './withReceipts'; import withReceiptActions from './withReceiptActions'; import withViewsActions from 'containers/Views/withViewsActions'; +import withAlertsActions from 'containers/Alert/withAlertActions'; import { compose } from 'utils'; @@ -26,21 +26,19 @@ function ReceiptsList({ // #withViewsActions requestFetchResourceViews, - requestFetchResourceFields, //#withReceipts receiptTableQuery, + // #withAlertsActions, + openAlert, + //#withReceiptActions requestFetchReceiptsTable, - requestDeleteReceipt, - requestCloseReceipt, addReceiptsTableQueries, }) { const history = useHistory(); const { formatMessage } = useIntl(); - const [deleteReceipt, setDeleteReceipt] = useState(false); - const [closeReceipt, setCloseReceipt] = useState(false); const [selectedRows, setSelectedRows] = useState([]); const fetchReceipts = useQuery( @@ -59,76 +57,20 @@ function ReceiptsList({ // handle delete receipt click const handleDeleteReceipt = useCallback( - (_receipt) => { - setDeleteReceipt(_receipt); + ({ id }) => { + openAlert('receipt-delete', { receiptId: id }); }, - [setDeleteReceipt], + [openAlert], ); - // handle cancel receipt - const handleCancelReceiptDelete = useCallback(() => { - setDeleteReceipt(false); - }, [setDeleteReceipt]); - - // handle confirm delete receipt - const handleConfirmReceiptDelete = useCallback(() => { - requestDeleteReceipt(deleteReceipt.id).then(() => { - AppToaster.show({ - message: formatMessage({ - id: 'the_receipt_has_been_deleted_successfully', - }), - intent: Intent.SUCCESS, - }); - setDeleteReceipt(false); - }); - }, [deleteReceipt, requestDeleteReceipt, formatMessage]); - // Handle cancel/confirm receipt deliver. - const handleCloseReceipt = useCallback((receipt) => { - setCloseReceipt(receipt); + const handleCloseReceipt = useCallback(({ id }) => { + openAlert('receipt-close', { receiptId: id }); }, []); - // Handle cancel close receipt alert. - const handleCancelCloseReceipt = useCallback(() => { - setCloseReceipt(false); - }, []); - - // Handle confirm receipt close. - const handleConfirmReceiptClose = useCallback(() => { - requestCloseReceipt(closeReceipt.id) - .then(() => { - setCloseReceipt(false); - AppToaster.show({ - message: formatMessage({ - id: 'the_receipt_has_been_closed_successfully', - }), - intent: Intent.SUCCESS, - }); - queryCache.invalidateQueries('receipts-table'); - }) - .catch((error) => { - setCloseReceipt(false); - }); - }, [closeReceipt, requestCloseReceipt, formatMessage]); - - // Handle filter change to re-fetch data-table. - // const handleFilterChanged = useCallback( - // (filterConditions) => { - // addReceiptsTableQueries({ - // filter_roles: filterConditions || '', - // }); - // }, - // [fetchReceipt], - // ); - // Handle filter change to re-fetch data-table. const handleFilterChanged = useCallback(() => {}, [fetchReceipts]); - // Calculates the selected rows - const selectedRowsCount = useMemo(() => Object.values(selectedRows).length, [ - selectedRows, - ]); - const handleEditReceipt = useCallback( (receipt) => { history.push(`/receipts/${receipt.id}/edit`); @@ -167,32 +109,7 @@ function ReceiptsList({ /> - - } - confirmButtonText={} - icon={'trash'} - intent={Intent.DANGER} - isOpen={deleteReceipt} - onCancel={handleCancelReceiptDelete} - onConfirm={handleConfirmReceiptDelete} - > -

- -

-
- } - confirmButtonText={} - intent={Intent.WARNING} - isOpen={closeReceipt} - onCancel={handleCancelCloseReceipt} - onConfirm={handleConfirmReceiptClose} - > -

- -

-
+
); @@ -206,4 +123,5 @@ export default compose( withReceipts(({ receiptTableQuery }) => ({ receiptTableQuery, })), + withAlertsActions, )(ReceiptsList); From 25d4b558b6ee48854a853a4fe02982cdb292b7b3 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Wed, 27 Jan 2021 20:01:33 +0200 Subject: [PATCH 6/8] refactor: customers alerts. --- .../Customers/CustomerBulkDeleteAlert.js | 81 ++++++++ .../Alerts/Customers/CustomerDeleteAlert.js | 87 ++++++++ .../Alerts/Items/ItemBulkDeleteAlert.js | 3 +- .../Customers/CustomerActionsBar.js | 42 ++-- .../src/containers/Customers/CustomerTable.js | 1 - .../containers/Customers/CustomersAlerts.js | 15 ++ .../src/containers/Customers/CustomersList.js | 190 +----------------- .../containers/Customers/CustomersViewPage.js | 61 ++++++ client/src/containers/Customers/utils.js | 25 +++ .../src/containers/Customers/withCustomers.js | 3 +- .../Customers/withCustomersActions.js | 5 + .../src/store/customers/customers.reducer.js | 10 +- client/src/store/customers/customers.type.js | 1 + 13 files changed, 311 insertions(+), 213 deletions(-) create mode 100644 client/src/containers/Alerts/Customers/CustomerBulkDeleteAlert.js create mode 100644 client/src/containers/Alerts/Customers/CustomerDeleteAlert.js create mode 100644 client/src/containers/Customers/CustomersAlerts.js create mode 100644 client/src/containers/Customers/CustomersViewPage.js create mode 100644 client/src/containers/Customers/utils.js diff --git a/client/src/containers/Alerts/Customers/CustomerBulkDeleteAlert.js b/client/src/containers/Alerts/Customers/CustomerBulkDeleteAlert.js new file mode 100644 index 000000000..253f04016 --- /dev/null +++ b/client/src/containers/Alerts/Customers/CustomerBulkDeleteAlert.js @@ -0,0 +1,81 @@ +import React, { useCallback, useState } from 'react'; +import { FormattedMessage as T, useIntl } from 'react-intl'; +import { Intent, Alert } from '@blueprintjs/core'; +import { AppToaster } from 'components'; +import { transformErrors } from 'containers/Customers/utils'; + +import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect'; +import withAlertActions from 'containers/Alert/withAlertActions'; +import withCustomersActions from 'containers/Customers/withCustomersActions'; + +import { compose } from 'utils'; + +/** + * Customer bulk delete alert. + */ +function CustomerBulkDeleteAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { customersIds }, + // #withCustomersActions + requestDeleteBulkCustomers, + + // #withAlertActions + closeAlert, +}) { + const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); + + // handle cancel delete alert. + const handleCancelDeleteAlert = () => { + closeAlert(name); + }; + + console.log(customersIds, 'EE'); + + // Handle confirm customers bulk delete. + const handleConfirmBulkDelete = useCallback(() => { + setLoading(true); + requestDeleteBulkCustomers(customersIds) + .then(() => { + AppToaster.show({ + message: formatMessage({ + id: 'the_customers_has_been_deleted_successfully', + }), + intent: Intent.SUCCESS, + }); + }) + .catch((errors) => { + transformErrors(errors); + }) + .finally(() => { + setLoading(false); + closeAlert(name); + }); + }, [requestDeleteBulkCustomers, customersIds, formatMessage]); + + return ( + } + confirmButtonText={} + icon="trash" + intent={Intent.DANGER} + isOpen={isOpen} + onCancel={handleCancelDeleteAlert} + onConfirm={handleConfirmBulkDelete} + loading={isLoading} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withCustomersActions, +)(CustomerBulkDeleteAlert); diff --git a/client/src/containers/Alerts/Customers/CustomerDeleteAlert.js b/client/src/containers/Alerts/Customers/CustomerDeleteAlert.js new file mode 100644 index 000000000..c90da2124 --- /dev/null +++ b/client/src/containers/Alerts/Customers/CustomerDeleteAlert.js @@ -0,0 +1,87 @@ +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 { transformErrors } from 'containers/Customers/utils'; + +import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect'; +import withAlertActions from 'containers/Alert/withAlertActions'; +import withCustomersActions from 'containers/Customers/withCustomersActions'; + +import { compose } from 'utils'; + +/** + * Customer delete alert. + */ +function CustomerDeleteAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { customerId }, + // #withCustomersActions + requestDeleteCustomer, + + // #withAlertActions + closeAlert, +}) { + const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); + + // handle cancel delete alert. + const handleCancelDeleteAlert = () => { + closeAlert(name); + }; + + // handle confirm delete customer. + const handleConfirmDeleteCustomer = useCallback(() => { + setLoading(true); + requestDeleteCustomer(customerId) + .then(() => { + AppToaster.show({ + message: formatMessage({ + id: 'the_customer_has_been_deleted_successfully', + }), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('customers-table'); + }) + .catch((errors) => { + transformErrors(errors); + }) + .finally(() => { + setLoading(false); + closeAlert(name); + }); + }, [requestDeleteCustomer, customerId, formatMessage]); + + return ( + } + confirmButtonText={} + icon="trash" + intent={Intent.DANGER} + isOpen={isOpen} + onCancel={handleCancelDeleteAlert} + onConfirm={handleConfirmDeleteCustomer} + loading={isLoading} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withCustomersActions, +)(CustomerDeleteAlert); diff --git a/client/src/containers/Alerts/Items/ItemBulkDeleteAlert.js b/client/src/containers/Alerts/Items/ItemBulkDeleteAlert.js index 354fd43e4..7da176ab3 100644 --- a/client/src/containers/Alerts/Items/ItemBulkDeleteAlert.js +++ b/client/src/containers/Alerts/Items/ItemBulkDeleteAlert.js @@ -27,6 +27,7 @@ function ItemBulkDeleteAlert({ }) { const { formatMessage } = useIntl(); const [isLoading, setLoading] = useState(false); + // handle cancel item bulk delete alert. const handleCancelBulkDelete = () => { closeAlert(name); @@ -49,7 +50,6 @@ function ItemBulkDeleteAlert({ closeAlert(name); }); }; - return ( } @@ -61,6 +61,7 @@ function ItemBulkDeleteAlert({ isOpen={isOpen} onCancel={handleCancelBulkDelete} onConfirm={handleConfirmBulkDelete} + loading={isLoading} >

diff --git a/client/src/containers/Customers/CustomerActionsBar.js b/client/src/containers/Customers/CustomerActionsBar.js index aaf60526c..678b5ff10 100644 --- a/client/src/containers/Customers/CustomerActionsBar.js +++ b/client/src/containers/Customers/CustomerActionsBar.js @@ -14,33 +14,31 @@ import classNames from 'classnames'; import { connect } from 'react-redux'; import { useHistory } from 'react-router-dom'; -import Icon from 'components/Icon'; import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; -import FilterDropdown from 'components/FilterDropdown'; -import { If, DashboardActionViewsList } from 'components'; +import { If, Icon, DashboardActionViewsList } from 'components'; import withResourceDetail from 'containers/Resources/withResourceDetails'; import withCustomers from 'containers/Customers/withCustomers'; import withCustomersActions from 'containers/Customers/withCustomersActions'; +import withAlertActions from 'containers/Alert/withAlertActions'; + import { compose } from 'utils'; const CustomerActionsBar = ({ - // #withResourceDetail - resourceFields, - // #withCustomers customersViews, + customersSelectedRows, //#withCustomersActions addCustomersTableQueries, changeCustomerView, + // #withAlertActions + openAlert, + // #ownProps - selectedRows = [], onFilterChanged, - onBulkDelete, }) => { - const [filterCount, setFilterCount] = useState(0); const history = useHistory(); const { formatMessage } = useIntl(); @@ -48,14 +46,10 @@ const CustomerActionsBar = ({ history.push('/customers/new'); }, [history]); - - const hasSelectedRows = useMemo(() => selectedRows.length > 0, [ - selectedRows, - ]); - - const handleBulkDelete = useCallback(() => { - onBulkDelete && onBulkDelete(selectedRows.map((r) => r.id)); - }, [onBulkDelete, selectedRows]); + // Handle Customers bulk delete button click., + const handleBulkDelete = () => { + openAlert('customers-bulk-delete', { customersIds: customersSelectedRows }); + }; const handleTabChange = (viewId) => { changeCustomerView(viewId.id || -1); @@ -88,18 +82,12 @@ const CustomerActionsBar = ({ >