diff --git a/packages/webapp/src/components/Contacts/ContactsMultiSelect.tsx b/packages/webapp/src/components/Contacts/ContactsMultiSelect.tsx index 2eb3536a4..02de5b22d 100644 --- a/packages/webapp/src/components/Contacts/ContactsMultiSelect.tsx +++ b/packages/webapp/src/components/Contacts/ContactsMultiSelect.tsx @@ -1,43 +1,78 @@ // @ts-nocheck import React, { useCallback } from 'react'; -import { MenuItem } from '@blueprintjs/core'; -import { MultiSelect } from '../MultiSelectTaggable'; +import * as R from 'ramda'; +import { FMultiSelect } from '../Forms'; +import withDrawerActions from '@/containers/Drawer/withDrawerActions'; +import { DRAWERS } from '@/constants/drawers'; /** * Contacts multi-select component. */ -export function ContactsMultiSelect({ ...multiSelectProps }) { - // Filters accounts items. - const filterContactsPredicater = useCallback( - (query, contact, _index, exactMatch) => { - const normalizedTitle = contact.display_name.toLowerCase(); - const normalizedQuery = query.toLowerCase(); - - if (exactMatch) { - return normalizedTitle === normalizedQuery; - } else { - return normalizedTitle.indexOf(normalizedQuery) >= 0; - } - }, - [], - ); +export function ContactsMultiSelect({ allowCreate, ...multiSelectProps }) { + // Maybe inject new item props to select component. + const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null; + const maybeCreateNewItemFromQuery = allowCreate + ? createNewItemFromQuery + : null; return ( - ( - - )} + item.display_name} + createNewItemRenderer={maybeCreateNewItemRenderer} + createNewItemFromQuery={maybeCreateNewItemFromQuery} {...multiSelectProps} /> ); } + +/** + * Customers multi-select component. + */ +function CustomersMultiSelectRoot({ + // #withDrawerAction + openDrawer, + closeDrawer, + ...props +}) { + const handleCreateItemClick = () => { + openDrawer(DRAWERS.QUICK_CREATE_CUSTOMER); + }; + return ( + + ); +} + +/** + * Vendors multi-select component. + */ +function VendorsMultiSelectRoot({ + // #withDrawerAction + openDrawer, + closeDrawer, + ...props +}) { + const handleCreateItemClick = () => { + openDrawer(DRAWERS.QUICK_WRITE_VENDOR); + }; + return ( + + ); +} + +export const CustomersMultiSelect = R.compose(withDrawerActions)( + CustomersMultiSelectRoot, +); + +export const VendorsMultiSelect = R.compose(withDrawerActions)( + VendorsMultiSelectRoot, +); diff --git a/packages/webapp/src/components/Items/ItemsMultiSelect.tsx b/packages/webapp/src/components/Items/ItemsMultiSelect.tsx index 31c2a18cb..aed937376 100644 --- a/packages/webapp/src/components/Items/ItemsMultiSelect.tsx +++ b/packages/webapp/src/components/Items/ItemsMultiSelect.tsx @@ -1,49 +1,48 @@ // @ts-nocheck -import React, { useCallback } from 'react'; -import { MenuItem } from '@blueprintjs/core'; -import { MultiSelect } from '@/components'; +import React from 'react'; +import * as R from 'ramda'; +import { FMultiSelect } from '@/components/Forms'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; /** * Items multi-select. */ -export function ItemsMultiSelect({ ...multiSelectProps }) { - // Filters accounts items. - const filterItemsPredicater = useCallback( - (query, item, _index, exactMatch) => { - const normalizedTitle = item.name.toLowerCase(); - const normalizedQuery = query.toLowerCase(); +function ItemsMultiSelectRoot({ + // #withDialogAction + openDialog, + closeDialog, - if (exactMatch) { - return normalizedTitle === normalizedQuery; - } else { - return `${normalizedTitle} ${item.code}`.indexOf(normalizedQuery) >= 0; - } - }, - [], - ); + // #props + allowCreate, + ...multiSelectProps +}) { + // Maybe inject new item props to select component. + const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null; + const maybeCreateNewItemFromQuery = allowCreate + ? createNewItemFromQuery + : null; + + // Handles the create item click. + const handleCreateItemClick = () => { + openDialog(DialogsName.AccountForm); + }; return ( - ( - - )} - popoverProps={{ minimal: true, usePortal: false, targetTagName: 'div ' }} + item.name} + popoverProps={{ minimal: true }} resetOnSelect={true} + createNewItemRenderer={maybeCreateNewItemRenderer} + createNewItemFromQuery={maybeCreateNewItemFromQuery} + onCreateItemSelect={handleCreateItemClick} {...multiSelectProps} /> ); } -ItemsMultiSelect.defaultProps = { - initialSelectedItems: [], -}; +export const ItemsMultiSelect = + R.compose(withDialogActions)(ItemsMultiSelectRoot); diff --git a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummary.tsx b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummary.tsx index 123b6c418..0e16bac3e 100644 --- a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummary.tsx +++ b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummary.tsx @@ -1,8 +1,8 @@ // @ts-nocheck -import React, { useState, useCallback, useEffect } from 'react'; +import React, { useCallback, useEffect } from 'react'; import moment from 'moment'; -import { getDefaultAPAgingSummaryQuery } from './common'; +import { useAPAgingSummaryQuery } from './common'; import { FinancialStatement, DashboardPageContent } from '@/components'; import APAgingSummaryHeader from './APAgingSummaryHeader'; @@ -26,25 +26,22 @@ function APAgingSummary({ // #withAPAgingSummaryActions toggleAPAgingSummaryFilterDrawer: toggleDisplayFilterDrawer, }) { - const [filter, setFilter] = useState({ - ...getDefaultAPAgingSummaryQuery(), - }); + const { query, setLocationQuery } = useAPAgingSummaryQuery(); // Handle filter submit. - const handleFilterSubmit = useCallback((filter) => { - const _filter = { - ...filter, - asDate: moment(filter.asDate).format('YYYY-MM-DD'), - }; - setFilter(_filter); - }, []); - + const handleFilterSubmit = useCallback( + (filter) => { + const _filter = { + ...filter, + asDate: moment(filter.asDate).format('YYYY-MM-DD'), + }; + setLocationQuery(_filter); + }, + [setLocationQuery], + ); // Handle number format submit. const handleNumberFormatSubmit = (numberFormat) => { - setFilter({ - ...filter, - numberFormat, - }); + setLocationQuery({ ...filter, numberFormat }); }; // Hide the report filter drawer once the page unmount. useEffect( @@ -55,9 +52,9 @@ function APAgingSummary({ ); return ( - + @@ -65,7 +62,7 @@ function APAgingSummary({ diff --git a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeader.tsx b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeader.tsx index 1eeecb772..f935a39ee 100644 --- a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeader.tsx @@ -1,7 +1,5 @@ // @ts-nocheck import React from 'react'; -import moment from 'moment'; -import * as Yup from 'yup'; import styled from 'styled-components'; import { FormattedMessage as T } from '@/components'; import { Formik, Form } from 'formik'; @@ -17,6 +15,10 @@ import withAPAgingSummaryActions from './withAPAgingSummaryActions'; import { transformToForm, compose } from '@/utils'; import { useFeatureCan } from '@/hooks/state'; import { Features } from '@/constants'; +import { + getAPAgingSummaryQuerySchema, + getDefaultAPAgingSummaryQuery, +} from './common'; /** * AP Aging Summary Report - Drawer Header. @@ -33,39 +35,22 @@ function APAgingSummaryHeader({ isFilterDrawerOpen, }) { // Validation schema. - const validationSchema = Yup.object({ - asDate: Yup.date().required().label('asDate'), - agingDaysBefore: Yup.number() - .required() - .integer() - .positive() - .label('agingBeforeDays'), - agingPeriods: Yup.number() - .required() - .integer() - .positive() - .label('agingPeriods'), - }); + const validationSchema = getAPAgingSummaryQuerySchema(); // Initial values. - const defaultValues = { - asDate: moment(pageFilter.asDate).toDate(), - agingDaysBefore: 30, - agingPeriods: 3, - vendorsIds: [], - branchesIds: [], - filterByOption: 'without-zero-balance', - }; - // Formik initial values. - const initialValues = transformToForm({ ...pageFilter }, defaultValues); + const defaultValues = getDefaultAPAgingSummaryQuery(); + // Formik initial values. + const initialValues = transformToForm( + { ...defaultValues, ...pageFilter }, + defaultValues, + ); // Handle form submit. const handleSubmit = (values, { setSubmitting }) => { onSubmitFilter(values); toggleFilterDrawerDisplay(false); setSubmitting(false); }; - // Handle cancel button click. const handleCancelClick = () => { toggleFilterDrawerDisplay(false); @@ -74,9 +59,8 @@ function APAgingSummaryHeader({ const handleDrawerClose = () => { toggleFilterDrawerDisplay(false); }; - // Detarmines the feature whether is enabled. + // Detarmines whether the feature is enabled. const { featureCan } = useFeatureCan(); - const isBranchesFeatureCan = featureCan(Features.Branches); return ( diff --git a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeaderGeneralContent.tsx b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeaderGeneralContent.tsx index d1fd8de43..c079f39df 100644 --- a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeaderGeneralContent.tsx +++ b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeaderGeneralContent.tsx @@ -1,21 +1,15 @@ // @ts-nocheck import React from 'react'; -import { FastField, Field } from 'formik'; +import { FastField } from 'formik'; +import { Intent, FormGroup, InputGroup, Position } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; -import { - Intent, - FormGroup, - InputGroup, - Position, - Classes, -} from '@blueprintjs/core'; -import classNames from 'classnames'; import { FormattedMessage as T, - ContactsMultiSelect, Row, Col, FieldHint, + FFormGroup, + VendorsMultiSelect, } from '@/components'; import { useAPAgingSummaryGeneralContext } from './APAgingSummaryGeneralProvider'; import FinancialStatementsFilter from '../FinancialStatementsFilter'; @@ -104,22 +98,9 @@ export default function APAgingSummaryHeaderGeneralContent() { - - {({ form: { setFieldValue }, field: { value } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const vendorsIds = vendors.map((customer) => customer.id); - setFieldValue('vendorsIds', vendorsIds); - }} - /> - - )} - + } name={'vendorsIds'}> + + diff --git a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/common.tsx b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/common.tsx index 4bb594970..87ed03627 100644 --- a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/common.tsx +++ b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/common.tsx @@ -1,18 +1,80 @@ // @ts-nocheck import moment from 'moment'; -import { transformToCamelCase, flatObject } from '@/utils'; +import * as Yup from 'yup'; +import { transformToCamelCase, flatObject, transformToForm } from '@/utils'; +import { useAppQueryString } from '@/hooks'; +import { useMemo } from 'react'; +import { castArray } from 'lodash'; export const transformFilterFormToQuery = (form) => { return flatObject(transformToCamelCase(form)); }; +/** + * The default query of AP aging summary. + * @returns + */ export const getDefaultAPAgingSummaryQuery = () => { return { asDate: moment().endOf('day').format('YYYY-MM-DD'), agingDaysBefore: 30, agingPeriods: 3, + filterByOption: 'without-zero-balance', vendorsIds: [], branchesIds: [], - filterByOption: 'without-zero-balance', - } -} \ No newline at end of file + }; +}; + +/** + * Retrieves the query validation schema. + * @returns {Yup} + */ +export const getAPAgingSummaryQuerySchema = () => { + return Yup.object({ + asDate: Yup.date().required().label('asDate'), + agingDaysBefore: Yup.number() + .required() + .integer() + .positive() + .label('agingBeforeDays'), + agingPeriods: Yup.number() + .required() + .integer() + .positive() + .label('agingPeriods'), + }); +}; + +/** + * Parses the AP aging summary query state. + * @param locationQuery + * @returns + */ +const parseAPAgingSummaryQuery = (locationQuery) => { + const defaultQuery = getDefaultAPAgingSummaryQuery(); + + const transformed = { + ...defaultQuery, + ...transformToForm(locationQuery, defaultQuery), + }; + return { + ...transformed, + vendorsIds: castArray(transformed.vendorsIds), + branchesIds: castArray(transformed.branchesIds), + }; +}; + +/** + * AP aging summary query state. + */ +export const useAPAgingSummaryQuery = () => { + // Retrieves location query. + const [locationQuery, setLocationQuery] = useAppQueryString(); + + // Merges the default filter query with location URL query. + const query = useMemo( + () => parseAPAgingSummaryQuery(locationQuery), + [locationQuery], + ); + return { query, locationQuery, setLocationQuery }; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.tsx b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.tsx index 99456ae26..2ff0550bb 100644 --- a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.tsx +++ b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.tsx @@ -2,7 +2,6 @@ import React, { useState, useCallback, useEffect } from 'react'; import moment from 'moment'; - import ARAgingSummaryHeader from './ARAgingSummaryHeader'; import ARAgingSummaryActionsBar from './ARAgingSummaryActionsBar'; @@ -13,7 +12,7 @@ import { ARAgingSummaryBody } from './ARAgingSummaryBody'; import withARAgingSummaryActions from './withARAgingSummaryActions'; -import { getDefaultARAgingSummaryQuery } from './common'; +import { useARAgingSummaryQuery } from './common'; import { compose } from '@/utils'; /** @@ -23,9 +22,7 @@ function ReceivableAgingSummarySheet({ // #withARAgingSummaryActions toggleARAgingSummaryFilterDrawer: toggleDisplayFilterDrawer, }) { - const [filter, setFilter] = useState({ - ...getDefaultARAgingSummaryQuery(), - }); + const { query, setLocationQuery } = useARAgingSummaryQuery(); // Handle filter submit. const handleFilterSubmit = useCallback((filter) => { @@ -33,25 +30,23 @@ function ReceivableAgingSummarySheet({ ...filter, asDate: moment(filter.asDate).format('YYYY-MM-DD'), }; - setFilter(_filter); - }, []); + setLocationQuery(_filter); + }, [setLocationQuery]); // Handle number format submit. const handleNumberFormatSubmit = (numberFormat) => { - setFilter({ ...filter, numberFormat }); + setLocationQuery({ ...query, numberFormat }); }; // Hide the filter drawer once the page unmount. useEffect( - () => () => { - toggleDisplayFilterDrawer(false); - }, + () => () => toggleDisplayFilterDrawer(false), [toggleDisplayFilterDrawer], ); return ( - + @@ -59,7 +54,7 @@ function ReceivableAgingSummarySheet({ diff --git a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeader.tsx b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeader.tsx index 5e0c8e471..2dcb33c32 100644 --- a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeader.tsx @@ -2,7 +2,6 @@ import React from 'react'; import styled from 'styled-components'; import moment from 'moment'; -import * as Yup from 'yup'; import { FormattedMessage as T } from '@/components'; import { Formik, Form } from 'formik'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; @@ -17,6 +16,10 @@ import withARAgingSummaryActions from './withARAgingSummaryActions'; import { compose, transformToForm } from '@/utils'; import { useFeatureCan } from '@/hooks/state'; import { Features } from '@/constants'; +import { + getARAgingSummaryQuerySchema, + getDefaultARAgingSummaryQuery, +} from './common'; /** * AR Aging Summary Report - Drawer Header. @@ -33,32 +36,15 @@ function ARAgingSummaryHeader({ isFilterDrawerOpen, }) { // Validation schema. - const validationSchema = Yup.object().shape({ - asDate: Yup.date().required().label('asDate'), - agingDaysBefore: Yup.number() - .required() - .integer() - .positive() - .label('agingDaysBefore'), - agingPeriods: Yup.number() - .required() - .integer() - .positive() - .label('agingPeriods'), - }); + const validationSchema = getARAgingSummaryQuerySchema(); + // Initial values. - const defaultValues = { - asDate: moment().toDate(), - agingDaysBefore: 30, - agingPeriods: 3, - customersIds: [], - branchesIds: [], - filterByOption: 'without-zero-balance', - }; + const defaultValues = getDefaultARAgingSummaryQuery(); // Initial values. const initialValues = transformToForm( { + ...defaultValues, ...pageFilter, asDate: moment(pageFilter.asDate).toDate(), }, @@ -80,7 +66,6 @@ function ARAgingSummaryHeader({ }; // Detarmines the feature whether is enabled. const { featureCan } = useFeatureCan(); - const isBranchesFeatureCan = featureCan(Features.Branches); return ( diff --git a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneralContent.tsx b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneralContent.tsx index 64dc309fe..9d7ded2dc 100644 --- a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneralContent.tsx +++ b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneralContent.tsx @@ -2,22 +2,16 @@ import React from 'react'; import { FastField, Field } from 'formik'; import { DateInput } from '@blueprintjs/datetime'; -import { - Intent, - FormGroup, - InputGroup, - Position, - Classes, -} from '@blueprintjs/core'; -import classNames from 'classnames'; - +import { Intent, FormGroup, InputGroup, Position } from '@blueprintjs/core'; import FinancialStatementsFilter from '../FinancialStatementsFilter'; import { FormattedMessage as T, - ContactsMultiSelect, Row, Col, FieldHint, + FInputGroup, + FFormGroup, + CustomersMultiSelect, } from '@/components'; import { momentFormatter } from '@/utils'; import { useARAgingSummaryGeneralContext } from './ARAgingSummaryGeneralProvider'; @@ -81,22 +75,13 @@ export default function ARAgingSummaryHeaderGeneralContent() { - - {({ field, meta: { error, touched } }) => ( - } - labelInfo={} - className={'form-group--aging-periods'} - intent={error && Intent.DANGER} - > - - - )} - + } + labelInfo={} + > + + @@ -111,24 +96,12 @@ export default function ARAgingSummaryHeaderGeneralContent() { - - {({ form: { setFieldValue }, field: { value } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const customersIds = customers.map( - (customer) => customer.id, - ); - setFieldValue('customersIds', customersIds); - }} - /> - - )} - + } + > + + diff --git a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/common.tsx b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/common.tsx index 8684c277f..e70c6efb3 100644 --- a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/common.tsx +++ b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/common.tsx @@ -1,6 +1,10 @@ // @ts-nocheck import moment from 'moment'; -import { transformToCamelCase, flatObject } from '@/utils'; +import * as Yup from 'yup'; +import { transformToCamelCase, flatObject, transformToForm } from '@/utils'; +import { useAppQueryString } from '@/hooks'; +import { useMemo } from 'react'; +import { castArray } from 'lodash'; export const transfromFilterFormToQuery = (form) => { return flatObject(transformToCamelCase(form)); @@ -14,8 +18,57 @@ export const getDefaultARAgingSummaryQuery = () => { asDate: moment().endOf('day').format('YYYY-MM-DD'), agingDaysBefore: 30, agingPeriods: 3, - customersIds: [], filterByOption: 'without-zero-balance', + customersIds: [], branchesIds: [], }; }; + +/** + * Retrieves the AR aging summary query schema. + * @returns {Yup} + */ +export const getARAgingSummaryQuerySchema = () => { + return Yup.object().shape({ + asDate: Yup.date().required().label('asDate'), + agingDaysBefore: Yup.number() + .required() + .integer() + .positive() + .label('agingDaysBefore'), + agingPeriods: Yup.number() + .required() + .integer() + .positive() + .label('agingPeriods'), + }); +}; + +/** + * Parses the AR aging summary state. + */ +const parseARAgingSummaryQuery = (locationQuery) => { + const defaultQuery = getDefaultARAgingSummaryQuery(); + const transformed = { + ...defaultQuery, + ...transformToForm(locationQuery, defaultQuery), + }; + return { + ...transformed, + branchesIds: castArray(transformed.branchesIds), + customersIds: castArray(transformed.customersIds), + }; +}; + +/** + * AR aging summary query state. + */ +export const useARAgingSummaryQuery = () => { + const [locationQuery, setLocationQuery] = useAppQueryString(); + + const query = useMemo( + () => parseARAgingSummaryQuery(locationQuery), + [locationQuery], + ); + return { query, locationQuery, setLocationQuery }; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/BalanceSheet/BalanceSheetHeader.tsx b/packages/webapp/src/containers/FinancialStatements/BalanceSheet/BalanceSheetHeader.tsx index f90c9d980..310a3c059 100644 --- a/packages/webapp/src/containers/FinancialStatements/BalanceSheet/BalanceSheetHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/BalanceSheet/BalanceSheetHeader.tsx @@ -68,7 +68,6 @@ function BalanceSheetHeader({ }; // Detarmines the given feature whether is enabled. const { featureCan } = useFeatureCan(); - const isBranchesFeatureCan = featureCan(Features.Branches); return ( diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummary.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummary.tsx index ab4fa5b54..84d93e75d 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummary.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummary.tsx @@ -1,5 +1,5 @@ // @ts-nocheck -import React, { useEffect, useState } from 'react'; +import React, { useEffect } from 'react'; import moment from 'moment'; import * as R from 'ramda'; @@ -10,11 +10,10 @@ import CustomersBalanceSummaryHeader from './CustomersBalanceSummaryHeader'; import { CustomerBalanceSummaryBody } from './CustomerBalanceSummaryBody'; import { CustomersBalanceSummaryProvider } from './CustomersBalanceSummaryProvider'; -import { getDefaultCustomersBalanceQuery } from './utils'; +import { useCustomerBalanceSummaryQuery } from './utils'; import { CustomersBalanceLoadingBar } from './components'; import withCustomersBalanceSummaryActions from './withCustomersBalanceSummaryActions'; - /** * Customers Balance summary. */ @@ -22,36 +21,33 @@ function CustomersBalanceSummary({ // #withCustomersBalanceSummaryActions toggleCustomerBalanceFilterDrawer, }) { - const [filter, setFilter] = useState({ - ...getDefaultCustomersBalanceQuery(), - }); + const { query, setLocationQuery } = useCustomerBalanceSummaryQuery(); + // Handle re-fetch customers balance summary after filter change. const handleFilterSubmit = (filter) => { const _filter = { ...filter, asDate: moment(filter.asDate).format('YYYY-MM-DD'), }; - setFilter({ ..._filter }); + setLocationQuery({ ..._filter }); }; // Handle number format. const handleNumberFormat = (values) => { - setFilter({ + setLocationQuery({ ...filter, numberFormat: values, }); }; useEffect( - () => () => { - toggleCustomerBalanceFilterDrawer(false); - }, + () => () => toggleCustomerBalanceFilterDrawer(false), [toggleCustomerBalanceFilterDrawer], ); return ( - + @@ -59,7 +55,7 @@ function CustomersBalanceSummary({ diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryGeneralPanelContent.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryGeneralPanelContent.tsx index fbd81fa24..227929af3 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryGeneralPanelContent.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryGeneralPanelContent.tsx @@ -1,17 +1,16 @@ // @ts-nocheck import React from 'react'; -import { FastField, Field } from 'formik'; +import { FastField } from 'formik'; import { DateInput } from '@blueprintjs/datetime'; -import { Classes, FormGroup, Position, Checkbox } from '@blueprintjs/core'; +import { FormGroup, Position, Checkbox } from '@blueprintjs/core'; import { - ContactsMultiSelect, FormattedMessage as T, Row, Col, FieldHint, + CustomersMultiSelect, + FFormGroup, } from '@/components'; -import classNames from 'classnames'; - import { momentFormatter, tansformDateValue, @@ -86,26 +85,12 @@ export default function CustomersBalanceSummaryGeneralPanelContent() { - - {({ - form: { setFieldValue }, - field: { value }, - meta: { error, touched }, - }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const customersIds = contacts.map((contact) => contact.id); - setFieldValue('customersIds', customersIds); - }} - /> - - )} - + } + > + + diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryHeader.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryHeader.tsx index 131668761..2ceaf1c1d 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryHeader.tsx @@ -1,6 +1,6 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; + import styled from 'styled-components'; import moment from 'moment'; import { Formik, Form } from 'formik'; @@ -13,6 +13,7 @@ import withCustomersBalanceSummaryActions from './withCustomersBalanceSummaryAct import CustomersBalanceSummaryGeneralPanel from './CustomersBalanceSummaryGeneralPanel'; import { compose, transformToForm } from '@/utils'; +import { getCustomersBalanceQuerySchema } from './utils'; /** * Customers balance summary. @@ -29,9 +30,8 @@ function CustomersBalanceSummaryHeader({ toggleCustomerBalanceFilterDrawer, }) { // validation schema. - const validationSchema = Yup.object().shape({ - asDate: Yup.date().required().label('asDate'), - }); + const validationSchema = getCustomersBalanceQuerySchema(); + // Default form values. const defaultValues = { ...pageFilter, diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/utils.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/utils.tsx index 61d3d29f2..5335a7d82 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/utils.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/utils.tsx @@ -1,9 +1,58 @@ // @ts-nocheck +import { useMemo } from 'react'; +import { castArray } from 'lodash'; import moment from 'moment'; +import * as Yup from 'yup'; +import { useAppQueryString } from '@/hooks'; +import { getDefaultARAgingSummaryQuery } from '../ARAgingSummary/common'; +import { transformToForm } from '@/utils'; +/** + * Default query of customers balance summary. + */ export const getDefaultCustomersBalanceQuery = () => { return { asDate: moment().endOf('day').format('YYYY-MM-DD'), filterByOption: 'with-transactions', + customersIds: [], }; }; + +/** + * Retrieves the customers balance query schema. + * @returns {Yup} + */ +export const getCustomersBalanceQuerySchema = () => { + return Yup.object().shape({ + asDate: Yup.date().required().label('asDate'), + }); +}; + +/** + * Parses the customer balance summary query. + */ +const parseCustomersBalanceSummaryQuery = (locationQuery) => { + const defaultQuery = getDefaultARAgingSummaryQuery(); + + const transformed = { + ...defaultQuery, + ...transformToForm(locationQuery, defaultQuery), + }; + return { + ...transformed, + customersIds: castArray(transformed.customersIds), + }; +}; + +/** + * Getter/setter query state of customers balance summary. + */ +export const useCustomerBalanceSummaryQuery = () => { + const [locationQuery, setLocationQuery] = useAppQueryString(); + + const query = useMemo( + () => parseCustomersBalanceSummaryQuery(locationQuery), + [locationQuery], + ); + return { query, locationQuery, setLocationQuery }; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeader.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeader.tsx index a96527b4f..3f9104d73 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeader.tsx @@ -1,7 +1,5 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; -import intl from 'react-intl-universal'; import moment from 'moment'; import styled from 'styled-components'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; @@ -15,6 +13,10 @@ import withCustomersTransactions from './withCustomersTransactions'; import withCustomersTransactionsActions from './withCustomersTransactionsActions'; import { compose, transformToForm } from '@/utils'; +import { + getCustomersTransactionsDefaultQuery, + getCustomersTransactionsQuerySchema, +} from './_utils'; /** * Customers transactions header. @@ -31,12 +33,8 @@ function CustomersTransactionsHeader({ toggleCustomersTransactionsFilterDrawer: toggleFilterDrawer, }) { // Default form values. - const defaultValues = { - ...pageFilter, - fromDate: moment().toDate(), - toDate: moment().toDate(), - customersIds: [], - }; + const defaultValues = getCustomersTransactionsDefaultQuery(); + // Initial form values. const initialValues = transformToForm( { @@ -49,13 +47,7 @@ function CustomersTransactionsHeader({ ); // Validation schema. - const validationSchema = Yup.object().shape({ - fromDate: Yup.date().required().label(intl.get('fromDate')), - toDate: Yup.date() - .min(Yup.ref('fromDate')) - .required() - .label(intl.get('toDate')), - }); + const validationSchema = getCustomersTransactionsQuerySchema(); // Handle form submit. const handleSubmit = (values, { setSubmitting }) => { diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeaderGeneralPanel.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeaderGeneralPanel.tsx index 40394e175..509a70cc1 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeaderGeneralPanel.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeaderGeneralPanel.tsx @@ -1,15 +1,13 @@ // @ts-nocheck import React from 'react'; -import classNames from 'classnames'; -import { Field } from 'formik'; -import { Classes, FormGroup } from '@blueprintjs/core'; import FinancialStatementDateRange from '../FinancialStatementDateRange'; import FinancialStatementsFilter from '../FinancialStatementsFilter'; import { Row, Col, - ContactsMultiSelect, FormattedMessage as T, + CustomersMultiSelect, + FFormGroup, } from '@/components'; import { filterCustomersOptions } from '../constants'; @@ -51,24 +49,12 @@ function CustomersTransactionsHeaderGeneralPanelContent() { - - {({ form: { setFieldValue }, field: { value } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const customersIds = customers.map( - (customer) => customer.id, - ); - setFieldValue('customersIds', customersIds); - }} - /> - - )} - + } + name={'customersIds'} + > + + diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/_utils.ts b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/_utils.ts new file mode 100644 index 000000000..e2a7b1336 --- /dev/null +++ b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/_utils.ts @@ -0,0 +1,19 @@ +import * as Yup from 'yup'; +import intl from 'react-intl-universal'; +import moment from 'moment'; + +export const getCustomersTransactionsQuerySchema = () => { + return Yup.object().shape({ + fromDate: Yup.date().required().label(intl.get('fromDate')), + toDate: Yup.date() + .min(Yup.ref('fromDate')) + .required() + .label(intl.get('toDate')), + }); +}; + +export const getCustomersTransactionsDefaultQuery = () => ({ + fromDate: moment().toDate(), + toDate: moment().toDate(), + customersIds: [], +}); diff --git a/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedger.tsx b/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedger.tsx index 934f5c628..6f6047c9f 100644 --- a/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedger.tsx +++ b/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedger.tsx @@ -1,5 +1,5 @@ // @ts-nocheck -import React, { useCallback } from 'react'; +import React, { useCallback, useEffect } from 'react'; import moment from 'moment'; import GeneralLedgerHeader from './GeneralLedgerHeader'; @@ -41,10 +41,8 @@ function GeneralLedger({ ); // Hide the filter drawer once the page unmount. - React.useEffect( - () => () => { - toggleGeneralLedgerFilterDrawer(false); - }, + useEffect( + () => () => toggleGeneralLedgerFilterDrawer(false), [toggleGeneralLedgerFilterDrawer], ); diff --git a/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedgerHeader.tsx b/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedgerHeader.tsx index 8728bfa22..831c24f5f 100644 --- a/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedgerHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedgerHeader.tsx @@ -2,12 +2,14 @@ import React from 'react'; import moment from 'moment'; import styled from 'styled-components'; -import * as Yup from 'yup'; import { Formik, Form } from 'formik'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; import { FormattedMessage as T } from '@/components'; -import { getDefaultGeneralLedgerQuery } from './common'; +import { + getDefaultGeneralLedgerQuery, + getGeneralLedgerQuerySchema, +} from './common'; import { compose, transformToForm, saveInvoke } from '@/utils'; import FinancialStatementHeader from '../FinancialStatementHeader'; @@ -39,6 +41,7 @@ function GeneralLedgerHeader({ // Initial values. const initialValues = transformToForm( { + ...defaultValues, ...pageFilter, fromDate: moment(pageFilter.fromDate).toDate(), toDate: moment(pageFilter.toDate).toDate(), @@ -46,11 +49,8 @@ function GeneralLedgerHeader({ defaultValues, ); // Validation schema. - const validationSchema = Yup.object().shape({ - dateRange: Yup.string().optional(), - fromDate: Yup.date().required(), - toDate: Yup.date().min(Yup.ref('fromDate')).required(), - }); + const validationSchema = getGeneralLedgerQuerySchema(); + // Handle form submit. const handleSubmit = (values, { setSubmitting }) => { saveInvoke(onSubmitFilter, values); @@ -68,6 +68,7 @@ function GeneralLedgerHeader({ // Detarmines the feature whether is enabled. const { featureCan } = useFeatureCan(); + // Detarmine if the feature is enabled. const isBranchesFeatureCan = featureCan(Features.Branches); return ( diff --git a/packages/webapp/src/containers/FinancialStatements/GeneralLedger/common.tsx b/packages/webapp/src/containers/FinancialStatements/GeneralLedger/common.tsx index 491e7bffd..7ca26c7a3 100644 --- a/packages/webapp/src/containers/FinancialStatements/GeneralLedger/common.tsx +++ b/packages/webapp/src/containers/FinancialStatements/GeneralLedger/common.tsx @@ -2,6 +2,7 @@ import React from 'react'; import intl from 'react-intl-universal'; import moment from 'moment'; +import * as Yup from 'yup'; import { castArray } from 'lodash'; import { useAppQueryString } from '@/hooks'; @@ -26,15 +27,25 @@ export const filterAccountsOptions = [ /** * Retrieves the default general ledger query. */ -export const getDefaultGeneralLedgerQuery = () => { - return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), - basis: 'accrual', - filterByOption: 'with-transactions', - branchesIds: [], - accountsIds: [], - }; +export const getDefaultGeneralLedgerQuery = () => ({ + fromDate: moment().startOf('year').format('YYYY-MM-DD'), + toDate: moment().endOf('year').format('YYYY-MM-DD'), + basis: 'accrual', + filterByOption: 'with-transactions', + branchesIds: [], + accountsIds: [], +}); + +/** + * Retrieves the validation schema of general ledger. + * @returns {Yup} + */ +export const getGeneralLedgerQuerySchema = () => { + return Yup.object().shape({ + dateRange: Yup.string().optional(), + fromDate: Yup.date().required(), + toDate: Yup.date().min(Yup.ref('fromDate')).required(), + }); }; /** diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeader.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeader.tsx index 1af6bc2a9..31821760c 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeader.tsx @@ -1,10 +1,9 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; + import moment from 'moment'; import { Formik, Form } from 'formik'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; -import intl from 'react-intl-universal'; import styled from 'styled-components'; import { FormattedMessage as T } from '@/components'; @@ -16,7 +15,10 @@ import InventoryItemDetailsHeaderDimensionsPanel from './InventoryItemDetailsHea import withInventoryItemDetails from './withInventoryItemDetails'; import withInventoryItemDetailsActions from './withInventoryItemDetailsActions'; -import { getInventoryItemDetailsDefaultQuery } from './utils2'; +import { + getInventoryItemDetailsDefaultQuery, + getInventoryItemDetailsQuerySchema, +} from './utils2'; import { compose, transformToForm } from '@/utils'; import { useFeatureCan } from '@/hooks/state'; import { Features } from '@/constants'; @@ -28,6 +30,7 @@ function InventoryItemDetailsHeader({ // #ownProps onSubmitFilter, pageFilter, + // #withInventoryItemDetails isFilterDrawerOpen, @@ -40,30 +43,29 @@ function InventoryItemDetailsHeader({ // Filter form initial values. const initialValues = transformToForm( { + ...defaultValues, ...pageFilter, fromDate: moment(pageFilter.fromDate).toDate(), toDate: moment(pageFilter.toDate).toDate(), }, defaultValues, ); + // Validation schema. - const validationSchema = Yup.object().shape({ - fromDate: Yup.date().required().label(intl.get('fromDate')), - toDate: Yup.date() - .min(Yup.ref('fromDate')) - .required() - .label(intl.get('toDate')), - }); + const validationSchema = getInventoryItemDetailsQuerySchema(); + // Handle form submit. const handleSubmit = (values, { setSubmitting }) => { onSubmitFilter(values); toggleFilterDrawer(false); setSubmitting(false); }; + // Handle drawer close action. const handleDrawerClose = () => { toggleFilterDrawer(false); }; + // Detarmines the given feature whether is enabled. const { featureCan } = useFeatureCan(); diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeaderGeneralPanel.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeaderGeneralPanel.tsx index 9335ab79c..74edcbfa8 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeaderGeneralPanel.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeaderGeneralPanel.tsx @@ -1,14 +1,12 @@ // @ts-nocheck import React from 'react'; -import { FormGroup, Classes } from '@blueprintjs/core'; -import { Field } from 'formik'; import { ItemsMultiSelect, Row, Col, FormattedMessage as T, + FFormGroup, } from '@/components'; -import classNames from 'classnames'; import FinancialStatementDateRange from '../FinancialStatementDateRange'; import { @@ -39,26 +37,9 @@ function InventoryItemDetailsHeaderGeneralPanelContent() { - - {({ - form: { setFieldValue }, - field: { value }, - meta: { error, touched }, - }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const itemsIds = items.map((item) => item.id); - setFieldValue('itemsIds', itemsIds); - }} - /> - - )} - + } name={'itemsIds'}> + + diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/utils2.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/utils2.tsx index 345e84a95..02637e36e 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/utils2.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/utils2.tsx @@ -2,6 +2,8 @@ import React from 'react'; import moment from 'moment'; import { castArray } from 'lodash'; +import * as Yup from 'yup'; +import intl from 'react-intl-universal'; import { useAppQueryString } from '@/hooks'; import { transformToForm } from '@/utils'; @@ -9,13 +11,26 @@ import { transformToForm } from '@/utils'; /** * Retrieves inventory item details default query. */ -export const getInventoryItemDetailsDefaultQuery = () => { - return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), - warehousesIds: [], - branchesIds: [], - }; +export const getInventoryItemDetailsDefaultQuery = () => ({ + fromDate: moment().startOf('year').format('YYYY-MM-DD'), + toDate: moment().endOf('year').format('YYYY-MM-DD'), + itemsIds: [], + warehousesIds: [], + branchesIds: [], +}); + +/** + * Retrieves inventory item details query schema. + * @returns {Yup} + */ +export const getInventoryItemDetailsQuerySchema = () => { + return Yup.object().shape({ + fromDate: Yup.date().required().label(intl.get('fromDate')), + toDate: Yup.date() + .min(Yup.ref('fromDate')) + .required() + .label(intl.get('toDate')), + }); }; /** @@ -32,7 +47,8 @@ const parseInventoryItemDetailsQuery = (locationQuery) => { return { ...transformed, - // Ensures the branches/warehouses ids is always array. + // Ensure the branches, warehouses and items ids is always array. + itemsIds: castArray(transformed.itemsIds), branchesIds: castArray(transformed.branchesIds), warehousesIds: castArray(transformed.warehousesIds), }; diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeader.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeader.tsx index 09d29c7d9..1dd9d86c4 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeader.tsx @@ -1,6 +1,5 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; import moment from 'moment'; import styled from 'styled-components'; import { Formik, Form } from 'formik'; @@ -17,6 +16,10 @@ import withInventoryValuationActions from './withInventoryValuationActions'; import { compose, transformToForm } from '@/utils'; import { useFeatureCan } from '@/hooks/state'; import { Features } from '@/constants'; +import { + getInventoryValuationQuery, + getInventoryValuationQuerySchema, +} from './utils'; /** * inventory valuation header. @@ -33,25 +36,17 @@ function InventoryValuationHeader({ toggleInventoryValuationFilterDrawer, }) { // Form validation schema. - const validationSchema = Yup.object().shape({ - asDate: Yup.date().required().label('asDate'), - }); + const validationSchema = getInventoryValuationQuerySchema(); + const defaultQuery = getInventoryValuationQuery(); - // Default values. - const defaultValues = { - ...pageFilter, - asDate: moment().toDate(), - itemsIds: [], - warehousesIds: [], - }; // Initial values. const initialValues = transformToForm( { - ...defaultValues, + ...defaultQuery, ...pageFilter, asDate: moment(pageFilter.asDate).toDate(), }, - defaultValues, + defaultQuery, ); // Handle the form of header submit. @@ -71,6 +66,7 @@ function InventoryValuationHeader({ // Detarmines the given feature whether is enabled. const { featureCan } = useFeatureCan(); + // Detarmine if these feature are enabled. const isBranchesFeatureCan = featureCan(Features.Branches); const isWarehousesFeatureCan = featureCan(Features.Warehouses); diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeaderGeneralPanel.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeaderGeneralPanel.tsx index ef343192e..3981a5577 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeaderGeneralPanel.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeaderGeneralPanel.tsx @@ -2,8 +2,7 @@ import React from 'react'; import { FastField, Field } from 'formik'; import { DateInput } from '@blueprintjs/datetime'; -import { FormGroup, Position, Classes } from '@blueprintjs/core'; -import classNames from 'classnames'; +import { FormGroup, Position } from '@blueprintjs/core'; import { FormattedMessage as T, @@ -11,9 +10,9 @@ import { Row, Col, FieldHint, + FFormGroup, } from '@/components'; import { filterInventoryValuationOptions } from '../constants'; - import { momentFormatter, tansformDateValue, @@ -83,22 +82,9 @@ function InventoryValuationHeaderGeneralPanelContent() { - - {({ form: { setFieldValue } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const itemsIds = items.map((item) => item.id); - setFieldValue('itemsIds', itemsIds); - }} - /> - - )} - + }> + + diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/utils.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/utils.tsx index 5e96d5745..cfc00af75 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/utils.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/utils.tsx @@ -2,25 +2,33 @@ import React from 'react'; import moment from 'moment'; import { castArray } from 'lodash'; +import * as Yup from 'yup'; import { useAppQueryString } from '@/hooks'; import { transformToForm } from '@/utils'; /** - * Retrieves the inventory valuation sheet default query. + * Retrieves the validation schema of inventory valuation query. */ -export const getInventoryValuationQuery = () => { - return { - asDate: moment().endOf('day').format('YYYY-MM-DD'), - filterByOption: 'with-transactions', - - branchesIds: [], - warehousesIds: [], - }; +export const getInventoryValuationQuerySchema = () => { + return Yup.object().shape({ + asDate: Yup.date().required().label('asDate'), + }); }; /** - * Parses inventory valiation location query to report query. + * Retrieves the inventory valuation sheet default query. + */ +export const getInventoryValuationQuery = () => ({ + asDate: moment().endOf('day').format('YYYY-MM-DD'), + filterByOption: 'with-transactions', + itemsIds: [], + branchesIds: [], + warehousesIds: [], +}); + +/** + * Parses inventory valuation location query to report query. */ const parseInventoryValuationQuery = (locationQuery) => { const defaultQuery = getInventoryValuationQuery(); @@ -33,6 +41,7 @@ const parseInventoryValuationQuery = (locationQuery) => { ...transformed, // Ensures the branches/warehouses ids is always array. + itemsIds: castArray(transformed.itemsIds), branchesIds: castArray(transformed.branchesIds), warehousesIds: castArray(transformed.warehousesIds), }; diff --git a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItems.tsx b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItems.tsx index 485922d87..7fa14d85d 100644 --- a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItems.tsx +++ b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItems.tsx @@ -1,5 +1,5 @@ // @ts-nocheck -import React, { useEffect, useState, useCallback } from 'react'; +import React, { useEffect, useCallback } from 'react'; import moment from 'moment'; import PurchasesByItemsActionsBar from './PurchasesByItemsActionsBar'; @@ -9,7 +9,7 @@ import { FinancialStatement, DashboardPageContent } from '@/components'; import { PurchasesByItemsLoadingBar } from './components'; import { PurchasesByItemsProvider } from './PurchasesByItemsProvider'; import { PurchasesByItemsBody } from './PurchasesByItemsBody'; -import { getDefaultPurchasesByItemsQuery } from './utils'; +import { usePurchasesByItemsQuery } from './utils'; import { compose } from '@/utils'; import withPurchasesByItemsActions from './withPurchasesByItemsActions'; @@ -21,9 +21,7 @@ function PurchasesByItems({ // #withPurchasesByItemsActions togglePurchasesByItemsFilterDrawer, }) { - const [filter, setFilter] = useState({ - ...getDefaultPurchasesByItemsQuery(), - }); + const { query, setLocationQuery } = usePurchasesByItemsQuery(); // Handle filter form submit. const handleFilterSubmit = useCallback( @@ -33,11 +31,10 @@ function PurchasesByItems({ fromDate: moment(filter.fromDate).format('YYYY-MM-DD'), toDate: moment(filter.toDate).format('YYYY-MM-DD'), }; - setFilter(parsedFilter); + setLocationQuery(parsedFilter); }, - [setFilter], + [setLocationQuery], ); - // Handle number format form submit. const handleNumberFormatSubmit = (numberFormat) => { setFilter({ @@ -45,7 +42,6 @@ function PurchasesByItems({ numberFormat, }); }; - // Hide the filter drawer once the page unmount. useEffect( () => () => { @@ -55,9 +51,9 @@ function PurchasesByItems({ ); return ( - + @@ -65,7 +61,7 @@ function PurchasesByItems({ diff --git a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsGeneralPanel.tsx b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsGeneralPanel.tsx index c9bd572b3..859f4a3dd 100644 --- a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsGeneralPanel.tsx +++ b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsGeneralPanel.tsx @@ -1,14 +1,12 @@ // @ts-nocheck import React from 'react'; -import { FormGroup, Classes } from '@blueprintjs/core'; -import { Field } from 'formik'; import { Row, Col, FormattedMessage as T, ItemsMultiSelect, + FFormGroup, } from '@/components'; -import classNames from 'classnames'; import FinancialStatementDateRange from '../FinancialStatementDateRange'; import FinancialStatementsFilter from '../FinancialStatementsFilter'; import { filterItemsOptions } from '../constants'; @@ -51,22 +49,9 @@ function PurchasesByItemsGeneralPanelContent() { - - {({ form: { setFieldValue } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const itemsIds = items.map((item) => item.id); - setFieldValue('itemsIds', itemsIds); - }} - /> - - )} - + }> + + diff --git a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.tsx b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.tsx index 5ea0f6da8..935a6eaa6 100644 --- a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.tsx @@ -1,14 +1,11 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; import moment from 'moment'; -import intl from 'react-intl-universal'; -import styled from 'styled-components'; +import styled from 'styled-components'; import { Formik, Form } from 'formik'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; import { FormattedMessage as T } from '@/components'; - import FinancialStatementHeader from '@/containers/FinancialStatements/FinancialStatementHeader'; import PurchasesByItemsGeneralPanel from './PurchasesByItemsGeneralPanel'; @@ -16,6 +13,10 @@ import withPurchasesByItems from './withPurchasesByItems'; import withPurchasesByItemsActions from './withPurchasesByItemsActions'; import { compose, transformToForm } from '@/utils'; +import { + getDefaultPurchasesByItemsQuery, + getPurchasesByItemsQuerySchema, +} from './utils'; /** * Purchases by items header. @@ -32,38 +33,26 @@ function PurchasesByItemsHeader({ togglePurchasesByItemsFilterDrawer, }) { // Form validation schema. - const validationSchema = Yup.object().shape({ - fromDate: Yup.date().required().label(intl.get('from_date')), - toDate: Yup.date() - .min(Yup.ref('fromDate')) - .required() - .label(intl.get('to_date')), - }); - // Default form values. - const defaultValues = { - ...pageFilter, - fromDate: moment().toDate(), - toDate: moment().toDate(), - itemsIds: [], - }; + const validationSchema = getPurchasesByItemsQuerySchema(); + + const defaultQuery = getDefaultPurchasesByItemsQuery(); + // Initial form values. const initialValues = transformToForm( { - ...defaultValues, + ...defaultQuery, ...pageFilter, fromDate: moment(pageFilter.fromDate).toDate(), toDate: moment(pageFilter.toDate).toDate(), }, - defaultValues, + defaultQuery, ); - // Handle form submit. const handleSubmit = (values, { setSubmitting }) => { onSubmitFilter(values); setSubmitting(false); togglePurchasesByItemsFilterDrawer(false); }; - // Handle drawer close & cancel action. const handleDrawerClose = () => { togglePurchasesByItemsFilterDrawer(false); diff --git a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/utils.tsx b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/utils.tsx index b4309f30c..6613e6255 100644 --- a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/utils.tsx +++ b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/utils.tsx @@ -1,11 +1,62 @@ // @ts-nocheck +import React from 'react'; import moment from 'moment'; +import * as Yup from 'yup'; +import intl from 'react-intl-universal'; +import { useAppQueryString } from '@/hooks'; +import { transformToForm } from '@/utils'; +import { castArray } from 'lodash'; +/** + * Retrieves the purchases by items query. + */ +export const getDefaultPurchasesByItemsQuery = () => ({ + fromDate: moment().startOf('year').format('YYYY-MM-DD'), + toDate: moment().endOf('year').format('YYYY-MM-DD'), + filterByOption: 'with-transactions', + itemsIds: [], +}); -export const getDefaultPurchasesByItemsQuery = () => { +/** + * Retrieves the purchases by items query validation schema. + * @returns {Yup} + */ +export const getPurchasesByItemsQuerySchema = () => { + return Yup.object().shape({ + fromDate: Yup.date().required().label(intl.get('from_date')), + toDate: Yup.date() + .min(Yup.ref('fromDate')) + .required() + .label(intl.get('to_date')), + }); +}; + +/** + * Parses the purchases by items query. + */ +const parsePurchasesByItemsQuery = (locationQuery) => { + const defaultQuery = getDefaultPurchasesByItemsQuery(); + + const transformed = { + ...defaultQuery, + ...transformToForm(locationQuery, defaultQuery), + }; return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), - filterByOption: 'with-transactions', - } -} \ No newline at end of file + ...transformed, + itemsIds: castArray(transformed.itemsIds), + }; +}; + +/** + * Purchases by items query state. + */ +export const usePurchasesByItemsQuery = () => { + // Retrieves location query. + const [locationQuery, setLocationQuery] = useAppQueryString(); + + const query = React.useMemo( + () => parsePurchasesByItemsQuery(locationQuery), + [locationQuery], + ); + return { query, locationQuery, setLocationQuery }; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItems.tsx b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItems.tsx index b094d1b69..3382b3072 100644 --- a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItems.tsx +++ b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItems.tsx @@ -1,5 +1,5 @@ // @ts-nocheck -import React, { useEffect, useState, useCallback } from 'react'; +import React, { useEffect, useCallback } from 'react'; import moment from 'moment'; import { SalesByItemsBody } from './SalesByItemsBody'; @@ -11,7 +11,7 @@ import SalesByItemsHeader from './SalesByItemsHeader'; import withSalesByItemsActions from './withSalesByItemsActions'; -import { getDefaultSalesByItemsQuery } from './utils'; +import { useSalesByItemsQuery } from './utils'; import { compose } from '@/utils'; /** @@ -21,9 +21,7 @@ function SalesByItems({ // #withSellsByItemsActions toggleSalesByItemsFilterDrawer, }) { - const [filter, setFilter] = useState({ - ...getDefaultSalesByItemsQuery(), - }); + const { query, setLocationQuery } = useSalesByItemsQuery(); // Handle filter form submit. const handleFilterSubmit = useCallback( @@ -33,30 +31,28 @@ function SalesByItems({ fromDate: moment(filter.fromDate).format('YYYY-MM-DD'), toDate: moment(filter.toDate).format('YYYY-MM-DD'), }; - setFilter(parsedFilter); + setLocationQuery(parsedFilter); }, - [setFilter], + [setLocationQuery], ); // Handle number format form submit. const handleNumberFormatSubmit = (numberFormat) => { - setFilter({ + setLocationQuery({ ...filter, numberFormat, }); }; // Hide the filter drawer once the page unmount. useEffect( - () => () => { - toggleSalesByItemsFilterDrawer(false); - }, + () => () => toggleSalesByItemsFilterDrawer(false), [toggleSalesByItemsFilterDrawer], ); return ( - + @@ -64,7 +60,7 @@ function SalesByItems({ diff --git a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeader.tsx b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeader.tsx index 0fc4fa1f6..f0c024b04 100644 --- a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeader.tsx @@ -1,8 +1,6 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; import moment from 'moment'; -import intl from 'react-intl-universal'; import styled from 'styled-components'; import { Formik, Form } from 'formik'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; @@ -14,7 +12,11 @@ import SalesByItemsHeaderGeneralPanel from './SalesByItemsHeaderGeneralPanel'; import withSalesByItems from './withSalesByItems'; import withSalesByItemsActions from './withSalesByItemsActions'; -import { compose } from '@/utils'; +import { compose, transformToForm } from '@/utils'; +import { + getDefaultSalesByItemsQuery, + getSalesByItemsQueryShema, +} from './utils'; /** * Sales by items header. @@ -31,21 +33,22 @@ function SalesByItemsHeader({ toggleSalesByItemsFilterDrawer, }) { // Form validation schema. - const validationSchema = Yup.object().shape({ - fromDate: Yup.date().required().label(intl.get('from_date')), - toDate: Yup.date() - .min(Yup.ref('fromDate')) - .required() - .label(intl.get('to_date')), - }); + const validationSchema = getSalesByItemsQueryShema(); + + const defaultQuery = getDefaultSalesByItemsQuery(); // Initial values. - const initialValues = { - ...pageFilter, - fromDate: moment(pageFilter.fromDate).toDate(), - toDate: moment(pageFilter.toDate).toDate(), - }; + const initialValues = transformToForm( + { + ...defaultQuery, + ...pageFilter, + fromDate: moment(pageFilter.fromDate).toDate(), + toDate: moment(pageFilter.toDate).toDate(), + }, + defaultQuery, + ); + // Handle the form submitting. const handleSubmit = (values, { setSubmitting }) => { onSubmitFilter(values); setSubmitting(false); diff --git a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeaderGeneralPanel.tsx b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeaderGeneralPanel.tsx index 46f2f6416..01d267fbd 100644 --- a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeaderGeneralPanel.tsx +++ b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeaderGeneralPanel.tsx @@ -1,13 +1,15 @@ // @ts-nocheck import React from 'react'; -import { FormGroup, Classes } from '@blueprintjs/core'; -import { Field } from 'formik'; -import classNames from 'classnames'; - -import { filterItemsOptions } from '../constants'; -import { Row, Col, ItemsMultiSelect, FormattedMessage as T } from '@/components'; +import { + Row, + Col, + ItemsMultiSelect, + FormattedMessage as T, + FFormGroup, +} from '@/components'; import FinancialStatementDateRange from '../FinancialStatementDateRange'; import FinancialStatementsFilter from '../FinancialStatementsFilter'; +import { filterItemsOptions } from '../constants'; import { SalesByItemGeneralPanelProvider, useSalesByItemsGeneralPanelContext, @@ -46,22 +48,9 @@ function SalesByItemsHeaderGeneralPanelContent() { - - {({ form: { setFieldValue }, field: { value } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const itemsIds = items.map((item) => item.id); - setFieldValue('itemsIds', itemsIds); - }} - /> - - )} - + } name={'itemsIds'}> + + diff --git a/packages/webapp/src/containers/FinancialStatements/SalesByItems/utils.tsx b/packages/webapp/src/containers/FinancialStatements/SalesByItems/utils.tsx index 102b157b9..461304506 100644 --- a/packages/webapp/src/containers/FinancialStatements/SalesByItems/utils.tsx +++ b/packages/webapp/src/containers/FinancialStatements/SalesByItems/utils.tsx @@ -1,10 +1,63 @@ // @ts-nocheck +import React from 'react'; import moment from 'moment'; +import * as Yup from 'yup'; +import intl from 'react-intl-universal'; +import { castArray } from 'lodash'; +import { useAppQueryString } from '@/hooks'; +import { transformToForm } from '@/utils'; -export const getDefaultSalesByItemsQuery = () => { +/** + * Retrieves the validation schema. + * @returns {Yup} + */ +export const getSalesByItemsQueryShema = () => { + return Yup.object().shape({ + fromDate: Yup.date().required().label(intl.get('from_date')), + toDate: Yup.date() + .min(Yup.ref('fromDate')) + .required() + .label(intl.get('to_date')), + }); +}; + +/** + * Retrieves the default query. + */ +export const getDefaultSalesByItemsQuery = () => ({ + fromDate: moment().startOf('year').format('YYYY-MM-DD'), + toDate: moment().endOf('year').format('YYYY-MM-DD'), + filterByOption: 'with-transactions', + itemsIds: [], +}); + +/** + * Parses sales by items query of browser location. + */ +const parseSalesByItemsQuery = (locationQuery) => { + const defaultQuery = getDefaultSalesByItemsQuery(); + + const transformed = { + ...defaultQuery, + ...transformToForm(locationQuery, defaultQuery), + }; return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), - filterByOption: 'with-transactions', + ...transformed, + itemsIds: castArray(transformed.itemsIds), }; }; + +/** + * Sales by items query state. + */ +export const useSalesByItemsQuery = () => { + // Retrieves location query. + const [locationQuery, setLocationQuery] = useAppQueryString(); + + // Merges the default filter query with location URL query. + const query = React.useMemo( + () => parseSalesByItemsQuery(locationQuery), + [locationQuery], + ); + return { query, locationQuery, setLocationQuery }; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummary.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummary.tsx index 85ee52a96..dcf4e2486 100644 --- a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummary.tsx +++ b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummary.tsx @@ -13,7 +13,7 @@ import { VendorBalanceSummaryBody } from './VendorsBalanceSummaryBody'; import withVendorsBalanceSummaryActions from './withVendorsBalanceSummaryActions'; -import { getDefaultVendorsBalanceQuery } from './utils'; +import { useVendorsBalanceSummaryQuery } from './utils'; import { compose } from '@/utils'; /** @@ -23,9 +23,7 @@ function VendorsBalanceSummary({ // #withVendorsBalanceSummaryActions toggleVendorSummaryFilterDrawer, }) { - const [filter, setFilter] = useState({ - ...getDefaultVendorsBalanceQuery(), - }); + const { query, setLocationQuery } = useVendorsBalanceSummaryQuery(); // Handle refetch vendors balance summary. const handleFilterSubmit = (filter) => { @@ -33,28 +31,26 @@ function VendorsBalanceSummary({ ...filter, asDate: moment(filter.asDate).format('YYYY-MM-DD'), }; - setFilter(_filter); + setLocationQuery(_filter); }; // Handle number format submit. const handleNumberFormatSubmit = (format) => { - setFilter({ + setLocationQuery({ ...filter, numberFormat: format, }); }; useEffect( - () => () => { - toggleVendorSummaryFilterDrawer(false); - }, + () => () => toggleVendorSummaryFilterDrawer(false), [toggleVendorSummaryFilterDrawer], ); return ( - + @@ -62,7 +58,7 @@ function VendorsBalanceSummary({ diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeader.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeader.tsx index c102596e8..c5aef9f42 100644 --- a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeader.tsx @@ -1,6 +1,6 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; + import moment from 'moment'; import styled from 'styled-components'; import { Formik, Form } from 'formik'; @@ -13,6 +13,7 @@ import FinancialStatementHeader from '../FinancialStatementHeader'; import VendorsBalanceSummaryHeaderGeneral from './VendorsBalanceSummaryHeaderGeneral'; import withVendorsBalanceSummary from './withVendorsBalanceSummary'; import withVendorsBalanceSummaryActions from './withVendorsBalanceSummaryActions'; +import { getVendorsBalanceQuerySchema } from './utils'; /** * Vendors balance summary drawer header. @@ -28,10 +29,8 @@ function VendorsBalanceSummaryHeader({ //#withVendorsBalanceSummaryActions toggleVendorSummaryFilterDrawer, }) { - // validation schema. - const validationSchema = Yup.object().shape({ - asDate: Yup.date().required().label('asDate'), - }); + // Validation schema. + const validationSchema = getVendorsBalanceQuerySchema(); // filter form initial values. const defaultValues = { @@ -80,6 +79,7 @@ function VendorsBalanceSummaryHeader({ panel={} /> +
diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/utils.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/utils.tsx index 195b35b31..e661ab241 100644 --- a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/utils.tsx +++ b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/utils.tsx @@ -1,9 +1,44 @@ // @ts-nocheck import moment from 'moment'; +import { useMemo } from 'react'; +import * as Yup from 'yup'; +import { castArray } from 'lodash'; +import { useAppQueryString } from '@/hooks'; +import { transformToForm } from '@/utils'; export const getDefaultVendorsBalanceQuery = () => { return { asDate: moment().endOf('day').format('YYYY-MM-DD'), filterByOption: 'with-transactions', + vendorsIds: [], }; -} \ No newline at end of file +}; + +export const getVendorsBalanceQuerySchema = () => { + return Yup.object().shape({ + asDate: Yup.date().required().label('asDate'), + }); +}; + +export const parseVendorsBalanceSummaryQuery = (locationQuery) => { + const defaultQuery = getDefaultVendorsBalanceQuery(); + + const transformed = { + ...defaultQuery, + ...transformToForm(locationQuery, defaultQuery), + }; + return { + ...transformed, + vendorsIds: castArray(transformed.vendorsIds), + }; +}; + +export const useVendorsBalanceSummaryQuery = () => { + const [locationQuery, setLocationQuery] = useAppQueryString(); + + const query = useMemo( + () => parseVendorsBalanceSummaryQuery(locationQuery), + [locationQuery], + ); + return { query, locationQuery, setLocationQuery }; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeader.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeader.tsx index a61c5119e..df32211c0 100644 --- a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeader.tsx @@ -1,8 +1,7 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; + import moment from 'moment'; -import intl from 'react-intl-universal'; import { Formik, Form } from 'formik'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; import { FormattedMessage as T } from '@/components'; @@ -14,11 +13,14 @@ import withVendorsTransaction from './withVendorsTransaction'; import withVendorsTransactionsActions from './withVendorsTransactionsActions'; import { compose, transformToForm } from '@/utils'; +import { + getVendorTransactionsQuerySchema, + getVendorsTransactionsDefaultQuery, +} from './_utils'; /** * Vendors transactions header. */ - function VendorsTransactionsHeader({ // #ownProps onSubmitFilter, @@ -31,12 +33,7 @@ function VendorsTransactionsHeader({ toggleVendorsTransactionsFilterDrawer: toggleFilterDrawer, }) { // Default form values. - const defaultValues = { - ...pageFilter, - fromDate: moment().toDate(), - toDate: moment().toDate(), - vendorsIds: [], - }; + const defaultValues = getVendorsTransactionsDefaultQuery(); // Initial form values. const initialValues = transformToForm( @@ -48,15 +45,8 @@ function VendorsTransactionsHeader({ }, defaultValues, ); - // Validation schema. - const validationSchema = Yup.object().shape({ - fromDate: Yup.date().required().label(intl.get('fromDate')), - toDate: Yup.date() - .min(Yup.ref('fromDate')) - .required() - .label(intl.get('toDate')), - }); + const validationSchema = getVendorTransactionsQuerySchema(); // Handle form submit. const handleSubmit = (values, { setSubmitting }) => { @@ -64,7 +54,6 @@ function VendorsTransactionsHeader({ toggleFilterDrawer(false); setSubmitting(false); }; - // Handle drawer close action. const handleDrawerClose = () => { toggleFilterDrawer(false); diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeaderGeneralPanel.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeaderGeneralPanel.tsx index ab4db23ab..c6ef6eb51 100644 --- a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeaderGeneralPanel.tsx +++ b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeaderGeneralPanel.tsx @@ -1,8 +1,5 @@ // @ts-nocheck import React from 'react'; -import { Field } from 'formik'; -import { Classes, FormGroup } from '@blueprintjs/core'; -import classNames from 'classnames'; import FinancialStatementDateRange from '../FinancialStatementDateRange'; import FinancialStatementsFilter from '../FinancialStatementsFilter'; @@ -10,8 +7,9 @@ import FinancialStatementsFilter from '../FinancialStatementsFilter'; import { Row, Col, - ContactsMultiSelect, FormattedMessage as T, + FFormGroup, + VendorsMultiSelect, } from '@/components'; import { filterVendorsOptions } from '../constants'; @@ -53,22 +51,9 @@ function VendorsTransactionsHeaderGeneralPanelContent() { - - {({ form: { setFieldValue }, field: { value } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const vendorsIds = vendors.map((customer) => customer.id); - setFieldValue('vendorsIds', vendorsIds); - }} - /> - - )} - + } name={'vendorsIds'}> + + diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/_utils.ts b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/_utils.ts new file mode 100644 index 000000000..db28d7058 --- /dev/null +++ b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/_utils.ts @@ -0,0 +1,25 @@ +import * as Yup from 'yup'; +import intl from 'react-intl-universal'; +import moment from 'moment'; + +/** + * The validation schema of vendors transactions. + */ +export const getVendorTransactionsQuerySchema = () => { + return Yup.object().shape({ + fromDate: Yup.date().required().label(intl.get('fromDate')), + toDate: Yup.date() + .min(Yup.ref('fromDate')) + .required() + .label(intl.get('toDate')), + }); +}; + +/** + * Retrieves the default query of vendors transactions. + */ +export const getVendorsTransactionsDefaultQuery = () => ({ + fromDate: moment().toDate(), + toDate: moment().toDate(), + vendorsIds: [], +});