diff --git a/client/package.json b/client/package.json index 77cc1fb6e..b8345e974 100644 --- a/client/package.json +++ b/client/package.json @@ -85,7 +85,7 @@ "react-scrollbars-custom": "^4.0.21", "react-sortablejs": "^2.0.11", "react-split-pane": "^0.1.91", - "react-table": "^7.0.0", + "react-table": "^7.6.3", "react-table-sticky": "^1.1.2", "react-transition-group": "^4.4.1", "react-use": "^13.26.1", diff --git a/client/src/common/classes.js b/client/src/common/classes.js index 396700ebb..009ae4734 100644 --- a/client/src/common/classes.js +++ b/client/src/common/classes.js @@ -1,6 +1,7 @@ import { Classes } from '@blueprintjs/core'; const CLASSES = { + DASHBOARD_PAGE: 'dashboard__page', DASHBOARD_DATATABLE: 'dashboard__datatable', DASHBOARD_CARD: 'dashboard__card', DASHBOARD_CARD_PAGE: 'dashboard__card--page', diff --git a/client/src/components/Dashboard/DashboardContentRoute.js b/client/src/components/Dashboard/DashboardContentRoute.js index ad7291ed2..01bc66186 100644 --- a/client/src/components/Dashboard/DashboardContentRoute.js +++ b/client/src/components/Dashboard/DashboardContentRoute.js @@ -1,20 +1,31 @@ -import React from 'react'; -import { Route, Switch } from 'react-router-dom'; -import routes from 'routes/dashboard' +import React, { useEffect, Suspense } from 'react'; +import { Route, Switch } from 'react-router-dom'; +import routes from 'routes/dashboard'; +import DashboardPage from './DashboardPage'; + +/** + * Dashboard content route. + */ export default function DashboardContentRoute() { - return ( - { routes.map((route, index) => ( + {routes.map((route, index) => ( + > + + ))} ); -} \ No newline at end of file +} diff --git a/client/src/components/Dashboard/DashboardContentTable.js b/client/src/components/Dashboard/DashboardContentTable.js new file mode 100644 index 000000000..f08819c2d --- /dev/null +++ b/client/src/components/Dashboard/DashboardContentTable.js @@ -0,0 +1,10 @@ +import React from 'react'; +import classNames from 'classnames'; +import { CLASSES } from 'common/classes'; + +/** + * Dashboard content table. + */ +export default function DashboardContentTable({ children }) { + return (
{ children }
) +} \ No newline at end of file diff --git a/client/src/components/Dashboard/DashboardPage.js b/client/src/components/Dashboard/DashboardPage.js new file mode 100644 index 000000000..85748c677 --- /dev/null +++ b/client/src/components/Dashboard/DashboardPage.js @@ -0,0 +1,56 @@ +import React, { useEffect, Suspense } from 'react'; +import { CLASSES } from 'common/classes'; +import withDashboardActions from 'containers/Dashboard/withDashboardActions'; +import { compose } from 'utils'; +/** + * Dashboard pages wrapper. + */ +function DashboardPage({ + // #ownProps + pageTitle, + backLink, + sidebarShrink, + Component, + + // #withDashboardActions + changePageTitle, + setDashboardBackLink, + setSidebarShrink, + resetSidebarPreviousExpand, +}) { + useEffect(() => { + pageTitle && changePageTitle(pageTitle); + + return () => { + pageTitle && changePageTitle(''); + }; + }); + + useEffect(() => { + backLink && setDashboardBackLink(backLink); + + return () => { + backLink && setDashboardBackLink(false); + }; + }, [backLink, setDashboardBackLink]); + + // Handle sidebar shrink in mount and reset to the pervious state + // once the page unmount. + useEffect(() => { + sidebarShrink && setSidebarShrink(); + + return () => { + sidebarShrink && resetSidebarPreviousExpand(); + }; + }, [resetSidebarPreviousExpand, sidebarShrink, setSidebarShrink]); + + return ( +
+ + + +
+ ); +} + +export default compose(withDashboardActions)(DashboardPage); diff --git a/client/src/components/Dashboard/DashboardPageContent.js b/client/src/components/Dashboard/DashboardPageContent.js index f3e938628..3fd57e941 100644 --- a/client/src/components/Dashboard/DashboardPageContent.js +++ b/client/src/components/Dashboard/DashboardPageContent.js @@ -1,5 +1,8 @@ import React from 'react'; +/** + * Dashboard page content. + */ export default function DashboardPageContent({ children }) { return (
diff --git a/client/src/components/DataTable.js b/client/src/components/DataTable.js index fbe5a3450..1226afe57 100644 --- a/client/src/components/DataTable.js +++ b/client/src/components/DataTable.js @@ -20,6 +20,7 @@ import TableNoResultsRow from './Datatable/TableNoResultsRow'; import TableLoadingRow from './Datatable/TableLoading'; import TableHeader from './Datatable/TableHeader'; import TablePage from './Datatable/TablePage'; +import TableFooter from './Datatable/TableFooter'; import TableRow from './Datatable/TableRow'; import TableRows from './Datatable/TableRows'; import TableCell from './Datatable/TableCell'; @@ -75,6 +76,7 @@ export default function DataTable(props) { TableWrapperRenderer, TableTBodyRenderer, TablePaginationRenderer, + TableFooterRenderer, ...restProps } = props; @@ -124,11 +126,11 @@ export default function DataTable(props) { }, useSortBy, useExpanded, - useRowSelect, useResizeColumns, useFlexLayout, useSticky, usePagination, + useRowSelect, (hooks) => { hooks.visibleColumns.push((columns) => [ // Let's make a column for selection @@ -170,6 +172,8 @@ export default function DataTable(props) { + + @@ -194,6 +198,7 @@ DataTable.defaultProps = { autoResetRowState: true, TableHeaderRenderer: TableHeader, + TableFooterRenderer: TableFooter, TableLoadingRenderer: TableLoadingRow, TablePageRenderer: TablePage, TableRowsRenderer: TableRows, diff --git a/client/src/components/Datatable/DatatableEditable.js b/client/src/components/Datatable/DatatableEditable.js index 57e922426..911ef15cf 100644 --- a/client/src/components/Datatable/DatatableEditable.js +++ b/client/src/components/Datatable/DatatableEditable.js @@ -1,10 +1,7 @@ import React from 'react'; import classNames from 'classnames'; import { CLASSES } from 'common/classes'; -import { - DataTable, - If, -} from 'components'; +import { DataTable, If } from 'components'; import 'style/components/DataTable/DataTableEditable.scss'; export default function DatatableEditable({ @@ -14,11 +11,7 @@ export default function DatatableEditable({ ...tableProps }) { return ( -
+
diff --git a/client/src/components/Datatable/TableFooter.js b/client/src/components/Datatable/TableFooter.js new file mode 100644 index 000000000..3c2d5fcff --- /dev/null +++ b/client/src/components/Datatable/TableFooter.js @@ -0,0 +1,29 @@ +import React, { useContext } from 'react'; +import TableContext from './TableContext'; + +/** + * Table footer. + */ +export default function TableFooter() { + const { + table: { footerGroups }, + } = useContext(TableContext); + + return ( +
+ {footerGroups.map((group) => ( +
+ {group.headers.map((column) => ( +
+ {column.render('Footer')} +
+ ))} +
+ ))} +
+ ); +} diff --git a/client/src/components/DialogsContainer.js b/client/src/components/DialogsContainer.js index c7fb79fff..9d63f23b2 100644 --- a/client/src/components/DialogsContainer.js +++ b/client/src/components/DialogsContainer.js @@ -1,6 +1,6 @@ import React from 'react'; -import AccountFormDialog from 'containers/Dialogs/AccountFormDialog'; +import AccountDialog from 'containers/Dialogs/AccountDialog'; import InviteUserDialog from 'containers/Dialogs/InviteUserDialog'; import ItemCategoryDialog from 'containers/Dialogs/ItemCategoryDialog'; import CurrencyFormDialog from 'containers/Dialogs/CurrencyFormDialog'; @@ -19,7 +19,7 @@ import PaymentViaVoucherDialog from 'containers/Dialogs/PaymentViaVoucherDialog' export default function DialogsContainer() { return (
- {/* */} + diff --git a/client/src/components/index.js b/client/src/components/index.js index c97be1dfa..fb3a87114 100644 --- a/client/src/components/index.js +++ b/client/src/components/index.js @@ -47,6 +47,8 @@ import CustomersMultiSelect from './CustomersMultiSelect'; import Skeleton from './Skeleton' import ContextMenu from './ContextMenu' import TableFastCell from './Datatable/TableFastCell'; +import DashboardContentTable from './Dashboard/DashboardContentTable'; +import DashboardPageContent from './Dashboard/DashboardPageContent'; const Hint = FieldHint; @@ -99,5 +101,7 @@ export { CustomersMultiSelect, TableFastCell, Skeleton, - ContextMenu + ContextMenu, + DashboardContentTable, + DashboardPageContent }; diff --git a/client/src/containers/Accounting/JournalsLanding/ManualJournalsDataTable.js b/client/src/containers/Accounting/JournalsLanding/ManualJournalsDataTable.js index d9f89d5e1..848bf23c9 100644 --- a/client/src/containers/Accounting/JournalsLanding/ManualJournalsDataTable.js +++ b/client/src/containers/Accounting/JournalsLanding/ManualJournalsDataTable.js @@ -1,7 +1,7 @@ import React from 'react'; -import classNames from 'classnames'; -import { DataTable, Choose } from 'components'; -import { CLASSES } from 'common/classes'; +import { useHistory } from 'react-router-dom'; + +import { DataTable } from 'components'; import ManualJournalsEmptyStatus from './ManualJournalsEmptyStatus'; import TableSkeletonRows from 'components/Datatable/TableSkeletonRows'; @@ -35,20 +35,22 @@ function ManualJournalsDataTable({ pagination, isManualJournalsLoading, isManualJournalsFetching, - isEmptyStatus + isEmptyStatus, } = useManualJournalsContext(); + const history = useHistory(); + // Manual journals columns. const columns = useManualJournalsColumns(); // Handles the journal publish action. const handlePublishJournal = ({ id }) => { - openAlert('journal-publish', { manualJournalId: id }) + openAlert('journal-publish', { manualJournalId: id }); }; // Handle the journal edit action. const handleEditJournal = ({ id }) => { - + history.push(`/manual-journals/${id}/edit`); }; // Handle the journal delete action. @@ -68,51 +70,41 @@ function ManualJournalsDataTable({ [setManualJournalsTableState], ); + // Display manual journal empty status instead of the table. + if (isEmptyStatus) { + return ; + } + return ( -
- - - - - - - - - -
+ ); } export default compose( withManualJournalsActions, - withAlertsActions + withAlertsActions, )(ManualJournalsDataTable); diff --git a/client/src/containers/Accounting/JournalsLanding/ManualJournalsList.js b/client/src/containers/Accounting/JournalsLanding/ManualJournalsList.js index b04d2c786..042db2dfe 100644 --- a/client/src/containers/Accounting/JournalsLanding/ManualJournalsList.js +++ b/client/src/containers/Accounting/JournalsLanding/ManualJournalsList.js @@ -1,7 +1,7 @@ import React, { useEffect } from 'react'; import { useIntl } from 'react-intl'; -import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; +import { DashboardContentTable, DashboardPageContent } from 'components'; import { ManualJournalsListProvider } from './ManualJournalsListProvider'; import ManualJournalsAlerts from './ManualJournalsAlerts'; @@ -41,7 +41,11 @@ function ManualJournalsTable({ - + + + + + diff --git a/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesField.js b/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesField.js index 3286b422a..b0fa4d569 100644 --- a/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesField.js +++ b/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesField.js @@ -3,12 +3,12 @@ import { FastField } from 'formik'; import classNames from 'classnames'; import { CLASSES } from 'common/classes'; import MakeJournalEntriesTable from './MakeJournalEntriesTable'; -import { orderingLinesIndexes, repeatValue } from 'utils'; +import { defaultManualJournal, MIN_LINES_NUMBER } from './utils'; -export default function MakeJournalEntriesField({ - defaultRow, - linesNumber = 4, -}) { +/** + * Make journal entries field. + */ +export default function MakeJournalEntriesField() { return (
@@ -18,16 +18,9 @@ export default function MakeJournalEntriesField({ form.setFieldValue('entries', entries); }} entries={value} + defaultEntry={defaultManualJournal} + initialLinesNumber={MIN_LINES_NUMBER} error={error} - onClickAddNewRow={() => { - form.setFieldValue('entries', [...value, defaultRow]); - }} - onClickClearAllLines={() => { - form.setFieldValue( - 'entries', - orderingLinesIndexes([...repeatValue(defaultRow, linesNumber)]) - ); - }} /> )} diff --git a/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesFooter.js b/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesFooter.js index 63057c804..8752d8ff6 100644 --- a/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesFooter.js +++ b/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesFooter.js @@ -10,79 +10,70 @@ import { MenuItem, } from '@blueprintjs/core'; import { FormattedMessage as T } from 'react-intl'; +import { useFormikContext } from 'formik'; import { CLASSES } from 'common/classes'; import classNames from 'classnames'; -import { saveInvoke } from 'utils'; import { If, Icon } from 'components'; +import { useMakeJournalFormContext } from './MakeJournalProvider'; +import { useHistory } from 'react-router-dom'; /** * Make Journal floating actions bar. */ -export default function MakeJournalEntriesFooter({ - isSubmitting, - onSubmitClick, - onCancelClick, - manualJournalId, - onSubmitForm, - onResetForm, - manualJournalPublished, -}) { +export default function MakeJournalEntriesFooter() { + const history = useHistory(); + + // Formik context. + const { isSubmitting, submitForm } = useFormikContext(); + + // Make journal form context. + const { + manualJournalId, + setSubmitPayload, + manualJournalPublished = false, + } = useMakeJournalFormContext(); + + // Handle `submit & publish` button click. const handleSubmitPublishBtnClick = (event) => { - saveInvoke(onSubmitClick, event, { - redirect: true, - publish: true, - }); + setSubmitPayload({ redirect: true, publish: true }); + submitForm(); }; + // Handle `submit, publish & new` button click. const handleSubmitPublishAndNewBtnClick = (event) => { - onSubmitForm(); - saveInvoke(onSubmitClick, event, { - redirect: false, - publish: true, - resetForm: true, - }); + setSubmitPayload({ redirect: false, publish: true, resetForm: true }); + submitForm(); }; + // Handle `submit, publish & continue editing` button click. const handleSubmitPublishContinueEditingBtnClick = (event) => { - onSubmitForm(); - saveInvoke(onSubmitClick, event, { - redirect: false, - publish: true, - }); + setSubmitPayload({ redirect: false, publish: true }); + submitForm(); }; + // Handle `submit as draft` button click. const handleSubmitDraftBtnClick = (event) => { - saveInvoke(onSubmitClick, event, { - redirect: true, - publish: false, - }); + setSubmitPayload({ redirect: true, publish: false }); }; + // Handle `submit as draft & new` button click. const handleSubmitDraftAndNewBtnClick = (event) => { - onSubmitForm(); - saveInvoke(onSubmitClick, event, { - redirect: false, - publish: false, - resetForm: true, - }); + setSubmitPayload({ redirect: false, publish: false, resetForm: true }); + submitForm(); }; + // Handles submit as draft & continue editing button click. const handleSubmitDraftContinueEditingBtnClick = (event) => { - onSubmitForm(); - saveInvoke(onSubmitClick, event, { - redirect: false, - publish: false, - }); + setSubmitPayload({ redirect: false, publish: false }); + submitForm(); }; + // Handle cancel button action click. const handleCancelBtnClick = (event) => { - saveInvoke(onCancelClick, event); + history.goBack(); }; - const handleClearBtnClick = (event) => { - // saveInvoke(onClearClick, event); - onResetForm(); - }; + const handleClearBtnClick = (event) => {}; return (
diff --git a/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesForm.js b/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesForm.js index 673105ef1..be6ef6452 100644 --- a/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesForm.js +++ b/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesForm.js @@ -1,9 +1,8 @@ -import React, { useMemo, useState, useEffect, useCallback } from 'react'; +import React, { useMemo } from 'react'; import { Formik, Form } from 'formik'; -import moment from 'moment'; import { Intent } from '@blueprintjs/core'; import { useIntl } from 'react-intl'; -import { pick, defaultTo } from 'lodash'; +import { defaultTo, isEmpty } from 'lodash'; import classNames from 'classnames'; import { useHistory } from 'react-router-dom'; @@ -15,56 +14,30 @@ import { import MakeJournalEntriesHeader from './MakeJournalEntriesHeader'; import MakeJournalFormFloatingActions from './MakeJournalFormFloatingActions'; import MakeJournalEntriesField from './MakeJournalEntriesField'; -import MakeJournalNumberWatcher from './MakeJournalNumberWatcher'; import MakeJournalFormFooter from './MakeJournalFormFooter'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withSettings from 'containers/Settings/withSettings'; import AppToaster from 'components/AppToaster'; import withMediaActions from 'containers/Media/withMediaActions'; +import { compose, orderingLinesIndexes, transactionNumber } from 'utils'; import { - compose, - repeatValue, - orderingLinesIndexes, - defaultToTransform, - transactionNumber, -} from 'utils'; -import { transformErrors } from './utils'; + transformErrors, + transformToEditForm, + defaultManualJournal, +} from './utils'; import { useMakeJournalFormContext } from './MakeJournalProvider'; -const defaultEntry = { - index: 0, - account_id: '', - credit: '', - debit: '', - contact_id: '', - note: '', -}; -const defaultInitialValues = { - journal_number: '', - journal_type: 'Journal', - date: moment(new Date()).format('YYYY-MM-DD'), - description: '', - reference: '', - currency_code: '', - publish: '', - entries: [...repeatValue(defaultEntry, 4)], -}; - /** * Journal entries form. */ function MakeJournalEntriesForm({ - // #withDashboard - changePageTitle, - changePageSubtitle, - // #withSettings journalNextNumber, journalNumberPrefix, baseCurrency, }) { + // Journal form context. const { createJournalMutate, editJournalMutate, @@ -81,58 +54,23 @@ function MakeJournalEntriesForm({ journalNumberPrefix, journalNextNumber, ); - // Changes the page title based on the form in new and edit mode. - useEffect(() => { - const transactionNumber = manualJournal - ? manualJournal.journal_number - : journalNumber; - - if (isNewMode) { - changePageTitle(formatMessage({ id: 'new_journal' })); - } else { - changePageTitle(formatMessage({ id: 'edit_journal' })); - } - changePageSubtitle( - defaultToTransform(transactionNumber, `No. ${transactionNumber}`, ''), - ); - }, [ - changePageTitle, - changePageSubtitle, - journalNumber, - manualJournal, - formatMessage, - isNewMode, - ]); - + // Form initial values. const initialValues = useMemo( () => ({ - ...(manualJournal + ...(!isEmpty(manualJournal) ? { - ...pick(manualJournal, Object.keys(defaultInitialValues)), - entries: manualJournal.entries.map((entry) => ({ - ...pick(entry, Object.keys(defaultEntry)), - })), + ...transformToEditForm(manualJournal), } : { - ...defaultInitialValues, + ...defaultManualJournal, journal_number: defaultTo(journalNumber, ''), currency_code: defaultTo(baseCurrency, ''), - entries: orderingLinesIndexes(defaultInitialValues.entries), + entries: orderingLinesIndexes(defaultManualJournal.entries), }), }), [manualJournal, baseCurrency, journalNumber], ); - // Handle journal number field change. - const handleJournalNumberChanged = useCallback( - (journalNumber) => { - changePageSubtitle( - defaultToTransform(journalNumber, `No. ${journalNumber}`, ''), - ); - }, - [changePageSubtitle], - ); - // Handle the form submiting. const handleSubmit = (values, { setErrors, setSubmitting, resetForm }) => { setSubmitting(true); @@ -170,8 +108,12 @@ function MakeJournalEntriesForm({ const form = { ...values, publish: submitPayload.publish, entries }; // Handle the request error. - const handleError = (error) => { - transformErrors(error, { setErrors }); + const handleError = ({ + response: { + data: { errors }, + }, + }) => { + transformErrors(errors, { setErrors }); setSubmitting(false); }; @@ -201,7 +143,7 @@ function MakeJournalEntriesForm({ if (isNewMode) { createJournalMutate(form).then(handleSuccess).catch(handleError); } else { - editJournalMutate(manualJournal.id, form) + editJournalMutate([manualJournal.id, form]) .then(handleSuccess) .catch(handleError); } @@ -221,11 +163,8 @@ function MakeJournalEntriesForm({ onSubmit={handleSubmit} >
- - - + + @@ -235,7 +174,6 @@ function MakeJournalEntriesForm({ } export default compose( - withDashboardActions, withMediaActions, withSettings(({ manualJournalsSettings, organizationSettings }) => ({ journalNextNumber: parseInt(manualJournalsSettings?.nextNumber, 10), diff --git a/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesPage.js b/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesPage.js index dfc405bf3..ea2f3ff86 100644 --- a/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesPage.js +++ b/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesPage.js @@ -1,62 +1,20 @@ -import React, { useCallback, useEffect } from 'react'; -import { useParams, useHistory } from 'react-router-dom'; +import React from 'react'; +import { useParams } from 'react-router-dom'; import MakeJournalEntriesForm from './MakeJournalEntriesForm'; import { MakeJournalProvider } from './MakeJournalProvider'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; - -import { compose } from 'utils'; - import 'style/pages/ManualJournal/MakeJournal.scss'; /** * Make journal entries page. */ -function MakeJournalEntriesPage({ - // #withDashboardActions - setSidebarShrink, - resetSidebarPreviousExpand, - setDashboardBackLink, -}) { - const history = useHistory(); +export default function MakeJournalEntriesPage() { const { id: journalId } = useParams(); - - useEffect(() => { - // Shrink the sidebar by foce. - setSidebarShrink(); - // Show the back link on dashboard topbar. - setDashboardBackLink('/manual-journals'); - - return () => { - // Reset the sidebar to the previous status. - resetSidebarPreviousExpand(); - // Hide the back link on dashboard topbar. - setDashboardBackLink(false); - }; - }, [resetSidebarPreviousExpand, setDashboardBackLink, setSidebarShrink]); - - const handleFormSubmit = useCallback( - (payload) => { - payload.redirect && history.push('/manual-journals'); - }, - [history], - ); - - const handleCancel = useCallback(() => { - history.goBack(); - }, [history]); - + return ( - + ); } - -export default compose( - withDashboardActions, -)(MakeJournalEntriesPage); diff --git a/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesTable.js b/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesTable.js index dbc089489..974735e57 100644 --- a/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesTable.js +++ b/client/src/containers/Accounting/MakeJournal/MakeJournalEntriesTable.js @@ -1,205 +1,111 @@ -import React, { useState, useMemo, useEffect, useCallback } from 'react'; +import React from 'react'; import { Button } from '@blueprintjs/core'; -import { FormattedMessage as T, useIntl } from 'react-intl'; -import { omit } from 'lodash'; -import { saveInvoke } from 'utils'; -import { - AccountsListFieldCell, - MoneyFieldCell, - InputGroupCell, - ContactsListFieldCell, -} from 'components/DataTableCells'; -import { - ContactHeaderCell, - ActionsCellRenderer, - TotalAccountCellRenderer, - TotalCreditDebitCellRenderer, - NoteCellRenderer, -} from './components'; +import { FormattedMessage as T } from 'react-intl'; +import { saveInvoke, removeRowsByIndex } from 'utils'; import { DataTableEditable } from 'components'; +import withAlertActions from 'containers/Alert/withAlertActions'; import { updateDataReducer } from './utils'; import { useMakeJournalFormContext } from './MakeJournalProvider'; +import { useJournalTableEntriesColumns } from './components'; + +import JournalDeleteEntriesAlert from 'containers/Alerts/ManualJournals/JournalDeleteEntriesAlert'; +import { compose } from 'redux'; +import { repeatValue } from 'utils'; /** * Make journal entries table component. */ -export default function MakeJournalEntriesTable({ +function MakeJournalEntriesTable({ + // #withAlertsActions + openAlert, + // #ownPorps - onClickRemoveRow, - onClickAddNewRow, - onClickClearAllLines, onChange, entries, + defaultEntry, error, + initialLinesNumber = 4, + minLinesNumber = 4, }) { - const [rows, setRows] = useState([]); - const { formatMessage } = useIntl(); - const { accounts, customers } = useMakeJournalFormContext(); - useEffect(() => { - setRows([...entries.map((e) => ({ ...e, rowType: 'editor' }))]); - }, [entries, setRows]); - - // Final table rows editor rows and total and final blank row. - const tableRows = useMemo(() => [...rows, { rowType: 'total' }], [rows]); - // Memorized data table columns. - const columns = useMemo( - () => [ - { - Header: '#', - accessor: 'index', - Cell: ({ row: { index } }) => {index + 1}, - className: 'index', - width: 40, - disableResizing: true, - disableSortBy: true, - sticky: 'left', - }, - { - Header: formatMessage({ id: 'account' }), - id: 'account_id', - accessor: 'account_id', - Cell: TotalAccountCellRenderer(AccountsListFieldCell), - className: 'account', - disableSortBy: true, - width: 140, - }, - { - Header: formatMessage({ id: 'credit_currency' }, { currency: 'USD' }), - accessor: 'credit', - Cell: TotalCreditDebitCellRenderer(MoneyFieldCell, 'credit'), - className: 'credit', - disableSortBy: true, - width: 100, - }, - { - Header: formatMessage({ id: 'debit_currency' }, { currency: 'USD' }), - accessor: 'debit', - Cell: TotalCreditDebitCellRenderer(MoneyFieldCell, 'debit'), - className: 'debit', - disableSortBy: true, - width: 100, - }, - { - Header: ContactHeaderCell, - id: 'contact_id', - accessor: 'contact_id', - Cell: NoteCellRenderer(ContactsListFieldCell), - className: 'contact', - disableSortBy: true, - width: 120, - }, - { - Header: formatMessage({ id: 'note' }), - accessor: 'note', - Cell: NoteCellRenderer(InputGroupCell), - disableSortBy: true, - className: 'note', - width: 200, - }, - { - Header: '', - accessor: 'action', - Cell: ActionsCellRenderer, - className: 'actions', - disableSortBy: true, - disableResizing: true, - width: 45, - }, - ], - [formatMessage], - ); + const columns = useJournalTableEntriesColumns(); // Handles click new line. const onClickNewRow = () => { - saveInvoke(onClickAddNewRow); + const newRows = [...entries, defaultEntry]; + saveInvoke(onChange, newRows); }; // Handles update datatable data. const handleUpdateData = (rowIndex, columnId, value) => { - const newRows = updateDataReducer(rows, rowIndex, columnId, value); - - saveInvoke( - onChange, - newRows - .filter((row) => row.rowType === 'editor') - .map((row) => ({ - ...omit(row, ['rowType']), - })), - ); + const newRows = updateDataReducer(entries, rowIndex, columnId, value); + saveInvoke(onChange, newRows); }; + // Handle remove datatable row. const handleRemoveRow = (rowIndex) => { - // Can't continue if there is just one row line or less. - if (rows.length <= 2) { - return; - } - const removeIndex = parseInt(rowIndex, 10); - const newRows = rows.filter((row, index) => index !== removeIndex); - - saveInvoke( - onChange, - newRows - .filter((row) => row.rowType === 'editor') - .map((row) => ({ ...omit(row, ['rowType']) })), - ); - saveInvoke(onClickRemoveRow, removeIndex); + const newRows = removeRowsByIndex(entries, rowIndex); + saveInvoke(onChange, newRows); }; - // Rows class names callback. - const rowClassNames = useCallback( - (row) => ({ - 'row--total': rows.length === row.index + 2, - }), - [rows], - ); - + // Handle clear all lines action. const handleClickClearAllLines = () => { - saveInvoke(onClickClearAllLines); + openAlert('make-journal-delete-all-entries'); + }; + + // Handle clear all lines alaert confirm. + const handleCofirmClearEntriesAlert = () => { + const newRows = repeatValue(defaultEntry, initialLinesNumber); + saveInvoke(onChange, newRows); }; return ( - ({ + <> + ({ ...customer, contact_type: 'customer', })), - ], - autoFocus: ['account_id', 0], - }} - actions={ - <> - + autoFocus: ['account_id', 0], + }} + actions={ + <> + - - - } - /> + + + } + /> + + ); } + +export default compose(withAlertActions)(MakeJournalEntriesTable); diff --git a/client/src/containers/Accounting/MakeJournal/MakeJournalFormFloatingActions.js b/client/src/containers/Accounting/MakeJournal/MakeJournalFormFloatingActions.js index 1d367b614..80f42ace7 100644 --- a/client/src/containers/Accounting/MakeJournal/MakeJournalFormFloatingActions.js +++ b/client/src/containers/Accounting/MakeJournal/MakeJournalFormFloatingActions.js @@ -80,8 +80,8 @@ export default function MakeJournalFloatingAction() { + <> + + - - - } - /> + + + } + /> + + ); } + +ItemsEntriesTable.defaultProps = { + defaultEntry: { + index: 0, + item_id: '', + description: '', + quantity: 1, + rate: '', + discount: '', + }, + initialEntries: [], + linesNumber: 4, +}; + +export default compose(withAlertActions)(ItemsEntriesTable); diff --git a/client/src/containers/Entries/components.js b/client/src/containers/Entries/components.js new file mode 100644 index 000000000..5ad8f427b --- /dev/null +++ b/client/src/containers/Entries/components.js @@ -0,0 +1,166 @@ +import React from 'react'; +import { FormattedMessage as T, useIntl } from 'react-intl'; +import { Tooltip, Button, Intent, Position } from '@blueprintjs/core'; +import { sumBy } from 'lodash'; +import { Hint, Icon } from 'components'; +import { formattedAmount } from 'utils'; +import { + InputGroupCell, + MoneyFieldCell, + ItemsListCell, + PercentFieldCell, +} from 'components/DataTableCells'; + +/** + * Item header cell. + */ +export function ItemHeaderCell() { + return ( + <> + + + + ); +} + +/** + * Item column footer cell. + */ +export function ItemFooterCell() { + return Total; +} + +/** + * Actions cell renderer component. + */ +export function ActionsCellRenderer({ + row: { index }, + column: { id }, + cell: { value }, + data, + payload: { removeRow }, +}) { + const onRemoveRole = () => { + removeRow(index); + }; + + return ( + } position={Position.LEFT}> + - - - - } - totalRow={true} - /> - ); -} \ No newline at end of file diff --git a/client/src/containers/Expenses/ExpenseForm/ExpenseFormEntriesField.js b/client/src/containers/Expenses/ExpenseForm/ExpenseFormEntriesField.js index 61903c9eb..36c8794b9 100644 --- a/client/src/containers/Expenses/ExpenseForm/ExpenseFormEntriesField.js +++ b/client/src/containers/Expenses/ExpenseForm/ExpenseFormEntriesField.js @@ -1,30 +1,27 @@ import { FastField } from 'formik'; import React from 'react'; -import ExpenseFormEntries from './ExpenseFormEntries'; -import { orderingLinesIndexes, repeatValue } from 'utils'; +import ExpenseFormEntriesTable from './ExpenseFormEntriesTable'; +import { useExpenseFormContext } from './ExpenseFormPageProvider'; +/** + * Expense form entries field. + */ export default function ExpenseFormEntriesField({ - defaultRow, linesNumber = 4, }) { + const { defaultCategoryEntry } = useExpenseFormContext(); + return ( {({ form, field: { value }, meta: { error, touched } }) => ( - { form.setFieldValue('categories', entries); }} - onClickAddNewRow={() => { - form.setFieldValue('categories', [...value, defaultRow]); - }} - onClickClearAllLines={() => { - form.setFieldValue( - 'categories', - orderingLinesIndexes([...repeatValue(defaultRow, linesNumber)]) - ); - }} + defaultEntry={defaultCategoryEntry} + linesNumber={linesNumber} /> )} diff --git a/client/src/containers/Expenses/ExpenseForm/ExpenseFormEntriesTable.js b/client/src/containers/Expenses/ExpenseForm/ExpenseFormEntriesTable.js new file mode 100644 index 000000000..be5029625 --- /dev/null +++ b/client/src/containers/Expenses/ExpenseForm/ExpenseFormEntriesTable.js @@ -0,0 +1,121 @@ +import React, { useCallback } from 'react'; +import { Button } from '@blueprintjs/core'; +import { FormattedMessage as T } from 'react-intl'; + +import { DataTableEditable } from 'components'; +import ExpenseDeleteEntriesAlert from 'containers/Alerts/Expenses/ExpenseDeleteEntriesAlert'; +import { useExpenseFormContext } from './ExpenseFormPageProvider'; +import { useExpenseFormTableColumns } from './components'; + +import withAlertActions from 'containers/Alert/withAlertActions'; + +import { transformUpdatedRows, compose, saveInvoke, repeatValue } from 'utils'; + +/** + * Expenses form entries. + */ +function ExpenseFormEntriesTable({ + // #withAlertActions + openAlert, + + // #ownPorps + entries, + defaultEntry, + error, + onChange, +}) { + // Expense form context. + const { accounts } = useExpenseFormContext(); + + // Memorized data table columns. + const columns = useExpenseFormTableColumns(); + + // Handles update datatable data. + const handleUpdateData = useCallback( + (rowIndex, columnIdOrObj, value) => { + const newRows = transformUpdatedRows( + entries, + rowIndex, + columnIdOrObj, + value, + ); + saveInvoke(onChange, newRows); + }, + [entries, onChange], + ); + + // Handles click remove datatable row. + const handleRemoveRow = useCallback( + (rowIndex) => { + // Can't continue if there is just one row line or less. + if (entries.length <= 1) { + return; + } + const newRows = entries.filter((row, index) => index !== rowIndex); + saveInvoke(onChange, newRows); + }, + [entries, onChange], + ); + + // Invoke when click on add new line button. + const onClickNewRow = () => { + const newRows = [...entries, defaultEntry]; + saveInvoke(onChange, newRows); + }; + + // Invoke when click on clear all lines button. + const handleClickClearAllLines = () => { + openAlert('expense-delete-entries'); + }; + + // handle confirm clear all entries alert. + const handleConfirmClearEntriesAlert = () => { + const newRows = repeatValue(defaultEntry, 3); + saveInvoke(onChange, newRows); + }; + + return ( + <> + + + + + + } + totalRow={true} + /> + + + ); +} + +export default compose( + withAlertActions +)(ExpenseFormEntriesTable); \ No newline at end of file diff --git a/client/src/containers/Expenses/ExpenseForm/ExpenseFormFooter.js b/client/src/containers/Expenses/ExpenseForm/ExpenseFormFooter.js index 658547382..a6c84882f 100644 --- a/client/src/containers/Expenses/ExpenseForm/ExpenseFormFooter.js +++ b/client/src/containers/Expenses/ExpenseForm/ExpenseFormFooter.js @@ -7,7 +7,7 @@ import { inputIntent } from 'utils'; import { Row, Dragzone, Col } from 'components'; import { CLASSES } from 'common/classes'; -export default function ExpenseFormFooter({}) { +export default function ExpenseFormFooter() { return (
diff --git a/client/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.js b/client/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.js index f6f4d5c43..8bec4f675 100644 --- a/client/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.js +++ b/client/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.js @@ -6,7 +6,6 @@ import { FormattedMessage as T } from 'react-intl'; import { CLASSES } from 'common/classes'; import { momentFormatter, - compose, tansformDateValue, inputIntent, handleDateChange, @@ -27,7 +26,7 @@ import { useExpenseFormContext } from './ExpenseFormPageProvider'; /** * Expense form header. */ -export default function ExpenseFormHeader({}) { +export default function ExpenseFormHeader() { const { currencies, accounts, customers } = useExpenseFormContext(); return ( diff --git a/client/src/containers/Expenses/ExpenseForm/ExpenseFormPage.js b/client/src/containers/Expenses/ExpenseForm/ExpenseFormPage.js index 05b3e611c..0e7731b17 100644 --- a/client/src/containers/Expenses/ExpenseForm/ExpenseFormPage.js +++ b/client/src/containers/Expenses/ExpenseForm/ExpenseFormPage.js @@ -1,48 +1,21 @@ -import React, { useCallback, useEffect } from 'react'; -import { useParams, useHistory } from 'react-router-dom'; +import React from 'react'; +import { useParams } from 'react-router-dom'; import ExpenseForm from './ExpenseForm'; import { ExpenseFormPageProvider } from './ExpenseFormPageProvider'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; - -import { compose } from 'utils'; - import 'style/pages/Expense/PageForm.scss'; /** * Expense page form. */ -function ExpenseFormPage({ - // #withDashboardActions - setSidebarShrink, - resetSidebarPreviousExpand, - setDashboardBackLink, -}) { - const history = useHistory(); +export default function ExpenseFormPage() { const { id } = useParams(); - useEffect(() => { - // Shrink the sidebar by foce. - setSidebarShrink(); - // Show the back link on dashboard topbar. - setDashboardBackLink(true); - - return () => { - // Reset the sidebar to the previous status. - resetSidebarPreviousExpand(); - // Hide the back link on dashboard topbar. - setDashboardBackLink(false); - }; - }, [resetSidebarPreviousExpand, setSidebarShrink, setDashboardBackLink]); - return ( ); } - -export default compose( - withDashboardActions, -)(ExpenseFormPage); + \ No newline at end of file diff --git a/client/src/containers/Expenses/ExpenseForm/ExpenseFormPageProvider.js b/client/src/containers/Expenses/ExpenseForm/ExpenseFormPageProvider.js index 7378ef722..c9fc648ba 100644 --- a/client/src/containers/Expenses/ExpenseForm/ExpenseFormPageProvider.js +++ b/client/src/containers/Expenses/ExpenseForm/ExpenseFormPageProvider.js @@ -24,7 +24,12 @@ function ExpenseFormPageProvider({ expenseId, ...props }) { } = useCustomers(); // Fetch the expense details. - const { data: expense, isFetching: isExpenseLoading } = useExpense(expenseId); + const { data: expense, isFetching: isExpenseLoading } = useExpense( + expenseId, + { + enabled: !!expenseId, + }, + ); // Fetch accounts list. const { data: accounts, isFetching: isAccountsLoading } = useAccounts(); @@ -33,9 +38,17 @@ function ExpenseFormPageProvider({ expenseId, ...props }) { const { mutateAsync: createExpenseMutate } = useCreateExpense(); const { mutateAsync: editExpenseMutate } = useEditExpense(); + // Submit form payload. + const [submitPayload, setSubmitPayload] = React.useState({}); + + // + const isNewMode = !expenseId; + // Provider payload. const provider = { + isNewMode, expenseId, + submitPayload, currencies, customers, @@ -49,6 +62,7 @@ function ExpenseFormPageProvider({ expenseId, ...props }) { createExpenseMutate, editExpenseMutate, + setSubmitPayload, }; return ( diff --git a/client/src/containers/Expenses/ExpenseForm/components.js b/client/src/containers/Expenses/ExpenseForm/components.js index 33bd30c30..6992c6992 100644 --- a/client/src/containers/Expenses/ExpenseForm/components.js +++ b/client/src/containers/Expenses/ExpenseForm/components.js @@ -1,6 +1,17 @@ +import React from 'react'; +import { Button, Tooltip, Intent, Position } from '@blueprintjs/core'; +import { FormattedMessage as T, useIntl } from 'react-intl'; +import { Icon, Hint } from 'components'; +import { + InputGroupCell, + MoneyFieldCell, + AccountsListFieldCell, +} from 'components/DataTableCells'; +import { formattedAmount, safeSumBy } from 'utils'; - - +/** + * Expense category header cell. + */ const ExpenseCategoryHeaderCell = () => { return ( <> @@ -10,7 +21,9 @@ const ExpenseCategoryHeaderCell = () => { ); }; -// Actions cell renderer. +/** + * Actions cell renderer. + */ const ActionsCellRenderer = ({ row: { index }, column: { id }, @@ -18,9 +31,6 @@ const ActionsCellRenderer = ({ data, payload, }) => { - if (data.length <= index + 1) { - return ''; - } const onClickRemoveRole = () => { payload.removeRow(index); }; @@ -38,95 +48,76 @@ const ActionsCellRenderer = ({ ); }; -// Total text cell renderer. -const TotalExpenseCellRenderer = (chainedComponent) => (props) => { - if (props.data.length <= props.row.index + 1) { - return ( - - - - ); - } - return chainedComponent(props); -}; +/** + * Amount footer cell. + */ +function AmountFooterCell({ rows }) { + const total = safeSumBy(rows, 'original.amount'); + return {formattedAmount(total, 'USD')}; +} /** - * Note cell renderer. + * Expense account footer cell. */ -const NoteCellRenderer = (chainedComponent) => (props) => { - if (props.data.length === props.row.index + 1) { - return ''; - } - return chainedComponent(props); -}; +function ExpenseAccountFooterCell() { + return 'Total'; +} /** - * Total amount cell renderer. + * Retrieve expense form table entries columns. */ -const TotalAmountCellRenderer = (chainedComponent, type) => (props) => { - if (props.data.length === props.row.index + 1) { - const total = props.data.reduce((total, entry) => { - const amount = parseInt(entry[type], 10); - const computed = amount ? total + amount : total; - - return computed; - }, 0); - - return {formattedAmount(total, 'USD')}; - } - return chainedComponent(props); - }; - +export function useExpenseFormTableColumns() { + const { formatMessage } = useIntl(); - - export function useExpenseFormTableColumns() { - return React.useMemo( - () => [ - { - Header: '#', - accessor: 'index', - Cell: ({ row: { index } }) => {index + 1}, - className: 'index', - width: 40, - disableResizing: true, - disableSortBy: true, - }, - { - Header: ExpenseCategoryHeaderCell, - id: 'expense_account_id', - accessor: 'expense_account_id', - Cell: TotalExpenseCellRenderer(AccountsListFieldCell), - className: 'expense_account_id', - disableSortBy: true, - width: 40, - filterAccountsByRootType: ['expense'], - }, - { - Header: formatMessage({ id: 'amount_currency' }, { currency: 'USD' }), - accessor: 'amount', - Cell: TotalAmountCellRenderer(MoneyFieldCell, 'amount'), - disableSortBy: true, - width: 40, - className: 'amount', - }, - { - Header: formatMessage({ id: 'description' }), - accessor: 'description', - Cell: NoteCellRenderer(InputGroupCell), - disableSortBy: true, - className: 'description', - width: 100, - }, - { - Header: '', - accessor: 'action', - Cell: ActionsCellRenderer, - className: 'actions', - disableSortBy: true, - disableResizing: true, - width: 45, - }, - ], - [formatMessage], - ) - } \ No newline at end of file + return React.useMemo( + () => [ + { + Header: '#', + accessor: 'index', + Cell: ({ row: { index } }) => {index + 1}, + className: 'index', + width: 40, + disableResizing: true, + disableSortBy: true, + }, + { + Header: ExpenseCategoryHeaderCell, + id: 'expense_account_id', + accessor: 'expense_account_id', + Cell: AccountsListFieldCell, + Footer: ExpenseAccountFooterCell, + className: 'expense_account_id', + disableSortBy: true, + width: 40, + filterAccountsByRootType: ['expense'], + }, + { + Header: formatMessage({ id: 'amount_currency' }, { currency: 'USD' }), + accessor: 'amount', + Cell: MoneyFieldCell, + Footer: AmountFooterCell, + disableSortBy: true, + width: 40, + className: 'amount', + }, + { + Header: formatMessage({ id: 'description' }), + accessor: 'description', + Cell: InputGroupCell, + disableSortBy: true, + className: 'description', + width: 100, + }, + { + Header: '', + accessor: 'action', + Cell: ActionsCellRenderer, + className: 'actions', + disableSortBy: true, + disableResizing: true, + width: 45, + }, + ], + [formatMessage], + ); +} diff --git a/client/src/containers/Expenses/ExpenseForm/utils.js b/client/src/containers/Expenses/ExpenseForm/utils.js index b2184bdec..741052db2 100644 --- a/client/src/containers/Expenses/ExpenseForm/utils.js +++ b/client/src/containers/Expenses/ExpenseForm/utils.js @@ -1,5 +1,7 @@ import { AppToaster } from 'components'; +import moment from 'moment'; import { formatMessage } from 'services/intl'; +import { transformToForm, repeatValue } from 'utils'; const ERROR = { EXPENSE_ALREADY_PUBLISHED: 'EXPENSE.ALREADY.PUBLISHED', @@ -18,4 +20,46 @@ export const transformErrors = (errors, { setErrors }) => { }), ); } -}; \ No newline at end of file +}; + +export const MIN_LINES_NUMBER = 4; + +export const defaultExpenseEntry = { + index: 0, + amount: '', + expense_account_id: '', + description: '', +}; + +export const defaultExpense = { + payment_account_id: '', + beneficiary: '', + payment_date: moment(new Date()).format('YYYY-MM-DD'), + description: '', + reference_no: '', + currency_code: '', + publish: '', + categories: [...repeatValue(defaultExpenseEntry, MIN_LINES_NUMBER)], +}; + +/** + * Transformes the expense to form initial values in edit mode. + */ +export const transformToEditForm = ( + expense, + defaultExpense, + linesNumber = 4, +) => { + return { + ...transformToForm(expense, defaultExpense), + categories: [ + ...expense.categories.map((category) => ({ + ...transformToForm(category, defaultExpense.categories[0]), + })), + ...repeatValue( + expense, + Math.max(linesNumber - expense.categories.length, 0), + ), + ], + }; +}; diff --git a/client/src/containers/Expenses/ExpensesLanding/ExpenseDataTable.js b/client/src/containers/Expenses/ExpensesLanding/ExpenseDataTable.js index aa959266b..c0b62ab01 100644 --- a/client/src/containers/Expenses/ExpensesLanding/ExpenseDataTable.js +++ b/client/src/containers/Expenses/ExpensesLanding/ExpenseDataTable.js @@ -1,8 +1,8 @@ import React, { useCallback } from 'react'; import classNames from 'classnames'; +import { useHistory } from 'react-router-dom'; import { compose } from 'utils'; - import { useExpensesListContext } from './ExpensesListProvider'; import { Choose } from 'components'; @@ -39,6 +39,8 @@ function ExpensesDataTable({ isEmptyStatus } = useExpensesListContext(); + const history = useHistory(); + // Expenses table columns. const columns = useExpensesTableColumns(); @@ -59,7 +61,9 @@ function ExpensesDataTable({ openAlert('expense-publish', { expenseId: expense.id }); }; - const handleEditExpense = (expense) => { + // Handle the expense edit action. + const handleEditExpense = ({ id }) => { + history.push(`/expenses/${id}/edit`); }; // Handle the expense delete action. @@ -67,49 +71,45 @@ function ExpensesDataTable({ openAlert('expense-delete', { expenseId: expense.id }); }; + // Display empty status instead of the table. + if (isEmptyStatus) { + return ; + } + return ( -
- - - - + - - - -
+ payload={{ + onPublish: handlePublishExpense, + onDelete: handleDeleteExpense, + onEdit: handleEditExpense + }} + /> ); } diff --git a/client/src/containers/Expenses/ExpensesLanding/ExpensesList.js b/client/src/containers/Expenses/ExpensesLanding/ExpensesList.js index 4765654cd..edaaa4783 100644 --- a/client/src/containers/Expenses/ExpensesLanding/ExpensesList.js +++ b/client/src/containers/Expenses/ExpensesLanding/ExpensesList.js @@ -1,16 +1,14 @@ -import React, { useEffect } from 'react'; -import { useIntl } from 'react-intl'; +import React from 'react'; import 'style/pages/Expense/List.scss'; -import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; +import { DashboardContentTable, DashboardPageContent } from 'components'; import ExpenseActionsBar from './ExpenseActionsBar'; import ExpenseViewTabs from './ExpenseViewTabs'; import ExpenseDataTable from './ExpenseDataTable'; import ExpensesAlerts from '../ExpensesAlerts'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withExpenses from './withExpenses'; import { compose, transformTableStateToQuery } from 'utils'; @@ -20,19 +18,9 @@ import { ExpensesListProvider } from './ExpensesListProvider'; * Expenses list. */ function ExpensesList({ - // #withDashboardActions - changePageTitle, - // #withExpenses expensesTableState, }) { - const { formatMessage } = useIntl(); - - // Changes the page title once the page mount. - useEffect(() => { - changePageTitle(formatMessage({ id: 'expenses_list' })); - }, [changePageTitle, formatMessage]); - return ( - + + + + @@ -50,6 +41,5 @@ function ExpensesList({ } export default compose( - withDashboardActions, withExpenses(({ expensesTableState }) => ({ expensesTableState })), )(ExpensesList); diff --git a/client/src/containers/Expenses/ExpensesLanding/components.js b/client/src/containers/Expenses/ExpensesLanding/components.js index 2f831171d..da7e98761 100644 --- a/client/src/containers/Expenses/ExpensesLanding/components.js +++ b/client/src/containers/Expenses/ExpensesLanding/components.js @@ -107,6 +107,24 @@ export function PublishAccessor(row) { ); } +/** + * Expense account accessor. + */ +export function ExpenseAccountAccessor(expense) { + if (expense.categories.length === 1) { + return expense.categories[0].expense_account.name; + } else if (expense.categories.length > 1) { + const mutliCategories = expense.categories.map((category) => ( +
+ - {category.expense_account.name} ${category.amount} +
+ )); + return ( + {'- Multi Categories -'} + ); + } +} + /** * Retrieve the expenses table columns. */ @@ -168,18 +186,3 @@ export function useExpensesTableColumns() { [], ); } - -export function ExpenseAccountAccessor(expense) { - if (expense.categories.length === 1) { - return expense.categories[0].expense_account.name; - } else if (expense.categories.length > 1) { - const mutliCategories = expense.categories.map((category) => ( -
- - {category.expense_account.name} ${category.amount} -
- )); - return ( - {'- Multi Categories -'} - ); - } -} diff --git a/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheet.js b/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheet.js index ac5a51e21..ff9c1eaee 100644 --- a/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheet.js +++ b/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheet.js @@ -1,9 +1,5 @@ -import React, { useEffect, useState } from 'react'; - -import { compose } from 'utils'; - +import React, { useState } from 'react'; import moment from 'moment'; -import { useIntl } from 'react-intl'; import 'style/pages/FinancialStatements/BalanceSheet.scss'; @@ -14,25 +10,18 @@ import BalanceSheetActionsBar from './BalanceSheetActionsBar'; import { FinancialStatement } from 'components'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withSettings from 'containers/Settings/withSettings'; - import { BalanceSheetProvider } from './BalanceSheetProvider'; +import { compose } from 'utils'; + /** * Balance sheet. */ function BalanceSheet({ - // #withDashboardActions - changePageTitle, - setDashboardBackLink, - setSidebarShrink, - // #withPreferences organizationName, }) { - const { formatMessage } = useIntl(); - const [filter, setFilter] = useState({ fromDate: moment().startOf('year').format('YYYY-MM-DD'), toDate: moment().endOf('year').format('YYYY-MM-DD'), @@ -41,21 +30,6 @@ function BalanceSheet({ accountsFilter: 'all-accounts', }); - useEffect(() => { - setSidebarShrink(); - changePageTitle(formatMessage({ id: 'balance_sheet' })); - }, [changePageTitle, formatMessage, setSidebarShrink]); - - useEffect(() => { - // Show the back link on dashboard topbar. - setDashboardBackLink(true); - - return () => { - // Hide the back link on dashboard topbar. - setDashboardBackLink(false); - }; - }, [setDashboardBackLink]); - // Handle re-fetch balance sheet after filter change. const handleFilterSubmit = (filter) => { const _filter = { @@ -95,7 +69,6 @@ function BalanceSheet({ } export default compose( - withDashboardActions, withSettings(({ organizationSettings }) => ({ organizationName: organizationSettings.name, })), diff --git a/client/src/containers/FinancialStatements/FinancialReports.js b/client/src/containers/FinancialStatements/FinancialReports.js index 11051c587..cc478561e 100644 --- a/client/src/containers/FinancialStatements/FinancialReports.js +++ b/client/src/containers/FinancialStatements/FinancialReports.js @@ -34,16 +34,7 @@ function FinancialReportsSection({ sectionTitle, reports }) { ); } -function FinancialReports({ - // #withDashboardActions - changePageTitle, -}) { - const { formatMessage } = useIntl(); - - useEffect(() => { - changePageTitle(formatMessage({ id: 'all_financial_reports' })); - }, [changePageTitle, formatMessage]); - +export default function FinancialReports() { return (
@@ -53,4 +44,3 @@ function FinancialReports({ ); } -export default compose(withDashboardActions)(FinancialReports); diff --git a/client/src/containers/InventoryAdjustments/InventoryAdjustmentList.js b/client/src/containers/InventoryAdjustments/InventoryAdjustmentList.js index b64c8bd69..36645bd36 100644 --- a/client/src/containers/InventoryAdjustments/InventoryAdjustmentList.js +++ b/client/src/containers/InventoryAdjustments/InventoryAdjustmentList.js @@ -1,15 +1,12 @@ -import React, { useEffect } from 'react'; -import { useIntl } from 'react-intl'; - -import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; +import React from 'react'; +import { DashboardContentTable, DashboardPageContent } from 'components'; import InventoryAdjustmentsAlerts from './InventoryAdjustmentsAlerts'; import { InventoryAdjustmentsProvider } from './InventoryAdjustmentsProvider'; import InventoryAdjustmentTable from './InventoryAdjustmentTable'; import withInventoryAdjustments from './withInventoryAdjustments'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import { compose, transformTableStateToQuery } from 'utils'; @@ -17,25 +14,18 @@ import { compose, transformTableStateToQuery } from 'utils'; * Inventory Adjustment List. */ function InventoryAdjustmentList({ - // #withDashboardActions - changePageTitle, - // #withInventoryAdjustments inventoryAdjustmentTableState, }) { - const { formatMessage } = useIntl(); - - // Changes the dashboard title once the page mount. - useEffect(() => { - changePageTitle(formatMessage({ id: 'inventory_adjustment_list' })); - }, [changePageTitle, formatMessage]); - return ( - + + + + @@ -43,7 +33,6 @@ function InventoryAdjustmentList({ } export default compose( - withDashboardActions, withInventoryAdjustments(({ inventoryAdjustmentTableState }) => ({ inventoryAdjustmentTableState, })), diff --git a/client/src/containers/InventoryAdjustments/InventoryAdjustmentTable.js b/client/src/containers/InventoryAdjustments/InventoryAdjustmentTable.js index f195f6167..24f9416d7 100644 --- a/client/src/containers/InventoryAdjustments/InventoryAdjustmentTable.js +++ b/client/src/containers/InventoryAdjustments/InventoryAdjustmentTable.js @@ -1,9 +1,5 @@ import React, { useCallback } from 'react'; - -import classNames from 'classnames'; - import { DataTable } from 'components'; -import { CLASSES } from 'common/classes'; import { useInventoryAdjustmentsColumns, ActionsMenu } from './components'; import withAlertsActions from 'containers/Alert/withAlertActions'; @@ -57,38 +53,36 @@ function InventoryAdjustmentDataTable({ [setInventoryAdjustmentTableState], ); - return ( -
- -
+ payload={{ + onDelete: handleDeleteAdjustment, + }} + ContextMenu={ActionsMenu} + noResults={'There is no inventory adjustments transactions yet.'} + {...tableProps} + /> ); } diff --git a/client/src/containers/Items/ItemFormPage.js b/client/src/containers/Items/ItemFormPage.js index ab2098229..00d51a96e 100644 --- a/client/src/containers/Items/ItemFormPage.js +++ b/client/src/containers/Items/ItemFormPage.js @@ -1,32 +1,15 @@ -import React, { useEffect } from 'react'; +import React from 'react'; import { useParams } from 'react-router-dom'; import { ItemFormProvider } from './ItemFormProvider'; import DashboardCard from 'components/Dashboard/DashboardCard'; import ItemForm from 'containers/Items/ItemForm'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; - -import { compose } from 'utils'; - /** * Item form page. */ -function ItemFormPage({ - // #withDashboardActions - setDashboardBackLink -}) { +export default function ItemFormPage() { const { id } = useParams(); - - useEffect(() => { - // Show the back link on dashboard topbar. - setDashboardBackLink(true); - - return () => { - // Hide the back link on dashboard topbar. - setDashboardBackLink(false); - }; - }, [setDashboardBackLink]); return ( @@ -35,8 +18,4 @@ function ItemFormPage({ ); -} - -export default compose( - withDashboardActions, -)(ItemFormPage); +} \ No newline at end of file diff --git a/client/src/containers/Items/ItemsDataTable.js b/client/src/containers/Items/ItemsDataTable.js index 20177eb3e..df1a02dc3 100644 --- a/client/src/containers/Items/ItemsDataTable.js +++ b/client/src/containers/Items/ItemsDataTable.js @@ -1,5 +1,4 @@ import React from 'react'; -import classNames from 'classnames'; import { useHistory } from 'react-router-dom'; import { DataTable } from 'components'; @@ -8,7 +7,6 @@ import ItemsEmptyStatus from './ItemsEmptyStatus'; import TableSkeletonRows from 'components/Datatable/TableSkeletonRows'; import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton'; -import { CLASSES } from 'common/classes'; import withItems from 'containers/Items/withItems'; import withItemsActions from 'containers/Items/withItemsActions'; @@ -95,53 +93,51 @@ function ItemsDataTable({ openDialog('inventory-adjustment', { itemId: id }); }; - // Cannot continue in case the items has empty status. + // Display empty status instead of the table. if (isEmptyStatus) { return ; } return ( -
- -
+ ContextMenu={ItemsActionMenuList} + onFetchData={handleFetchData} + payload={{ + onDeleteItem: handleDeleteItem, + onEditItem: handleEditItem, + onInactivateItem: handleInactiveItem, + onActivateItem: handleActivateItem, + onMakeAdjustment: handleMakeAdjustment, + }} + noResults={'There is no items in the table yet.'} + {...tableProps} + /> ); } diff --git a/client/src/containers/Items/ItemsList.js b/client/src/containers/Items/ItemsList.js index 15dcdc25c..463e5265e 100644 --- a/client/src/containers/Items/ItemsList.js +++ b/client/src/containers/Items/ItemsList.js @@ -3,7 +3,7 @@ import { compose } from 'utils'; import 'style/pages/Items/List.scss'; -import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; +import { DashboardContentTable, DashboardPageContent } from 'components'; import ItemsActionsBar from './ItemsActionsBar'; import ItemsAlerts from './ItemsAlerts'; @@ -27,7 +27,10 @@ function ItemsList({ - + + + + diff --git a/client/src/containers/ItemsCategories/ItemCategoriesList.js b/client/src/containers/ItemsCategories/ItemCategoriesList.js index 8cd428810..71b5ac805 100644 --- a/client/src/containers/ItemsCategories/ItemCategoriesList.js +++ b/client/src/containers/ItemsCategories/ItemCategoriesList.js @@ -1,46 +1,25 @@ -import React, { useEffect } from 'react'; -import { useParams } from 'react-router-dom'; -import { useIntl } from 'react-intl'; - -import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; +import React from 'react'; +import { DashboardContentTable, DashboardPageContent } from 'components'; import ItemsCategoriesAlerts from './ItemsCategoriesAlerts'; import ItemsCategoryActionsBar from './ItemsCategoryActionsBar'; import { ItemsCategoriesProvider } from './ItemsCategoriesProvider'; import ItemCategoriesTable from './ItemCategoriesTable'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; -import { compose } from 'utils'; - /** * Item categories list. */ -const ItemCategoryList = ({ - // #withDashboardActions - changePageTitle, -}) => { - const { id } = useParams(); - const { formatMessage } = useIntl(); - - // Changes the dashboard page title once the page mount. - useEffect(() => { - id - ? changePageTitle(formatMessage({ id: 'edit_category_details' })) - : changePageTitle(formatMessage({ id: 'category_list' })); - }, [id, changePageTitle, formatMessage]); - +export default function ItemCategoryList() { return ( - + + + ); -}; - -export default compose( - withDashboardActions, -)(ItemCategoryList); +} diff --git a/client/src/containers/ItemsCategories/ItemCategoriesTable.js b/client/src/containers/ItemsCategories/ItemCategoriesTable.js index 3f5367e7d..2927baf75 100644 --- a/client/src/containers/ItemsCategories/ItemCategoriesTable.js +++ b/client/src/containers/ItemsCategories/ItemCategoriesTable.js @@ -24,7 +24,7 @@ function ItemsCategoryTable({ openDialog, // #withAlertActions - openAlert + openAlert, }) { // Items categories context. const { @@ -49,34 +49,27 @@ function ItemsCategoryTable({ }; return ( -
- -
+ ); } -export default compose( - withDialogActions, - withAlertActions, -)(ItemsCategoryTable); \ No newline at end of file +export default compose(withDialogActions, withAlertActions)(ItemsCategoryTable); diff --git a/client/src/containers/JournalNumber/ReferenceNumberForm.js b/client/src/containers/JournalNumber/ReferenceNumberForm.js index 0794ce2aa..0617eae12 100644 --- a/client/src/containers/JournalNumber/ReferenceNumberForm.js +++ b/client/src/containers/JournalNumber/ReferenceNumberForm.js @@ -11,11 +11,10 @@ import { InputGroup, Intent, } from '@blueprintjs/core'; -import withSettingsActions from 'containers/Settings/withSettingsActions'; - -import { compose } from 'utils'; - +/** + * Reference number form. + */ export default function ReferenceNumberForm({ onSubmit, onClose, @@ -62,6 +61,7 @@ export default function ReferenceNumberForm({ {/* prefix */} + } className={'form-group--'} diff --git a/client/src/containers/Purchases/Bills/BillForm/BillForm.js b/client/src/containers/Purchases/Bills/BillForm/BillForm.js index 2f3493ebd..21bfa842e 100644 --- a/client/src/containers/Purchases/Bills/BillForm/BillForm.js +++ b/client/src/containers/Purchases/Bills/BillForm/BillForm.js @@ -1,4 +1,4 @@ -import React, { useMemo, useCallback, useEffect } from 'react'; +import React, { useMemo } from 'react'; import { Formik, Form } from 'formik'; import moment from 'moment'; import { Intent } from '@blueprintjs/core'; @@ -13,12 +13,10 @@ import BillFormHeader from './BillFormHeader'; import BillFloatingActions from './BillFloatingActions'; import BillFormFooter from './BillFormFooter'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; - import { AppToaster } from 'components'; import { ERROR } from 'common/errors'; -import { compose, repeatValue, orderingLinesIndexes } from 'utils'; +import { repeatValue, orderingLinesIndexes } from 'utils'; import BillFormBody from './BillFormBody'; import { useBillFormContext } from './BillFormProvider'; @@ -47,10 +45,8 @@ const defaultInitialValues = { /** * Bill form. */ -function BillForm({ - //#withDashboard - changePageTitle, - changePageSubtitle, +export default function BillForm({ + }) { const { formatMessage } = useIntl(); const history = useHistory(); @@ -65,14 +61,6 @@ function BillForm({ const isNewMode = !billId; - useEffect(() => { - if (!isNewMode) { - changePageTitle(formatMessage({ id: 'edit_bill' })); - } else { - changePageTitle(formatMessage({ id: 'new_bill' })); - } - }, [changePageTitle, isNewMode, formatMessage]); - // Initial values in create and edit mode. const initialValues = useMemo( () => ({ @@ -146,8 +134,6 @@ function BillForm({ }); setSubmitting(false); - changePageSubtitle(''); - if (submitPayload.redirect) { history.push('/bills'); } @@ -167,14 +153,6 @@ function BillForm({ } }; - // Handle bill number changed once the field blur. - const handleBillNumberChanged = useCallback( - (billNumber) => { - changePageSubtitle(billNumber); - }, - [changePageSubtitle], - ); - return (
- + @@ -198,5 +176,3 @@ function BillForm({
); } - -export default compose(withDashboardActions)(BillForm); diff --git a/client/src/containers/Purchases/Bills/BillForm/BillFormBody.js b/client/src/containers/Purchases/Bills/BillForm/BillFormBody.js index cef960258..8cd05cf77 100644 --- a/client/src/containers/Purchases/Bills/BillForm/BillFormBody.js +++ b/client/src/containers/Purchases/Bills/BillForm/BillFormBody.js @@ -1,7 +1,6 @@ import React from 'react'; import classNames from 'classnames'; import { CLASSES } from 'common/classes'; -import EditableItemsEntriesTable from 'containers/Entries/EditableItemsEntriesTable'; import { useBillFormContext } from './BillFormProvider'; export default function BillFormBody({ defaultBill }) { @@ -9,11 +8,7 @@ export default function BillFormBody({ defaultBill }) { return (
- +
); } diff --git a/client/src/containers/Purchases/Bills/BillForm/BillFormHeader.js b/client/src/containers/Purchases/Bills/BillForm/BillFormHeader.js index 4bfce6343..ea8ac2aeb 100644 --- a/client/src/containers/Purchases/Bills/BillForm/BillFormHeader.js +++ b/client/src/containers/Purchases/Bills/BillForm/BillFormHeader.js @@ -14,8 +14,6 @@ import { compose } from 'redux'; * Fill form header. */ function BillFormHeader({ - onBillNumberChanged, - // #withSettings baseCurrency, }) { @@ -28,7 +26,7 @@ function BillFormHeader({ return (
- + { - // Shrink the sidebar by foce. - setSidebarShrink(); - // Show the back link on dashboard topbar. - setDashboardBackLink(true); - - return () => { - // Reset the sidebar to the previous status. - resetSidebarPreviousExpand(); - // Hide the back link on dashboard topbar. - setDashboardBackLink(false); - }; - }, [resetSidebarPreviousExpand, setSidebarShrink, setDashboardBackLink]); - return ( ); -} - -export default compose( - - withDashboardActions -)(BillFormPage); +} \ No newline at end of file diff --git a/client/src/containers/Purchases/Bills/BillsLanding/BillsList.js b/client/src/containers/Purchases/Bills/BillsLanding/BillsList.js index 6c8ea1244..3aad2bd11 100644 --- a/client/src/containers/Purchases/Bills/BillsLanding/BillsList.js +++ b/client/src/containers/Purchases/Bills/BillsLanding/BillsList.js @@ -1,7 +1,5 @@ -import React, { useEffect } from 'react'; - -import { useIntl } from 'react-intl'; -import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; +import React from 'react'; +import { DashboardContentTable, DashboardPageContent } from 'components'; import { BillsListProvider } from './BillsListProvider'; @@ -10,7 +8,6 @@ import BillsAlerts from './BillsAlerts'; import BillsViewsTabs from './BillsViewsTabs'; import BillsTable from './BillsTable'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withBills from './withBills'; import { transformTableStateToQuery, compose } from 'utils'; @@ -19,25 +16,19 @@ import { transformTableStateToQuery, compose } from 'utils'; * Bills list. */ function BillsList({ - // #withDashboardActions - changePageTitle, - // #withBills billsTableState, }) { - const { formatMessage } = useIntl(); - - useEffect(() => { - changePageTitle(formatMessage({ id: 'bills_list' })); - }, [changePageTitle, formatMessage]); - return ( - + + + + @@ -46,6 +37,5 @@ function BillsList({ } export default compose( - withDashboardActions, withBills(({ billsTableState }) => ({ billsTableState })), )(BillsList); diff --git a/client/src/containers/Purchases/Bills/BillsLanding/BillsTable.js b/client/src/containers/Purchases/Bills/BillsLanding/BillsTable.js index 9a401044b..48a4628e2 100644 --- a/client/src/containers/Purchases/Bills/BillsLanding/BillsTable.js +++ b/client/src/containers/Purchases/Bills/BillsLanding/BillsTable.js @@ -1,9 +1,7 @@ import React, { useCallback } from 'react'; -import classNames from 'classnames'; import { useHistory } from 'react-router-dom'; import { compose } from 'utils'; -import { CLASSES } from 'common/classes'; import DataTable from 'components/DataTable'; import TableSkeletonRows from 'components/Datatable/TableSkeletonRows'; @@ -25,7 +23,7 @@ function BillsDataTable({ setBillsTableState, // #withAlerts - openAlert + openAlert, }) { // Bills list context. const { @@ -72,30 +70,28 @@ function BillsDataTable({ } return ( -
- -
+ ); } diff --git a/client/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMadeList.js b/client/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMadeList.js index 3f4318ab2..e6e597d2f 100644 --- a/client/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMadeList.js +++ b/client/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMadeList.js @@ -1,14 +1,11 @@ -import React, { useEffect } from 'react'; -import { useIntl } from 'react-intl'; - -import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; +import React from 'react'; +import { DashboardContentTable, DashboardPageContent } from 'components'; import PaymentMadeActionsBar from './PaymentMadeActionsBar'; import PaymentMadesAlerts from '../PaymentMadesAlerts'; import PaymentMadesTable from './PaymentMadesTable'; import { PaymentMadesListProvider } from './PaymentMadesListProvider'; import PaymentMadeViewTabs from './PaymentMadeViewTabs'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withPaymentMades from './withPaymentMade'; import { compose, transformTableStateToQuery } from 'utils'; @@ -17,18 +14,9 @@ import { compose, transformTableStateToQuery } from 'utils'; * Payment mades list. */ function PaymentMadeList({ - // #withDashboardActions - changePageTitle, - // #withPaymentMades paymentMadesTableState, }) { - const { formatMessage } = useIntl(); - - useEffect(() => { - changePageTitle(formatMessage({ id: 'payment_made_list' })); - }, [changePageTitle, formatMessage]); - return ( - + + + + @@ -46,7 +37,6 @@ function PaymentMadeList({ } export default compose( - withDashboardActions, withPaymentMades(({ paymentMadesTableState }) => ({ paymentMadesTableState, })), diff --git a/client/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMadesTable.js b/client/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMadesTable.js index 28b8663c0..b95dbb221 100644 --- a/client/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMadesTable.js +++ b/client/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMadesTable.js @@ -23,7 +23,7 @@ function PaymentMadesTable({ addPaymentMadesTableQueries, // #withAlerts - openAlert + openAlert, }) { // Payment mades table columns. const columns = usePaymentMadesTableColumns(); @@ -42,7 +42,7 @@ function PaymentMadesTable({ // Handles the delete payment made action. const handleDeletePaymentMade = (paymentMade) => { - openAlert('payment-made-delete', { paymentMadeId: paymentMade.id }) + openAlert('payment-made-delete', { paymentMadeId: paymentMade.id }); }; // Handle datatable fetch data once the table state change. @@ -52,37 +52,36 @@ function PaymentMadesTable({ }, [addPaymentMadesTableQueries], ); - + + // Display empty status instead of the table. if (isEmptyStatus) { return ; } return ( -
- -
+ ); } diff --git a/client/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.js b/client/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.js index 4786bce3b..96e9bbd75 100644 --- a/client/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.js +++ b/client/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.js @@ -13,70 +13,55 @@ import { FormattedMessage as T } from 'react-intl'; import { CLASSES } from 'common/classes'; import classNames from 'classnames'; import { useFormikContext } from 'formik'; -import { saveInvoke } from 'utils'; import { If, Icon } from 'components'; +import { useEstimateFormContext } from './EstimateFormProvider'; /** * Estimate floating actions bar. */ -export default function EstimateFloatingActions({ - isSubmitting, - onSubmitClick, - onCancelClick, - estimate, -}) { - const { resetForm, submitForm } = useFormikContext(); +export default function EstimateFloatingActions() { + const { resetForm, submitForm, isSubmitting } = useFormikContext(); + // Estimate form context. + const { estimate, setSubmitPayload } = useEstimateFormContext(); + + // Handle submit & deliver button click. const handleSubmitDeliverBtnClick = (event) => { - saveInvoke(onSubmitClick, event, { - redirect: true, - deliver: true, - }); + setSubmitPayload({ redirect: true, deliver: true, }); }; + // Handle submit, deliver & new button click. const handleSubmitDeliverAndNewBtnClick = (event) => { + setSubmitPayload({ redirect: false, deliver: true, resetForm: true }); submitForm(); - saveInvoke(onSubmitClick, event, { - redirect: false, - deliver: true, - resetForm: true, - }); }; + // Handle submit, deliver & continue editing button click. const handleSubmitDeliverContinueEditingBtnClick = (event) => { + setSubmitPayload({ redirect: false, deliver: true }); submitForm(); - saveInvoke(onSubmitClick, event, { - redirect: false, - deliver: true, - }); }; + // Handle submit as draft button click. const handleSubmitDraftBtnClick = (event) => { - saveInvoke(onSubmitClick, event, { - redirect: true, - deliver: false, - }); + setSubmitPayload({ redirect: true, deliver: false }); + submitForm(); }; + // Handle submit as draft & new button click. const handleSubmitDraftAndNewBtnClick = (event) => { + setSubmitPayload({ redirect: false, deliver: false, resetForm: true }); submitForm(); - saveInvoke(onSubmitClick, event, { - redirect: false, - deliver: false, - resetForm: true, - }); }; + // Handle submit as draft & continue editing button click. const handleSubmitDraftContinueEditingBtnClick = (event) => { + setSubmitPayload({ redirect: false, deliver: false }); submitForm(); - saveInvoke(onSubmitClick, event, { - redirect: false, - deliver: false, - }); }; const handleCancelBtnClick = (event) => { - saveInvoke(onCancelClick, event); + }; const handleClearBtnClick = (event) => { @@ -90,6 +75,7 @@ export default function EstimateFloatingActions({