From 62fcbf7c02e77d892ce610adf3694fdd70d8a226 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Wed, 27 Jan 2021 13:04:32 +0200 Subject: [PATCH] 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', };