diff --git a/client/src/common/classes.js b/client/src/common/classes.js
index dca1f9ad9..213774aed 100644
--- a/client/src/common/classes.js
+++ b/client/src/common/classes.js
@@ -11,6 +11,7 @@ const CLASSES = {
PAGE_FORM_HEADER_FIELDS: 'page-form__header-fields',
PAGE_FORM_HEADER_BIG_NUMBERS: 'page-form__big-numbers',
PAGE_FORM_TABS: 'page-form__tabs',
+ PAGE_FORM_BODY: 'page-form__body',
PAGE_FORM_FOOTER: 'page-form__footer',
PAGE_FORM_FLOATING_ACTIONS: 'page-form__floating-actions',
@@ -22,6 +23,7 @@ const CLASSES = {
PAGE_FORM_PAYMENT_MADE: 'page-form--payment-made',
PAGE_FORM_PAYMENT_RECEIVE: 'page-form--payment-receive',
PAGE_FORM_CUSTOMER: 'page-form--customer',
+ PAGE_FORM_ITEM: 'page-form--item',
FORM_GROUP_LIST_SELECT: 'form-group--select-list',
diff --git a/client/src/containers/Items/ItemForm.js b/client/src/containers/Items/ItemForm.js
index 74fd054ed..fa41d397d 100644
--- a/client/src/containers/Items/ItemForm.js
+++ b/client/src/containers/Items/ItemForm.js
@@ -1,69 +1,55 @@
-import React, { useState, useMemo, useCallback, useEffect } from 'react';
+import React, { useMemo, useCallback, useEffect } from 'react';
import * as Yup from 'yup';
-import { useFormik, Formik } from 'formik';
+import { useFormik } from 'formik';
import {
- FormGroup,
- MenuItem,
- Intent,
- InputGroup,
- HTMLSelect,
- Button,
- Classes,
- Checkbox,
+ Intent
} from '@blueprintjs/core';
-import { Row, Col } from 'react-grid-system';
-import { FormattedMessage as T, useIntl } from 'react-intl';
import { queryCache } from 'react-query';
import { useHistory } from 'react-router-dom';
import { pick } from 'lodash';
+import { useIntl } from 'react-intl';
import classNames from 'classnames';
+import { CLASSES } from 'common/classes';
import AppToaster from 'components/AppToaster';
-import ErrorMessage from 'components/ErrorMessage';
-import Icon from 'components/Icon';
-import MoneyInputGroup from 'components/MoneyInputGroup';
-import Dragzone from 'components/Dragzone';
-import {
- ListSelect,
- AccountsSelectList,
- CategoriesSelectList,
-} from 'components';
+import ItemFormPrimarySection from './ItemFormPrimarySection';
+import ItemFormBody from './ItemFormBody';
+import ItemFormFloatingActions from './ItemFormFloatingActions';
+import ItemFormInventorySection from './ItemFormInventorySection';
import withItemsActions from 'containers/Items/withItemsActions';
-import withItemCategories from 'containers/Items/withItemCategories';
-import withAccounts from 'containers/Accounts/withAccounts';
import withMediaActions from 'containers/Media/withMediaActions';
import useMedia from 'hooks/useMedia';
import withItemDetail from 'containers/Items/withItemDetail';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
-import withAccountDetail from 'containers/Accounts/withAccountDetail';
import { compose } from 'utils';
-const ItemForm = ({
+/**
+ * Item form.
+ */
+function ItemForm({
// #withItemActions
requestSubmitItem,
requestEditItem,
- accountsList,
+ itemId,
itemDetail,
onFormSubmit,
- onCancelForm,
// #withDashboardActions
changePageTitle,
-
- // #withItemCategories
- categoriesList,
+ changePageSubtitle,
// #withMediaActions
requestSubmitMedia,
requestDeleteMedia,
-}) => {
- const [payload, setPayload] = useState({});
+}) {
+ const isNewMode = !itemId;
const history = useHistory();
const { formatMessage } = useIntl();
+
const {
setFiles,
saveMedia,
@@ -75,16 +61,6 @@ 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 validationSchema = Yup.object().shape({
active: Yup.boolean(),
name: Yup.string()
@@ -118,7 +94,7 @@ const ItemForm = ({
() => ({
active: true,
name: '',
- type: '',
+ type: 'service',
sku: '',
cost_price: 0,
sell_price: 0,
@@ -127,8 +103,8 @@ const ItemForm = ({
inventory_account_id: null,
category_id: null,
note: '',
- sellable: null,
- purchasable: null,
+ sellable: true,
+ purchasable: true,
}),
[],
);
@@ -145,18 +121,44 @@ const ItemForm = ({
[itemDetail, defaultInitialValues],
);
- const saveInvokeSubmit = useCallback(
- (payload) => {
- onFormSubmit && onFormSubmit(payload);
- },
- [onFormSubmit],
- );
-
useEffect(() => {
- itemDetail && itemDetail.id
+ (!isNewMode)
? changePageTitle(formatMessage({ id: 'edit_item_details' }))
: changePageTitle(formatMessage({ id: 'new_item' }));
- }, [changePageTitle, itemDetail, formatMessage]);
+ }, [changePageTitle, isNewMode, formatMessage]);
+
+ // Handles the form submit.
+ const handleFormSubmit = (values, { setSubmitting, resetForm, setErrors }) => {
+ setSubmitting(true);
+ const form = { ...values };
+
+ const onSuccess = (response) => {
+ AppToaster.show({
+ message: formatMessage(
+ {
+ id: (isNewMode) ?
+ 'service_has_been_successful_created' :
+ 'the_item_has_been_successfully_edited',
+ },
+ {
+ number: itemDetail.id,
+ },
+ ),
+ intent: Intent.SUCCESS,
+ });
+ setSubmitting(false);
+ history.push('/items');
+ queryCache.removeQueries(['items-table']);
+ };
+ const onError = (response) => {
+ setSubmitting(false);
+ };
+ if (isNewMode) {
+ requestSubmitItem(form).then(onSuccess).catch(onError);
+ } else {
+ requestEditItem(form).then(onSuccess).catch(onError);
+ }
+ };
const {
getFieldProps,
@@ -169,78 +171,17 @@ const ItemForm = ({
} = useFormik({
enableReinitialize: true,
validationSchema: validationSchema,
- initialValues: {
- ...initialValues,
- },
- onSubmit: (values, { setSubmitting, resetForm, setErrors }) => {
- const saveItem = (mediaIds) => {
- const formValues = { ...values };
- 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);
- });
- } else {
- requestSubmitItem(formValues).then((response) => {
- AppToaster.show({
- 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);
- },
- );
- },
+ initialValues,
+ onSubmit: handleFormSubmit
});
- const onItemAccountSelect = useCallback(
- (filedName) => {
- return (account) => {
- setFieldValue(filedName, account.id);
- };
- },
- [setFieldValue],
- );
-
- const requiredSpan = useMemo(() => *, []);
- const infoIcon = useMemo(() =>