feat: List select component.

This commit is contained in:
Ahmed Bouhuolia
2020-05-24 01:48:07 +02:00
parent 80bca1d7a3
commit 18a032ffd1
6 changed files with 115 additions and 118 deletions

View File

@@ -0,0 +1,35 @@
import React, { useState, useEffect } from 'react';
import {
Button,
} from '@blueprintjs/core';
import { Select } from '@blueprintjs/select';
export default function ListSelect ({
buttonProps,
defaultText,
labelProp,
selectedItem,
selectedItemProp = 'id',
...selectProps
}) {
const [currentItem, setCurrentItem] = useState(null);
useEffect(() => {
if (selectedItem && selectedItemProp) {
const item = selectProps.items.find(i => i[selectedItemProp] === selectedItem);
setCurrentItem(item);
}
}, [selectedItem, selectedItemProp, selectProps.items]);
return (
<Select
{...selectProps}
>
<Button
text={currentItem ? currentItem[labelProp] : defaultText}
{...buttonProps}
/>
</Select>
)
}

View File

@@ -3,11 +3,13 @@ import Money from './Money';
import Icon from './Icon'; import Icon from './Icon';
// import Choose from './Utils/Choose'; // import Choose from './Utils/Choose';
// import For from './Utils/For'; // import For from './Utils/For';
import ListSelect from './ListSelect';
export { export {
If, If,
Money, Money,
Icon, Icon,
ListSelect,
// Choose, // Choose,
// For, // For,
}; };

View File

@@ -28,6 +28,9 @@ import Icon from 'components/Icon';
import ErrorMessage from 'components/ErrorMessage'; import ErrorMessage from 'components/ErrorMessage';
import { fetchAccountTypes } from 'store/accounts/accounts.actions'; import { fetchAccountTypes } from 'store/accounts/accounts.actions';
import {ListSelect} from 'components';
function AccountFormDialog({ function AccountFormDialog({
name, name,
payload, payload,
@@ -229,7 +232,6 @@ function AccountFormDialog({
const onChangeAccountType = useCallback( const onChangeAccountType = useCallback(
(accountType) => { (accountType) => {
setSelectedAccountType(accountType);
formik.setFieldValue('account_type_id', accountType.id); formik.setFieldValue('account_type_id', accountType.id);
}, },
[setSelectedAccountType, formik] [setSelectedAccountType, formik]
@@ -294,19 +296,20 @@ function AccountFormDialog({
errors.account_type_id && touched.account_type_id && Intent.DANGER errors.account_type_id && touched.account_type_id && Intent.DANGER
} }
> >
<Select <ListSelect
items={accountsTypes} items={accountsTypes}
noResults={<MenuItem disabled={true} text='No results.' />} noResults={<MenuItem disabled={true} text='No results.' />}
itemRenderer={accountTypeItem} itemRenderer={accountTypeItem}
itemPredicate={filterAccountTypeItems} itemPredicate={filterAccountTypeItems}
popoverProps={{ minimal: true }} popoverProps={{ minimal: true }}
onItemSelect={onChangeAccountType} onItemSelect={onChangeAccountType}
>
<Button selectedItem={formik.values.account_type_id}
text={selectedAccountType ? selectedAccountType.name : <T id={'select_account_type'} />} selectedItemProp={'id'}
disabled={payload.action === 'edit'}
/> defaultText={<T id={'select_account_type'} />}
</Select> labelProp={'name'}
buttonProps={{ disabled: payload.action === 'edit' }} />
</FormGroup> </FormGroup>
<FormGroup <FormGroup

View File

@@ -27,6 +27,7 @@ import { pick } from 'lodash';
import { getDialogPayload } from 'store/dashboard/dashboard.reducer'; import { getDialogPayload } from 'store/dashboard/dashboard.reducer';
function CurrencyDialog({ function CurrencyDialog({
name, name,
payload, payload,

View File

@@ -1,6 +1,6 @@
import React, { useState, useMemo, useCallback,useEffect } from 'react'; import React, { useState, useMemo, useCallback,useEffect } from 'react';
import * as Yup from 'yup'; import * as Yup from 'yup';
import { useFormik } from 'formik'; import { useFormik, Formik } from 'formik';
import { import {
FormGroup, FormGroup,
MenuItem, MenuItem,
@@ -13,31 +13,32 @@ import {
} from '@blueprintjs/core'; } from '@blueprintjs/core';
import { Row, Col } from 'react-grid-system'; import { Row, Col } from 'react-grid-system';
import { FormattedMessage as T, useIntl } from 'react-intl'; import { FormattedMessage as T, useIntl } from 'react-intl';
import { Select } from '@blueprintjs/select';
import { queryCache } from 'react-query'; import { queryCache } from 'react-query';
import {useParams ,useHistory} from 'react-router-dom'; import { useParams, useHistory } from 'react-router-dom';
import AppToaster from 'components/AppToaster'; import { pick } from 'lodash';
import { compose } from 'utils';
import ErrorMessage from 'components/ErrorMessage';
import classNames from 'classnames'; import classNames from 'classnames';
import AppToaster from 'components/AppToaster';
import ErrorMessage from 'components/ErrorMessage';
import Icon from 'components/Icon'; import Icon from 'components/Icon';
import MoneyInputGroup from 'components/MoneyInputGroup';
import Dragzone from 'components/Dragzone';
import { ListSelect } from 'components';
import withItemsActions from 'containers/Items/withItemsActions'; import withItemsActions from 'containers/Items/withItemsActions';
import withItemCategories from 'containers/Items/withItemCategories' import withItemCategories from 'containers/Items/withItemCategories'
import withAccounts from 'containers/Accounts/withAccounts'; import withAccounts from 'containers/Accounts/withAccounts';
import withMediaActions from 'containers/Media/withMediaActions'; import withMediaActions from 'containers/Media/withMediaActions';
import MoneyInputGroup from 'components/MoneyInputGroup';
import Dragzone from 'components/Dragzone';
import useMedia from 'hooks/useMedia'; import useMedia from 'hooks/useMedia';
import withItems from './withItems'; import withItems from './withItems';
import withItemDetail from 'containers/Items/withItemDetail' import withItemDetail from 'containers/Items/withItemDetail'
import { pick } from 'lodash';
import withDashboardActions from 'containers/Dashboard/withDashboard'; import withDashboardActions from 'containers/Dashboard/withDashboard';
import withAccountDetail from 'containers/Accounts/withAccountDetail'; import withAccountDetail from 'containers/Accounts/withAccountDetail';
import { compose } from 'utils';
const ItemForm = ({ const ItemForm = ({
// #withItemActions // #withItemActions
requestSubmitItem, requestSubmitItem,
requestEditItem, requestEditItem,
@@ -47,23 +48,16 @@ const ItemForm = ({
onFormSubmit, onFormSubmit,
onCancelForm, onCancelForm,
// #withDashboard // #withDashboard
changePageTitle, changePageTitle,
// #withItemCategories // #withItemCategories
categoriesList, categoriesList,
// #withMediaActions
// #withMediaActions
requestSubmitMedia, requestSubmitMedia,
requestDeleteMedia, requestDeleteMedia,
}) => { }) => {
const [selectedAccounts, setSelectedAccounts] = useState({});
const [payload, setPayload] = useState({}); const [payload, setPayload] = useState({});
const history = useHistory(); const history = useHistory();
@@ -232,19 +226,11 @@ const ItemForm = ({
} }
}; };
const onItemAccountSelect = useCallback((filedName) => {
const onItemAccountSelect = useCallback( return (account) => {
(filedName) => { setFieldValue(filedName, account.id);
return (account) => { };
setSelectedAccounts({ }, [setFieldValue]);
...selectedAccounts,
[filedName]: account,
});
setFieldValue(filedName, account.id);
};
},
[setFieldValue, selectedAccounts]
);
const categoryItem = useCallback( const categoryItem = useCallback(
(item, { handleClick }) => ( (item, { handleClick }) => (
@@ -253,16 +239,6 @@ const ItemForm = ({
[] []
); );
const getSelectedAccountLabel = useCallback(
(fieldName, defaultLabel) => {
return typeof selectedAccounts[fieldName] !== 'undefined'
? selectedAccounts[fieldName].name
: defaultLabel;
},
[selectedAccounts]
);
const requiredSpan = useMemo(() => <span class='required'>*</span>, []); const requiredSpan = useMemo(() => <span class='required'>*</span>, []);
const infoIcon = useMemo(() => <Icon icon='info-circle' iconSize={12} />, []); const infoIcon = useMemo(() => <Icon icon='info-circle' iconSize={12} />, []);
@@ -307,6 +283,8 @@ const ItemForm = ({
<div class='item-form__primary-section'> <div class='item-form__primary-section'>
<Row> <Row>
<Col xs={7}> <Col xs={7}>
{/* Item type */}
<FormGroup <FormGroup
medium={true} medium={true}
label={<T id={'item_type'} />} label={<T id={'item_type'} />}
@@ -325,6 +303,7 @@ const ItemForm = ({
/> />
</FormGroup> </FormGroup>
{/* Item name */}
<FormGroup <FormGroup
label={<T id={'item_name'} />} label={<T id={'item_name'} />}
labelInfo={requiredSpan} labelInfo={requiredSpan}
@@ -342,14 +321,13 @@ const ItemForm = ({
/> />
</FormGroup> </FormGroup>
{/* SKU */}
<FormGroup <FormGroup
label={<T id={'sku'} />} label={<T id={'sku'} />}
labelInfo={infoIcon} labelInfo={infoIcon}
className={'form-group--item-sku'} className={'form-group--item-sku'}
intent={errors.sku && touched.sku && Intent.DANGER} intent={errors.sku && touched.sku && Intent.DANGER}
helperText={ helperText={<ErrorMessage {...{ errors, touched }} name='sku' />}
<ErrorMessage {...{ errors, touched }} name='sku' />
}
inline={true} inline={true}
> >
<InputGroup <InputGroup
@@ -359,6 +337,7 @@ const ItemForm = ({
/> />
</FormGroup> </FormGroup>
{/* Item category */}
<FormGroup <FormGroup
label={<T id={'category'} />} label={<T id={'category'} />}
labelInfo={infoIcon} labelInfo={infoIcon}
@@ -375,24 +354,22 @@ const ItemForm = ({
Classes.FILL Classes.FILL
)} )}
> >
<Select <ListSelect
items={categoriesList} items={categoriesList}
itemRenderer={categoryItem} itemRenderer={categoryItem}
itemPredicate={filterAccounts} itemPredicate={filterAccounts}
popoverProps={{ minimal: true }} popoverProps={{ minimal: true }}
onItemSelect={onItemAccountSelect('category_id')} onItemSelect={onItemAccountSelect('category_id')}
>
<Button selectedItem={values.category_id}
fill={true} selectedItemProp={'id'}
rightIcon='caret-down'
text={getSelectedAccountLabel( defaultText={<T id={'select_category'} />}
'category_id', labelProp={'name'}
formatMessage({id:'select_category'}) />
)}
/>
</Select>
</FormGroup> </FormGroup>
{/* Active checkbox */}
<FormGroup <FormGroup
label={' '} label={' '}
inline={true} inline={true}
@@ -426,9 +403,7 @@ const ItemForm = ({
<FormGroup <FormGroup
label={<T id={'selling_price'}/>} label={<T id={'selling_price'}/>}
className={'form-group--item-selling-price'} className={'form-group--item-selling-price'}
intent={ intent={errors.selling_price && touched.selling_price && Intent.DANGER}
errors.selling_price && touched.selling_price && Intent.DANGER
}
helperText={ helperText={
<ErrorMessage {...{ errors, touched }} name='selling_price' /> <ErrorMessage {...{ errors, touched }} name='selling_price' />
} }
@@ -448,6 +423,7 @@ const ItemForm = ({
/> />
</FormGroup> </FormGroup>
{/* Selling account */}
<FormGroup <FormGroup
label={<T id={'account'} />} label={<T id={'account'} />}
labelInfo={infoIcon} labelInfo={infoIcon}
@@ -466,30 +442,26 @@ const ItemForm = ({
Classes.FILL Classes.FILL
)} )}
> >
<Select <ListSelect
items={accounts} items={accounts}
itemRenderer={accountItem} itemRenderer={accountItem}
itemPredicate={filterAccounts} itemPredicate={filterAccounts}
popoverProps={{ minimal: true }} popoverProps={{ minimal: true }}
onItemSelect={onItemAccountSelect('sell_account_id')} onItemSelect={onItemAccountSelect('sell_account_id')}
>
<Button selectedItem={values.sell_account_id}
fill={true} selectedItemProp={'id'}
rightIcon='caret-down'
text={getSelectedAccountLabel( defaultText={<T id={'select_account'} />}
'sell_account_id', labelProp={'name'}
formatMessage({id:'select_account'}) />
)}
/>
</Select>
</FormGroup> </FormGroup>
</Col> </Col>
<Col width={404}> <Col width={404}>
<h4> <h4><T id={'sales_information'} /></h4>
<T id={'sales_information'} />
</h4>
{/* Cost price */}
<FormGroup <FormGroup
label={<T id={'cost_price'} />} label={<T id={'cost_price'} />}
className={'form-group--item-cost-price'} className={'form-group--item-cost-price'}
@@ -529,23 +501,18 @@ const ItemForm = ({
Classes.FILL Classes.FILL
)} )}
> >
<Select <ListSelect
items={accounts} items={accounts}
itemRenderer={accountItem} itemRenderer={accountItem}
itemPredicate={filterAccounts} itemPredicate={filterAccounts}
popoverProps={{ minimal: true }} popoverProps={{ minimal: true }}
onItemSelect={onItemAccountSelect('cost_account_id')} onItemSelect={onItemAccountSelect('cost_account_id')}
>
<Button
fill={true}
rightIcon='caret-down'
text={getSelectedAccountLabel(
'cost_account_id',
formatMessage({id:'select_account'})
)} defaultText={<T id={'select_account'} />}
/> labelProp={'name'}
</Select> selectedItem={values.cost_account_id}
selectedItemProp={'id'}
/>
</FormGroup> </FormGroup>
</Col> </Col>
</Row> </Row>
@@ -564,35 +531,24 @@ const ItemForm = ({
touched.inventory_account_id && touched.inventory_account_id &&
Intent.DANGER Intent.DANGER
} }
helperText={ helperText={<ErrorMessage {...{ errors, touched }} name='inventory_account_id' />}
<ErrorMessage
{...{ errors, touched }}
name='inventory_account_id'
/>
}
className={classNames( className={classNames(
'form-group--item-inventory_account', 'form-group--item-inventory_account',
'form-group--select-list', 'form-group--select-list',
Classes.FILL Classes.FILL
)} )}
> >
<Select <ListSelect
items={accounts} items={accounts}
itemRenderer={accountItem} itemRenderer={accountItem}
itemPredicate={filterAccounts} itemPredicate={filterAccounts}
popoverProps={{ minimal: true }} popoverProps={{ minimal: true }}
onItemSelect={onItemAccountSelect('inventory_account_id')} onItemSelect={onItemAccountSelect('inventory_account_id')}
>
<Button
fill={true}
rightIcon='caret-down'
text={getSelectedAccountLabel(
'inventory_account_id',
formatMessage({id:'select_account'})
)} defaultText={<T id={'select_account'} />}
/> labelProp={'name'}
</Select> selectedItem={values.inventory_account_id}
selectedItemProp={'id'} />
</FormGroup> </FormGroup>
<FormGroup <FormGroup

View File

@@ -104,7 +104,7 @@ export default {
const costAccountPromise = Account.query().findById(form.cost_account_id); const costAccountPromise = Account.query().findById(form.cost_account_id);
const sellAccountPromise = Account.query().findById(form.sell_account_id); const sellAccountPromise = Account.query().findById(form.sell_account_id);
const inventoryAccountPromise = (form.type === 'inventory') const inventoryAccountPromise = (form.type === 'inventory')
? Account.query().findByid(form.inventory_account_id) : null; ? Account.query().findById(form.inventory_account_id) : null;
const itemCategoryPromise = (form.category_id) const itemCategoryPromise = (form.category_id)
? ItemCategory.query().findById(form.category_id) : null; ? ItemCategory.query().findById(form.category_id) : null;