mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 22:30:31 +00:00
refactoring: migrating to react-query to manage service-side state.
This commit is contained in:
84
client/src/containers/Sales/Estimate/EstiamtesViewPage.js
Normal file
84
client/src/containers/Sales/Estimate/EstiamtesViewPage.js
Normal file
@@ -0,0 +1,84 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { Switch, Route, useHistory } from 'react-router-dom';
|
||||
|
||||
import EstimateViewTabs from './EstimateViewTabs';
|
||||
import EstimatesDataTable from './EstimatesDataTable';
|
||||
|
||||
import withAlertsActions from 'containers/Alert/withAlertActions';
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
/**
|
||||
* Estimates list view page.
|
||||
*/
|
||||
function EstimatesViewPage({
|
||||
// #withAlertActions
|
||||
openAlert,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
|
||||
// handle delete estimate click
|
||||
const handleDeleteEstimate = useCallback(
|
||||
({ id }) => {
|
||||
openAlert('estimate-delete', { estimateId: id });
|
||||
},
|
||||
[openAlert],
|
||||
);
|
||||
|
||||
// Handle cancel/confirm estimate deliver.
|
||||
const handleDeliverEstimate = useCallback(
|
||||
({ id }) => {
|
||||
openAlert('estimate-deliver', { estimateId: id });
|
||||
},
|
||||
[openAlert],
|
||||
);
|
||||
|
||||
// Handle cancel/confirm estimate approve.
|
||||
const handleApproveEstimate = useCallback(
|
||||
({ id }) => {
|
||||
openAlert('estimate-Approve', { estimateId: id });
|
||||
},
|
||||
[openAlert],
|
||||
);
|
||||
|
||||
// Handle cancel/confirm estimate reject.
|
||||
const handleRejectEstimate = useCallback(
|
||||
({ id }) => {
|
||||
openAlert('estimate-reject', { estimateId: id });
|
||||
},
|
||||
[openAlert],
|
||||
);
|
||||
|
||||
const handleEditEstimate = useCallback(
|
||||
(estimate) => {
|
||||
history.push(`/estimates/${estimate.id}/edit`);
|
||||
},
|
||||
[history],
|
||||
);
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Route
|
||||
exact={true}
|
||||
path={['/estimates/:custom_view_id/custom_view', '/estimates']}
|
||||
>
|
||||
<EstimateViewTabs />
|
||||
|
||||
{/* <EstimatesDataTable
|
||||
onDeleteEstimate={handleDeleteEstimate}
|
||||
onEditEstimate={handleEditEstimate}
|
||||
onDeliverEstimate={handleDeliverEstimate}
|
||||
onApproveEstimate={handleApproveEstimate}
|
||||
onRejectEstimate={handleRejectEstimate}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
/> */}
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withAlertsActions,
|
||||
withDialogActions,
|
||||
)(EstimatesViewPage)
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useCallback, useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import Icon from 'components/Icon';
|
||||
import {
|
||||
Button,
|
||||
@@ -11,65 +11,51 @@ import {
|
||||
Intent,
|
||||
} from '@blueprintjs/core';
|
||||
import classNames from 'classnames';
|
||||
import { useRouteMatch, useHistory } from 'react-router-dom';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
|
||||
import { If, DashboardActionViewsList } from 'components';
|
||||
import FilterDropdown from 'components/FilterDropdown';
|
||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||
|
||||
import withResourceDetail from 'containers/Resources/withResourceDetails';
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
import withEstimateActions from './withEstimateActions';
|
||||
|
||||
import withEstimates from './withEstimates';
|
||||
import { useEstimatesListContext } from './EstimatesListProvider';
|
||||
|
||||
import { compose } from 'utils';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
/**
|
||||
* Estimates list actions bar.
|
||||
*/
|
||||
function EstimateActionsBar({
|
||||
// #withResourceDetail
|
||||
resourceFields,
|
||||
|
||||
//#withEstimates
|
||||
estimateViews,
|
||||
|
||||
// #withEstimateActions
|
||||
addEstimatesTableQueries,
|
||||
changeEstimateView,
|
||||
// #own Porps
|
||||
onFilterChanged,
|
||||
selectedRows = [],
|
||||
}) {
|
||||
const { path } = useRouteMatch();
|
||||
const history = useHistory();
|
||||
const [filterCount, setFilterCount] = useState(0);
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const onClickNewEstimate = useCallback(() => {
|
||||
history.push('/estimates/new');
|
||||
}, [history]);
|
||||
const [filterCount, setFilterCount] = useState(0);
|
||||
|
||||
const hasSelectedRows = useMemo(() => selectedRows.length > 0, [
|
||||
selectedRows,
|
||||
]);
|
||||
// Estimates list context.
|
||||
const { estimatesViews } = useEstimatesListContext();
|
||||
|
||||
// Handle click a new sale estimate.
|
||||
const onClickNewEstimate = () => {
|
||||
history.push('/estimates/new');
|
||||
};
|
||||
|
||||
const handleTabChange = (viewId) => {
|
||||
changeEstimateView(viewId.id || -1);
|
||||
addEstimatesTableQueries({
|
||||
custom_view_id: viewId.id || null,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<DashboardActionsBar>
|
||||
<DashboardActionsBar>
|
||||
<NavbarGroup>
|
||||
<DashboardActionViewsList
|
||||
resourceName={'estimates'}
|
||||
views={estimateViews}
|
||||
views={estimatesViews}
|
||||
onChange={handleTabChange}
|
||||
/>
|
||||
|
||||
<NavbarDivider />
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
@@ -79,7 +65,6 @@ function EstimateActionsBar({
|
||||
/>
|
||||
<Popover
|
||||
minimal={true}
|
||||
// content={filterDropdown}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
@@ -95,7 +80,7 @@ function EstimateActionsBar({
|
||||
icon={<Icon icon={'filter-16'} iconSize={16} />}
|
||||
/>
|
||||
</Popover>
|
||||
<If condition={hasSelectedRows}>
|
||||
<If condition={false}>
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon={'trash-16'} iconSize={16} />}
|
||||
@@ -125,19 +110,6 @@ function EstimateActionsBar({
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
resourceName: 'sale_estimate',
|
||||
});
|
||||
const withEstimateActionsBar = connect(mapStateToProps);
|
||||
|
||||
export default compose(
|
||||
withEstimateActionsBar,
|
||||
withDialogActions,
|
||||
withEstimates(({ estimateViews }) => ({
|
||||
estimateViews,
|
||||
})),
|
||||
withResourceDetail(({ resourceFields }) => ({
|
||||
resourceFields,
|
||||
})),
|
||||
withEstimateActions,
|
||||
)(EstimateActionsBar);
|
||||
|
||||
@@ -27,8 +27,6 @@ import withMediaActions from 'containers/Media/withMediaActions';
|
||||
import withSettings from 'containers/Settings/withSettings';
|
||||
|
||||
import { AppToaster } from 'components';
|
||||
import Dragzone from 'components/Dragzone';
|
||||
import useMedia from 'hooks/useMedia';
|
||||
import { ERROR } from 'common/errors';
|
||||
|
||||
import {
|
||||
|
||||
@@ -1,66 +1,39 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { useHistory } from 'react-router';
|
||||
import React from 'react';
|
||||
|
||||
import { Alignment, Navbar, NavbarGroup } from '@blueprintjs/core';
|
||||
import { useParams, withRouter } from 'react-router-dom';
|
||||
import { connect } from 'react-redux';
|
||||
import { pick, debounce } from 'lodash';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { pick } from 'lodash';
|
||||
|
||||
import { DashboardViewsTabs } from 'components';
|
||||
|
||||
import withEstimates from './withEstimates';
|
||||
import withEstimateActions from './withEstimateActions';
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
import withViewDetails from 'containers/Views/withViewDetails';
|
||||
|
||||
import { useEstimatesListContext } from './EstimatesListProvider';
|
||||
import { compose } from 'utils';
|
||||
|
||||
/**
|
||||
* Estimates views tabs.
|
||||
*/
|
||||
function EstimateViewTabs({
|
||||
// #withExpenses
|
||||
estimateViews,
|
||||
|
||||
// #withViewDetails
|
||||
viewItem,
|
||||
|
||||
//#withEstimatesActions
|
||||
addEstimatesTableQueries,
|
||||
changeEstimateView,
|
||||
|
||||
// #withDashboardActions
|
||||
setTopbarEditView,
|
||||
changePageSubtitle,
|
||||
// props
|
||||
customViewChanged,
|
||||
onViewChanged,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
const { custom_view_id: customViewId = null } = useParams();
|
||||
|
||||
useEffect(() => {
|
||||
setTopbarEditView(customViewId);
|
||||
changePageSubtitle(customViewId && viewItem ? viewItem.name : '');
|
||||
}, [customViewId]);
|
||||
|
||||
const tabs = estimateViews.map((view) => ({
|
||||
// Estimates list context.
|
||||
const { estimatesViews } = useEstimatesListContext();
|
||||
|
||||
const tabs = estimatesViews.map((view) => ({
|
||||
...pick(view, ['name', 'id']),
|
||||
}));
|
||||
|
||||
const handleTabsChange = (viewId) => {
|
||||
changeEstimateView(viewId || -1);
|
||||
addEstimatesTableQueries({
|
||||
custom_view_id: viewId || null,
|
||||
});
|
||||
setTopbarEditView(viewId);
|
||||
};
|
||||
|
||||
// Handle click a new view tab.
|
||||
const handleClickNewView = () => {
|
||||
setTopbarEditView(null);
|
||||
history.push('/custom_views/estimates/new');
|
||||
};
|
||||
|
||||
return (
|
||||
<Navbar className={'navbar--dashboard-views'}>
|
||||
<NavbarGroup align={Alignment.LEFT}>
|
||||
@@ -75,19 +48,6 @@ function EstimateViewTabs({
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
viewId: ownProps.match.params.custom_view_id,
|
||||
});
|
||||
|
||||
const withEstimatesViewTabs = connect(mapStateToProps);
|
||||
|
||||
export default compose(
|
||||
withRouter,
|
||||
withEstimatesViewTabs,
|
||||
withEstimateActions,
|
||||
withDashboardActions,
|
||||
withViewDetails(),
|
||||
withEstimates(({ estimateViews }) => ({
|
||||
estimateViews,
|
||||
})),
|
||||
)(EstimateViewTabs);
|
||||
|
||||
@@ -1,170 +1,48 @@
|
||||
import React, { useEffect, useCallback, useMemo, useState } from 'react';
|
||||
import { Route, Switch, useHistory } from 'react-router-dom';
|
||||
import { useQuery, queryCache } from 'react-query';
|
||||
import { Alert, Intent } from '@blueprintjs/core';
|
||||
|
||||
import AppToaster from 'components/AppToaster';
|
||||
import React, { useEffect } from 'react';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
|
||||
import EstimatesAlerts from './EstimatesAlerts';
|
||||
import EstimatesDataTable from './EstimatesDataTable';
|
||||
import EstimateActionsBar from './EstimateActionsBar';
|
||||
import EstimateViewTabs from './EstimateViewTabs';
|
||||
import EstimatesAlerts from './EstimatesAlerts';
|
||||
import EstiamtesViewPage from './EstiamtesViewPage';
|
||||
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
import withResourceActions from 'containers/Resources/withResourcesActions';
|
||||
import withEstimates from './withEstimates';
|
||||
import withEstimateActions from 'containers/Sales/Estimate/withEstimateActions';
|
||||
import withViewsActions from 'containers/Views/withViewsActions';
|
||||
import withAlertsActions from 'containers/Alert/withAlertActions';
|
||||
|
||||
import { EstimatesListProvider } from './EstimatesListProvider';
|
||||
import { compose } from 'utils';
|
||||
|
||||
/**
|
||||
* Sale estimates list page.
|
||||
*/
|
||||
function EstimatesList({
|
||||
// #withDashboardActions
|
||||
changePageTitle,
|
||||
|
||||
// #withViewsActions
|
||||
requestFetchResourceViews,
|
||||
requestFetchResourceFields,
|
||||
|
||||
// #withEstimate
|
||||
estimatesTableQuery,
|
||||
estimateViews,
|
||||
|
||||
// #withAlertsActions.
|
||||
openAlert,
|
||||
|
||||
//#withEistimateActions
|
||||
requestFetchEstimatesTable,
|
||||
requestDeliverdEstimate,
|
||||
requestApproveEstimate,
|
||||
requestRejectEstimate,
|
||||
addEstimatesTableQueries,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
const { formatMessage } = useIntl();
|
||||
const [deliverEstimate, setDeliverEstimate] = useState(false);
|
||||
const [approveEstimate, setApproveEstimate] = useState(false);
|
||||
const [rejectEstimate, setRejectEstimate] = useState(false);
|
||||
|
||||
const [selectedRows, setSelectedRows] = useState([]);
|
||||
|
||||
const fetchResourceViews = useQuery(
|
||||
['resource-views', 'sale_estimate'],
|
||||
(key, resourceName) => requestFetchResourceViews(resourceName),
|
||||
);
|
||||
|
||||
const fetchResourceFields = useQuery(
|
||||
['resource-fields', 'sale_estimate'],
|
||||
(key, resourceName) => requestFetchResourceFields(resourceName),
|
||||
);
|
||||
|
||||
const fetchEstimate = useQuery(
|
||||
['estimates-table', estimatesTableQuery],
|
||||
(key, _query) => requestFetchEstimatesTable({ ..._query }),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
changePageTitle(formatMessage({ id: 'estimates_list' }));
|
||||
}, [changePageTitle, formatMessage]);
|
||||
|
||||
// handle delete estimate click
|
||||
const handleDeleteEstimate = useCallback(
|
||||
({ id }) => {
|
||||
openAlert('estimate-delete', { estimateId: id });
|
||||
},
|
||||
[openAlert],
|
||||
);
|
||||
|
||||
// Handle cancel/confirm estimate deliver.
|
||||
const handleDeliverEstimate = useCallback(
|
||||
({ id }) => {
|
||||
openAlert('estimate-deliver', { estimateId: id });
|
||||
},
|
||||
[openAlert],
|
||||
);
|
||||
|
||||
// Handle cancel/confirm estimate approve.
|
||||
const handleApproveEstimate = useCallback(
|
||||
({ id }) => {
|
||||
openAlert('estimate-Approve', { estimateId: id });
|
||||
},
|
||||
[openAlert],
|
||||
);
|
||||
|
||||
// Handle cancel/confirm estimate reject.
|
||||
const handleRejectEstimate = useCallback(
|
||||
({ id }) => {
|
||||
openAlert('estimate-reject', { estimateId: id });
|
||||
},
|
||||
[openAlert],
|
||||
);
|
||||
|
||||
// Handle filter change to re-fetch data-table.
|
||||
const handleFilterChanged = useCallback(() => {}, []);
|
||||
|
||||
// Calculates the selected rows
|
||||
const selectedRowsCount = useMemo(() => Object.values(selectedRows).length, [
|
||||
selectedRows,
|
||||
]);
|
||||
|
||||
const handleEditEstimate = useCallback(
|
||||
(estimate) => {
|
||||
history.push(`/estimates/${estimate.id}/edit`);
|
||||
},
|
||||
[history],
|
||||
);
|
||||
|
||||
const handleSelectedRowsChange = useCallback(
|
||||
(estimate) => {
|
||||
setSelectedRows(estimate);
|
||||
},
|
||||
[setSelectedRows],
|
||||
);
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={fetchResourceViews.isFetching || fetchResourceFields.isFetching}
|
||||
name={'sale_estimate'}
|
||||
>
|
||||
<EstimateActionsBar
|
||||
// onBulkDelete={}
|
||||
selectedRows={selectedRows}
|
||||
onFilterChanged={handleFilterChanged}
|
||||
/>
|
||||
<EstimatesListProvider query={estimatesTableQuery}>
|
||||
<EstimateActionsBar />
|
||||
|
||||
<DashboardPageContent>
|
||||
<Switch>
|
||||
<Route
|
||||
exact={true}
|
||||
path={['/estimates/:custom_view_id/custom_view', '/estimates']}
|
||||
>
|
||||
<EstimateViewTabs />
|
||||
<EstimatesDataTable
|
||||
onDeleteEstimate={handleDeleteEstimate}
|
||||
onEditEstimate={handleEditEstimate}
|
||||
onDeliverEstimate={handleDeliverEstimate}
|
||||
onApproveEstimate={handleApproveEstimate}
|
||||
onRejectEstimate={handleRejectEstimate}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
/>
|
||||
</Route>
|
||||
</Switch>
|
||||
<EstiamtesViewPage />
|
||||
<EstimatesAlerts />
|
||||
</DashboardPageContent>
|
||||
</DashboardInsider>
|
||||
</EstimatesListProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withResourceActions,
|
||||
withEstimateActions,
|
||||
withDashboardActions,
|
||||
withViewsActions,
|
||||
withEstimates(({ estimatesTableQuery, estimateViews }) => ({
|
||||
withEstimates(({ estimatesTableQuery }) => ({
|
||||
estimatesTableQuery,
|
||||
estimateViews,
|
||||
})),
|
||||
withAlertsActions,
|
||||
)(EstimatesList);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import React, { createContext } from 'react';
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import { useResourceViews, useResourceFields, useEstimates } from 'hooks/query';
|
||||
|
||||
const EstimatesListContext = createContext();
|
||||
|
||||
/**
|
||||
* Sale estimates data provider.
|
||||
*/
|
||||
function EstimatesListProvider({ query, ...props }) {
|
||||
// Fetch estimates resource views and fields.
|
||||
const { data: estimatesViews, isFetching: isViewsLoading } = useResourceViews(
|
||||
'sale_estimates',
|
||||
);
|
||||
|
||||
// Fetch the estimates resource fields.
|
||||
const {
|
||||
data: estimatesFields,
|
||||
isFetching: isFieldsLoading,
|
||||
} = useResourceFields('sale_estimates');
|
||||
|
||||
// Fetch estimates list according to the given custom view id.
|
||||
const {
|
||||
data: { estimates, pagination },
|
||||
isFetching: isEstimatesLoading,
|
||||
} = useEstimates(query);
|
||||
|
||||
// Provider payload.
|
||||
const provider = {
|
||||
estimates,
|
||||
pagination,
|
||||
estimatesFields,
|
||||
estimatesViews,
|
||||
|
||||
isEstimatesLoading,
|
||||
isFieldsLoading,
|
||||
isViewsLoading,
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={isViewsLoading || isFieldsLoading}
|
||||
name={'sale_estimate'}
|
||||
>
|
||||
<EstimatesListContext.Provider value={provider} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
|
||||
const useEstimatesListContext = () => React.useContext(EstimatesListContext);
|
||||
|
||||
export { EstimatesListProvider, useEstimatesListContext };
|
||||
Reference in New Issue
Block a user