From de2a71433b1b06e1939f1f9ee2f21934f92170eb Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Sun, 23 Jan 2022 14:07:23 +0200
Subject: [PATCH] feat(warehouseTransfer): add warehouseTransfer.
---
src/common/classes.js | 1 +
src/common/drawers.js | 3 +-
src/components/DrawersContainer.js | 2 +
src/config/sidebarMenu.js | 8 +
.../WarehouseTransferNumberDialogContent.js | 103 +++++++++
.../WarehouseTransferNumberDialogProvider.js | 34 +++
.../WarehouseTransferNumberDialog/index.js | 40 ++++
.../WarehouseTransferDetail.js | 39 ++++
.../WarehouseTransferDetailActionsBar.js | 74 ++++++
.../WarehouseTransferDetailDrawerContent.js | 23 ++
.../WarehouseTransferDetailDrawerProvider.js | 43 ++++
.../WarehouseTransferDetailHeader.js | 59 +++++
.../WarehouseTransferDetailPanel.js | 17 ++
.../WarehouseTransferDetailTable.js | 22 ++
.../WarehouseTransferDetailDrawer/index.js | 36 +++
.../WarehouseTransferDetailDrawer/utils.js | 31 +++
src/containers/Settings/withSettings.js | 1 +
.../WarehouseTransferEditorField.js | 38 ++++
.../WarehouseTransferFloatingActions.js | 0
.../WarehouseTransferForm.js | 89 ++++++++
.../WarehouseTransferForm.schema.js | 28 +++
.../WarehouseTransferFormDialog.js | 23 ++
.../WarehouseTransferFormEntriesTable.js | 42 ++++
.../WarehouseTransferFormFooter.js | 42 ++++
.../WarehouseTransferFormHeader.js | 20 ++
.../WarehouseTransferFormHeaderFields.js | 212 ++++++++++++++++++
.../WarehouseTransferFormPage.js | 16 ++
.../WarehouseTransferFormProvider.js | 42 ++++
.../WarehouseTransferForm/utils.js | 55 +++++
.../WarehouseTransfersActionsBar.js | 99 ++++++++
.../WarehouseTransfersDataTable.js | 108 +++++++++
.../WarehouseTransfersEmptyStatus.js | 32 +++
.../WarehouseTransfersList.js | 25 +++
.../WarehouseTransfersListProvider.js | 29 +++
.../WarehouseTransfersViewTabs.js | 37 +++
.../WarehouseTransfersLanding/components.js | 121 ++++++++++
src/containers/WarehouseTransfers/utils.js | 64 ++++++
src/hooks/query/settings.js | 11 +
src/hooks/query/types.js | 9 +-
src/lang/en/index.json | 32 ++-
src/routes/dashboard.js | 30 +++
src/store/settings/settings.reducer.js | 3 +
.../pages/WarehouseTransfers/PageForm.scss | 50 +++++
43 files changed, 1786 insertions(+), 7 deletions(-)
create mode 100644 src/containers/Dialogs/WarehouseTransferNumberDialog/WarehouseTransferNumberDialogContent.js
create mode 100644 src/containers/Dialogs/WarehouseTransferNumberDialog/WarehouseTransferNumberDialogProvider.js
create mode 100644 src/containers/Dialogs/WarehouseTransferNumberDialog/index.js
create mode 100644 src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetail.js
create mode 100644 src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailActionsBar.js
create mode 100644 src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerContent.js
create mode 100644 src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js
create mode 100644 src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailHeader.js
create mode 100644 src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailPanel.js
create mode 100644 src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailTable.js
create mode 100644 src/containers/Drawers/WarehouseTransferDetailDrawer/index.js
create mode 100644 src/containers/Drawers/WarehouseTransferDetailDrawer/utils.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferEditorField.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFloatingActions.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.schema.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormDialog.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormEntriesTable.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooter.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeader.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeaderFields.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormPage.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransferForm/utils.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersActionsBar.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersDataTable.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersEmptyStatus.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersList.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersListProvider.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersViewTabs.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransfersLanding/components.js
create mode 100644 src/containers/WarehouseTransfers/utils.js
create mode 100644 src/style/pages/WarehouseTransfers/PageForm.scss
diff --git a/src/common/classes.js b/src/common/classes.js
index 6b0872396..1bbcf9873 100644
--- a/src/common/classes.js
+++ b/src/common/classes.js
@@ -41,6 +41,7 @@ const CLASSES = {
PAGE_FORM_EXPENSE: 'page-form--expense',
PAGE_FORM_CREDIT_NOTE:'page-form--credit-note',
PAGE_FORM_VENDOR_CREDIT_NOTE:'page-form--vendor-credit-note',
+ PAGE_FORM_WAREHOUSE_TRANSFER:'page-form--warehouse-transfer',
FORM_GROUP_LIST_SELECT: 'form-group--select-list',
diff --git a/src/common/drawers.js b/src/common/drawers.js
index 5ec6d05a2..205d7fc53 100644
--- a/src/common/drawers.js
+++ b/src/common/drawers.js
@@ -17,5 +17,6 @@ export const DRAWERS = {
CREDIT_NOTE_DETAIL_DRAWER: 'credit-note-detail-drawer',
VENDOR_CREDIT_DETAIL_DRAWER: 'vendor-credit-detail-drawer',
REFUND_CREDIT_NOTE_DETAIL_DRAWER:'refund-credit-detail-drawer',
- REFUND_VENDOR_CREDIT_DETAIL_DRAWER:'refund-vendor-detail-drawer'
+ REFUND_VENDOR_CREDIT_DETAIL_DRAWER:'refund-vendor-detail-drawer',
+ WAREHOUSE_TRANSFER_DETAIL_DRAWER:'warehouse-transfer-detail-drawer'
};
diff --git a/src/components/DrawersContainer.js b/src/components/DrawersContainer.js
index e508519bd..17090b5d9 100644
--- a/src/components/DrawersContainer.js
+++ b/src/components/DrawersContainer.js
@@ -21,6 +21,7 @@ import CreditNoteDetailDrawer from '../containers/Drawers/CreditNoteDetailDrawer
import VendorCreditDetailDrawer from '../containers/Drawers/VendorCreditDetailDrawer';
import RefundCreditNoteDetailDrawer from '../containers/Drawers/RefundCreditNoteDetailDrawer';
import RefundVendorCreditDetailDrawer from '../containers/Drawers/RefundVendorCreditDetailDrawer';
+import WarehouseTransferDetailDrawer from '../containers/Drawers/WarehouseTransferDetailDrawer'
import { DRAWERS } from 'common/drawers';
@@ -59,6 +60,7 @@ export default function DrawersContainer() {
+
);
}
diff --git a/src/config/sidebarMenu.js b/src/config/sidebarMenu.js
index 1ea65f2a0..14812dfea 100644
--- a/src/config/sidebarMenu.js
+++ b/src/config/sidebarMenu.js
@@ -78,6 +78,10 @@ export default [
ability: InventoryAdjustmentAction.View,
},
},
+ {
+ text: ,
+ href: '/warehouse-transfers',
+ },
{
text: ,
href: '/items/categories',
@@ -113,6 +117,10 @@ export default [
ability: ItemAction.Create,
},
},
+ {
+ text: ,
+ href: '/warehouse-transfers/new',
+ },
{
text: ,
href: '/items/new',
diff --git a/src/containers/Dialogs/WarehouseTransferNumberDialog/WarehouseTransferNumberDialogContent.js b/src/containers/Dialogs/WarehouseTransferNumberDialog/WarehouseTransferNumberDialogContent.js
new file mode 100644
index 000000000..a992b8be0
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseTransferNumberDialog/WarehouseTransferNumberDialogContent.js
@@ -0,0 +1,103 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { useSaveSettings } from 'hooks/query';
+
+import { WarehouseTransferNumberDialogProvider } from './WarehouseTransferNumberDialogProvider';
+import ReferenceNumberForm from 'containers/JournalNumber/ReferenceNumberForm';
+
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import withSettings from 'containers/Settings/withSettings';
+import withSettingsActions from 'containers/Settings/withSettingsActions';
+import { compose } from 'utils';
+import {
+ transformFormToSettings,
+ transformSettingsToForm,
+} from 'containers/JournalNumber/utils';
+
+/**
+ * Warehouse transfer no dialog content.
+ */
+function WarehouseTransferNumberDialogContent({
+ // #ownProps
+ initialValues,
+ onConfirm,
+
+ // #withSettings
+ nextNumber,
+ numberPrefix,
+ autoIncrement,
+
+ // #withDialogActions
+ closeDialog,
+}) {
+ const { mutateAsync: saveSettings } = useSaveSettings();
+ const [referenceFormValues, setReferenceFormValues] = React.useState(null);
+
+ // Handle the submit form.
+ const handleSubmitForm = (values, { setSubmitting }) => {
+ // Handle the form success.
+ const handleSuccess = () => {
+ setSubmitting(false);
+ closeDialog('warehouse-transfer-no-form');
+ onConfirm(values);
+ };
+
+ // Handle the form errors.
+ const handleErrors = () => {
+ setSubmitting(false);
+ };
+
+ if (values.incrementMode === 'manual-transaction') {
+ handleSuccess();
+ return;
+ }
+ // Transformes the form values to settings to save it.
+ const options = transformFormToSettings(values, 'warehouse_transfer');
+
+ // Save the settings.
+ saveSettings({ options }).then(handleSuccess).catch(handleErrors);
+ };
+
+ // Handle the dialog close.
+ const handleClose = () => {
+ closeDialog('warehouse-transfer-no-form');
+ };
+
+ // Handle form change.
+ const handleChange = (values) => {
+ setReferenceFormValues(values);
+ };
+ // Description.
+ const description =
+ referenceFormValues?.incrementMode === 'auto'
+ ? intl.get('warehouse_transfer.auto_increment.auto')
+ : intl.get('warehouse_transfer.auto_increment.manually');
+
+ return (
+
+
+
+ );
+}
+export default compose(
+ withDialogActions,
+ withSettingsActions,
+ withSettings(({ warehouseTransferSettings }) => ({
+ autoIncrement: warehouseTransferSettings?.autoIncrement,
+ nextNumber: warehouseTransferSettings?.nextNumber,
+ numberPrefix: warehouseTransferSettings?.numberPrefix,
+ })),
+)(WarehouseTransferNumberDialogContent);
diff --git a/src/containers/Dialogs/WarehouseTransferNumberDialog/WarehouseTransferNumberDialogProvider.js b/src/containers/Dialogs/WarehouseTransferNumberDialog/WarehouseTransferNumberDialogProvider.js
new file mode 100644
index 000000000..0bbad114f
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseTransferNumberDialog/WarehouseTransferNumberDialogProvider.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import { DialogContent } from 'components';
+import { useSettingsWarehouseTransfers } from 'hooks/query';
+
+const WarehouseTransferNumberDilaogContext = React.createContext();
+
+/**
+ * Warehouse transfer number dialog provier.
+ */
+function WarehouseTransferNumberDialogProvider({ query, ...props }) {
+ const { isLoading: isSettingsLoading } = useSettingsWarehouseTransfers();
+
+ // Provider payload.
+ const provider = {
+ isSettingsLoading,
+ };
+
+ return (
+
+
+
+ );
+}
+
+const useWarehouseTransferNumberDialogContext = () =>
+ React.useContext(WarehouseTransferNumberDilaogContext);
+
+export {
+ WarehouseTransferNumberDialogProvider,
+ useWarehouseTransferNumberDialogContext,
+};
diff --git a/src/containers/Dialogs/WarehouseTransferNumberDialog/index.js b/src/containers/Dialogs/WarehouseTransferNumberDialog/index.js
new file mode 100644
index 000000000..6832ec825
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseTransferNumberDialog/index.js
@@ -0,0 +1,40 @@
+import React from 'react';
+import { FormattedMessage as T } from 'components';
+import { Dialog, DialogSuspense } from 'components';
+import withDialogRedux from 'components/DialogReduxConnect';
+import { compose, saveInvoke } from 'utils';
+
+const WarehouseTransferNumberDialogContent = React.lazy(() =>
+ import('./WarehouseTransferNumberDialogContent'),
+);
+
+/**
+ * Warehouse transfer number dialog.
+ */
+function WarehouseTransferNumberDilaog({
+ dialogName,
+ payload: { initialFormValues },
+ isOpen,
+ onConfirm,
+}) {
+ const handleConfirm = (values) => {
+ saveInvoke(onConfirm, values);
+ };
+ return (
+ }
+ name={dialogName}
+ autoFocus={true}
+ canEscapeKeyClose={true}
+ isOpen={isOpen}
+ >
+
+
+
+
+ );
+}
+export default compose(withDialogRedux())(WarehouseTransferNumberDilaog);
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetail.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetail.js
new file mode 100644
index 000000000..4296e419c
--- /dev/null
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetail.js
@@ -0,0 +1,39 @@
+import React from 'react';
+import { Tab } from '@blueprintjs/core';
+import styled from 'styled-components';
+import intl from 'react-intl-universal';
+import { DrawerMainTabs } from 'components';
+
+import WarehouseTransferDetailPanel from './WarehouseTransferDetailPanel';
+import WarehouseTransferDetailActionsBar from './WarehouseTransferDetailActionsBar';
+
+/**
+ * Warehouse transfer view detail.
+ * @returns {React.JSX}
+ */
+export default function WarehouseTransferDetail() {
+ return (
+
+
+
+
+ );
+}
+
+/**
+ * Warehouse transfer details tabs.
+ * @returns {React.JSX}
+ */
+function WarehouseTransferDetailsTabs() {
+ return (
+
+ }
+ />
+
+ );
+}
+
+const WarehouseTransferRoot = styled.div``;
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailActionsBar.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailActionsBar.js
new file mode 100644
index 000000000..9202666f4
--- /dev/null
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailActionsBar.js
@@ -0,0 +1,74 @@
+import React from 'react';
+import { useHistory } from 'react-router-dom';
+import {
+ Button,
+ NavbarGroup,
+ Classes,
+ NavbarDivider,
+ Intent,
+} from '@blueprintjs/core';
+
+import { useWarehouseDetailDrawerContext } from './WarehouseTransferDetailDrawerProvider';
+import {
+ DrawerActionsBar,
+ Can,
+ Icon,
+ FormattedMessage as T,
+ If,
+} from 'components';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import withAlertsActions from 'containers/Alert/withAlertActions';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
+
+import { compose } from 'utils';
+
+/**
+ * Warehouse transfer detail actions bar.
+ */
+function WarehouseTransferDetailActionsBar({
+ // #withAlertsActions
+ openAlert,
+
+ // #withDrawerActions
+ closeDrawer,
+}) {
+ const history = useHistory();
+
+ // Handle edit warehosue transfer.
+ const handleEditWarehosueTransfer = () => {
+ // history.push(`/warehouse-transfers/${warehouseTransferId}/edit`);
+ closeDrawer('warehouse-transfer-detail-drawer');
+ };
+
+ // Handle delete warehouse transfer.
+ const handleDeletetWarehosueTransfer = () => {
+ // openAlert('warehouse-transfer-delete', { warehouseTransferId });
+ };
+
+ return (
+
+
+ }
+ text={}
+ onClick={handleEditWarehosueTransfer}
+ />
+
+ }
+ text={}
+ intent={Intent.DANGER}
+ onClick={handleDeletetWarehosueTransfer}
+ />
+
+
+ );
+}
+
+export default compose(
+ withDialogActions,
+ withAlertsActions,
+ withDrawerActions,
+)(WarehouseTransferDetailActionsBar);
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerContent.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerContent.js
new file mode 100644
index 000000000..74bfa27af
--- /dev/null
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerContent.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import { DrawerBody } from 'components';
+
+import WarehouseTransferDetail from './WarehouseTransferDetail';
+import { WarehouseTransferDetailDrawerProvider } from './WarehouseTransferDetailDrawerProvider';
+
+/**
+ * Warehouse transfer detail drawer content.
+ */
+export default function WarehouseTransferDetailDrawerContent({
+ // #ownProp
+ warehouseTransferId,
+}) {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js
new file mode 100644
index 000000000..0d1d6525d
--- /dev/null
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js
@@ -0,0 +1,43 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+// import {} from 'hooks/query';
+import { DrawerHeaderContent, DrawerLoading } from 'components';
+
+const WarehouseTransferDetailDrawerContext = React.createContext();
+
+/**
+ * Warehouse transfer detail drawer provider.
+ */
+function WarehouseTransferDetailDrawerProvider({
+ warehouseTransferId,
+ ...props
+}) {
+ const provider = {
+ warehouseTransferId,
+ };
+
+ return (
+
+
+
+
+ );
+}
+
+const useWarehouseDetailDrawerContext = () =>
+ React.useContext(WarehouseTransferDetailDrawerContext);
+
+export {
+ WarehouseTransferDetailDrawerProvider,
+ useWarehouseDetailDrawerContext,
+};
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailHeader.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailHeader.js
new file mode 100644
index 000000000..cfb5a8960
--- /dev/null
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailHeader.js
@@ -0,0 +1,59 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { defaultTo } from 'lodash';
+import styled from 'styled-components';
+
+import {
+ FormatDate,
+ T,
+ Row,
+ Col,
+ DetailsMenu,
+ DetailItem,
+ CommercialDocHeader,
+ CommercialDocTopHeader,
+} from 'components';
+import { useWarehouseDetailDrawerContext } from './WarehouseTransferDetailDrawerProvider';
+
+/**
+ * Warehouse transfer details drawer header
+ */
+export default function WarehouseTransferDetailHeader() {
+ return (
+
+
+
+
+ '$10'
+
+
+
+
+
+ {/* */}
+
+
+
+
+
+
+
+
+ );
+}
+
+const AmountItem = styled(DetailItem)`
+ width: 50%;
+`;
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailPanel.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailPanel.js
new file mode 100644
index 000000000..cd995ad42
--- /dev/null
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailPanel.js
@@ -0,0 +1,17 @@
+import React from 'react';
+import { CommercialDocBox } from 'components';
+
+import WarehouseTransferDetailHeader from './WarehouseTransferDetailHeader';
+import WarehouseTransferDetailTable from './WarehouseTransferDetailTable';
+
+/**
+ * Warehouse transfer details panel.
+ */
+export default function WarehouseTransferDetailPanel() {
+ return (
+
+
+
+
+ );
+}
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailTable.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailTable.js
new file mode 100644
index 000000000..e85b7014f
--- /dev/null
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailTable.js
@@ -0,0 +1,22 @@
+import React from 'react';
+
+import { CommercialDocEntriesTable } from 'components';
+import { TableStyle } from '../../../common';
+import { useWarehouseTransferReadOnlyEntriesColumns } from './utils';
+
+/**
+ * Warehouse transfer detail table.
+ * @returns {React.JSX}
+ */
+export default function WarehouseTransferDetailTable() {
+ // Warehouse transfer entries table columns.
+ const columns = useWarehouseTransferReadOnlyEntriesColumns();
+
+ return (
+
+ );
+}
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/index.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/index.js
new file mode 100644
index 000000000..b1c62099e
--- /dev/null
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/index.js
@@ -0,0 +1,36 @@
+import React from 'react';
+import { Drawer, DrawerSuspense } from 'components';
+import withDrawers from 'containers/Drawer/withDrawers';
+
+import { compose } from 'utils';
+
+const WarehouseTransferDetailDrawerContent = React.lazy(() =>
+ import('./WarehouseTransferDetailDrawerContent'),
+);
+
+/**
+ * Warehouse transfer detail drawer.
+ */
+function WarehouseTransferDetailDrawer({
+ name,
+ // #withDrawer
+ isOpen,
+ payload: { warehouseTransferId },
+}) {
+ return (
+
+
+
+
+
+ );
+}
+
+export default compose(withDrawers())(WarehouseTransferDetailDrawer);
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/utils.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/utils.js
new file mode 100644
index 000000000..c5ca6409c
--- /dev/null
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/utils.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+
+import {
+ Icon,
+ FormattedMessage as T,
+ FormatNumberCell,
+ Choose,
+} from '../../../components';
+
+export const useWarehouseTransferReadOnlyEntriesColumns = () =>
+ React.useMemo(
+ () => [
+ {
+ Header: intl.get('warehouse_transfer.column.item_name'),
+ accessor: 'item.name',
+ width: 150,
+ className: 'name',
+ disableSortBy: true,
+ },
+ {
+ Header: intl.get('warehouse_transfer.column.transfer_quantity'),
+ accessor: 'quantity',
+ Cell: FormatNumberCell,
+ width: 100,
+ align: 'right',
+ disableSortBy: true,
+ },
+ ],
+ [],
+ );
diff --git a/src/containers/Settings/withSettings.js b/src/containers/Settings/withSettings.js
index 867e56dc7..b712e4430 100644
--- a/src/containers/Settings/withSettings.js
+++ b/src/containers/Settings/withSettings.js
@@ -21,6 +21,7 @@ export default (mapState) => {
cashflowSetting: state.settings.data.cashflow,
creditNoteSettings: state.settings.data.creditNote,
vendorsCreditNoteSetting: state.settings.data.vendorCredit,
+ warehouseTransferSettings: state.settings.data.warehouseTransfer,
};
return mapState ? mapState(mapped, state, props) : mapped;
};
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferEditorField.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferEditorField.js
new file mode 100644
index 000000000..7c80c21ac
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferEditorField.js
@@ -0,0 +1,38 @@
+import React from 'react';
+import { FastField } from 'formik';
+import classNames from 'classnames';
+import { CLASSES } from 'common/classes';
+import { useWarehouseTransferFormContext } from './WarehouseTransferFormProvider';
+import { entriesFieldShouldUpdate } from './utils';
+import WarehouseTransferFormEntriesTable from './WarehouseTransferFormEntriesTable';
+
+/**
+ * Warehouse transafer editor field.
+ */
+export default function WarehouseTransferEditorField() {
+ const { items } = useWarehouseTransferFormContext();
+ return (
+
+
+ {({
+ form: { values, setFieldValue },
+ field: { value },
+ meta: { error, touched },
+ }) => (
+ {
+ setFieldValue('entries', entries);
+ }}
+ items={items}
+ errors={error}
+ />
+ )}
+
+
+ );
+}
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFloatingActions.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFloatingActions.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js
new file mode 100644
index 000000000..3487ca548
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js
@@ -0,0 +1,89 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { Formik, Form } from 'formik';
+import { Intent } from '@blueprintjs/core';
+import { useHistory } from 'react-router-dom';
+import { CLASSES } from 'common/classes';
+import classNames from 'classnames';
+
+import {
+ CreateWarehouseFormSchema,
+ EditWarehouseFormSchema,
+} from './WarehouseTransferForm.schema';
+
+import WarehouseTransferFormHeader from './WarehouseTransferFormHeader';
+import WarehouseTransferEditorField from './WarehouseTransferEditorField';
+import WarehouseTransferFormFooter from './WarehouseTransferFormFooter';
+import WarehouseTransferFormDialog from './WarehouseTransferFormDialog';
+import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+
+import { compose, orderingLinesIndexes, transactionNumber } from 'utils';
+import { defaultWareTransferEntry, defaultWarehouseTransfer } from './utils';
+
+function WarehouseTransferForm({
+ // #withSettings
+ warehouseTransferNextNumber,
+ warehouseTransferNumberPrefix,
+ warehouseTransferIncrementMode,
+}) {
+ const history = useHistory();
+
+ // WarehouseTransfer number.
+ const warehouseTransferNumber = transactionNumber(
+ warehouseTransferNumberPrefix,
+ warehouseTransferNextNumber,
+ );
+
+ // Form initial values.
+ const initialValues = React.useMemo(
+ () => ({
+ ...defaultWarehouseTransfer,
+ }),
+ [],
+ );
+
+ // Handles form submit.
+ const handleSubmit = (values, { setSubmitting, setErrors, resetForm }) => {
+ // Transformes the values of the form to request.
+ const form = {};
+
+ // Handle the request success.
+ const onSuccess = () => {};
+
+ // Handle the request error.
+ const onError = ({
+ response: {
+ data: { errors },
+ },
+ }) => {
+ setSubmitting(false);
+ };
+ };
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default compose(withDashboardActions)(WarehouseTransferForm);
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.schema.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.schema.js
new file mode 100644
index 000000000..efe3afe45
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.schema.js
@@ -0,0 +1,28 @@
+import * as Yup from 'yup';
+import intl from 'react-intl-universal';
+import { DATATYPES_LENGTH } from 'common/dataTypes';
+
+const Schema = Yup.object().shape({
+ date: Yup.date().required().label(intl.get('date')),
+ transfer_number: Yup.string()
+ .max(DATATYPES_LENGTH.STRING)
+ .label(intl.get('transfer_number')),
+ from_warehouse: Yup.number().required().label(intl.get('from_warehouse')),
+ to_warehouse: Yup.number().required().label(intl.get('from_warehouse')),
+ reason: Yup.string()
+ .trim()
+ .min(1)
+ .max(DATATYPES_LENGTH.STRING)
+ .label(intl.get('reason')),
+ entries: Yup.array().of(
+ Yup.object().shape({
+ item_id: Yup.number().nullable(),
+ source_warehouse: Yup.number().nullable(),
+ destination_warehouse: Yup.number().nullable(),
+ quantity: Yup.number().nullable().max(DATATYPES_LENGTH.INT_10),
+ }),
+ ),
+});
+
+export const CreateWarehouseFormSchema = Schema;
+export const EditWarehouseFormSchema = Schema;
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormDialog.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormDialog.js
new file mode 100644
index 000000000..0471ff6a3
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormDialog.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import WarehouseTransferNumberDialog from '../../Dialogs/WarehouseTransferNumberDialog';
+import { useFormikContext } from 'formik';
+
+/**
+ * Warehouse transfer form dialog.
+ */
+export default function WarehouseTransferFormDialog() {
+ // Update the form once the credit number form submit confirm.
+ const handleWarehouseNumberFormConfirm = ({ incrementNumber, manually }) => {
+ setFieldValue('transfer_no', incrementNumber || '');
+ setFieldValue('transfer_no_manually', manually);
+ };
+ const { setFieldValue } = useFormikContext();
+ return (
+
+
+
+ );
+}
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormEntriesTable.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormEntriesTable.js
new file mode 100644
index 000000000..1d1ca8141
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormEntriesTable.js
@@ -0,0 +1,42 @@
+import React from 'react';
+
+import { useWarehouseTransferTableColumns } from '../utils';
+import { DataTableEditable } from 'components';
+import { compose, saveInvoke, updateTableCell } from 'utils';
+
+/**
+ * Warehouse transfer form entries table.
+ */
+export default function WarehouseTransferFormEntriesTable({
+ // #ownProps
+ items,
+ entries,
+ onUpdateData,
+ errors,
+}) {
+ // Retrieve the warehouse transfer table columns.
+ const columns = useWarehouseTransferTableColumns();
+
+ // Handle update data.
+ const handleUpdateData = React.useCallback(
+ (rowIndex, columnId, value) => {
+ const newRows = compose(updateTableCell(rowIndex, columnId, value))(
+ entries,
+ );
+ onUpdateData(newRows);
+ },
+ [onUpdateData, entries],
+ );
+
+ return (
+
+ );
+}
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooter.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooter.js
new file mode 100644
index 000000000..7e0a70ff5
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooter.js
@@ -0,0 +1,42 @@
+import React from 'react';
+import classNames from 'classnames';
+import { FormGroup, TextArea } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'components';
+import { FastField, ErrorMessage } from 'formik';
+import { Row, Col, Postbox } from 'components';
+import { CLASSES } from 'common/classes';
+import { inputIntent } from 'utils';
+
+export default function WarehouseTransferFormFooter() {
+ return (
+
+
}
+ defaultOpen={false}
+ >
+
+
+ {/*------------ reason -----------*/}
+
+ {({ field, meta: { error, touched } }) => (
+ }
+ className={'form-group--reason'}
+ intent={inputIntent({ error, touched })}
+ helperText={}
+ >
+
+
+ )}
+
+
+
+
+
+ );
+}
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeader.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeader.js
new file mode 100644
index 000000000..3137b1e99
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeader.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import classNames from 'classnames';
+import { useFormikContext } from 'formik';
+import intl from 'react-intl-universal';
+import { CLASSES } from 'common/classes';
+
+import WarehouseTransferFormHeaderFields from './WarehouseTransferFormHeaderFields';
+
+/**
+ * Warehose transfer form header section.
+ */
+function WarehouseTransferFormHeader() {
+ return (
+
+
+
+ );
+}
+
+export default WarehouseTransferFormHeader;
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeaderFields.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeaderFields.js
new file mode 100644
index 000000000..c036eb167
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeaderFields.js
@@ -0,0 +1,212 @@
+import React from 'react';
+import {
+ FormGroup,
+ InputGroup,
+ TextArea,
+ Position,
+ ControlGroup,
+} from '@blueprintjs/core';
+import { DateInput } from '@blueprintjs/datetime';
+import { FastField, Field, ErrorMessage } from 'formik';
+import { FormattedMessage as T } from 'components';
+import { momentFormatter, compose, tansformDateValue } from 'utils';
+import classNames from 'classnames';
+
+import { CLASSES } from 'common/classes';
+import {
+ AccountsSelectList,
+ FieldRequiredHint,
+ Icon,
+ InputPrependButton,
+} from 'components';
+import { inputIntent, handleDateChange } from 'utils';
+import { useWarehouseTransferFormContext } from './WarehouseTransferFormProvider';
+import { useObserveTransferNoSettings } from './utils';
+import withSettings from 'containers/Settings/withSettings';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+
+/**
+ * Warehouse transfer form header fields.
+ */
+function WarehouseTransferFormHeaderFields({
+ // #withDialogActions
+ openDialog,
+
+ // #withSettings
+ warehouseTransferAutoIncrement,
+ warehouseTransferNextNumber,
+ warehouseTransferNumberPrefix,
+}) {
+ const { accounts } = useWarehouseTransferFormContext();
+
+ // Handle warehouse transfer number changing.
+ const handleTransferNumberChange = () => {
+ openDialog('warehouse-transfer-no-form');
+ };
+
+ // Handle transfer no. field blur.
+ const handleTransferNoBlur = (form, field) => (event) => {
+ const newValue = event.target.value;
+
+ if (field.value !== newValue && warehouseTransferAutoIncrement) {
+ openDialog('warehouse-transfer-no-form', {
+ initialFormValues: {
+ manualTransactionNo: newValue,
+ incrementMode: 'manual-transaction',
+ },
+ });
+ }
+ };
+
+ // Syncs transfer number settings with form.
+ useObserveTransferNoSettings(
+ warehouseTransferNumberPrefix,
+ warehouseTransferNextNumber,
+ );
+
+ return (
+
+ {/* ----------- Date ----------- */}
+
+ {({ form, field: { value }, meta: { error, touched } }) => (
+ }
+ inline={true}
+ labelInfo={}
+ className={classNames('form-group--date', CLASSES.FILL)}
+ intent={inputIntent({ error, touched })}
+ helperText={}
+ >
+ {
+ form.setFieldValue('date', formattedDate);
+ })}
+ popoverProps={{ position: Position.BOTTOM_LEFT, minimal: true }}
+ inputProps={{
+ leftIcon: ,
+ }}
+ />
+
+ )}
+
+ {/* ----------- Transfer number ----------- */}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ labelInfo={}
+ inline={true}
+ className={classNames('form-group--transfer-no', CLASSES.FILL)}
+ intent={inputIntent({ error, touched })}
+ helperText={}
+ >
+
+
+ ,
+ }}
+ tooltip={true}
+ tooltipProps={{
+ content: (
+
+ ),
+ position: Position.BOTTOM_LEFT,
+ }}
+ />
+
+
+ )}
+
+ {/* ----------- Form Warehouse ----------- */}
+
+ {({ form, field: { value }, meta: { error, touched } }) => (
+ }
+ className={classNames(
+ 'form-group--warehouse-transfer',
+ CLASSES.FILL,
+ )}
+ inline={true}
+ labelInfo={}
+ intent={inputIntent({ error, touched })}
+ helperText={}
+ >
+ {
+ form.setFieldValue('form_warehouse', account.id);
+ }}
+ defaultSelectText={'Select Warehouse Transfer'}
+ selectedAccountId={value}
+ popoverFill={true}
+ allowCreate={true}
+ />
+
+ )}
+
+ {/* ----------- To Warehouse ----------- */}
+
+ {({ form, field: { value }, meta: { error, touched } }) => (
+ }
+ className={classNames(
+ 'form-group--warehouse-transfer',
+ CLASSES.FILL,
+ )}
+ inline={true}
+ labelInfo={}
+ intent={inputIntent({ error, touched })}
+ helperText={}
+ >
+ {
+ form.setFieldValue('to_warehouse', account.id);
+ }}
+ defaultSelectText={'Select Warehouse Transfer'}
+ selectedAccountId={value}
+ popoverFill={true}
+ allowCreate={true}
+ />
+
+ )}
+
+ {/*------------ reason -----------*/}
+
+ {({ field, meta: { error, touched } }) => (
+ }
+ className={'form-group--reason'}
+ intent={inputIntent({ error, touched })}
+ inline={true}
+ helperText={}
+ >
+
+
+ )}
+
+
+ );
+}
+
+export default compose(
+ withDialogActions,
+ withSettings(({ warehouseTransferSettings }) => ({
+ warehouseTransferAutoIncrement: warehouseTransferSettings?.autoIncrement,
+ warehouseTransferNextNumber: warehouseTransferSettings?.nextNumber,
+ warehouseTransferNumberPrefix: warehouseTransferSettings?.numberPrefix,
+ })),
+)(WarehouseTransferFormHeaderFields);
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormPage.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormPage.js
new file mode 100644
index 000000000..b9862488c
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormPage.js
@@ -0,0 +1,16 @@
+import React from 'react';
+
+import '../../../style/pages/WarehouseTransfers/PageForm.scss'
+import WarehouseTransferForm from './WarehouseTransferForm';
+import { WarehouseTransferFormProvider } from './WarehouseTransferFormProvider';
+
+/**
+ * WarehouseTransfer form page.
+ */
+export default function WarehouseTransferFormPage() {
+ return (
+
+
+
+ );
+}
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
new file mode 100644
index 000000000..664262689
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
@@ -0,0 +1,42 @@
+import React from 'react';
+import DashboardInsider from 'components/Dashboard/DashboardInsider';
+import { useItems, useAccounts } from 'hooks/query';
+import { ITEMS_FILTER_ROLES_QUERY } from './utils.js';
+
+const WarehouseFormContext = React.createContext();
+
+/**
+ * Warehouse transfer form provider.
+ */
+function WarehouseTransferFormProvider({ warehouseTransferId, ...props }) {
+ // Handle fetch Items data table or list
+ const {
+ data: { items },
+ isFetching: isItemsFetching,
+ isLoading: isItemsLoading,
+ } = useItems({
+ page_size: 10000,
+ stringified_filter_roles: ITEMS_FILTER_ROLES_QUERY,
+ });
+
+ // Fetch accounts list.
+ const { data: accounts, isLoading: isAccountsLoading } = useAccounts();
+
+ // Provider payload.
+ const provider = {
+ items,
+ accounts,
+ };
+ return (
+
+
+
+ );
+}
+const useWarehouseTransferFormContext = () =>
+ React.useContext(WarehouseFormContext);
+
+export { WarehouseTransferFormProvider, useWarehouseTransferFormContext };
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/utils.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/utils.js
new file mode 100644
index 000000000..0fac70605
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/utils.js
@@ -0,0 +1,55 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import clsx from 'classnames';
+import { useFormikContext } from 'formik';
+import moment from 'moment';
+
+import { transactionNumber, repeatValue } from 'utils';
+
+export const defaultWareTransferEntry = {
+ index: 0,
+ item_id: '',
+ source_warehouse: '100',
+ destination_warehouse: '0',
+ quantity: '',
+};
+
+export const MIN_LINES_NUMBER = 4;
+
+export const defaultWarehouseTransfer = {
+ date: moment(new Date()).format('YYYY-MM-DD'),
+ transfer_number: '',
+ from_warehouse: '',
+ to_warehouse: '',
+ reason: '',
+ entries: [...repeatValue(defaultWareTransferEntry, MIN_LINES_NUMBER)],
+};
+
+export const ITEMS_FILTER_ROLES_QUERY = JSON.stringify([
+ {
+ index: 1,
+ fieldKey: 'sellable',
+ value: true,
+ condition: '&&',
+ comparator: 'equals',
+ },
+ {
+ index: 2,
+ fieldKey: 'active',
+ value: true,
+ condition: '&&',
+ comparator: 'equals',
+ },
+]);
+
+/**
+ * Syncs transfer no. settings with form.
+ */
+export const useObserveTransferNoSettings = (prefix, nextNumber) => {
+ const { setFieldValue } = useFormikContext();
+
+ React.useEffect(() => {
+ const transferNo = transactionNumber(prefix, nextNumber);
+ setFieldValue('transfer_no', transferNo);
+ }, [setFieldValue, prefix, nextNumber]);
+};
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersActionsBar.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersActionsBar.js
new file mode 100644
index 000000000..f3ec0832e
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersActionsBar.js
@@ -0,0 +1,99 @@
+import React from 'react';
+import { useHistory } from 'react-router-dom';
+import {
+ Button,
+ Classes,
+ NavbarDivider,
+ NavbarGroup,
+ Intent,
+ Alignment,
+} from '@blueprintjs/core';
+import {
+ Icon,
+ FormattedMessage as T,
+ AdvancedFilterPopover,
+ DashboardFilterButton,
+ DashboardRowsHeightButton,
+ DashboardActionViewsList,
+} from 'components';
+import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
+
+import withSettingsActions from 'containers/Settings/withSettingsActions';
+
+import { compose } from 'utils';
+
+/**
+ * Warehouse Transfers actions bar.
+ */
+function WarehouseTransfersActionsBar({
+ // #withSettingsActions
+ addSetting,
+}) {
+ const history = useHistory();
+
+ // Handle new warehouse transfer button click.
+ const handleClickNewWarehouseTransfer = () => {
+ history.push('/warehouse-transfers/new');
+ };
+
+ // Handle click a refresh warehouse transfers
+ const handleRefreshBtnClick = () => {
+ // refresh();
+ };
+
+ // Handle views tab change.
+ const handleTabChange = (view) => {};
+
+ // Handle table row size change.
+ const handleTableRowSizeChange = (size) => {};
+ return (
+
+
+
+
+
+ }
+ text={}
+ onClick={handleClickNewWarehouseTransfer}
+ />
+
+ }
+ text={}
+ />
+ }
+ text={}
+ />
+ }
+ text={}
+ />
+
+
+
+
+
+ }
+ // onClick={handleRefreshBtnClick}
+ />
+
+
+ );
+}
+
+export default compose(withSettingsActions)(WarehouseTransfersActionsBar);
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersDataTable.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersDataTable.js
new file mode 100644
index 000000000..5a571df84
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersDataTable.js
@@ -0,0 +1,108 @@
+import React from 'react';
+import { useHistory } from 'react-router-dom';
+
+import WarehouseTransfersEmptyStatus from './WarehouseTransfersEmptyStatus';
+
+import { DataTable, DashboardContentTable } from 'components';
+import { TABLES } from 'common/tables';
+import { useMemorizedColumnsWidths } from 'hooks';
+
+import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
+import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
+
+import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import withAlertsActions from 'containers/Alert/withAlertActions';
+import withSettings from '../../Settings/withSettings';
+
+import { useWarehouseTransfersTableColumns, ActionsMenu } from './components';
+import { useWarehouseTranfersListContext } from './WarehouseTransfersListProvider';
+
+import { compose } from 'utils';
+
+/**
+ * Warehouse transfers datatable.
+ */
+function WarehouseTransfersDataTable({
+ // #withAlertsActions
+ openAlert,
+
+ // #withDrawerActions
+ openDrawer,
+
+ // #withDialogAction
+ openDialog,
+}) {
+ const history = useHistory();
+
+ // Warehouse transfers list context.
+ const { isEmptyStatus } = useWarehouseTranfersListContext();
+
+ // Invoices table columns.
+ const columns = useWarehouseTransfersTableColumns();
+
+ // Handle view detail.
+ const handleViewDetailWarehouseTransfer = () => {
+ openDrawer('warehouse-transfer-detail-drawer', {});
+ };
+
+ // Handle edit warehouse transfer.
+ const handleEditWarehouseTransfer = () => {};
+
+ // Handle delete warehouse transfer.
+ const handleDeleteWarehouseTransfer = () => {};
+
+ // Handle cell click.
+ const handleCellClick = (cell, event) => {};
+
+ // Local storage memorizing columns widths.
+ const [initialColumnsWidths, , handleColumnResizing] =
+ useMemorizedColumnsWidths(TABLES.WAREHOUSETRANSFERS);
+
+ // Handles fetch data once the table state change.
+ const handleDataTableFetchData = React.useCallback(
+ ({ pageSize, pageIndex, sortBy }) => {},
+ [],
+ );
+
+ // Display invoice empty status instead of the table.
+ if (isEmptyStatus) {
+ return ;
+ }
+
+ return (
+
+
+
+ );
+}
+export default compose(
+ withDashboardActions,
+ withAlertsActions,
+ withDrawerActions,
+ withDialogActions,
+)(WarehouseTransfersDataTable);
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersEmptyStatus.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersEmptyStatus.js
new file mode 100644
index 000000000..2672f4be0
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersEmptyStatus.js
@@ -0,0 +1,32 @@
+import React from 'react';
+import { useHistory } from 'react-router-dom';
+import { Button, Intent } from '@blueprintjs/core';
+import { EmptyStatus } from 'components';
+import { Can, FormattedMessage as T } from 'components';
+
+export default function WarehouseTransfersEmptyStatus() {
+ const history = useHistory();
+
+ return (
+ }
+ description={}
+ action={
+ <>
+
+
+ >
+ }
+ />
+ );
+}
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersList.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersList.js
new file mode 100644
index 000000000..8f5eeb3a4
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersList.js
@@ -0,0 +1,25 @@
+import React from 'react';
+
+// style..
+import { DashboardPageContent } from 'components';
+import WarehouseTransfersActionsBar from './WarehouseTransfersActionsBar';
+
+import WarehouseTransfersViewTabs from './WarehouseTransfersViewTabs';
+import WarehouseTransfersDataTable from './WarehouseTransfersDataTable';
+
+import { WarehouseTransfersListProvider } from './WarehouseTransfersListProvider';
+import { compose } from 'utils';
+
+function WarehouseTransfersList({}) {
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+export default WarehouseTransfersList;
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersListProvider.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersListProvider.js
new file mode 100644
index 000000000..24714d977
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersListProvider.js
@@ -0,0 +1,29 @@
+import React from 'react';
+import { isEmpty } from 'lodash';
+
+import DashboardInsider from 'components/Dashboard/DashboardInsider';
+
+const WarehouseTransfersListContext = React.createContext();
+
+/**
+ * WarehouseTransfer data provider
+ */
+function WarehouseTransfersListProvider({ ...props }) {
+ // Detarmines the datatable empty status.
+ const isEmptyStatus = false;
+
+ // Provider payload.
+ const provider = {
+ isEmptyStatus,
+ };
+ return (
+
+
+
+ );
+}
+
+const useWarehouseTranfersListContext = () =>
+ React.useContext(WarehouseTransfersListContext);
+
+export { WarehouseTransfersListProvider, useWarehouseTranfersListContext };
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersViewTabs.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersViewTabs.js
new file mode 100644
index 000000000..8be06aa31
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersViewTabs.js
@@ -0,0 +1,37 @@
+import React from 'react';
+import { useHistory } from 'react-router';
+import { Alignment, Navbar, NavbarGroup } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'components';
+
+import { DashboardViewsTabs } from 'components';
+
+import { useWarehouseTranfersListContext } from './WarehouseTransfersListProvider';
+
+import { compose } from 'utils';
+
+/**
+ * Warehouse transfer view tabs.
+ */
+function WarehouseTransfersViewTabs() {
+ // Handles click a new view tab.
+ const handleClickNewView = () => {};
+
+ // Handles the active tab chaing.
+ const handleTabsChange = (customView) => {};
+
+ return (
+
+
+ }
+ onNewViewTabClick={handleClickNewView}
+ onChange={handleTabsChange}
+ />
+
+
+ );
+}
+
+export default WarehouseTransfersViewTabs;
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/components.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/components.js
new file mode 100644
index 000000000..0a4eb0dab
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/components.js
@@ -0,0 +1,121 @@
+import React from 'react';
+import {
+ Intent,
+ Tag,
+ Menu,
+ MenuItem,
+ MenuDivider,
+ ProgressBar,
+} from '@blueprintjs/core';
+import intl from 'react-intl-universal';
+import clsx from 'classnames';
+import { CLASSES } from '../../../common/classes';
+import { safeCallback } from 'utils';
+import {
+ FormatDateCell,
+ FormattedMessage as T,
+ AppToaster,
+ Choose,
+ If,
+ Icon,
+ Can,
+} from 'components';
+
+export function ActionsMenu({
+ payload: { onEdit, onDelete, onViewDetails, onPrint },
+ row: { original },
+}) {
+ return (
+
+ );
+}
+
+/**
+ * Retrieve warehouse transfer table columns.
+ */
+export function useWarehouseTransfersTableColumns() {
+ return React.useMemo(
+ () => [
+ {
+ id: 'date',
+ Header: intl.get('date'),
+ accessor: 'date',
+ Cell: FormatDateCell,
+ width: 120,
+ className: 'date',
+ clickable: true,
+ textOverview: true,
+ },
+ {
+ id: 'transfer_no',
+ Header: intl.get('warehouse_transfer.column.transfer_no'),
+ accessor: 'transfer_no',
+ width: 120,
+ className: 'transfer_no',
+ clickable: true,
+ textOverview: true,
+ },
+ {
+ id: 'from_warehouse',
+ Header: intl.get('warehouse_transfer.column.from_warehouse'),
+ accessor: 'from_warehouse',
+ width: 150,
+ clickable: true,
+ textOverview: true,
+ },
+ {
+ id: 'to_warehouse',
+ Header: intl.get('warehouse_transfer.column.to_warehouse'),
+ accessor: 'to_warehouse',
+ width: 150,
+ clickable: true,
+ textOverview: true,
+ },
+ {
+ id: 'reason',
+ Header: intl.get('reason'),
+ accessor: 'reason',
+ className: 'reason',
+ width: 120,
+ clickable: true,
+ textOverview: true,
+ },
+ {
+ id: 'status',
+ Header: intl.get('status'),
+ // accessor: (row) => statusAccessor(row),
+ width: 160,
+ className: 'status',
+ clickable: true,
+ },
+ {
+ id: 'created_at',
+ Header: intl.get('created_at'),
+ accessor: 'created_at',
+ Cell: FormatDateCell,
+ width: 120,
+ clickable: true,
+ },
+ ],
+ [],
+ );
+}
diff --git a/src/containers/WarehouseTransfers/utils.js b/src/containers/WarehouseTransfers/utils.js
new file mode 100644
index 000000000..e3d67946c
--- /dev/null
+++ b/src/containers/WarehouseTransfers/utils.js
@@ -0,0 +1,64 @@
+import React from 'react';
+import { CLASSES } from 'common/classes';
+import { MoneyFieldCell, FormatDateCell, AppToaster, T } from 'components';
+import { InputGroupCell, ItemsListCell } from 'components/DataTableCells';
+
+// Index table cell.
+export function IndexTableCell({ row: { index } }) {
+ return {index + 1};
+}
+
+/**
+ * Retrieves warehouse transfer table columns.
+ * @returns
+ */
+export const useWarehouseTransferTableColumns = () => {
+ return React.useMemo(
+ () => [
+ {
+ Header: '#',
+ accessor: 'index',
+ Cell: IndexTableCell,
+ width: 40,
+ disableResizing: true,
+ disableSortBy: true,
+ className: 'index',
+ },
+ {
+ id: 'item_id',
+ Header: 'Item Name',
+ accessor: 'item_id',
+ Cell: ItemsListCell,
+ disableSortBy: true,
+ width: '120',
+ className: 'item',
+ fieldProps: { allowCreate: true },
+ },
+ {
+ id: 'source_warehouse',
+ Header: 'Source Warehouse',
+ accessor: 'source_warehouse',
+ disableSortBy: true,
+ align: 'right',
+ width: '100',
+ },
+ {
+ id: 'destination_warehouse',
+ Header: 'Destination Warehouse',
+ accessor: 'destination_warehouse',
+ disableSortBy: true,
+ align: 'right',
+ width: '100',
+ },
+ {
+ Header: 'Transfer Quantity',
+ accessor: 'quantity',
+ Cell: MoneyFieldCell,
+ disableSortBy: true,
+ align: 'right',
+ width: '150',
+ },
+ ],
+ [],
+ );
+};
diff --git a/src/hooks/query/settings.js b/src/hooks/query/settings.js
index bc28b9e57..7e56d6cac 100644
--- a/src/hooks/query/settings.js
+++ b/src/hooks/query/settings.js
@@ -144,6 +144,17 @@ export function useSettingsVendorCredits(props) {
);
}
+/**
+ * Retrieve warehouse transfer settings.
+ */
+export function useSettingsWarehouseTransfers(props) {
+ return useSettingsQuery(
+ [t.SETTING, t.SETTING_WAREHOUSE_TRANSFER],
+ { group: 'warehouse_transfer' },
+ props,
+ );
+}
+
/**
* Retrieve SMS Notifications settings.
*/
diff --git a/src/hooks/query/types.js b/src/hooks/query/types.js
index 27d7e3f77..1bd1584b3 100644
--- a/src/hooks/query/types.js
+++ b/src/hooks/query/types.js
@@ -146,6 +146,7 @@ const SETTING = {
SETTING_EDIT_SMS_NOTIFICATION: 'SETTING_EDIT_SMS_NOTIFICATION',
SETTING_CREDIT_NOTES: 'SETTING_CREDIT_NOTES',
SETTING_VENDOR_CREDITS: 'SETTING_VENDOR_CREDITS',
+ SETTING_WAREHOUSE_TRANSFER: 'SETTING_WAREHOUSE_TRANSFER',
};
const ORGANIZATIONS = {
@@ -196,6 +197,11 @@ const WAREHOUSES = {
WAREHOUSES: 'WAREHOUSES',
};
+const WAREHOUSE_TRANSFERS = {
+ WAREHOUSE_TRANSFER: 'WAREHOUSE_TRANSFER',
+ WAREHOUSE_TRANSFERS: 'WAREHOUSE_TRANSFERS',
+};
+
export default {
...ACCOUNTS,
...BILLS,
@@ -223,5 +229,6 @@ export default {
...CREDIT_NOTES,
...VENDOR_CREDIT_NOTES,
...TARNSACTIONS_LOCKING,
- ...WAREHOUSES
+ ...WAREHOUSES,
+ ...WAREHOUSE_TRANSFERS,
};
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index 0bf96dab9..8f754473d 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -642,6 +642,7 @@
"Estimate_number_settings": "Estimate Number Settings",
"receipt_number_settings": "Receipt Number Settings",
"invoice_number_settings": "Invoice Number Settings",
+ "warehouse_transfer_no_settings": "Transfer Number Settings",
"transaction_number_settings": "Transaction Number Settings",
"receipt_number": "Receipt Number",
"estimate_number_is_not_unqiue": "Estimate number is not unqiue",
@@ -1770,9 +1771,6 @@
"credit_note_preview.dialog.title": "Credit Note PDF Preview",
"payment_receive_preview.dialog.title": "Payment Receive PDF Preview",
- "credit_note_preview.dialog.title": "Credit Note PDF Preview",
- "payment_receive_preview.dialog.title": "Payment Receive PDF Preview",
-
"warehouses.label": "Warehouses",
"warehouses.label.new_warehouse": "New Warehouse",
"warehouse.dialog.label.new_warehouse": "New Warehouse",
@@ -1795,6 +1793,30 @@
"warehouses.action.edit_warehouse": "Edit Warehouse",
"warehouses.action.delete_warehouse": "Delete Warehouse",
"warehouses.action.make_as_parimary": "Mark as Primary",
- "warehouse.alert.delete_message":"The warehouse has been deleted successfully",
- "warehouse.once_delete_this_warehouse":"Once you delete this warehouse, you won't be able to restore it later. Are you sure you want to delete this warehouse?"
+ "warehouse.alert.delete_message": "The warehouse has been deleted successfully",
+ "warehouse.once_delete_this_warehouse": "Once you delete this warehouse, you won't be able to restore it later. Are you sure you want to delete this warehouse?",
+
+ "sidebar_warehouse_transfer": "Warehouse Transfers",
+ "warehouse_transfer.label.transfer_no": "Transfer No",
+ "warehouse_transfer.label.form_warehouse": "Form Warehouse",
+ "warehouse_transfer.label.to_warehouse": "To Warehouse",
+ "warehouse_transfer.label.warehouse_transfer_detail": "Warehouse Transfer details",
+ "warehouse_transfer.action.edit_warehouse_transfer": "Edit Warehouse Transfer",
+ "warehouse_transfer.action.delete_warehouse_transfer": "Delete Warehouse Transfer",
+ "warehouse_transfer.action.new_warehouse_transfer": "New Warehouse Transfer",
+ "warehouse_transfer.column.transfer_no": "Transfer #",
+ "warehouse_transfer.column.from_warehouse": "From Warehouse",
+ "warehouse_transfer.column.to_warehouse": "To Warehouse",
+ "warehouse_transfer.column.item_name": "Item Name",
+ "warehouse_transfer.column.transfer_quantity": "Transfer Quantity",
+ "warehouse_transfer.auto_increment.auto": "Your transfer numbers are set on auto-increment mode. Are you sure changing this setting?",
+ "warehouse_transfer.auto_increment.manually": "Your transfer numbers are set on manual mode. Are you sure chaning this settings?",
+ "warehouse_transfer.setting_your_auto_generated_transfer_no": "Setting your auto-generated transfer number",
+ "warehouse_transfer.drawer.title": "Warehouse Transfer details ({number})",
+ "warehouse_transfer.drawer.label.transfer_number": "Transfer Number",
+ "warehouse_transfer.drawer.label.from_warehouse": "From Warehouse",
+ "warehouse_transfer.drawer.label.to_warehouse": "To Warehouse",
+ "warehouse_transfer.label.edit_warehouse_transfer": "Edit Warehouse Transfer",
+ "warehouse_transfer.label.new_warehouse_transfer": "New Warehouse Transfer",
+ "warehouse_transfer.label.warehouse_transfer_list": "Warehouse Transfers List"
}
\ No newline at end of file
diff --git a/src/routes/dashboard.js b/src/routes/dashboard.js
index 491b32238..428fb447b 100644
--- a/src/routes/dashboard.js
+++ b/src/routes/dashboard.js
@@ -117,6 +117,36 @@ export const getDashboardRoutes = () => [
defaultSearchResource: RESOURCES_TYPES.ITEM,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
+ // Warehouse Transfer.
+ {
+ path: `/warehouse-transfers/:id/edit`,
+ component: lazy(() => import('containers/Items/ItemFormPage')),
+ name: 'warehouse-transfer-edit',
+ pageTitle: intl.get('warehouse_transfer.label.edit_warehouse_transfer'),
+ backLink: true,
+ },
+ {
+ path: `/warehouse-transfers/new`,
+ component: lazy(() =>
+ import(
+ '../containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormPage'
+ ),
+ ),
+ name: 'warehouse-transfer-new',
+ pageTitle: intl.get('warehouse_transfer.label.new_warehouse_transfer'),
+ backLink: true,
+ },
+ {
+ path: `/warehouse-transfers`,
+ component: lazy(() =>
+ import(
+ '../containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersList'
+ ),
+ ),
+ pageTitle: intl.get('warehouse_transfer.label.warehouse_transfer_list'),
+ // defaultSearchResource: RESOURCES_TYPES.ITEM,
+ // subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
+ },
// Financial Reports.
{
diff --git a/src/store/settings/settings.reducer.js b/src/store/settings/settings.reducer.js
index 853ab0589..ee140bf98 100644
--- a/src/store/settings/settings.reducer.js
+++ b/src/store/settings/settings.reducer.js
@@ -58,6 +58,9 @@ const initialState = {
vendorCredit: {
tableSize: 'medium',
},
+ warehouseTransfer: {
+ tableSize: 'medium',
+ },
},
};
diff --git a/src/style/pages/WarehouseTransfers/PageForm.scss b/src/style/pages/WarehouseTransfers/PageForm.scss
new file mode 100644
index 000000000..27fe8d405
--- /dev/null
+++ b/src/style/pages/WarehouseTransfers/PageForm.scss
@@ -0,0 +1,50 @@
+body.page-warehouse-transfer-new,
+body.page-warehouse-transfer-edit {
+ .dashboard__footer {
+ display: none;
+ }
+}
+
+.dashboard__insider--warehouse-transfer-form {
+ padding-bottom: 64px;
+}
+
+.page-form--warehouse-transfer {
+ $self: '.page-form';
+
+ #{$self}__header {
+ display: flex;
+
+ &-fields {
+ flex: 1 0 0;
+ }
+
+ .bp3-label {
+ min-width: 150px;
+ }
+ .bp3-form-content {
+ width: 100%;
+ }
+
+ .bp3-form-group {
+ &.bp3-inline {
+ max-width: 450px;
+ }
+ }
+ .col--date {
+ max-width: 435px;
+ }
+ }
+
+ #{$self}__footer {
+ .form-group--reason {
+ max-width: 450px;
+ width: 100%;
+
+ textarea {
+ width: 100%;
+ min-height: 60px;
+ }
+ }
+ }
+}