diff --git a/client/src/components/AccountsSelectList.js b/client/src/components/AccountsSelectList.js
index dec6a7061..0a70fa140 100644
--- a/client/src/components/AccountsSelectList.js
+++ b/client/src/components/AccountsSelectList.js
@@ -9,6 +9,7 @@ export default function AccountsSelectList({
selectedAccountId,
defaultSelectText = 'Select account',
onAccountSelected,
+ disabled = false,
}) {
// Find initial account object to set it as default account in initial render.
const initialAccount = useMemo(
@@ -77,6 +78,7 @@ export default function AccountsSelectList({
onItemSelect={onAccountSelect}
>
diff --git a/client/src/components/DataTableCells/DivFieldCell.js b/client/src/components/DataTableCells/DivFieldCell.js
index a9274ceae..c02ec5f13 100644
--- a/client/src/components/DataTableCells/DivFieldCell.js
+++ b/client/src/components/DataTableCells/DivFieldCell.js
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
-export default function DivFieldCell({ cell: { value: initialValue } }) {
+export const DivFieldCell = ({ cell: { value: initialValue } }) => {
const [value, setValue] = useState(initialValue);
useEffect(() => {
@@ -8,4 +8,13 @@ export default function DivFieldCell({ cell: { value: initialValue } }) {
}, [initialValue]);
return
@@ -312,5 +417,9 @@ export default compose(
withItemCategories(({ categoriesList }) => ({
categoriesList,
})),
+ withAccounts(({ accountsList }) => ({
+ accountsList,
+ })),
withItemCategoriesActions,
+ withAccountsActions,
)(ItemCategoryDialog);
diff --git a/client/src/containers/Items/ItemCategoriesList.js b/client/src/containers/Items/ItemCategoriesList.js
index c7d229d1c..a7bf770ea 100644
--- a/client/src/containers/Items/ItemCategoriesList.js
+++ b/client/src/containers/Items/ItemCategoriesList.js
@@ -14,6 +14,7 @@ import ItemCategoriesDataTable from 'containers/Items/ItemCategoriesTable';
import ItemsCategoryActionsBar from 'containers/Items/ItemsCategoryActionsBar';
import withDialogActions from 'containers/Dialog/withDialogActions';
+import withResourceActions from 'containers/Resources/withResourcesActions';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withItemCategoriesActions from 'containers/Items/withItemCategoriesActions';
import { compose } from 'utils';
@@ -25,10 +26,15 @@ const ItemCategoryList = ({
// #withDashboardActions
changePageTitle,
+ // #withViewsActions
+ requestFetchResourceViews,
+ requestFetchResourceFields,
+
// #withItemCategoriesActions
requestFetchItemCategories,
requestDeleteItemCategory,
requestDeleteBulkItemCategories,
+ addItemCategoriesTableQueries,
// #withDialog
openDialog,
@@ -48,9 +54,13 @@ const ItemCategoryList = ({
: changePageTitle(formatMessage({ id: 'category_list' }));
}, [id, changePageTitle, formatMessage]);
- const fetchCategories = useQuery(
- ['items-categories-list', filter],
- (key, query) => requestFetchItemCategories(query),
+ const fetchCategories = useQuery(['items-categories-list'], () =>
+ requestFetchItemCategories(),
+ );
+
+ const fetchResourceFields = useQuery(
+ ['resource-fields', 'items_categories'],
+ (key, resourceName) => requestFetchResourceFields(resourceName),
);
const handleFilterChanged = useCallback(() => {}, []);
@@ -63,17 +73,23 @@ const ItemCategoryList = ({
[setSelectedRows],
);
- // Handle fetch data of accounts datatable.
- const handleFetchData = useCallback(({ pageIndex, pageSize, sortBy }) => {
- setFilter({
- ...(sortBy.length > 0
- ? {
- column_sort_by: sortBy[0].id,
- sort_order: sortBy[0].desc ? 'desc' : 'asc',
- }
- : {}),
- });
- }, []);
+ const handleFetchData = useCallback(
+ ({ pageIndex, pageSize, sortBy }) => {
+ const page = pageIndex + 1;
+
+ addItemCategoriesTableQueries({
+ ...(sortBy.length > 0
+ ? {
+ column_sort_by: sortBy[0].id,
+ sort_order: sortBy[0].desc ? 'desc' : 'asc',
+ }
+ : {}),
+ page_size: pageSize,
+ page,
+ });
+ },
+ [addItemCategoriesTableQueries],
+ );
const handleDeleteCategory = (itemCategory) => {
setDeleteCategory(itemCategory);
@@ -139,7 +155,10 @@ const ItemCategoryList = ({
]);
return (
-
+
{
const [payload, setPayload] = useState({});
-
+
const history = useHistory();
const { formatMessage } = useIntl();
const {
@@ -72,22 +71,34 @@ const ItemForm = ({
deleteCallback: requestDeleteMedia,
});
- const ItemTypeDisplay = useMemo(() => [
- { value: null, label: formatMessage({id:'select_item_type'}) },
- { value: 'service', label: formatMessage({id:'service'}) },
- { value: 'inventory', label: formatMessage({id:'inventory'}) },
- { value: 'non-inventory', label: formatMessage({id:'non_inventory'}) },
- ], [formatMessage]);
+ const ItemTypeDisplay = useMemo(
+ () => [
+ { value: null, label: formatMessage({ id: 'select_item_type' }) },
+ { value: 'service', label: formatMessage({ id: 'service' }) },
+ { value: 'inventory', label: formatMessage({ id: 'inventory' }) },
+ { value: 'non-inventory', label: formatMessage({ id: 'non_inventory' }) },
+ ],
+ [formatMessage],
+ );
const validationSchema = Yup.object().shape({
active: Yup.boolean(),
- name: Yup.string().required().label(formatMessage({id:'item_name_'})),
- type: Yup.string().trim().required().label(formatMessage({id:'item_type_'})),
+ name: Yup.string()
+ .required()
+ .label(formatMessage({ id: 'item_name_' })),
+ type: Yup.string()
+ .trim()
+ .required()
+ .label(formatMessage({ id: 'item_type_' })),
sku: Yup.string().trim(),
cost_price: Yup.number(),
sell_price: Yup.number(),
- cost_account_id: Yup.number().required().label(formatMessage({id:'cost_account_id'})),
- sell_account_id: Yup.number().required().label(formatMessage({id:'sell_account_id'})),
+ cost_account_id: Yup.number()
+ .required()
+ .label(formatMessage({ id: 'cost_account_id' })),
+ sell_account_id: Yup.number()
+ .required()
+ .label(formatMessage({ id: 'sell_account_id' })),
inventory_account_id: Yup.number().when('type', {
is: (value) => value === 'inventory',
then: Yup.number().required(),
@@ -95,6 +106,8 @@ const ItemForm = ({
}),
category_id: Yup.number().nullable(),
stock: Yup.string() || Yup.boolean(),
+ sellable: Yup.boolean().required(),
+ purchasable: Yup.boolean().required(),
});
const defaultInitialValues = useMemo(
@@ -110,27 +123,36 @@ const ItemForm = ({
inventory_account_id: null,
category_id: null,
note: '',
+ sellable: null,
+ purchasable: null,
}),
- []
+ [],
+ );
+ const initialValues = useMemo(
+ () => ({
+ ...(itemDetail
+ ? {
+ ...pick(itemDetail, Object.keys(defaultInitialValues)),
+ }
+ : {
+ ...defaultInitialValues,
+ }),
+ }),
+ [itemDetail, defaultInitialValues],
);
- const initialValues = useMemo(() => ({
- ...(itemDetail) ? {
- ...pick(itemDetail, Object.keys(defaultInitialValues)),
-
- } : {
- ...defaultInitialValues,
- }
- }), [itemDetail, defaultInitialValues]);
- const saveInvokeSubmit = useCallback((payload) => {
- onFormSubmit && onFormSubmit(payload)
- }, [onFormSubmit]);
+ const saveInvokeSubmit = useCallback(
+ (payload) => {
+ onFormSubmit && onFormSubmit(payload);
+ },
+ [onFormSubmit],
+ );
useEffect(() => {
- itemDetail && itemDetail.id ?
- changePageTitle(formatMessage({id:'edit_item_details'})) :
- changePageTitle(formatMessage({id:'new_item'}));
- }, [changePageTitle,itemDetail,formatMessage]);
+ itemDetail && itemDetail.id
+ ? changePageTitle(formatMessage({ id: 'edit_item_details' }))
+ : changePageTitle(formatMessage({ id: 'new_item' }));
+ }, [changePageTitle, itemDetail, formatMessage]);
const {
getFieldProps,
@@ -146,55 +168,56 @@ const ItemForm = ({
initialValues: {
...initialValues,
},
- onSubmit: (values, { setSubmitting,resetForm,setErrors }) => {
-
+ onSubmit: (values, { setSubmitting, resetForm, setErrors }) => {
const saveItem = (mediaIds) => {
const formValues = { ...values, media_ids: mediaIds };
- if(itemDetail && itemDetail.id ){
-
- requestEditItem(itemDetail.id,formValues)
- .then((response)=>{
- AppToaster.show({
- message:formatMessage({
- id:'the_item_has_been_successfully_edited',
- },{
- number:itemDetail.id
- }),
- intent:Intent.SUCCESS
+ if (itemDetail && itemDetail.id) {
+ requestEditItem(itemDetail.id, formValues)
+ .then((response) => {
+ AppToaster.show({
+ message: formatMessage(
+ {
+ id: 'the_item_has_been_successfully_edited',
+ },
+ {
+ number: itemDetail.id,
+ },
+ ),
+ intent: Intent.SUCCESS,
+ });
+ setSubmitting(false);
+ saveInvokeSubmit({ action: 'update', ...payload });
+ history.push('/items');
+ resetForm();
+ })
+ .catch((errors) => {
+ setSubmitting(false);
});
- setSubmitting(false);
- saveInvokeSubmit({action:'update',...payload})
- history.push('/items');
- resetForm();
- }).catch((errors)=>{
- setSubmitting(false)
- });
-
- }else{
-
+ } else {
requestSubmitItem(formValues).then((response) => {
AppToaster.show({
- message: formatMessage({
- id: 'service_has_been_successful_created',
- }, {
- name: values.name,
- service: formatMessage({ id: 'item' }),
- }),
+ message: formatMessage(
+ {
+ id: 'service_has_been_successful_created',
+ },
+ {
+ name: values.name,
+ service: formatMessage({ id: 'item' }),
+ },
+ ),
intent: Intent.SUCCESS,
});
queryCache.removeQueries(['items-table']);
history.push('/items');
});
- };
}
-
-
+ };
Promise.all([saveMedia(), deleteMedia()]).then(
([savedMediaResponses]) => {
const mediaIds = savedMediaResponses.map((res) => res.data.media.id);
return saveItem(mediaIds);
- }
+ },
);
},
});
@@ -208,53 +231,52 @@ const ItemForm = ({
onClick={handleClick}
/>
),
- []
+ [],
);
-
// Filter Account Items
- const filterAccounts = (query, account, _index, exactMatch) => {
- const normalizedTitle = account.name.toLowerCase();
+ const filterAccounts = (query, item, _index, exactMatch) => {
+ const normalizedTitle = item.name.toLowerCase();
const normalizedQuery = query.toLowerCase();
if (exactMatch) {
return normalizedTitle === normalizedQuery;
} else {
- return `${account.code} ${normalizedTitle}`.indexOf(normalizedQuery) >= 0;
+ return `${item.code} ${normalizedTitle}`.indexOf(normalizedQuery) >= 0;
}
};
- const onItemAccountSelect = useCallback((filedName) => {
- return (account) => {
- setFieldValue(filedName, account.id);
- };
- }, [setFieldValue]);
+ const onItemAccountSelect = useCallback(
+ (filedName) => {
+ return (account) => {
+ setFieldValue(filedName, account.id);
+ };
+ },
+ [setFieldValue],
+ );
const categoryItem = useCallback(
(item, { handleClick }) => (
-
+
),
- []
+ [],
);
- const requiredSpan = useMemo(() => *, []);
- const infoIcon = useMemo(() => , []);
+ const requiredSpan = useMemo(() => *, []);
+ const infoIcon = useMemo(() => , []);
const handleMoneyInputChange = (fieldKey) => (e, value) => {
setFieldValue(fieldKey, value);
};
-
- const initialAttachmentFiles =useMemo(()=>{
+ const initialAttachmentFiles = useMemo(() => {
return itemDetail && itemDetail.media
- ? itemDetail.media.map((attach)=>({
-
- preview:attach.attachment_file,
- upload:true,
- metadata:{...attach}
-
- })):[];
-
- },[itemDetail])
+ ? itemDetail.media.map((attach) => ({
+ preview: attach.attachment_file,
+ upload: true,
+ metadata: { ...attach },
+ }))
+ : [];
+ }, [itemDetail]);
const handleDropFiles = useCallback((_files) => {
setFiles(_files.filter((file) => file.uploaded === false));
}, []);
@@ -267,7 +289,7 @@ const ItemForm = ({
}
});
},
- [setDeletedFiles, deletedFiles,]
+ [setDeletedFiles, deletedFiles],
);
const handleCancelClickBtn = () => {
@@ -275,12 +297,11 @@ const ItemForm = ({
};
return (
-