diff --git a/client/src/containers/Items/ItemsDataTable.js b/client/src/containers/Items/ItemsDataTable.js index 948d99979..305a21b2c 100644 --- a/client/src/containers/Items/ItemsDataTable.js +++ b/client/src/containers/Items/ItemsDataTable.js @@ -12,7 +12,14 @@ import { import { FormattedMessage as T, useIntl } from 'react-intl'; import classNames from 'classnames'; -import { Icon, DataTable, Money, LoadingIndicator, Choose } from 'components'; +import { + Icon, + DataTable, + Money, + LoadingIndicator, + Choose, + If, +} from 'components'; import ItemsEmptyStatus from './ItemsEmptyStatus'; import { useIsValuePassed } from 'hooks'; import { CLASSES } from 'common/classes'; @@ -36,6 +43,8 @@ function ItemsDataTable({ // props onEditItem, onDeleteItem, + onInactiveItem, + onActivateItem, onSelectedRowsChange, }) { const { formatMessage } = useIntl(); @@ -83,6 +92,20 @@ function ItemsDataTable({ text={formatMessage({ id: 'edit_item' })} onClick={handleEditItem(item)} /> + + } + onClick={() => onInactiveItem(item)} + /> + + + } + onClick={() => onActivateItem(item)} + /> + } @@ -91,7 +114,13 @@ function ItemsDataTable({ /> ), - [handleEditItem, handleDeleteItem, formatMessage], + [ + handleEditItem, + handleDeleteItem, + onInactiveItem, + onActivateItem, + formatMessage, + ], ); const handleRowContextMenu = useCallback( @@ -148,11 +177,11 @@ function ItemsDataTable({ { Header: formatMessage({ id: 'cost_price' }), accessor: (row) => - !isBlank(row.sell_price) ? ( - - ) : ( - '' - ), + !isBlank(row.sell_price) ? ( + + ) : ( + '' + ), className: 'cost-price', width: 150, }, @@ -196,6 +225,12 @@ function ItemsDataTable({ [onSelectedRowsChange], ); + const rowClassNames = (row) => { + return { + inactive: !row.original.active, + }; + }; + const showEmptyStatus = [ itemsCurrentPage.length === 0, itemsCurrentViewId === -1, @@ -221,6 +256,7 @@ function ItemsDataTable({ rowContextMenu={handleRowContextMenu} expandable={false} sticky={true} + rowClassNames={rowClassNames} pagination={true} pagesCount={itemsPagination.pagesCount} autoResetSortBy={false} diff --git a/client/src/containers/Items/ItemsList.js b/client/src/containers/Items/ItemsList.js index 606501507..25f41f142 100644 --- a/client/src/containers/Items/ItemsList.js +++ b/client/src/containers/Items/ItemsList.js @@ -1,7 +1,7 @@ import React, { useEffect, useCallback, useState, useMemo } from 'react'; import { Route, Switch, useHistory } from 'react-router-dom'; import { Intent, Alert } from '@blueprintjs/core'; -import { useQuery } from 'react-query'; +import { useQuery, queryCache } from 'react-query'; import { FormattedMessage as T, FormattedHTMLMessage, @@ -38,10 +38,14 @@ function ItemsList({ // #withItemsActions requestDeleteItem, requestFetchItems, + requestInactiveItem, + requestActivateItem, addItemsTableQueries, requestDeleteBulkItems, }) { const [deleteItem, setDeleteItem] = useState(false); + const [inactiveItem, setInactiveItem] = useState(false); + const [activateItem, setActivateItem] = useState(false); const [selectedRows, setSelectedRows] = useState([]); const [bulkDelete, setBulkDelete] = useState(false); @@ -65,9 +69,8 @@ function ItemsList({ ); // Handle fetching the items table based on the given query. - const fetchItems = useQuery( - ['items-table', itemsTableQuery], - (key, _query) => requestFetchItems({ ..._query }), + const fetchItems = useQuery(['items-table', itemsTableQuery], (key, _query) => + requestFetchItems({ ..._query }), ); // Handle click delete item. @@ -92,33 +95,36 @@ function ItemsList({ // handle confirm delete item. const handleConfirmDeleteItem = useCallback(() => { - requestDeleteItem(deleteItem.id).then(() => { - AppToaster.show({ - message: formatMessage({ - id: 'the_item_has_been_successfully_deleted', - }), - intent: Intent.SUCCESS, - }); - setDeleteItem(false); - }).catch(({ errors }) => { - if (errors.find(error => error.type === 'ITEM_HAS_ASSOCIATED_TRANSACTINS')) { + requestDeleteItem(deleteItem.id) + .then(() => { AppToaster.show({ message: formatMessage({ - id: 'the_item_has_associated_transactions', + id: 'the_item_has_been_successfully_deleted', }), - intent: Intent.DANGER, + intent: Intent.SUCCESS, }); - } - setDeleteItem(false); - }); + setDeleteItem(false); + }) + .catch(({ errors }) => { + if ( + errors.find( + (error) => error.type === 'ITEM_HAS_ASSOCIATED_TRANSACTINS', + ) + ) { + AppToaster.show({ + message: formatMessage({ + id: 'the_item_has_associated_transactions', + }), + intent: Intent.DANGER, + }); + } + setDeleteItem(false); + }); }, [requestDeleteItem, deleteItem, formatMessage]); - const handleFetchData = useCallback( - ({ pageIndex, pageSize, sortBy }) => { - - }, - [addItemsTableQueries], - ); + const handleFetchData = useCallback(({ pageIndex, pageSize, sortBy }) => {}, [ + addItemsTableQueries, + ]); // Handle filter change to re-fetch the items. const handleFilterChanged = useCallback( @@ -174,6 +180,62 @@ function ItemsList({ setBulkDelete(false); }, []); + // Handle cancel/confirm item inactive. + const handleInactiveItem = useCallback((item) => { + setInactiveItem(item); + }, []); + + // Handle cancel inactive item alert. + const handleCancelInactiveItem = useCallback(() => { + setInactiveItem(false); + }, []); + + // Handle confirm item Inactive. + const handleConfirmItemInactive = useCallback(() => { + requestInactiveItem(inactiveItem.id) + .then(() => { + setInactiveItem(false); + AppToaster.show({ + message: formatMessage({ + id: 'the_item_has_been_successfully_inactivated', + }), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('items-table'); + }) + .catch((error) => { + setInactiveItem(false); + }); + }, [inactiveItem, requestInactiveItem, formatMessage]); + + // Handle activate item click. + const handleActivateItem = useCallback((item) => { + setActivateItem(item); + }); + + // Handle activate item alert cancel. + const handleCancelActivateItem = useCallback(() => { + setActivateItem(false); + }); + + // Handle activate item confirm. + const handleConfirmItemActivate = useCallback(() => { + requestActivateItem(activateItem.id) + .then(() => { + setActivateItem(false); + AppToaster.show({ + message: formatMessage({ + id: 'the_item_has_been_successfully_activated', + }), + intent: Intent.SUCCESS, + }); + queryCache.invalidateQueries('items-table'); + }) + .catch((error) => { + setActivateItem(false); + }); + }, [activateItem, requestActivateItem, formatMessage]); + return (

+ } + confirmButtonText={} + intent={Intent.WARNING} + isOpen={inactiveItem} + onCancel={handleCancelInactiveItem} + onConfirm={handleConfirmItemInactive} + > +

+ +

+
+ } + confirmButtonText={} + intent={Intent.WARNING} + isOpen={activateItem} + onCancel={handleCancelActivateItem} + onConfirm={handleConfirmItemActivate} + > +

+ +

+
diff --git a/client/src/containers/Items/withItemsActions.js b/client/src/containers/Items/withItemsActions.js index f117728c4..4458aace4 100644 --- a/client/src/containers/Items/withItemsActions.js +++ b/client/src/containers/Items/withItemsActions.js @@ -6,6 +6,8 @@ import { submitItem, editItem, deleteBulkItems, + activateItem, + inactiveItem, } from 'store/items/items.actions'; import t from 'store/types'; @@ -16,6 +18,8 @@ export const mapDispatchToProps = (dispatch) => ({ requestDeleteBulkItems: (ids) => dispatch(deleteBulkItems({ ids })), requestSubmitItem: (form) => dispatch(submitItem({ form })), requestEditItem: (id, form) => dispatch(editItem({ id, form })), + requestInactiveItem: (id) => dispatch(inactiveItem({ id })), + requestActivateItem: (id) => dispatch(activateItem({ id })), addBulkActionItem: (id) => dispatch({ type: t.ITEM_BULK_ACTION_ADD, diff --git a/client/src/containers/Purchases/Bill/BillsDataTable.js b/client/src/containers/Purchases/Bill/BillsDataTable.js index c6dc514dc..809e68059 100644 --- a/client/src/containers/Purchases/Bill/BillsDataTable.js +++ b/client/src/containers/Purchases/Bill/BillsDataTable.js @@ -185,26 +185,19 @@ function BillsDataTable({ width: 140, className: 'amount', }, - { - id: 'reference_no', - Header: formatMessage({ id: 'reference_no' }), - accessor: 'reference_no', - width: 140, - className: 'reference_no', - }, { id: 'status', Header: formatMessage({ id: 'status' }), accessor: (row) => ( - + - + @@ -213,6 +206,13 @@ function BillsDataTable({ width: 140, className: 'status', }, + { + id: 'reference_no', + Header: formatMessage({ id: 'reference_no' }), + accessor: 'reference_no', + width: 140, + className: 'reference_no', + }, { id: 'actions', Header: '', diff --git a/client/src/containers/Sales/Estimate/EstimateFloatingActions.js b/client/src/containers/Sales/Estimate/EstimateFloatingActions.js index bb9b4b93a..3864c01fc 100644 --- a/client/src/containers/Sales/Estimate/EstimateFloatingActions.js +++ b/client/src/containers/Sales/Estimate/EstimateFloatingActions.js @@ -25,38 +25,38 @@ export default function EstimateFloatingActions({ onCancelClick, onClearClick, estimateId, - estimatePublished, + isDelivered, }) { const { resetForm, submitForm } = useFormikContext(); - const handleSubmitPublishBtnClick = (event) => { + const handleSubmitDeliverBtnClick = (event) => { saveInvoke(onSubmitClick, event, { redirect: true, - publish: true, + deliver: true, }); }; - const handleSubmitPublishAndNewBtnClick = (event) => { + const handleSubmitDeliverAndNewBtnClick = (event) => { submitForm(); saveInvoke(onSubmitClick, event, { redirect: false, - publish: true, + deliver: true, resetForm: true, }); }; - const handleSubmitPublishContinueEditingBtnClick = (event) => { + const handleSubmitDeliverContinueEditingBtnClick = (event) => { submitForm(); saveInvoke(onSubmitClick, event, { redirect: false, - publish: true, + deliver: true, }); }; const handleSubmitDraftBtnClick = (event) => { saveInvoke(onSubmitClick, event, { redirect: true, - publish: false, + deliver: false, }); }; @@ -64,7 +64,7 @@ export default function EstimateFloatingActions({ submitForm(); saveInvoke(onSubmitClick, event, { redirect: false, - publish: false, + deliver: false, resetForm: true, }); }; @@ -73,7 +73,7 @@ export default function EstimateFloatingActions({ submitForm(); saveInvoke(onSubmitClick, event, { redirect: false, - publish: false, + deliver: false, }); }; @@ -88,26 +88,26 @@ export default function EstimateFloatingActions({ return (
- {/* ----------- Save And Publish ----------- */} - + {/* ----------- Save And Deliver ----------- */} +