From 0567b42e34db70b4624a0402b6cb0da591c95876 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Mon, 29 Mar 2021 19:27:09 +0200 Subject: [PATCH] feat(financial statement): purcahases by items. --- .../PurchasesByItems/PurchasesByItems.js | 88 ++++++++++++ .../PurchasesByItemsActionsBar.js | 125 ++++++++++++++++++ .../PurchasesByItemsGeneralPanel.js | 13 ++ .../PurchasesByItemsHeader.js | 99 ++++++++++++++ .../PurchasesByItemsProvider.js | 39 ++++++ .../PurchasesByItems/PurchasesByItemsTable.js | 61 +++++++++ .../PurchasesByItems/components.js | 76 +++++++++++ .../PurchasesByItems/withPurchasesByItems.js | 12 ++ .../withPurchasesByItemsActions.js | 9 ++ 9 files changed, 522 insertions(+) create mode 100644 client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItems.js create mode 100644 client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsActionsBar.js create mode 100644 client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsGeneralPanel.js create mode 100644 client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.js create mode 100644 client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsProvider.js create mode 100644 client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.js create mode 100644 client/src/containers/FinancialStatements/PurchasesByItems/components.js create mode 100644 client/src/containers/FinancialStatements/PurchasesByItems/withPurchasesByItems.js create mode 100644 client/src/containers/FinancialStatements/PurchasesByItems/withPurchasesByItemsActions.js diff --git a/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItems.js b/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItems.js new file mode 100644 index 000000000..b1fa012bf --- /dev/null +++ b/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItems.js @@ -0,0 +1,88 @@ +import React, { useEffect, useState, useCallback } from 'react'; +import moment from 'moment'; + +import 'style/pages/FinancialStatements/PurchasesByItems.scss'; + +import { PurchasesByItemsProvider } from './PurchasesByItemsProvider'; +import PurchasesByItemsActionsBar from './PurchasesByItemsActionsBar'; +import PurchasesByItemsHeader from './PurchasesByItemsHeader'; +import PurchasesByItemsTable from './PurchasesByItemsTable'; +import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; +import { PurchasesByItemsLoadingBar } from './components'; + +import withPurchasesByItemsActions from './withPurchasesByItemsActions'; +import withSettings from 'containers/Settings/withSettings'; +import { compose } from 'utils'; + +/** + * Purchases by items. + */ +function PurchasesByItems({ + // #withPreferences + organizationName, + + // #withPurchasesByItemsActions + togglePurchasesByItemsFilterDrawer, +}) { + const [filter, setFilter] = useState({ + fromDate: moment().startOf('year').format('YYYY-MM-DD'), + toDate: moment().endOf('year').format('YYYY-MM-DD'), + }); + + // Handle filter form submit. + const handleFilterSubmit = useCallback( + (filter) => { + const parsedFilter = { + ...filter, + fromDate: moment(filter.fromDate).format('YYYY-MM-DD'), + toDate: moment(filter.toDate).format('YYYY-MM-DD'), + }; + setFilter(parsedFilter); + }, + [setFilter], + ); + + // Handle number format form submit. + const handleNumberFormatSubmit = (numberFormat) => { + setFilter({ + ...filter, + numberFormat, + }); + }; + + // Hide the filter drawer once the page unmount. + useEffect( + () => () => { + togglePurchasesByItemsFilterDrawer(false); + }, + [togglePurchasesByItemsFilterDrawer], + ); + + return ( + + + + +
+ +
+
+ +
+
+
+ ); +} + +export default compose( + withPurchasesByItemsActions, + withSettings(({ organizationSettings }) => ({ + organizationName: organizationSettings.name, + })), +)(PurchasesByItems); diff --git a/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsActionsBar.js b/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsActionsBar.js new file mode 100644 index 000000000..6bbd3d542 --- /dev/null +++ b/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsActionsBar.js @@ -0,0 +1,125 @@ +import React from 'react'; +import { + NavbarGroup, + Button, + Classes, + NavbarDivider, + Popover, + PopoverInteractionKind, + Position, +} from '@blueprintjs/core'; +import classNames from 'classnames'; +import { FormattedMessage as T } from 'react-intl'; + +import { Icon } from 'components'; +import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; +import NumberFormatDropdown from 'components/NumberFormatDropdown'; + +import withPurchasesByItems from './withPurchasesByItems'; +import withPurchasesByItemsActions from './withPurchasesByItemsActions'; +import { compose, saveInvoke } from 'utils'; +import { usePurchaseByItemsContext } from './PurchasesByItemsProvider'; + +function PurchasesByItemsActionsBar({ + // #withPurchasesByItems + purchasesByItemsDrawerFilter, + + // #withPurchasesByItemsActions + togglePurchasesByItemsFilterDrawer, + + // #ownProps + numberFormat, + onNumberFormatSubmit, +}) { + const { refetchSheet, isLoading } = usePurchaseByItemsContext(); + + // Handle re-calc button click. + const handleRecalculateReport = () => { + refetchSheet(); + }; + + // Handle filter toggle click. + const handleFilterToggleClick = () => { + togglePurchasesByItemsFilterDrawer(); + }; + + // Handle number format submit. + const handleNumberFormatSubmit = (values) => { + saveInvoke(onNumberFormatSubmit, values); + }; + + return ( + + + + + + + + + ); +} + +export default compose( + withPurchasesByItems(({ purchasesByItemsDrawerFilter }) => ({ + purchasesByItemsDrawerFilter, + })), + withPurchasesByItemsActions, +)(PurchasesByItemsHeader); diff --git a/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsProvider.js b/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsProvider.js new file mode 100644 index 000000000..9de8c6c47 --- /dev/null +++ b/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsProvider.js @@ -0,0 +1,39 @@ +import React, { createContext, useContext } from 'react'; +import FinancialReportPage from '../FinancialReportPage'; +import { usePurchasesByItems } from 'hooks/query'; +import { transformFilterFormToQuery } from '../common'; + + +const PurchasesByItemsContext = createContext(); + +function PurchasesByItemsProvider({ query, ...props }) { + const { + data: purchaseByItems, + isFetching, + isLoading, + refetch, + } = usePurchasesByItems( + { + ...transformFilterFormToQuery(query), + }, + { + keepPreviousData: true, + }, + ); + + const provider = { + purchaseByItems, + isFetching, + isLoading, + refetchSheet: refetch, + }; + return ( + + + + ); +} + +const usePurchaseByItemsContext = () => useContext(PurchasesByItemsContext); + +export { PurchasesByItemsProvider, usePurchaseByItemsContext }; diff --git a/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.js b/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.js new file mode 100644 index 000000000..140bd28ae --- /dev/null +++ b/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.js @@ -0,0 +1,61 @@ +import React from 'react'; +import { useIntl } from 'react-intl'; + +import FinancialSheet from 'components/FinancialSheet'; +import { DataTable } from 'components'; + +import { usePurchaseByItemsContext } from './PurchasesByItemsProvider'; + +import { usePurchasesByItemsTableColumns } from './components'; + +/** + * purchases by items data table. + */ +export default function PurchasesByItemsTable({ companyName }) { + const { formatMessage } = useIntl(); + + // Purchases by items context. + const { + purchaseByItems: { tableRows, query }, + isLoading, + } = usePurchaseByItemsContext(); + + // Purchases by items table columns. + const columns = usePurchasesByItemsTableColumns(); + + const rowClassNames = (row) => { + const { original } = row; + const rowTypes = Array.isArray(original.rowType) + ? original.rowType + : [original.rowType]; + + return { + ...rowTypes.reduce((acc, rowType) => { + acc[`row_type--${rowType}`] = rowType; + return acc; + }, {}), + }; + }; + + return ( + + + + ); +} diff --git a/client/src/containers/FinancialStatements/PurchasesByItems/components.js b/client/src/containers/FinancialStatements/PurchasesByItems/components.js new file mode 100644 index 000000000..16b23c203 --- /dev/null +++ b/client/src/containers/FinancialStatements/PurchasesByItems/components.js @@ -0,0 +1,76 @@ +import React from 'react'; +import { useIntl } from 'react-intl'; +import { Button } from '@blueprintjs/core'; +import { getColumnWidth } from 'utils'; +import { If, Icon } from 'components'; +import { CellTextSpan } from 'components/Datatable/Cells'; +import { usePurchaseByItemsContext } from './PurchasesByItemsProvider'; +import FinancialLoadingBar from '../FinancialLoadingBar'; + +/** + * Retrieve purchases by items table columns. + */ +export const usePurchasesByItemsTableColumns = () => { + const { formatMessage } = useIntl(); + + // purchases by items context. + const { + purchaseByItems: { tableRows }, + } = usePurchaseByItemsContext(); + + return React.useMemo( + () => [ + { + Header: formatMessage({ id: 'item_name' }), + accessor: (row) => (row.code ? `${row.name} - ${row.code}` : row.name), + className: 'name', + width: 180, + textOverview: true, + }, + { + Header: formatMessage({ id: 'quantity_purchased' }), + accessor: 'quantity_purchased_formatted', + Cell: CellTextSpan, + className: 'quantity_purchased_formatted', + width: getColumnWidth(tableRows, `quantity_purchased_formatted`, { + minWidth: 150, + }), + textOverview: true, + }, + { + Header: formatMessage({ id: 'purchase_amount' }), + accessor: 'purchase_cost_formatted', + Cell: CellTextSpan, + className: 'purchase_cost_formatted', + width: getColumnWidth(tableRows, `purchase_cost_formatted`, { + minWidth: 150, + }), + textOverview: true, + }, + { + Header: formatMessage({ id: 'average_price' }), + accessor: 'average_cost_price_formatted', + Cell: CellTextSpan, + className: 'average_cost_price_formatted', + width: getColumnWidth(tableRows, `average_cost_price_formatted`, { + minWidth: 180, + }), + textOverview: true, + }, + ], + [tableRows,formatMessage], + ); +}; + +/** + * Purchases by items progress loading bar. + */ +export function PurchasesByItemsLoadingBar() { + const { isFetching } = usePurchaseByItemsContext(); + + return ( + + + + ); +} diff --git a/client/src/containers/FinancialStatements/PurchasesByItems/withPurchasesByItems.js b/client/src/containers/FinancialStatements/PurchasesByItems/withPurchasesByItems.js new file mode 100644 index 000000000..1eaf2b3fe --- /dev/null +++ b/client/src/containers/FinancialStatements/PurchasesByItems/withPurchasesByItems.js @@ -0,0 +1,12 @@ +import { connect } from 'react-redux'; +import { getPurchasesByItemsFilterDrawer } from 'store/financialStatement/financialStatements.selectors'; + +export default (mapState) => { + const mapStateToProps = (state, props) => { + const mapped = { + purchasesByItemsDrawerFilter: getPurchasesByItemsFilterDrawer(state), + }; + return mapState ? mapState(mapped, state, props) : mapped; + }; + return connect(mapStateToProps); +}; diff --git a/client/src/containers/FinancialStatements/PurchasesByItems/withPurchasesByItemsActions.js b/client/src/containers/FinancialStatements/PurchasesByItems/withPurchasesByItemsActions.js new file mode 100644 index 000000000..63744c190 --- /dev/null +++ b/client/src/containers/FinancialStatements/PurchasesByItems/withPurchasesByItemsActions.js @@ -0,0 +1,9 @@ +import { connect } from 'react-redux'; +import { togglePurchasesByItemsFilterDrawer } from 'store/financialStatement/financialStatements.actions'; + +export const mapDispatchToProps = (dispatch) => ({ + togglePurchasesByItemsFilterDrawer: (toggle) => + dispatch(togglePurchasesByItemsFilterDrawer(toggle)), +}); + +export default connect(null, mapDispatchToProps);