From 82e0b9c7f016aef84584c5e8e77d7d8eee9367d4 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Wed, 27 Jan 2021 21:33:41 +0200 Subject: [PATCH] refactor: vendors alerts. --- .../Alerts/Vendors/VendorDeleteAlert.js | 86 +++++++++++++ .../src/containers/Customers/CustomersList.js | 4 - .../src/containers/Vendors/VendorFormPage.js | 6 +- .../src/containers/Vendors/VendorsAlerts.js | 10 ++ client/src/containers/Vendors/VendorsList.js | 117 ++---------------- .../src/containers/Vendors/VendorsViewPage.js | 60 +++++++++ client/src/containers/Vendors/utils.js | 16 +++ .../containers/Vendors/withVendorActions.js | 11 +- client/src/containers/Vendors/withVendors.js | 3 +- client/src/store/vendors/vendors.reducer.js | 7 +- client/src/store/vendors/vendors.types.js | 1 + 11 files changed, 203 insertions(+), 118 deletions(-) create mode 100644 client/src/containers/Alerts/Vendors/VendorDeleteAlert.js create mode 100644 client/src/containers/Vendors/VendorsAlerts.js create mode 100644 client/src/containers/Vendors/VendorsViewPage.js create mode 100644 client/src/containers/Vendors/utils.js diff --git a/client/src/containers/Alerts/Vendors/VendorDeleteAlert.js b/client/src/containers/Alerts/Vendors/VendorDeleteAlert.js new file mode 100644 index 000000000..5e2d5b08e --- /dev/null +++ b/client/src/containers/Alerts/Vendors/VendorDeleteAlert.js @@ -0,0 +1,86 @@ +import React, { useCallback, useState } from 'react'; +import { + FormattedMessage as T, + FormattedHTMLMessage, + 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 withVendorActions from 'containers/Vendors/withVendorActions'; + +import { compose } from 'utils'; + +/** + * Vendor delete alert. + */ +function VendorDeleteAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { vendorId }, + + // #withVendorActions + requestDeleteVender, + + // #withAlertActions + closeAlert, +}) { + const { formatMessage } = useIntl(); + const [isLoading, setLoading] = useState(false); + + // Handle cancel delete the vendor. + const handleCancelDeleteAlert = () => { + closeAlert(name); + }; + + // handle confirm delete vendor. + const handleConfirmDeleteVendor = useCallback(() => { + setLoading(true); + requestDeleteVender(vendorId) + .then(() => { + AppToaster.show({ + message: formatMessage({ + id: 'the_vendor_has_been_deleted_successfully', + }), + intent: Intent.SUCCESS, + }); + }) + .catch((errors) => { + transformErrors(errors); + }) + .finally(() => { + closeAlert(name); + setLoading(false); + }); + }, [requestDeleteVender, vendorId, formatMessage]); + + return ( + } + confirmButtonText={} + icon="trash" + intent={Intent.DANGER} + isOpen={isOpen} + onCancel={handleCancelDeleteAlert} + onConfirm={handleConfirmDeleteVendor} + loading={isLoading} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withVendorActions, +)(VendorDeleteAlert); diff --git a/client/src/containers/Customers/CustomersList.js b/client/src/containers/Customers/CustomersList.js index 7aac45a7d..dd7b02020 100644 --- a/client/src/containers/Customers/CustomersList.js +++ b/client/src/containers/Customers/CustomersList.js @@ -31,12 +31,8 @@ function CustomersList({ // #withCustomers customersTableQuery, - // #withAlertsActions. - openAlert, - // #withCustomersActions requestFetchCustomers, - addCustomersTableQueries, }) { const [tableLoading, setTableLoading] = useState(false); diff --git a/client/src/containers/Vendors/VendorFormPage.js b/client/src/containers/Vendors/VendorFormPage.js index 454a63d0f..51dd7eed8 100644 --- a/client/src/containers/Vendors/VendorFormPage.js +++ b/client/src/containers/Vendors/VendorFormPage.js @@ -14,9 +14,9 @@ import { compose } from 'utils'; function VendorFormPage({ // #withVendorActions requestFetchVendorsTable, - requsetFetchVendor, + requestFetchVendor, - // #wihtCurrenciesActions + // #withCurrenciesActions requestFetchCurrencies, }) { const { id } = useParams(); @@ -35,7 +35,7 @@ function VendorFormPage({ // Handle fetch vendor details. const fetchVendor = useQuery( ['vendor', id], - (_id, vendorId) => requsetFetchVendor(vendorId), + (_id, vendorId) => requestFetchVendor(vendorId), { enabled: id && id }, ); diff --git a/client/src/containers/Vendors/VendorsAlerts.js b/client/src/containers/Vendors/VendorsAlerts.js new file mode 100644 index 000000000..d7cdec967 --- /dev/null +++ b/client/src/containers/Vendors/VendorsAlerts.js @@ -0,0 +1,10 @@ +import React from 'react'; +import VendorDeleteAlert from 'containers/Alerts/Vendors/VendorDeleteAlert'; + +export default function VendorsAlerts() { + return ( +
+ +
+ ); +} diff --git a/client/src/containers/Vendors/VendorsList.js b/client/src/containers/Vendors/VendorsList.js index f5fb4dcf7..df5de3481 100644 --- a/client/src/containers/Vendors/VendorsList.js +++ b/client/src/containers/Vendors/VendorsList.js @@ -1,26 +1,19 @@ -import React, { useEffect, useCallback, useState, useMemo } from 'react'; -import { Route, Switch, useHistory } from 'react-router-dom'; -import { Intent, Alert } from '@blueprintjs/core'; +import React, { useEffect, useState } from 'react'; import { useQuery } from 'react-query'; -import { - FormattedMessage as T, - FormattedHTMLMessage, - useIntl, -} from 'react-intl'; +import { FormattedMessage as T, useIntl } from 'react-intl'; -import AppToaster from 'components/AppToaster'; import DashboardInsider from 'components/Dashboard/DashboardInsider'; import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; -import VendorsTable from './VendorsTable'; -import VendorActionsBar from './VendorActionsBar'; -import VendorsViewsTabs from './VendorViewsTabs'; +import VendorActionsBar from 'containers/Vendors/VendorActionsBar'; +import VendorsViewPage from 'containers/Vendors/VendorsViewPage'; +import VendorsAlerts from 'containers/Vendors/VendorsAlerts'; -import withVendors from './withVendors'; -import withVendorActions from './withVendorActions'; +import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withResourceActions from 'containers/Resources/withResourcesActions'; import withViewsActions from 'containers/Views/withViewsActions'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; +import withVendors from 'containers/Vendors/withVendors'; +import withVendorActions from 'containers/Vendors/withVendorActions'; import { compose } from 'utils'; @@ -35,15 +28,11 @@ function VendorsList({ vendorTableQuery, // #withVendorActions - requestDeleteVender, requestFetchVendorsTable, }) { - const [deleteVendor, setDeleteVendor] = useState(false); - const [selectedRows, setSelectedRows] = useState([]); const [tableLoading, setTableLoading] = useState(false); const { formatMessage } = useIntl(); - const history = useHistory(); useEffect(() => { changePageTitle(formatMessage({ id: 'vendors_list' })); @@ -61,64 +50,6 @@ function VendorsList({ (key, query) => requestFetchVendorsTable({ ...query }), ); - // Handle Edit vendor data table - const handleEditVendor = useCallback( - (vendor) => { - history.push(`/vendors/${vendor.id}/edit`); - }, - [history], - ); - // Handle click delete vendor. - const handleDeleteVendor = useCallback( - (vendor) => { - setDeleteVendor(vendor); - }, - [setDeleteVendor], - ); - - // Handle cancel delete the vendor. - const handleCancelDeleteVendor = useCallback(() => { - setDeleteVendor(false); - }, [setDeleteVendor]); - - // Transform API errors in toasts messages. - const transformErrors = useCallback((errors) => { - if (errors.some((e) => e.type === 'VENDOR.HAS.BILLS')) { - AppToaster.show({ - message: formatMessage({ - id: 'vendor_has_bills', - }), - intent: Intent.DANGER, - }); - } - }, []); - - // handle confirm delete vendor. - const handleConfirmDeleteVendor = useCallback(() => { - requestDeleteVender(deleteVendor.id) - .then(() => { - setDeleteVendor(false); - AppToaster.show({ - message: formatMessage({ - id: 'the_vendor_has_been_deleted_successfully', - }), - intent: Intent.SUCCESS, - }); - }) - .catch((errors) => { - setDeleteVendor(false); - transformErrors(errors); - }); - }, [requestDeleteVender, deleteVendor, formatMessage]); - - // Handle selected rows change. - const handleSelectedRowsChange = useCallback( - (vendor) => { - setSelectedRows(vendor); - }, - [setSelectedRows], - ); - useEffect(() => { if (tableLoading && !fetchVendors.isFetching) { setTableLoading(false); @@ -130,36 +61,10 @@ function VendorsList({ loading={fetchResourceViews.isFetching} name={'customers-list'} > - + - - - - - - - } - confirmButtonText={} - icon="trash" - intent={Intent.DANGER} - isOpen={deleteVendor} - onCancel={handleCancelDeleteVendor} - onConfirm={handleConfirmDeleteVendor} - > -

- -

-
+ +
); diff --git a/client/src/containers/Vendors/VendorsViewPage.js b/client/src/containers/Vendors/VendorsViewPage.js new file mode 100644 index 000000000..e7fc7f2ba --- /dev/null +++ b/client/src/containers/Vendors/VendorsViewPage.js @@ -0,0 +1,60 @@ +import React, { useCallback } from 'react'; +import { Route, Switch, useHistory } from 'react-router-dom'; + +import VendorsViewsTabs from './VendorViewsTabs'; +import VendorsTable from './VendorsTable'; + +import withVendorActions from './withVendorActions'; +import withAlertsActions from 'containers/Alert/withAlertActions'; + +import { compose } from 'utils'; + +function VendorsViewPage({ + // #withAlertsActions. + openAlert, + + // #withVendorActions. + setSelectedRowsVendors, +}) { + const history = useHistory(); + + // Handle Edit vendor data table + const handleEditVendor = useCallback( + (vendor) => { + history.push(`/vendors/${vendor.id}/edit`); + }, + [history], + ); + + // Handle click delete vendor. + const handleDeleteVendor = useCallback( + ({ id }) => { + openAlert('vendor-delete', { vendorId: id }); + }, + [openAlert], + ); + + // Handle select vendor rows. + const handleSelectedRowsChange = (selectedRows) => { + const selectedRowsIds = selectedRows.map((r) => r.id); + setSelectedRowsVendors(selectedRowsIds); + }; + + return ( + + + + + + + ); +} + +export default compose(withAlertsActions, withVendorActions)(VendorsViewPage); diff --git a/client/src/containers/Vendors/utils.js b/client/src/containers/Vendors/utils.js new file mode 100644 index 000000000..f647c6b0d --- /dev/null +++ b/client/src/containers/Vendors/utils.js @@ -0,0 +1,16 @@ +import { useCallback } from 'react'; +import { formatMessage } from 'services/intl'; +import { Intent } from '@blueprintjs/core'; +import { AppToaster } from 'components'; + +// Transform API errors in toasts messages. +export const transformErrors = useCallback((errors) => { + if (errors.some((e) => e.type === 'VENDOR.HAS.BILLS')) { + AppToaster.show({ + message: formatMessage({ + id: 'vendor_has_bills', + }), + intent: Intent.DANGER, + }); + } +}, []); diff --git a/client/src/containers/Vendors/withVendorActions.js b/client/src/containers/Vendors/withVendorActions.js index 7f6040b50..a178fb28c 100644 --- a/client/src/containers/Vendors/withVendorActions.js +++ b/client/src/containers/Vendors/withVendorActions.js @@ -8,10 +8,10 @@ import { } from 'store/vendors/vendors.actions'; import t from 'store/types'; -const mapDipatchToProps = (dispatch) => ({ +const mapDispatchToProps = (dispatch) => ({ requestSubmitVendor: (form) => dispatch(submitVendor({ form })), requestEditVendor: (id, form) => dispatch(editVendor({ id, form })), - requsetFetchVendor: (id) => dispatch(fetchVendor({ id })), + requestFetchVendor: (id) => dispatch(fetchVendor({ id })), requestFetchVendorsTable: (query = {}) => dispatch(fetchVendorsTable({ query: { ...query } })), requestDeleteVender: (id) => dispatch(deleteVendor({ id })), @@ -25,6 +25,11 @@ const mapDipatchToProps = (dispatch) => ({ type: t.VENDORS_TABLE_QUERIES_ADD, payload: { queries }, }), + setSelectedRowsVendors: (selectedRows) => + dispatch({ + type: t.VENDOR_SELECTED_ROWS_SET, + payload: { selectedRows }, + }), }); -export default connect(null, mapDipatchToProps); +export default connect(null, mapDispatchToProps); diff --git a/client/src/containers/Vendors/withVendors.js b/client/src/containers/Vendors/withVendors.js index 79a60f506..c24c45c04 100644 --- a/client/src/containers/Vendors/withVendors.js +++ b/client/src/containers/Vendors/withVendors.js @@ -13,7 +13,7 @@ export default (mapState) => { const getVendorsPaginationMeta = getVendorsPaginationMetaFactory(); const getVendorsCurrentViewId = getVendorsCurrentViewIdFactory(); const getVendorTableQuery = getVendorTableQueryFactory(); - + const mapStateToProps = (state, props) => { const query = getVendorTableQuery(state, props); @@ -25,6 +25,7 @@ export default (mapState) => { vendorsPageination: getVendorsPaginationMeta(state, props, query), vendorsLoading: state.vendors.loading, vendorsCurrentViewId: getVendorsCurrentViewId(state, props), + vendorsSelectedRows: state.vendors.selectedRows, }; return mapState ? mapState(mapped, state, props) : mapped; }; diff --git a/client/src/store/vendors/vendors.reducer.js b/client/src/store/vendors/vendors.reducer.js index 6732f13e9..cfe00a031 100644 --- a/client/src/store/vendors/vendors.reducer.js +++ b/client/src/store/vendors/vendors.reducer.js @@ -11,7 +11,7 @@ const initialState = { views: {}, loading: false, currentViewId: -1, - + selectedRows: [], tableQuery: { page_size: 12, page: 1, @@ -72,6 +72,11 @@ export default createReducer(initialState, { delete state.items[id]; } }, + + [t.VENDOR_SELECTED_ROWS_SET]: (state, action) => { + const { selectedRows } = action.payload; + state.selectedRows = selectedRows; + }, ...viewPaginationSetReducer(t.VENDORS_PAGINATION_SET), ...createTableQueryReducers('VENDORS'), }); diff --git a/client/src/store/vendors/vendors.types.js b/client/src/store/vendors/vendors.types.js index c433600d9..fa4d60087 100644 --- a/client/src/store/vendors/vendors.types.js +++ b/client/src/store/vendors/vendors.types.js @@ -8,4 +8,5 @@ export default { VENDORS_BULK_DELETE: 'VENDORS_BULK_DELETE', VENDORS_PAGINATION_SET: 'VENDORS_PAGINATION_SET', VENDORS_SET_CURRENT_VIEW: 'VENDORS_SET_CURRENT_VIEW', + VENDOR_SELECTED_ROWS_SET: 'VENDOR_SELECTED_ROWS_SET', };