From 13da985864d69fe759300c1f6942cb63c0244174 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 01/30] 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 | 7 +
src/lang/en/index.json | 38 +++-
src/routes/dashboard.js | 30 +++
src/store/settings/settings.reducer.js | 3 +
.../pages/WarehouseTransfers/PageForm.scss | 50 +++++
43 files changed, 1787 insertions(+), 10 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={
+ <>
+ {
+ history.push('/warehouse-transfers/new');
+ }}
+ >
+
+
+
+
+
+ >
+ }
+ />
+ );
+}
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 (
+
+ }
+ text={intl.get('view_details')}
+ onClick={safeCallback(onViewDetails, original)}
+ />
+
+ }
+ text={intl.get('warehouse_transfer.action.edit_warehouse_transfer')}
+ onClick={safeCallback(onEdit, original)}
+ />
+
+ }
+ />
+
+ );
+}
+
+/**
+ * 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 d98f99db8..1b4a5ec3e 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 = {
@@ -191,6 +192,11 @@ const TARNSACTIONS_LOCKING = {
TRANSACTIONS_LOCKING: 'TRANSACTIONS_LOCKING',
};
+const WAREHOUSE_TRANSFERS = {
+ WAREHOUSE_TRANSFER: 'WAREHOUSE_TRANSFER',
+ WAREHOUSE_TRANSFERS: 'WAREHOUSE_TRANSFERS',
+};
+
export default {
...ACCOUNTS,
...BILLS,
@@ -218,4 +224,5 @@ export default {
...CREDIT_NOTES,
...VENDOR_CREDIT_NOTES,
...TARNSACTIONS_LOCKING,
+ ...WAREHOUSE_TRANSFERS,
};
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index 4147975a2..bbee7801e 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",
@@ -1738,19 +1739,38 @@
"global_error.you_dont_have_permissions": "You do not have permissions to access this page.",
"global_error.transactions_locked": "Transactions before {lockedToDate} has been locked. Hence action cannot be performed.",
"global_error.authorized_user_inactive": "The authorized user is inactive.",
-
"the_vendor_has_been_inactivated_successfully": "The contact has been inactivated successfully.",
-
"vendor.alert.activated_message": "The vendor has been activated successfully.",
- "vendor.alert.are_you_sure_want_to_inactivate_this_vendor":"Are you sure want to inactivate this vendor? You will to able to activate it later.",
+ "vendor.alert.are_you_sure_want_to_inactivate_this_vendor": "Are you sure want to inactivate this vendor? You will to able to activate it later.",
"vendor.alert.inactivated_message": "The vendor has been inactivated successfully.",
"vendor.alert.are_you_sure_want_to_activate_this_vendor": "Are you sure want to activate this vendor? You will to able to inactivate it later.",
-
- "customer.alert.activated_message":"The customer has been activated successfully.",
+ "customer.alert.activated_message": "The customer has been activated successfully.",
"customer.alert.are_you_sure_want_to_activate_this_customer": "Are you sure want to activate this customer? You will to able to inactivate it later.",
"customer.alert.inactivated_message": "The customer has been inactivated successfully.",
- "customer.alert.are_you_sure_want_to_inactivate_this_customer":"Are you sure want to inactivate this customer? You will to able to activate it later.",
-
- "credit_note_preview.dialog.title":"Credit Note PDF Preview",
- "payment_receive_preview.dialog.title":"Payment Receive PDF Preview"
+ "customer.alert.are_you_sure_want_to_inactivate_this_customer": "Are you sure want to inactivate this customer? You will to able to activate it later.",
+ "credit_note_preview.dialog.title": "Credit Note PDF Preview",
+ "payment_receive_preview.dialog.title": "Payment Receive PDF Preview",
+ "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;
+ }
+ }
+ }
+}
From 45d9e2cc15fcdb1e484a878b14692a04c7f9dfc8 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Sun, 23 Jan 2022 23:23:40 +0200
Subject: [PATCH 02/30] feat(branches): add branches.
---
src/common/classes.js | 1 +
src/components/DialogsContainer.js | 2 +
.../Preferences/PreferencesTopbar.js | 6 +
src/config/preferencesMenu.js | 5 +-
.../Dialogs/BranchFormDialog/BranchForm.js | 45 +++++
.../BranchFormDialog/BranchForm.schema.js | 15 ++
.../BranchFormDialog/BranchFormContent.js | 17 ++
.../BranchFormDialogContent.js | 20 +++
.../BranchFormDialog/BranchFormFields.js | 157 ++++++++++++++++++
.../BranchFormFloatingActions.js | 46 +++++
.../BranchFormDialog/BranchFormProvider.js | 25 +++
.../Dialogs/BranchFormDialog/index.js | 31 ++++
.../Preferences/Branches/Branches.js | 21 +++
.../Preferences/Branches/BranchesActions.js | 29 ++++
.../Preferences/Branches/BranchesDataTable.js | 36 ++++
.../Preferences/Branches/BranchesProvider.js | 35 ++++
.../Preferences/Branches/components.js | 76 +++++++++
src/containers/Preferences/Branches/index.js | 15 ++
src/lang/en/index.json | 31 +++-
src/routes/preferences.js | 6 +
.../pages/Branches/BranchFormDialog.scss | 39 +++++
21 files changed, 648 insertions(+), 10 deletions(-)
create mode 100644 src/containers/Dialogs/BranchFormDialog/BranchForm.js
create mode 100644 src/containers/Dialogs/BranchFormDialog/BranchForm.schema.js
create mode 100644 src/containers/Dialogs/BranchFormDialog/BranchFormContent.js
create mode 100644 src/containers/Dialogs/BranchFormDialog/BranchFormDialogContent.js
create mode 100644 src/containers/Dialogs/BranchFormDialog/BranchFormFields.js
create mode 100644 src/containers/Dialogs/BranchFormDialog/BranchFormFloatingActions.js
create mode 100644 src/containers/Dialogs/BranchFormDialog/BranchFormProvider.js
create mode 100644 src/containers/Dialogs/BranchFormDialog/index.js
create mode 100644 src/containers/Preferences/Branches/Branches.js
create mode 100644 src/containers/Preferences/Branches/BranchesActions.js
create mode 100644 src/containers/Preferences/Branches/BranchesDataTable.js
create mode 100644 src/containers/Preferences/Branches/BranchesProvider.js
create mode 100644 src/containers/Preferences/Branches/components.js
create mode 100644 src/containers/Preferences/Branches/index.js
create mode 100644 src/style/pages/Branches/BranchFormDialog.scss
diff --git a/src/common/classes.js b/src/common/classes.js
index 6b0872396..d58ecc6f5 100644
--- a/src/common/classes.js
+++ b/src/common/classes.js
@@ -70,6 +70,7 @@ const CLASSES = {
PREFERENCES_PAGE_INSIDE_CONTENT_ACCOUNTANT: 'preferences-page__inside-content--accountant',
PREFERENCES_PAGE_INSIDE_CONTENT_SMS_INTEGRATION: 'preferences-page__inside-content--sms-integration',
PREFERENCES_PAGE_INSIDE_CONTENT_ROLES_FORM: 'preferences-page__inside-content--roles-form',
+ PREFERENCES_PAGE_INSIDE_CONTENT_BRANCHES: 'preferences-page__inside-content--branches',
FINANCIAL_REPORT_INSIDER: 'dashboard__insider--financial-report',
diff --git a/src/components/DialogsContainer.js b/src/components/DialogsContainer.js
index cd8eb745e..204b40264 100644
--- a/src/components/DialogsContainer.js
+++ b/src/components/DialogsContainer.js
@@ -34,6 +34,7 @@ import UnlockingTransactionsDialog from '../containers/Dialogs/UnlockingTransact
import UnlockingPartialTransactionsDialog from '../containers/Dialogs/UnlockingPartialTransactionsDialog';
import CreditNotePdfPreviewDialog from '../containers/Dialogs/CreditNotePdfPreviewDialog';
import PaymentReceivePdfPreviewDialog from '../containers/Dialogs/PaymentReceivePdfPreviewDialog';
+import BranchFormDialog from '../containers/Dialogs/BranchFormDialog';
/**
* Dialogs container.
@@ -78,6 +79,7 @@ export default function DialogsContainer() {
/>
+
);
}
diff --git a/src/components/Preferences/PreferencesTopbar.js b/src/components/Preferences/PreferencesTopbar.js
index 1633ecc8f..41ed14894 100644
--- a/src/components/Preferences/PreferencesTopbar.js
+++ b/src/components/Preferences/PreferencesTopbar.js
@@ -6,6 +6,7 @@ import { CLASSES } from 'common/classes';
import DashboardTopbarUser from 'components/Dashboard/TopbarUser';
import UsersActions from 'containers/Preferences/Users/UsersActions';
import CurrenciesActions from 'containers/Preferences/Currencies/CurrenciesActions';
+import BranchesActions from '../../containers/Preferences/Branches/BranchesActions';
import withDashboard from 'containers/Dashboard/withDashboard';
import { compose } from 'utils';
@@ -35,6 +36,11 @@ function PreferencesTopbar({ preferencesPageTitle }) {
path={'/preferences/currencies'}
component={CurrenciesActions}
/>
+
diff --git a/src/config/preferencesMenu.js b/src/config/preferencesMenu.js
index 031dfe0e1..b42ce876a 100644
--- a/src/config/preferencesMenu.js
+++ b/src/config/preferencesMenu.js
@@ -13,9 +13,12 @@ export default [
},
{
text: ,
-
href: '/preferences/currencies',
},
+ {
+ text: ,
+ href: '/preferences/branches',
+ },
{
text: ,
disabled: false,
diff --git a/src/containers/Dialogs/BranchFormDialog/BranchForm.js b/src/containers/Dialogs/BranchFormDialog/BranchForm.js
new file mode 100644
index 000000000..99f41f76e
--- /dev/null
+++ b/src/containers/Dialogs/BranchFormDialog/BranchForm.js
@@ -0,0 +1,45 @@
+import React from 'react';
+import { Formik } from 'formik';
+
+import { AppToaster } from 'components';
+import { CreateBranchFormSchema } from './BranchForm.schema';
+
+import BranchFormContent from './BranchFormContent';
+import { useBranchFormContext } from './BranchFormProvider';
+
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import { compose } from 'utils';
+
+const defaultInitialValues = {
+ branch_name: '',
+ branch_address_1: '',
+ branch_address_2: '',
+ phone_number: '',
+ email: '',
+ website: '',
+ branch_address_city: '',
+ branch_address_country: '',
+};
+
+function BranchForm({
+ // #withDialogActions
+ closeDialog,
+}) {
+ // Initial form values.
+ const initialValues = {
+ ...defaultInitialValues,
+ };
+
+ // Handles the form submit.
+ const handleFormSubmit = (values, { setSubmitting, setErrors }) => {};
+
+ return (
+
+ );
+}
+export default compose(withDialogActions)(BranchForm);
diff --git a/src/containers/Dialogs/BranchFormDialog/BranchForm.schema.js b/src/containers/Dialogs/BranchFormDialog/BranchForm.schema.js
new file mode 100644
index 000000000..2fe48f301
--- /dev/null
+++ b/src/containers/Dialogs/BranchFormDialog/BranchForm.schema.js
@@ -0,0 +1,15 @@
+import * as Yup from 'yup';
+import intl from 'react-intl-universal';
+
+const Schema = Yup.object().shape({
+ branch_name: Yup.string().required().label(intl.get('branch_name')),
+ branch_address_1: Yup.string().trim(),
+ branch_address_2: Yup.string().trim(),
+ branch_address_city: Yup.string().trim(),
+ branch_address_country: Yup.string().trim(),
+ website: Yup.string().url().nullable(),
+ phone_number: Yup.number(),
+ email: Yup.string().email().nullable(),
+});
+
+export const CreateBranchFormSchema = Schema;
diff --git a/src/containers/Dialogs/BranchFormDialog/BranchFormContent.js b/src/containers/Dialogs/BranchFormDialog/BranchFormContent.js
new file mode 100644
index 000000000..e47e5706e
--- /dev/null
+++ b/src/containers/Dialogs/BranchFormDialog/BranchFormContent.js
@@ -0,0 +1,17 @@
+import React from 'react';
+import { Form } from 'formik';
+
+import BranchFormFields from './BranchFormFields';
+import BranchFormFloatingActions from './BranchFormFloatingActions';
+
+/**
+ * Branch form content.
+ */
+export default function BranchFormContent() {
+ return (
+
+ );
+}
diff --git a/src/containers/Dialogs/BranchFormDialog/BranchFormDialogContent.js b/src/containers/Dialogs/BranchFormDialog/BranchFormDialogContent.js
new file mode 100644
index 000000000..b073f6f6e
--- /dev/null
+++ b/src/containers/Dialogs/BranchFormDialog/BranchFormDialogContent.js
@@ -0,0 +1,20 @@
+import React from 'react';
+
+import '../../../style/pages/Branches/BranchFormDialog.scss';
+
+import { BranchFormProvider } from './BranchFormProvider';
+import BranchForm from './BranchForm';
+
+/**
+ * Branch form dialog content.
+ */
+export default function BranchFormDialogContent({
+ // #ownProps
+ dialogName,
+}) {
+ return (
+
+
+
+ );
+}
diff --git a/src/containers/Dialogs/BranchFormDialog/BranchFormFields.js b/src/containers/Dialogs/BranchFormDialog/BranchFormFields.js
new file mode 100644
index 000000000..90eae49f9
--- /dev/null
+++ b/src/containers/Dialogs/BranchFormDialog/BranchFormFields.js
@@ -0,0 +1,157 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { FastField, ErrorMessage, Field } from 'formik';
+import styled from 'styled-components';
+import {
+ Classes,
+ FormGroup,
+ InputGroup,
+ ControlGroup,
+ Position,
+} from '@blueprintjs/core';
+import { inputIntent } from 'utils';
+import { FieldRequiredHint, Col, Row, FormattedMessage as T } from 'components';
+import { useBranchFormContext } from './BranchFormProvider';
+
+/**
+ * Branch form dialog fields.
+ */
+function BranchFormFields() {
+ return (
+
+ {/*------------ Branch Name -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ labelInfo={ }
+ intent={inputIntent({ error, touched })}
+ inline={true}
+ helperText={ }
+ className={'form-group--branch_name'}
+ >
+
+
+ )}
+
+
+ {/*------------ Branch Address 1 -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ className={'form-group--branch_address_1'}
+ >
+
+
+ )}
+
+
+ {/*------------ Branch Address 2 -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ className={'form-group--branch_address_2'}
+ >
+
+
+ )}
+
+
+ {/*------------ Branch Address City & Country-----------*/}
+ }
+ >
+
+
+ {({ field, meta: { error, touched } }) => (
+
+ )}
+
+
+
+ {({ field, meta: { error, touched } }) => (
+
+ )}
+
+
+
+
+
+ {/*------------ Phone Number -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ className={'form-group--phone_number'}
+ >
+
+
+ )}
+
+
+ {/*------------ Email -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ className={'form-group--email'}
+ >
+
+
+ )}
+
+
+ {/*------------ Website -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ className={'form-group--website'}
+ >
+
+
+ )}
+
+
+ );
+}
+
+export default BranchFormFields;
+
+const BranchAddressWrap = styled.div`
+ margin-left: 160px;
+`;
diff --git a/src/containers/Dialogs/BranchFormDialog/BranchFormFloatingActions.js b/src/containers/Dialogs/BranchFormDialog/BranchFormFloatingActions.js
new file mode 100644
index 000000000..8b2c558bc
--- /dev/null
+++ b/src/containers/Dialogs/BranchFormDialog/BranchFormFloatingActions.js
@@ -0,0 +1,46 @@
+import React from 'react';
+
+import { Intent, Button, Classes } from '@blueprintjs/core';
+import { useFormikContext } from 'formik';
+import { FormattedMessage as T } from 'components';
+
+import { useBranchFormContext } from './BranchFormProvider';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import { compose } from 'utils';
+
+/**
+ * Branch form floating actions.
+ */
+function BranchFormFloatingActions({
+ // #withDialogActions
+ closeDialog,
+}) {
+ // Formik context.
+ const { isSubmitting } = useFormikContext();
+
+ const { dialogName } = useBranchFormContext();
+
+ // Handle close button click.
+ const handleCancelBtnClick = () => {
+ closeDialog(dialogName);
+ };
+
+ return (
+
+ );
+}
+export default compose(withDialogActions)(BranchFormFloatingActions);
diff --git a/src/containers/Dialogs/BranchFormDialog/BranchFormProvider.js b/src/containers/Dialogs/BranchFormDialog/BranchFormProvider.js
new file mode 100644
index 000000000..18e97bc92
--- /dev/null
+++ b/src/containers/Dialogs/BranchFormDialog/BranchFormProvider.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import { DialogContent } from 'components';
+// import {} from 'hooks/query';
+
+const BranchFormContext = React.createContext();
+
+/**
+ * Branch form dialog provider.
+ */
+function BranchFormProvider({ dialogName, ...props }) {
+ // State provider.
+ const provider = {
+ dialogName,
+ };
+ return (
+
+
+
+ );
+}
+const useBranchFormContext = () => React.useContext(BranchFormContext);
+
+export { BranchFormProvider, useBranchFormContext };
diff --git a/src/containers/Dialogs/BranchFormDialog/index.js b/src/containers/Dialogs/BranchFormDialog/index.js
new file mode 100644
index 000000000..fca572330
--- /dev/null
+++ b/src/containers/Dialogs/BranchFormDialog/index.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import { FormattedMessage as T } from 'components';
+import { Dialog, DialogSuspense } from 'components';
+import withDialogRedux from 'components/DialogReduxConnect';
+
+import { compose } from 'utils';
+
+const BranchFormDialogContent = React.lazy(() =>
+ import('./BranchFormDialogContent'),
+);
+
+/**
+ * Branch form form dialog.
+ */
+function BranchFormDialog({ dialogName, payload = {}, isOpen }) {
+ return (
+ }
+ isOpen={isOpen}
+ canEscapeJeyClose={true}
+ autoFocus={true}
+ className={'dialog--branch-form'}
+ >
+
+
+
+
+ );
+}
+export default compose(withDialogRedux())(BranchFormDialog);
diff --git a/src/containers/Preferences/Branches/Branches.js b/src/containers/Preferences/Branches/Branches.js
new file mode 100644
index 000000000..af93b014c
--- /dev/null
+++ b/src/containers/Preferences/Branches/Branches.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import classNames from 'classnames';
+import { CLASSES } from 'common/classes';
+
+import BranchesDataTable from './BranchesDataTable';
+import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+
+import { compose } from 'utils';
+
+function Branches({
+ // #withDashboardActions
+ changePreferencesPageTitle,
+}) {
+ React.useEffect(() => {
+ changePreferencesPageTitle(intl.get('branches.label'));
+ }, [changePreferencesPageTitle]);
+
+ return ;
+}
+export default compose(withDashboardActions)(Branches);
diff --git a/src/containers/Preferences/Branches/BranchesActions.js b/src/containers/Preferences/Branches/BranchesActions.js
new file mode 100644
index 000000000..a73c4bb93
--- /dev/null
+++ b/src/containers/Preferences/Branches/BranchesActions.js
@@ -0,0 +1,29 @@
+import React from 'react';
+import { Button, Intent } from '@blueprintjs/core';
+
+import { FormattedMessage as T, Icon } from 'components';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import { compose } from 'utils';
+
+function BranchesActions({
+ //#ownProps
+ openDialog,
+}) {
+ const handleClickNewBranche = () => {
+ openDialog('branch-form');
+ };
+
+ return (
+
+ }
+ onClick={handleClickNewBranche}
+ intent={Intent.PRIMARY}
+ >
+
+
+
+ );
+}
+
+export default compose(withDialogActions)(BranchesActions);
diff --git a/src/containers/Preferences/Branches/BranchesDataTable.js b/src/containers/Preferences/Branches/BranchesDataTable.js
new file mode 100644
index 000000000..91e992a10
--- /dev/null
+++ b/src/containers/Preferences/Branches/BranchesDataTable.js
@@ -0,0 +1,36 @@
+import React from 'react';
+import styled from 'styled-components';
+
+import { DataTable } from 'components';
+import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
+import { useBranchesTableColumns, ActionsMenu } from './components';
+
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import { compose } from 'utils';
+
+/**
+ * Branches data table.
+ */
+function BranchesDataTable({
+ // #withDialogAction
+ openDialog,
+}) {
+ // Table columns.
+ const columns = useBranchesTableColumns();
+
+ return (
+
+ );
+}
+
+export default compose(withDialogActions)(BranchesDataTable);
+
+const BranchesTable = styled(DataTable)``;
diff --git a/src/containers/Preferences/Branches/BranchesProvider.js b/src/containers/Preferences/Branches/BranchesProvider.js
new file mode 100644
index 000000000..a8fdea708
--- /dev/null
+++ b/src/containers/Preferences/Branches/BranchesProvider.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import styled from 'styled-components';
+import classNames from 'classnames';
+import { CLASSES } from 'common/classes';
+import { Card } from 'components';
+
+const BranchesContext = React.createContext();
+
+/**
+ * Branches data provider.
+ */
+function BranchesProvider({ ...props }) {
+ // Provider state.
+ const provider = {};
+
+ return (
+
+
+
+
+
+ );
+}
+
+const useBranchesContext = () => React.useContext(BranchesContext);
+export { BranchesProvider, useBranchesContext };
+
+const BrachesPreferencesCard = styled(Card)`
+ padding: 0;
+`;
diff --git a/src/containers/Preferences/Branches/components.js b/src/containers/Preferences/Branches/components.js
new file mode 100644
index 000000000..00239bf23
--- /dev/null
+++ b/src/containers/Preferences/Branches/components.js
@@ -0,0 +1,76 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import {
+ Intent,
+ Button,
+ Popover,
+ Menu,
+ MenuDivider,
+ Tag,
+ MenuItem,
+ Position,
+} from '@blueprintjs/core';
+
+import { safeCallback } from 'utils';
+import { Icon } from 'components';
+
+/**
+ * Context menu of Branches.
+ */
+export function ActionsMenu({
+ payload: { onEdit, onDelete },
+ row: { original },
+}) {
+ return (
+
+ }
+ text={intl.get('branches.action.edit_branch')}
+ onClick={safeCallback(onEdit, original)}
+ />
+
+ }
+ text={intl.get('branches.action.delete_branch')}
+ onClick={safeCallback(onDelete, original)}
+ intent={Intent.DANGER}
+ />
+
+ );
+}
+
+/**
+ * Retrieve branches table columns
+ * @returns
+ */
+export function useBranchesTableColumns() {
+ return React.useMemo(
+ () => [
+ {
+ id: 'branch_name',
+ Header: intl.get('branches.column.branch_name'),
+ accessor: 'branch_name',
+ className: 'branch_name',
+ width: '120',
+ disableSortBy: true,
+ textOverview: true,
+ },
+ {
+ Header: intl.get('branches.column.address'),
+ accessor: 'address',
+ className: 'address',
+ width: '180',
+ disableSortBy: true,
+ textOverview: true,
+ },
+ {
+ Header: intl.get('branches.column.phone_number'),
+ accessor: 'phone_number',
+ className: 'phone_number',
+ width: '120',
+ disableSortBy: true,
+ },
+ ],
+ [],
+ );
+}
diff --git a/src/containers/Preferences/Branches/index.js b/src/containers/Preferences/Branches/index.js
new file mode 100644
index 000000000..9bd083d91
--- /dev/null
+++ b/src/containers/Preferences/Branches/index.js
@@ -0,0 +1,15 @@
+import React from 'react';
+
+import { BranchesProvider } from './BranchesProvider';
+import Branches from './Branches';
+
+/**
+ * Branches .
+ */
+export default function BranchesPreferences() {
+ return (
+
+
+
+ );
+}
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index 4147975a2..eb7b674b3 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -1738,19 +1738,32 @@
"global_error.you_dont_have_permissions": "You do not have permissions to access this page.",
"global_error.transactions_locked": "Transactions before {lockedToDate} has been locked. Hence action cannot be performed.",
"global_error.authorized_user_inactive": "The authorized user is inactive.",
-
"the_vendor_has_been_inactivated_successfully": "The contact has been inactivated successfully.",
-
"vendor.alert.activated_message": "The vendor has been activated successfully.",
- "vendor.alert.are_you_sure_want_to_inactivate_this_vendor":"Are you sure want to inactivate this vendor? You will to able to activate it later.",
+ "vendor.alert.are_you_sure_want_to_inactivate_this_vendor": "Are you sure want to inactivate this vendor? You will to able to activate it later.",
"vendor.alert.inactivated_message": "The vendor has been inactivated successfully.",
"vendor.alert.are_you_sure_want_to_activate_this_vendor": "Are you sure want to activate this vendor? You will to able to inactivate it later.",
-
- "customer.alert.activated_message":"The customer has been activated successfully.",
+ "customer.alert.activated_message": "The customer has been activated successfully.",
"customer.alert.are_you_sure_want_to_activate_this_customer": "Are you sure want to activate this customer? You will to able to inactivate it later.",
"customer.alert.inactivated_message": "The customer has been inactivated successfully.",
- "customer.alert.are_you_sure_want_to_inactivate_this_customer":"Are you sure want to inactivate this customer? You will to able to activate it later.",
-
- "credit_note_preview.dialog.title":"Credit Note PDF Preview",
- "payment_receive_preview.dialog.title":"Payment Receive PDF Preview"
+ "customer.alert.are_you_sure_want_to_inactivate_this_customer": "Are you sure want to inactivate this customer? You will to able to activate it later.",
+ "credit_note_preview.dialog.title": "Credit Note PDF Preview",
+ "payment_receive_preview.dialog.title": "Payment Receive PDF Preview",
+ "branches.label": "Branches",
+ "branches.label.new_branche": "New Branch",
+ "branches.action.edit_branch": "Edit Branch",
+ "branches.action.delete_branch": "Edit Branch",
+ "branches.column.branch_name": "Branch name",
+ "branches.column.address": "Address",
+ "branches.column.phone_number": "Phone number",
+ "branch.dialog.label": "New Branch",
+ "branch.dialog.label.branch_name": "Branch Name",
+ "branch.dialog.label.branch_address": "Branch Address",
+ "branch.dialog.label.address_1": "Address 1",
+ "branch.dialog.label.address_2": "Address 2",
+ "branch.dialog.label.city": "City",
+ "branch.dialog.label.country": "Country",
+ "branch.dialog.label.phone_number": "Phone Number",
+ "branch.dialog.label.email": "Email",
+ "branch.dialog.label.website": "Website"
}
\ No newline at end of file
diff --git a/src/routes/preferences.js b/src/routes/preferences.js
index 9fc454ddd..c8962e8b6 100644
--- a/src/routes/preferences.js
+++ b/src/routes/preferences.js
@@ -7,6 +7,7 @@ import Currencies from 'containers/Preferences/Currencies/Currencies';
import Item from 'containers/Preferences/Item';
import SMSIntegration from '../containers/Preferences/SMSIntegration';
import DefaultRoute from '../containers/Preferences/DefaultRoute';
+import Branches from '../containers/Preferences/Branches'
const BASE_URL = '/preferences';
@@ -36,6 +37,11 @@ export default [
component: Currencies,
exact: true,
},
+ {
+ path: `${BASE_URL}/branches`,
+ component: Branches,
+ exact: true,
+ },
{
path: `${BASE_URL}/accountant`,
component: Accountant,
diff --git a/src/style/pages/Branches/BranchFormDialog.scss b/src/style/pages/Branches/BranchFormDialog.scss
new file mode 100644
index 000000000..b10bea737
--- /dev/null
+++ b/src/style/pages/Branches/BranchFormDialog.scss
@@ -0,0 +1,39 @@
+.dialog--branch-form {
+ width: 600px;
+
+ .bp3-dialog-body {
+ .bp3-form-group {
+ margin-bottom: 15px;
+ }
+ .bp3-form-group.bp3-inline {
+ .bp3-label {
+ font-size: 13px;
+ margin-bottom: 3px;
+ min-width: 150px;
+ }
+ .bp3-form-content {
+ width: 320px;
+ }
+ }
+ .form-group {
+ &--branch_address_city {
+ .bp3-control-group > * {
+ flex-shrink: unset;
+ padding-right: 5px;
+ padding-left: 5px;
+
+ &:first-child {
+ padding-left: 0;
+ }
+ &:last-child {
+ padding-right: 0;
+ }
+ }
+ }
+ }
+ }
+
+ .bp3-dialog-footer {
+ padding-top: 10px;
+ }
+}
From bcb67c7142640a7855f8e98cf87222661834d201 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Mon, 24 Jan 2022 01:35:45 +0200
Subject: [PATCH 03/30] feat(warehouse): add warehouse.
---
src/components/DialogsContainer.js | 2 +
.../Preferences/PreferencesTopbar.js | 6 +
src/config/preferencesMenu.js | 4 +
.../WarehouseFormDialog/WarehouseForm.js | 46 +++++++
.../WarehouseForm.schema.js | 13 ++
.../WarehouseFormContent.js | 18 +++
.../WarehouseFormDialogContent.js | 19 +++
.../WarehouseFormFields.js | 126 ++++++++++++++++++
.../WarehouseFormFloatingActions.js | 48 +++++++
.../WarehouseFormProvider.js | 27 ++++
.../Dialogs/WarehouseFormDialog/index.js | 31 +++++
.../Warehouses/WarehousesActions.js | 32 +++++
src/lang/en/index.json | 24 ++--
.../pages/Warehouses/warehouseFormDialog.scss | 36 +++++
14 files changed, 423 insertions(+), 9 deletions(-)
create mode 100644 src/containers/Dialogs/WarehouseFormDialog/WarehouseForm.js
create mode 100644 src/containers/Dialogs/WarehouseFormDialog/WarehouseForm.schema.js
create mode 100644 src/containers/Dialogs/WarehouseFormDialog/WarehouseFormContent.js
create mode 100644 src/containers/Dialogs/WarehouseFormDialog/WarehouseFormDialogContent.js
create mode 100644 src/containers/Dialogs/WarehouseFormDialog/WarehouseFormFields.js
create mode 100644 src/containers/Dialogs/WarehouseFormDialog/WarehouseFormFloatingActions.js
create mode 100644 src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js
create mode 100644 src/containers/Dialogs/WarehouseFormDialog/index.js
create mode 100644 src/containers/Preferences/Warehouses/WarehousesActions.js
create mode 100644 src/style/pages/Warehouses/warehouseFormDialog.scss
diff --git a/src/components/DialogsContainer.js b/src/components/DialogsContainer.js
index cd8eb745e..f52002200 100644
--- a/src/components/DialogsContainer.js
+++ b/src/components/DialogsContainer.js
@@ -34,6 +34,7 @@ import UnlockingTransactionsDialog from '../containers/Dialogs/UnlockingTransact
import UnlockingPartialTransactionsDialog from '../containers/Dialogs/UnlockingPartialTransactionsDialog';
import CreditNotePdfPreviewDialog from '../containers/Dialogs/CreditNotePdfPreviewDialog';
import PaymentReceivePdfPreviewDialog from '../containers/Dialogs/PaymentReceivePdfPreviewDialog';
+import WarehouseFormDialog from '../containers/Dialogs/WarehouseFormDialog';
/**
* Dialogs container.
@@ -78,6 +79,7 @@ export default function DialogsContainer() {
/>
+
);
}
diff --git a/src/components/Preferences/PreferencesTopbar.js b/src/components/Preferences/PreferencesTopbar.js
index 1633ecc8f..7b27a83e8 100644
--- a/src/components/Preferences/PreferencesTopbar.js
+++ b/src/components/Preferences/PreferencesTopbar.js
@@ -6,6 +6,7 @@ import { CLASSES } from 'common/classes';
import DashboardTopbarUser from 'components/Dashboard/TopbarUser';
import UsersActions from 'containers/Preferences/Users/UsersActions';
import CurrenciesActions from 'containers/Preferences/Currencies/CurrenciesActions';
+import WarehousesActions from '../../containers/Preferences/Warehouses/WarehousesActions'
import withDashboard from 'containers/Dashboard/withDashboard';
import { compose } from 'utils';
@@ -35,6 +36,11 @@ function PreferencesTopbar({ preferencesPageTitle }) {
path={'/preferences/currencies'}
component={CurrenciesActions}
/>
+
diff --git a/src/config/preferencesMenu.js b/src/config/preferencesMenu.js
index 031dfe0e1..f01ca6e12 100644
--- a/src/config/preferencesMenu.js
+++ b/src/config/preferencesMenu.js
@@ -16,6 +16,10 @@ export default [
href: '/preferences/currencies',
},
+ {
+ text: ,
+ href: '/preferences/warehouses',
+ },
{
text: ,
disabled: false,
diff --git a/src/containers/Dialogs/WarehouseFormDialog/WarehouseForm.js b/src/containers/Dialogs/WarehouseFormDialog/WarehouseForm.js
new file mode 100644
index 000000000..1c5474fce
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseFormDialog/WarehouseForm.js
@@ -0,0 +1,46 @@
+import React from 'react';
+import { Formik } from 'formik';
+
+import { CreateWarehouseFormSchema } from './WarehouseForm.schema';
+import { useWarehouseFormContext } from './WarehouseFormProvider';
+import WarehouseFormContent from './WarehouseFormContent';
+
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import { compose } from 'utils';
+
+const defaultInitialValues = {
+ warehouse_name: '',
+ warehouse_address_1: '',
+ warehouse_address_2: '',
+ warehouse_address_city: '',
+ warehouse_address_country: '',
+ phone_number: '',
+};
+
+/**
+ * Warehouse form.
+ * @returns
+ */
+function WarehouseForm({
+ // #withDialogActions
+ closeDialog,
+}) {
+ // Initial form values.
+ const initialValues = {
+ ...defaultInitialValues,
+ };
+
+ // Handles the form submit.
+ const handleFormSubmit = (values, { setSubmitting, setErrors }) => {};
+
+ return (
+
+ );
+}
+
+export default compose(withDialogActions)(WarehouseForm);
diff --git a/src/containers/Dialogs/WarehouseFormDialog/WarehouseForm.schema.js b/src/containers/Dialogs/WarehouseFormDialog/WarehouseForm.schema.js
new file mode 100644
index 000000000..66a0d723a
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseFormDialog/WarehouseForm.schema.js
@@ -0,0 +1,13 @@
+import * as Yup from 'yup';
+import intl from 'react-intl-universal';
+
+const Schema = Yup.object().shape({
+ warehouse_name: Yup.string().required().label(intl.get('warehouse_name')),
+ warehouse_address_1: Yup.string().trim(),
+ warehouse_address_2: Yup.string().trim(),
+ warehouse_address_city: Yup.string().trim(),
+ warehouse_address_country: Yup.string().trim(),
+ phone_number: Yup.number(),
+});
+
+export const CreateWarehouseFormSchema = Schema;
diff --git a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormContent.js b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormContent.js
new file mode 100644
index 000000000..6816f703e
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormContent.js
@@ -0,0 +1,18 @@
+import React from 'react';
+import { Form } from 'formik';
+
+import WarehouseFormFields from './WarehouseFormFields';
+import WarehouseFormFloatingActions from './WarehouseFormFloatingActions';
+
+/**
+ * Warehouse form content.
+ * @returns
+ */
+export default function WarehouseFormContent() {
+ return (
+
+ );
+}
diff --git a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormDialogContent.js b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormDialogContent.js
new file mode 100644
index 000000000..0bf620e68
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormDialogContent.js
@@ -0,0 +1,19 @@
+import React from 'react';
+
+import '../../../style/pages/Warehouses/warehouseFormDialog.scss';
+import { WarehouseFormProvider } from './WarehouseFormProvider';
+import WarehouseForm from './WarehouseForm';
+
+/**
+ * Warehouse form dialog content.
+ */
+export default function WarehouseFormDialogContent({
+ // #ownProps
+ dialogName,
+}) {
+ return (
+
+
+
+ );
+}
diff --git a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormFields.js b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormFields.js
new file mode 100644
index 000000000..b1097462e
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormFields.js
@@ -0,0 +1,126 @@
+import React from 'react';
+
+import intl from 'react-intl-universal';
+import { FastField, ErrorMessage, Field } from 'formik';
+import styled from 'styled-components';
+import {
+ Classes,
+ FormGroup,
+ InputGroup,
+ ControlGroup,
+ Position,
+} from '@blueprintjs/core';
+import { inputIntent } from 'utils';
+import { FieldRequiredHint, Col, Row, FormattedMessage as T } from 'components';
+import { useWarehouseFormContext } from './WarehouseFormProvider';
+
+/**
+ * Warehouse form fields.
+ * @returns
+ */
+export default function WarehouseFormFields() {
+ return (
+
+ {/*------------ Warehouse Name -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ labelInfo={ }
+ intent={inputIntent({ error, touched })}
+ inline={true}
+ helperText={ }
+ className={'form-group--warehouse_name'}
+ >
+
+
+ )}
+
+ {/*------------ Warehouse Address -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ className={'form-group--warehouse_address_1'}
+ >
+
+
+ )}
+
+
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ className={'form-group--warehouse_address_2'}
+ >
+
+
+ )}
+
+ {/*------------ Warehouse Address City & Country-----------*/}
+ }
+ >
+
+
+ {({ field, meta: { error, touched } }) => (
+
+ )}
+
+
+ {({ field, meta: { error, touched } }) => (
+
+ )}
+
+
+
+
+ {/*------------ Phone Number -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ className={'form-group--phone_number'}
+ >
+
+
+ )}
+
+
+ );
+}
+
+const WarehouseAddressWrap = styled.div`
+ padding-left: 150px;
+`;
diff --git a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormFloatingActions.js b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormFloatingActions.js
new file mode 100644
index 000000000..f3da7c436
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormFloatingActions.js
@@ -0,0 +1,48 @@
+import React from 'react';
+
+import { Intent, Button, Classes } from '@blueprintjs/core';
+import { useFormikContext } from 'formik';
+import { FormattedMessage as T } from 'components';
+
+import { useWarehouseFormContext } from './WarehouseFormProvider';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import { compose } from 'utils';
+
+/**
+ * Warehouse form floating actions.
+ * @returns
+ */
+function WarehouseFormFloatingActions({
+ // #withDialogActions
+ closeDialog,
+}) {
+ // Formik context.
+ const { isSubmitting } = useFormikContext();
+
+ const { dialogName } = useWarehouseFormContext();
+
+ // Handle close button click.
+ const handleCancelBtnClick = () => {
+ closeDialog(dialogName);
+ };
+
+ return (
+
+ );
+}
+
+export default compose(withDialogActions)(WarehouseFormFloatingActions);
diff --git a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js
new file mode 100644
index 000000000..336a2f93f
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import { DialogContent } from 'components';
+// import {} from 'hooks/query';
+
+const WarehouseFormContext = React.createContext();
+
+/**
+ * Warehouse form provider.
+ */
+function WarehouseFormProvider({ dialogName, ...props }) {
+ // State provider.
+ const provider = {
+ dialogName,
+ };
+
+ return (
+
+
+
+ );
+}
+
+const useWarehouseFormContext = () => React.useContext(WarehouseFormContext);
+
+export { WarehouseFormProvider, useWarehouseFormContext };
diff --git a/src/containers/Dialogs/WarehouseFormDialog/index.js b/src/containers/Dialogs/WarehouseFormDialog/index.js
new file mode 100644
index 000000000..0f886e56d
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseFormDialog/index.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import { FormattedMessage as T } from 'components';
+import { Dialog, DialogSuspense } from 'components';
+import withDialogRedux from 'components/DialogReduxConnect';
+
+import { compose } from 'utils';
+
+const WarehouseFormDialogContent = React.lazy(() =>
+ import('./WarehouseFormDialogContent'),
+);
+
+/**
+ * Warehouse form form dialog.
+ */
+function WarehouseFormDialog({ dialogName, isOpen }) {
+ return (
+ }
+ isOpen={isOpen}
+ canEscapeJeyClose={true}
+ autoFocus={true}
+ className={'dialog--warehouse-form'}
+ >
+
+
+
+
+ );
+}
+export default compose(withDialogRedux())(WarehouseFormDialog);
diff --git a/src/containers/Preferences/Warehouses/WarehousesActions.js b/src/containers/Preferences/Warehouses/WarehousesActions.js
new file mode 100644
index 000000000..b737dc586
--- /dev/null
+++ b/src/containers/Preferences/Warehouses/WarehousesActions.js
@@ -0,0 +1,32 @@
+import React from 'react';
+import { Button, Intent } from '@blueprintjs/core';
+
+import { FormattedMessage as T, Icon } from 'components';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import { compose } from 'utils';
+
+/**
+ * Warehouse actions.
+ */
+function WarehousesActions({
+ //#ownProps
+ openDialog,
+}) {
+ const handleClickNewWarehouse = () => {
+ openDialog('warehouse-form');
+ };
+
+ return (
+
+ }
+ onClick={handleClickNewWarehouse}
+ intent={Intent.PRIMARY}
+ >
+
+
+
+ );
+}
+
+export default compose(withDialogActions)(WarehousesActions);
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index 4147975a2..5a4020188 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -1738,19 +1738,25 @@
"global_error.you_dont_have_permissions": "You do not have permissions to access this page.",
"global_error.transactions_locked": "Transactions before {lockedToDate} has been locked. Hence action cannot be performed.",
"global_error.authorized_user_inactive": "The authorized user is inactive.",
-
"the_vendor_has_been_inactivated_successfully": "The contact has been inactivated successfully.",
-
"vendor.alert.activated_message": "The vendor has been activated successfully.",
- "vendor.alert.are_you_sure_want_to_inactivate_this_vendor":"Are you sure want to inactivate this vendor? You will to able to activate it later.",
+ "vendor.alert.are_you_sure_want_to_inactivate_this_vendor": "Are you sure want to inactivate this vendor? You will to able to activate it later.",
"vendor.alert.inactivated_message": "The vendor has been inactivated successfully.",
"vendor.alert.are_you_sure_want_to_activate_this_vendor": "Are you sure want to activate this vendor? You will to able to inactivate it later.",
-
- "customer.alert.activated_message":"The customer has been activated successfully.",
+ "customer.alert.activated_message": "The customer has been activated successfully.",
"customer.alert.are_you_sure_want_to_activate_this_customer": "Are you sure want to activate this customer? You will to able to inactivate it later.",
"customer.alert.inactivated_message": "The customer has been inactivated successfully.",
- "customer.alert.are_you_sure_want_to_inactivate_this_customer":"Are you sure want to inactivate this customer? You will to able to activate it later.",
-
- "credit_note_preview.dialog.title":"Credit Note PDF Preview",
- "payment_receive_preview.dialog.title":"Payment Receive PDF Preview"
+ "customer.alert.are_you_sure_want_to_inactivate_this_customer": "Are you sure want to inactivate this customer? You will to able to activate it later.",
+ "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",
+ "warehouse.dialog.label.warehouse_name":"Warehouse Name",
+ "warehouse.dialog.label.warehouse_address":"Address",
+ "warehouse.dialog.label.warehouse_address_1":"Address 1",
+ "warehouse.dialog.label.warehouse_address_2":"Address 2",
+ "warehouse.dialog.label.city":"City",
+ "warehouse.dialog.label.country":"Country",
+ "warehouse.dialog.label.phone_number":"Phone Number"
}
\ No newline at end of file
diff --git a/src/style/pages/Warehouses/warehouseFormDialog.scss b/src/style/pages/Warehouses/warehouseFormDialog.scss
new file mode 100644
index 000000000..5a9a4433a
--- /dev/null
+++ b/src/style/pages/Warehouses/warehouseFormDialog.scss
@@ -0,0 +1,36 @@
+.dialog--warehouse-form {
+ width: 650px;
+
+ .bp3-dialog-body {
+ .bp3-form-group.bp3-inline {
+ .bp3-label {
+ font-size: 13px;
+ min-width: 140px;
+ }
+ .bp3-form-content {
+ width: 388px;
+ }
+ .bp3-control-group > * {
+ flex-shrink: unset;
+ padding-right: 5px;
+ padding-left: 5px;
+
+ &:first-child {
+ padding-left: 0;
+ }
+ &:last-child {
+ padding-right: 0;
+ }
+ }
+ &.form-group--warehouse_name,
+ &.form-group--phone_number {
+ .bp3-form-content {
+ width: 278px;
+ }
+ }
+ }
+ }
+ .bp3-dialog-footer {
+ padding-top: 10px;
+ }
+}
From dcac1053bea00429daef6ffe4d6e307b030672e8 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Mon, 24 Jan 2022 01:44:46 +0200
Subject: [PATCH 04/30] feat(warehouse): add warehouse fields.
---
.../BranchFormDialog/BranchFormFields.js | 6 ++--
.../pages/Branches/BranchFormDialog.scss | 33 ++++++++++---------
2 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/src/containers/Dialogs/BranchFormDialog/BranchFormFields.js b/src/containers/Dialogs/BranchFormDialog/BranchFormFields.js
index 90eae49f9..fcebeb72e 100644
--- a/src/containers/Dialogs/BranchFormDialog/BranchFormFields.js
+++ b/src/containers/Dialogs/BranchFormDialog/BranchFormFields.js
@@ -43,7 +43,7 @@ function BranchFormFields() {
intent={inputIntent({ error, touched })}
inline={true}
helperText={ }
- className={'form-group--branch_address_1'}
+ className={'form-group--branch_address'}
>
}
- className={'form-group--branch_address_2'}
+ className={'form-group--branch_address'}
>
}
>
diff --git a/src/style/pages/Branches/BranchFormDialog.scss b/src/style/pages/Branches/BranchFormDialog.scss
index b10bea737..9dd06954f 100644
--- a/src/style/pages/Branches/BranchFormDialog.scss
+++ b/src/style/pages/Branches/BranchFormDialog.scss
@@ -1,5 +1,5 @@
.dialog--branch-form {
- width: 600px;
+ width: 650px;
.bp3-dialog-body {
.bp3-form-group {
@@ -12,27 +12,28 @@
min-width: 150px;
}
.bp3-form-content {
- width: 320px;
+ width: 278px;
}
- }
- .form-group {
- &--branch_address_city {
- .bp3-control-group > * {
- flex-shrink: unset;
- padding-right: 5px;
- padding-left: 5px;
+ .bp3-control-group > * {
+ flex-shrink: unset;
+ padding-right: 5px;
+ padding-left: 5px;
- &:first-child {
- padding-left: 0;
- }
- &:last-child {
- padding-right: 0;
- }
+ &:first-child {
+ padding-left: 0;
+ }
+ &:last-child {
+ padding-right: 0;
+ }
+ }
+
+ &.form-group--branch_address {
+ .bp3-form-content {
+ width: 388px;
}
}
}
}
-
.bp3-dialog-footer {
padding-top: 10px;
}
From 5b0cb0c8bed1b34ba04392fa831c6cdd5de84981 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Thu, 27 Jan 2022 16:48:55 +0200
Subject: [PATCH 05/30] feat(warehouses): add Item quantity for each warehouse.
---
.../Drawers/ItemDetailDrawer/ItemDetailTab.js | 6 ++++
.../WarehousesLocations/components.js | 33 +++++++++++++++++++
.../WarehousesLocations/index.js | 24 ++++++++++++++
src/lang/en/index.json | 6 +++-
4 files changed, 68 insertions(+), 1 deletion(-)
create mode 100644 src/containers/Drawers/ItemDetailDrawer/WarehousesLocations/components.js
create mode 100644 src/containers/Drawers/ItemDetailDrawer/WarehousesLocations/index.js
diff --git a/src/containers/Drawers/ItemDetailDrawer/ItemDetailTab.js b/src/containers/Drawers/ItemDetailDrawer/ItemDetailTab.js
index e964d4bd5..a200ba943 100644
--- a/src/containers/Drawers/ItemDetailDrawer/ItemDetailTab.js
+++ b/src/containers/Drawers/ItemDetailDrawer/ItemDetailTab.js
@@ -3,6 +3,7 @@ import { Tab } from '@blueprintjs/core';
import { DrawerMainTabs, FormattedMessage as T } from 'components';
import { ItemPaymentTransactions } from './ItemPaymentTransactions';
import ItemDetailHeader from './ItemDetailHeader';
+import WarehousesLocationsTable from './WarehousesLocations';
export default function ItemDetailTab() {
@@ -18,6 +19,11 @@ export default function ItemDetailTab() {
title={ }
panel={ }
/>
+ }
+ panel={ }
+ />
);
}
diff --git a/src/containers/Drawers/ItemDetailDrawer/WarehousesLocations/components.js b/src/containers/Drawers/ItemDetailDrawer/WarehousesLocations/components.js
new file mode 100644
index 000000000..0e866a724
--- /dev/null
+++ b/src/containers/Drawers/ItemDetailDrawer/WarehousesLocations/components.js
@@ -0,0 +1,33 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+
+import clsx from 'classnames';
+import { CLASSES } from '../../../../common/classes';
+
+/**
+ * Warehouse locations columns
+ */
+export const useWarehouseLocationsColumns = () => {
+ return React.useMemo(
+ () => [
+ {
+ id: 'warehouse_name',
+ Header: intl.get('warehouse_locations.column.warehouse_name'),
+ width: 120,
+ },
+ {
+ id: 'quantity',
+ Header: intl.get('warehouse_locations.column.quantity'),
+ align: 'right',
+ width: 100,
+ },
+ {
+ id: 'available_for_sale',
+ Header: intl.get('warehouse_locations.column.available_for_sale'),
+ align: 'right',
+ width: 100,
+ },
+ ],
+ [],
+ );
+};
diff --git a/src/containers/Drawers/ItemDetailDrawer/WarehousesLocations/index.js b/src/containers/Drawers/ItemDetailDrawer/WarehousesLocations/index.js
new file mode 100644
index 000000000..39978b19c
--- /dev/null
+++ b/src/containers/Drawers/ItemDetailDrawer/WarehousesLocations/index.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import styled from 'styled-components';
+
+import { DataTable, CommercialDocEntriesTable, Card } from 'components';
+
+import { useWarehouseLocationsColumns } from './components';
+
+import { TableStyle } from '../../../../common';
+
+/**
+ * Warehouses locations table columns.
+ */
+export default function WarehouseLocationsTable() {
+ // Warehouses locations table columns.
+ const columns = useWarehouseLocationsColumns();
+
+ return (
+
+
+
+ );
+}
+
+const WarehouseLocationsGLEntriesRoot = styled(Card)``;
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index 5a4020188..4e820a97e 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -1758,5 +1758,9 @@
"warehouse.dialog.label.warehouse_address_2":"Address 2",
"warehouse.dialog.label.city":"City",
"warehouse.dialog.label.country":"Country",
- "warehouse.dialog.label.phone_number":"Phone Number"
+ "warehouse.dialog.label.phone_number":"Phone Number",
+ "warehouse_locations.label":"Warehouses Locations",
+ "warehouse_locations.column.warehouse_name":"Warehouse name",
+ "warehouse_locations.column.quantity":"Quantity",
+ "warehouse_locations.column.available_for_sale":"Available for sale"
}
\ No newline at end of file
From e4af460c0d1813cba1369e259e56aa728c7b74da Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Sun, 30 Jan 2022 18:04:36 +0200
Subject: [PATCH 06/30] feat(warehouse) add warehouse gird.
---
.../Preferences/Warehouses/Warehouses.js | 60 ++++++++++++++++
.../Warehouses/WarehousesGridItems.js | 69 +++++++++++++++++++
.../Preferences/Warehouses/WarehousesList.js | 24 +++++++
.../Warehouses/WarehousesProvider.js | 24 +++++++
.../Preferences/Warehouses/components.js | 37 ++++++++++
.../Preferences/Warehouses/index.js | 15 ++++
src/lang/en/index.json | 5 +-
src/routes/preferences.js | 6 ++
8 files changed, 239 insertions(+), 1 deletion(-)
create mode 100644 src/containers/Preferences/Warehouses/Warehouses.js
create mode 100644 src/containers/Preferences/Warehouses/WarehousesGridItems.js
create mode 100644 src/containers/Preferences/Warehouses/WarehousesList.js
create mode 100644 src/containers/Preferences/Warehouses/WarehousesProvider.js
create mode 100644 src/containers/Preferences/Warehouses/components.js
create mode 100644 src/containers/Preferences/Warehouses/index.js
diff --git a/src/containers/Preferences/Warehouses/Warehouses.js b/src/containers/Preferences/Warehouses/Warehouses.js
new file mode 100644
index 000000000..18e8a1f36
--- /dev/null
+++ b/src/containers/Preferences/Warehouses/Warehouses.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import styled from 'styled-components';
+import { ContextMenu2 } from '@blueprintjs/popover2';
+
+import WarehousesGridItems from './WarehousesGridItems';
+import { WarehouseContextMenu } from './components';
+import withAlertsActions from '../../Alert/withAlertActions';
+import withDialogActions from '../../Dialog/withDialogActions';
+import { compose } from 'utils';
+
+const WAREHOUSE = [
+ {
+ title: 'Warehouse #1',
+ code: '1001',
+ city: 'City',
+ email: 'email@emial.com',
+ phone: '09xxxxxxxx',
+ },
+ {
+ title: 'Warehouse #2',
+ code: '100',
+ city: 'City',
+ email: 'email@emial.com',
+ phone: '09xxxxxxxx',
+ },
+ {
+ title: 'Warehouse #2',
+ code: '100',
+ city: 'City',
+ email: 'email@emial.com',
+ phone: '09xxxxxxxx',
+ },
+];
+
+/**
+ * Warehouses.
+ * @returns
+ */
+function Warehouses({
+ // #withAlertsActions
+ openAlert,
+ // #withDialogActions
+ openDialog,
+}) {
+ return (
+ }>
+
+
+
+
+ );
+}
+
+export default compose(withAlertsActions, withDialogActions)(Warehouses);
+
+const WarehouseGridWrap = styled.div`
+ display: flex;
+ flex-wrap: wrap;
+ margin: 15px;
+`;
diff --git a/src/containers/Preferences/Warehouses/WarehousesGridItems.js b/src/containers/Preferences/Warehouses/WarehousesGridItems.js
new file mode 100644
index 000000000..74e7bd85a
--- /dev/null
+++ b/src/containers/Preferences/Warehouses/WarehousesGridItems.js
@@ -0,0 +1,69 @@
+import React from 'react';
+import styled from 'styled-components';
+
+function WarehousesGrid({ warehouse }) {
+ return (
+
+ {warehouse.title}
+ {warehouse.code}
+ {warehouse.city}
+ {warehouse.country}
+ {warehouse.email}
+ {warehouse.phone}
+
+ );
+}
+
+/**
+ * Warehouse Grid.
+ * @returns
+ */
+function WarehousesGridItems({ warehouses }) {
+ return warehouses.map((warehouse) => (
+
+ ));
+}
+export default WarehousesGridItems;
+
+const WarehouseGrid = styled.div`
+ display: flex;
+ flex-direction: column;
+ border-radius: 3px;
+ width: 300px; // 453px
+ height: 160px; //225px
+ background: #fff;
+ margin: 5px;
+ padding: 10px 12px;
+ border: 1px solid #c8cad0; //#CFD1D6
+ transition: all 0.1s ease-in-out;
+
+ &:hover {
+ border-color: #0153cc;
+ }
+`;
+
+const WarehouseTitle = styled.div`
+ font-size: 14px; //22px
+ font-style: inherit;
+ color: #000;
+ white-space: nowrap;
+ font-weight: 500;
+ line-height: 1;
+`;
+
+const WarehouseCode = styled.div`
+ display: inline-block;
+ font-size: 11px;
+ color: #6b7176;
+ margin: 4px 0px 15px;
+`;
+
+const WarehouseInfoItem = styled.div`
+ display: inline-block;
+ font-size: 12px;
+ color: #000;
+ line-height: 1.3rem;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin: 0;
+`;
diff --git a/src/containers/Preferences/Warehouses/WarehousesList.js b/src/containers/Preferences/Warehouses/WarehousesList.js
new file mode 100644
index 000000000..094e0d5d4
--- /dev/null
+++ b/src/containers/Preferences/Warehouses/WarehousesList.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+
+import Warehouses from './Warehouses';
+import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+
+import { compose } from 'utils';
+
+/**
+ * Warehouses List.
+ * @returns
+ */
+function WarehousesList({
+ // #withDashboardActions
+ changePreferencesPageTitle,
+}) {
+ React.useEffect(() => {
+ changePreferencesPageTitle(intl.get('warehouses.label'));
+ }, [changePreferencesPageTitle]);
+
+ return ;
+}
+
+export default compose(withDashboardActions)(WarehousesList);
diff --git a/src/containers/Preferences/Warehouses/WarehousesProvider.js b/src/containers/Preferences/Warehouses/WarehousesProvider.js
new file mode 100644
index 000000000..c42465b91
--- /dev/null
+++ b/src/containers/Preferences/Warehouses/WarehousesProvider.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import classNames from 'classnames';
+import { CLASSES } from 'common/classes';
+import styled from 'styled-components';
+
+const WarehousesContext = React.createContext();
+
+/**
+ * Warehouses data provider.
+ */
+function WarehousesProvider({ ...props }) {
+ // Provider state.
+ const provider = {};
+
+ return (
+
+
+
+ );
+}
+
+const useWarehousesContext = () => React.useContext(WarehousesContext);
+
+export { WarehousesProvider, useWarehousesContext };
diff --git a/src/containers/Preferences/Warehouses/components.js b/src/containers/Preferences/Warehouses/components.js
new file mode 100644
index 000000000..1ab35654b
--- /dev/null
+++ b/src/containers/Preferences/Warehouses/components.js
@@ -0,0 +1,37 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+
+import { Menu, MenuItem, MenuDivider, Intent } from '@blueprintjs/core';
+import { If, Icon, Can } from '../../../components';
+import { safeCallback } from 'utils';
+
+/**
+ * Warehouse context menu.
+ */
+export function WarehouseContextMenu({
+ onEditClick,
+ onDeleteClick,
+ onPrimary,
+}) {
+ return (
+
+ }
+ text={intl.get('warehouses.action.edit_warehouse')}
+ onClick={safeCallback(onEditClick)}
+ />
+ }
+ text={intl.get('warehouses.action.make_as_parimary')}
+ onClick={safeCallback(onPrimary)}
+ />
+
+ }
+ intent={Intent.DANGER}
+ onClick={safeCallback(onDeleteClick)}
+ />
+
+ );
+}
diff --git a/src/containers/Preferences/Warehouses/index.js b/src/containers/Preferences/Warehouses/index.js
new file mode 100644
index 000000000..65ec45d5a
--- /dev/null
+++ b/src/containers/Preferences/Warehouses/index.js
@@ -0,0 +1,15 @@
+import React from 'react';
+import { WarehousesProvider } from './WarehousesProvider';
+import Warehouses from './WarehousesList';
+
+/**
+ * Warehouses Preferences.
+ * @returns
+ */
+export default function WarehousesPerences() {
+ return (
+
+
+
+ );
+}
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index 4e820a97e..be431da0b 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -1762,5 +1762,8 @@
"warehouse_locations.label":"Warehouses Locations",
"warehouse_locations.column.warehouse_name":"Warehouse name",
"warehouse_locations.column.quantity":"Quantity",
- "warehouse_locations.column.available_for_sale":"Available for sale"
+ "warehouse_locations.column.available_for_sale":"Available for sale",
+ "warehouses.action.edit_warehouse":"Edit Warehouse",
+ "warehouses.action.delete_warehouse":"Delete Warehouse",
+ "warehouses.action.make_as_parimary":"Mark as Primary"
}
\ No newline at end of file
diff --git a/src/routes/preferences.js b/src/routes/preferences.js
index 9fc454ddd..b4200758e 100644
--- a/src/routes/preferences.js
+++ b/src/routes/preferences.js
@@ -7,6 +7,7 @@ import Currencies from 'containers/Preferences/Currencies/Currencies';
import Item from 'containers/Preferences/Item';
import SMSIntegration from '../containers/Preferences/SMSIntegration';
import DefaultRoute from '../containers/Preferences/DefaultRoute';
+import Warehouses from '../containers/Preferences/Warehouses';
const BASE_URL = '/preferences';
@@ -36,6 +37,11 @@ export default [
component: Currencies,
exact: true,
},
+ {
+ path: `${BASE_URL}/warehouses`,
+ component: Warehouses,
+ exact: true,
+ },
{
path: `${BASE_URL}/accountant`,
component: Accountant,
From 2aa26959e924af32a49bb943f2e5877dfede0ae9 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Sun, 30 Jan 2022 18:04:56 +0200
Subject: [PATCH 07/30] feat(warehouse) add warehouse propover.
---
.../DataTableCells/NumericInputCell.js | 4 +-
.../DataTableCells/RadioFieldCell.js | 44 +++++++++++
src/components/DataTableCells/index.js | 2 +
.../WarehouseListPopover/WarehousesList.js | 75 +++++++++++++++++++
.../WarehouseListPopover/components.js | 38 ++++++++++
src/containers/WarehouseListPopover/index.js | 36 +++++++++
6 files changed, 198 insertions(+), 1 deletion(-)
create mode 100644 src/components/DataTableCells/RadioFieldCell.js
create mode 100644 src/containers/WarehouseListPopover/WarehousesList.js
create mode 100644 src/containers/WarehouseListPopover/components.js
create mode 100644 src/containers/WarehouseListPopover/index.js
diff --git a/src/components/DataTableCells/NumericInputCell.js b/src/components/DataTableCells/NumericInputCell.js
index eaf933fb8..5e6c5d245 100644
--- a/src/components/DataTableCells/NumericInputCell.js
+++ b/src/components/DataTableCells/NumericInputCell.js
@@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import { FormGroup, NumericInput, Intent } from '@blueprintjs/core';
import classNames from 'classnames';
import { CLASSES } from 'common/classes';
+import WarehouseListPopover from '../../containers/WarehouseListPopover';
/**
* Numeric input table cell.
@@ -36,7 +37,8 @@ export default function NumericInputCell({
onValueChange={handleValueChange}
onBlur={onBlur}
fill={true}
- buttonPosition={"none"}
+ buttonPosition={'none'}
+ rightElement={ }
/>
);
diff --git a/src/components/DataTableCells/RadioFieldCell.js b/src/components/DataTableCells/RadioFieldCell.js
new file mode 100644
index 000000000..7471fb56c
--- /dev/null
+++ b/src/components/DataTableCells/RadioFieldCell.js
@@ -0,0 +1,44 @@
+import React from 'react';
+import classNames from 'classnames';
+import { FormGroup, Intent, Classes, Radio } from '@blueprintjs/core';
+
+const RadioEditableCell = ({
+ row: { index, original },
+ column: { id, radioProps },
+ cell: { value: initialValue },
+ payload,
+}) => {
+ const [value, setValue] = React.useState(initialValue);
+
+ const onChange = (e) => {
+ const newValue = e.target.checked;
+ debugger;
+ setValue(newValue);
+ payload.updateData(index, id, newValue);
+ };
+
+ React.useEffect(() => {
+ setValue(initialValue);
+ }, [initialValue]);
+
+ const error = payload.errors?.[index]?.[id];
+
+ return (
+
+
+
+ );
+};
+
+export default RadioEditableCell;
diff --git a/src/components/DataTableCells/index.js b/src/components/DataTableCells/index.js
index fed349eed..4e0a42835 100644
--- a/src/components/DataTableCells/index.js
+++ b/src/components/DataTableCells/index.js
@@ -9,6 +9,7 @@ import NumericInputCell from './NumericInputCell';
import CheckBoxFieldCell from './CheckBoxFieldCell';
import SwitchFieldCell from './SwitchFieldCell';
import TextAreaCell from './TextAreaCell';
+import RadioFieldCell from './RadioFieldCell';
export {
AccountsListFieldCell,
@@ -23,4 +24,5 @@ export {
CheckBoxFieldCell,
SwitchFieldCell,
TextAreaCell,
+ RadioFieldCell,
};
diff --git a/src/containers/WarehouseListPopover/WarehousesList.js b/src/containers/WarehouseListPopover/WarehousesList.js
new file mode 100644
index 000000000..15c85743c
--- /dev/null
+++ b/src/containers/WarehouseListPopover/WarehousesList.js
@@ -0,0 +1,75 @@
+import React from 'react';
+import styled from 'styled-components';
+
+import { CLASSES } from 'common/classes';
+import { TableStyle } from '../../common';
+import { DataTableEditable, DataTable } from 'components';
+import { compose, saveInvoke, updateTableCell } from 'utils';
+import { useWarehouseEntriesColumns } from './components';
+
+export default function IntegrateWarehousesTable({
+ // #ownProps
+ initialWarehouse,
+ selectedWarehouseId,
+ onUpdateData,
+ entries,
+ errors,
+}) {
+ const [rows, setRows] = React.useState(initialWarehouse);
+
+ // warehouses entries columns.
+ const columns = useWarehouseEntriesColumns();
+
+ // Handle update data.
+ const handleUpdateData = React.useCallback(
+ (rowIndex, columnId, value) => {
+ const newRows = compose(updateTableCell(rowIndex, columnId, value))(
+ entries,
+ );
+ onUpdateData(newRows);
+ },
+ [onUpdateData, entries],
+ );
+
+ const DATA = [
+ {
+ warehouse_name: true,
+ quantity: '9,444',
+ availiable_for_sale: 0,
+ },
+ {
+ warehouse_name: false,
+ quantity: '19,444',
+ availiable_for_sale: 0,
+ },
+ ];
+
+ return (
+
+ );
+}
+
+const WarehouseDataTableRoot = styled(DataTable)`
+ width: 600px;
+
+ .table {
+ border: 1px solid #000000;
+ .thead .th {
+ background: transparent;
+ color: #222222;
+ border-bottom: 1px solid #000000;
+ padding: 0.5rem;
+ }
+ .tbody .tr .td {
+ padding: 0.2rem 0.2rem;
+ border-bottom: 1px solid #cecbcb;
+ }
+ }
+`;
diff --git a/src/containers/WarehouseListPopover/components.js b/src/containers/WarehouseListPopover/components.js
new file mode 100644
index 000000000..1429a87e6
--- /dev/null
+++ b/src/containers/WarehouseListPopover/components.js
@@ -0,0 +1,38 @@
+import React from 'react';
+
+import { RadioFieldCell } from 'components/DataTableCells';
+
+/**
+ * Retrieve warehouse entries columns.
+ */
+export function useWarehouseEntriesColumns() {
+ return React.useMemo(
+ () => [
+ {
+ Header: 'Warehouse Name',
+ accessor: 'warehouse_name',
+ Cell: RadioFieldCell,
+ width: 120,
+ disableSortBy: true,
+ className: 'name',
+ },
+ {
+ id: 'quantity',
+ Header: 'Quantity on Hand',
+ accessor: 'quantity',
+ disableSortBy: true,
+ align: 'right',
+ width: '100',
+ },
+ {
+ id: 'availiable_for_sale',
+ Header: 'Availiable for Sale',
+ accessor: 'availiable_for_sale',
+ disableSortBy: true,
+ align: 'right',
+ width: '100',
+ },
+ ],
+ [],
+ );
+}
diff --git a/src/containers/WarehouseListPopover/index.js b/src/containers/WarehouseListPopover/index.js
new file mode 100644
index 000000000..d2026f8ec
--- /dev/null
+++ b/src/containers/WarehouseListPopover/index.js
@@ -0,0 +1,36 @@
+import React from 'react';
+import styled from 'styled-components';
+import { PopoverInteractionKind, Position, Button } from '@blueprintjs/core';
+import { Popover2 } from '@blueprintjs/popover2';
+import WarehousesList from './WarehousesList';
+import { Icon, FormattedMessage as T, ButtonLink } from 'components';
+
+export default function IntegrateWarehouseTable() {
+ return (
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ position={Position.BOTTOM_LEFT}
+ modifiers={{
+ offset: { offset: '0, 4' },
+ }}
+ >
+ →
+
+ );
+}
+
+const PopoverLink = styled.button`
+ border: 0;
+ cursor: pointer;
+ background: transparent;
+ margin-top: 18px;
+ padding-right: 0px;
+ color: #0052cc;
+
+ &:hover,
+ &:active {
+ text-decoration: underline;
+ }
+`;
From 0d11ea7c5ed818f59db0d64ecad7b3d7e43ce2a4 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Sun, 30 Jan 2022 18:29:10 +0200
Subject: [PATCH 08/30] feat(warehouse) add warehouse grid item style.
---
src/containers/Preferences/Warehouses/Warehouses.js | 3 +++
.../Preferences/Warehouses/WarehousesGridItems.js | 13 +++++++++----
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/src/containers/Preferences/Warehouses/Warehouses.js b/src/containers/Preferences/Warehouses/Warehouses.js
index 18e8a1f36..90446212d 100644
--- a/src/containers/Preferences/Warehouses/Warehouses.js
+++ b/src/containers/Preferences/Warehouses/Warehouses.js
@@ -13,6 +13,7 @@ const WAREHOUSE = [
title: 'Warehouse #1',
code: '1001',
city: 'City',
+ country: 'Country',
email: 'email@emial.com',
phone: '09xxxxxxxx',
},
@@ -20,6 +21,7 @@ const WAREHOUSE = [
title: 'Warehouse #2',
code: '100',
city: 'City',
+ country: 'Country',
email: 'email@emial.com',
phone: '09xxxxxxxx',
},
@@ -27,6 +29,7 @@ const WAREHOUSE = [
title: 'Warehouse #2',
code: '100',
city: 'City',
+ country: 'Country',
email: 'email@emial.com',
phone: '09xxxxxxxx',
},
diff --git a/src/containers/Preferences/Warehouses/WarehousesGridItems.js b/src/containers/Preferences/Warehouses/WarehousesGridItems.js
index 74e7bd85a..8ade20f5d 100644
--- a/src/containers/Preferences/Warehouses/WarehousesGridItems.js
+++ b/src/containers/Preferences/Warehouses/WarehousesGridItems.js
@@ -4,8 +4,10 @@ import styled from 'styled-components';
function WarehousesGrid({ warehouse }) {
return (
- {warehouse.title}
- {warehouse.code}
+
+ {warehouse.title}
+ {warehouse.code}
+
{warehouse.city}
{warehouse.country}
{warehouse.email}
@@ -33,7 +35,7 @@ const WarehouseGrid = styled.div`
height: 160px; //225px
background: #fff;
margin: 5px;
- padding: 10px 12px;
+ padding: 16px 12px 10px;
border: 1px solid #c8cad0; //#CFD1D6
transition: all 0.1s ease-in-out;
@@ -51,11 +53,14 @@ const WarehouseTitle = styled.div`
line-height: 1;
`;
+const WarehouseHeader = styled.div`
+ margin: 4px 0px 15px;
+`;
+
const WarehouseCode = styled.div`
display: inline-block;
font-size: 11px;
color: #6b7176;
- margin: 4px 0px 15px;
`;
const WarehouseInfoItem = styled.div`
From fc097378cb9bd6bbdcf0da6b128257a6c891d7ed Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Tue, 1 Feb 2022 21:05:54 +0200
Subject: [PATCH 09/30] feat(warehouse): add credit & edit & delete warehouse.
---
.../Alerts/Warehouses/WarehouseDeleteAlert.js | 77 ++++++++++++
src/containers/AlertsContainer/registered.js | 6 +-
.../WarehouseFormDialog/WarehouseForm.js | 59 ++++++++--
.../WarehouseForm.schema.js | 12 +-
.../WarehouseFormDialogContent.js | 3 +-
.../WarehouseFormFields.js | 77 ++++++++----
.../WarehouseFormProvider.js | 32 ++++-
.../Dialogs/WarehouseFormDialog/index.js | 19 ++-
.../Preferences/Warehouses/Warehouses.js | 65 +++--------
.../Warehouses/WarehousesAlerts.js | 10 ++
.../Warehouses/WarehousesGridItems.js | 110 ++++++++----------
.../Preferences/Warehouses/WarehousesList.js | 24 ----
.../Warehouses/WarehousesProvider.js | 26 ++++-
.../Preferences/Warehouses/components.js | 62 ++++++++++
.../Preferences/Warehouses/index.js | 2 +-
src/hooks/query/index.js | 1 +
src/hooks/query/types.js | 6 +
src/hooks/query/warehouses.js | 99 ++++++++++++++++
src/lang/en/index.json | 37 +++---
19 files changed, 524 insertions(+), 203 deletions(-)
create mode 100644 src/containers/Alerts/Warehouses/WarehouseDeleteAlert.js
create mode 100644 src/containers/Preferences/Warehouses/WarehousesAlerts.js
delete mode 100644 src/containers/Preferences/Warehouses/WarehousesList.js
create mode 100644 src/hooks/query/warehouses.js
diff --git a/src/containers/Alerts/Warehouses/WarehouseDeleteAlert.js b/src/containers/Alerts/Warehouses/WarehouseDeleteAlert.js
new file mode 100644
index 000000000..9d4cb0c83
--- /dev/null
+++ b/src/containers/Alerts/Warehouses/WarehouseDeleteAlert.js
@@ -0,0 +1,77 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
+import { Intent, Alert } from '@blueprintjs/core';
+import { AppToaster } from 'components';
+import { useDeleteWarehouse } from 'hooks/query';
+
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withAlertActions from 'containers/Alert/withAlertActions';
+
+import { compose } from 'utils';
+
+/**
+ * Warehouse delete alert
+ * @returns
+ */
+function WarehouseDeleteAlert({
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { warehouseId },
+
+ // #withAlertActions
+ closeAlert,
+}) {
+ const { mutateAsync: deleteWarehouseMutate, isLoading } =
+ useDeleteWarehouse();
+
+ // handle cancel delete warehouse alert.
+ const handleCancelDeleteAlert = () => {
+ closeAlert(name);
+ };
+
+ // handleConfirm delete invoice
+ const handleConfirmWarehouseDelete = () => {
+ deleteWarehouseMutate(warehouseId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get('warehouse.alert.delete_message'),
+ intent: Intent.SUCCESS,
+ });
+ })
+ .catch(
+ ({
+ response: {
+ data: { errors },
+ },
+ }) => {},
+ )
+ .finally(() => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={ }
+ icon="trash"
+ intent={Intent.DANGER}
+ isOpen={isOpen}
+ onCancel={handleCancelDeleteAlert}
+ onConfirm={handleConfirmWarehouseDelete}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+)(WarehouseDeleteAlert);
diff --git a/src/containers/AlertsContainer/registered.js b/src/containers/AlertsContainer/registered.js
index 57d66288a..c023ebf0c 100644
--- a/src/containers/AlertsContainer/registered.js
+++ b/src/containers/AlertsContainer/registered.js
@@ -19,7 +19,8 @@ import CurrenciesAlerts from '../Preferences/Currencies/CurrenciesAlerts';
import RolesAlerts from '../Preferences/Users/Roles/RolesAlerts';
import CreditNotesAlerts from '../Sales/CreditNotes/CreditNotesAlerts';
import VendorCreditNotesAlerts from '../Purchases/CreditNotes/VendorCreditNotesAlerts';
-import TransactionsLockingAlerts from '../TransactionsLocking/TransactionsLockingAlerts'
+import TransactionsLockingAlerts from '../TransactionsLocking/TransactionsLockingAlerts';
+import WarehousesAlerts from '../Preferences/Warehouses/WarehousesAlerts';
export default [
...AccountsAlerts,
@@ -43,5 +44,6 @@ export default [
...RolesAlerts,
...CreditNotesAlerts,
...VendorCreditNotesAlerts,
- ...TransactionsLockingAlerts
+ ...TransactionsLockingAlerts,
+ ...WarehousesAlerts,
];
diff --git a/src/containers/Dialogs/WarehouseFormDialog/WarehouseForm.js b/src/containers/Dialogs/WarehouseFormDialog/WarehouseForm.js
index 1c5474fce..e4c369d6b 100644
--- a/src/containers/Dialogs/WarehouseFormDialog/WarehouseForm.js
+++ b/src/containers/Dialogs/WarehouseFormDialog/WarehouseForm.js
@@ -1,20 +1,26 @@
import React from 'react';
-import { Formik } from 'formik';
+import intl from 'react-intl-universal';
+import { Formik } from 'formik';
+import { Intent } from '@blueprintjs/core';
+
+import { AppToaster } from 'components';
import { CreateWarehouseFormSchema } from './WarehouseForm.schema';
import { useWarehouseFormContext } from './WarehouseFormProvider';
import WarehouseFormContent from './WarehouseFormContent';
import withDialogActions from 'containers/Dialog/withDialogActions';
-import { compose } from 'utils';
+import { compose, transformToForm } from 'utils';
const defaultInitialValues = {
- warehouse_name: '',
- warehouse_address_1: '',
- warehouse_address_2: '',
- warehouse_address_city: '',
- warehouse_address_country: '',
+ name: '',
+ code: '',
+ address: '',
+ city: '',
+ country: '',
phone_number: '',
+ website: '',
+ email: '',
};
/**
@@ -25,13 +31,50 @@ function WarehouseForm({
// #withDialogActions
closeDialog,
}) {
+ const {
+ dialogName,
+ warehouse,
+ warehouseId,
+ createWarehouseMutate,
+ editWarehouseMutate,
+ } = useWarehouseFormContext();
+
// Initial form values.
const initialValues = {
...defaultInitialValues,
+ ...transformToForm(warehouse, defaultInitialValues),
};
// Handles the form submit.
- const handleFormSubmit = (values, { setSubmitting, setErrors }) => {};
+ const handleFormSubmit = (values, { setSubmitting, setErrors }) => {
+ const form = { ...values };
+
+ // Handle request response success.
+ const onSuccess = (response) => {
+ AppToaster.show({
+ message: intl.get('warehouse.dialog.success_message'),
+ intent: Intent.SUCCESS,
+ });
+ closeDialog(dialogName);
+ };
+
+ // Handle request response errors.
+ const onError = ({
+ response: {
+ data: { errors },
+ },
+ }) => {
+ if (errors) {
+ }
+ setSubmitting(false);
+ };
+
+ if (warehouseId) {
+ editWarehouseMutate([warehouseId, form]).then(onSuccess).catch(onError);
+ } else {
+ createWarehouseMutate(form).then(onSuccess).catch(onError);
+ }
+ };
return (
+
);
diff --git a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormFields.js b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormFields.js
index b1097462e..d86cc8bcf 100644
--- a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormFields.js
+++ b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormFields.js
@@ -22,28 +22,44 @@ export default function WarehouseFormFields() {
return (
{/*------------ Warehouse Name -----------*/}
-
+
{({ form, field, meta: { error, touched } }) => (
}
labelInfo={ }
intent={inputIntent({ error, touched })}
inline={true}
- helperText={ }
+ helperText={ }
className={'form-group--warehouse_name'}
>
)}
+
+ {/*------------ Warehouse Code -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ intent={inputIntent({ error, touched })}
+ inline={true}
+ helperText={ }
+ className={'form-group--warehouse_name'}
+ >
+
+
+ )}
+
+
{/*------------ Warehouse Address -----------*/}
-
+
{({ form, field, meta: { error, touched } }) => (
}
+ helperText={ }
className={'form-group--warehouse_address_1'}
>
-
- {({ form, field, meta: { error, touched } }) => (
- }
- className={'form-group--warehouse_address_2'}
- >
-
-
- )}
-
{/*------------ Warehouse Address City & Country-----------*/}
}
>
-
+
{({ field, meta: { error, touched } }) => (
)}
-
+
{({ field, meta: { error, touched } }) => (
+
{/*------------ Phone Number -----------*/}
{({ form, field, meta: { error, touched } }) => (
@@ -117,6 +116,36 @@ export default function WarehouseFormFields() {
)}
+
+ {/*------------ Email -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ className={'form-group--warehouse_name'}
+ >
+
+
+ )}
+
+
+ {/*------------ Website -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ className={'form-group--warehouse_name'}
+ >
+
+
+ )}
+
);
}
diff --git a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js
index 336a2f93f..901468fbd 100644
--- a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js
+++ b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js
@@ -1,22 +1,44 @@
import React from 'react';
import { DialogContent } from 'components';
-// import {} from 'hooks/query';
+import {
+ useCreateWarehouse,
+ useEditWarehouse,
+ useWarehouse,
+} from 'hooks/query';
+import { useLocation } from 'react-router-dom';
const WarehouseFormContext = React.createContext();
/**
* Warehouse form provider.
*/
-function WarehouseFormProvider({ dialogName, ...props }) {
+function WarehouseFormProvider({ dialogName, warehouseId, ...props }) {
+ const { state } = useLocation();
+
+ console.log(state, 'XXX');
+ // Create and edit warehouse mutations.
+ const { mutateAsync: createWarehouseMutate } = useCreateWarehouse();
+ const { mutateAsync: editWarehouseMutate } = useEditWarehouse();
+
+ // Handle fetch invoice detail.
+ const { data: warehouse, isLoading: isWarehouseLoading } = useWarehouse(
+ warehouseId,
+ {
+ enabled: !!warehouseId,
+ },
+ );
+
// State provider.
const provider = {
dialogName,
+ warehouse,
+ warehouseId,
+ createWarehouseMutate,
+ editWarehouseMutate,
};
return (
-
+
);
diff --git a/src/containers/Dialogs/WarehouseFormDialog/index.js b/src/containers/Dialogs/WarehouseFormDialog/index.js
index 0f886e56d..f03486120 100644
--- a/src/containers/Dialogs/WarehouseFormDialog/index.js
+++ b/src/containers/Dialogs/WarehouseFormDialog/index.js
@@ -12,18 +12,31 @@ const WarehouseFormDialogContent = React.lazy(() =>
/**
* Warehouse form form dialog.
*/
-function WarehouseFormDialog({ dialogName, isOpen }) {
+function WarehouseFormDialog({
+ dialogName,
+ payload: { warehouseId = null, action },
+ isOpen,
+}) {
return (
}
+ title={
+ action == 'edit' ? (
+
+ ) : (
+
+ )
+ }
isOpen={isOpen}
canEscapeJeyClose={true}
autoFocus={true}
className={'dialog--warehouse-form'}
>
-
+
);
diff --git a/src/containers/Preferences/Warehouses/Warehouses.js b/src/containers/Preferences/Warehouses/Warehouses.js
index 90446212d..30e1c0388 100644
--- a/src/containers/Preferences/Warehouses/Warehouses.js
+++ b/src/containers/Preferences/Warehouses/Warehouses.js
@@ -1,63 +1,30 @@
import React from 'react';
+import intl from 'react-intl-universal';
import styled from 'styled-components';
-import { ContextMenu2 } from '@blueprintjs/popover2';
+import { useWarehousesContext } from './WarehousesProvider';
import WarehousesGridItems from './WarehousesGridItems';
-import { WarehouseContextMenu } from './components';
-import withAlertsActions from '../../Alert/withAlertActions';
-import withDialogActions from '../../Dialog/withDialogActions';
-import { compose } from 'utils';
+import withDashboardActions from 'containers/Dashboard/withDashboardActions';
-const WAREHOUSE = [
- {
- title: 'Warehouse #1',
- code: '1001',
- city: 'City',
- country: 'Country',
- email: 'email@emial.com',
- phone: '09xxxxxxxx',
- },
- {
- title: 'Warehouse #2',
- code: '100',
- city: 'City',
- country: 'Country',
- email: 'email@emial.com',
- phone: '09xxxxxxxx',
- },
- {
- title: 'Warehouse #2',
- code: '100',
- city: 'City',
- country: 'Country',
- email: 'email@emial.com',
- phone: '09xxxxxxxx',
- },
-];
+import { compose } from 'utils';
/**
* Warehouses.
* @returns
*/
function Warehouses({
- // #withAlertsActions
- openAlert,
- // #withDialogActions
- openDialog,
+ // #withDashboardActions
+ changePreferencesPageTitle,
}) {
- return (
- }>
-
-
-
-
- );
+ const { warehouses } = useWarehousesContext();
+
+ React.useEffect(() => {
+ changePreferencesPageTitle(intl.get('warehouses.label'));
+ }, [changePreferencesPageTitle]);
+
+ return warehouses.map((warehouse) => (
+
+ ));
}
-export default compose(withAlertsActions, withDialogActions)(Warehouses);
-
-const WarehouseGridWrap = styled.div`
- display: flex;
- flex-wrap: wrap;
- margin: 15px;
-`;
+export default compose(withDashboardActions)(Warehouses);
diff --git a/src/containers/Preferences/Warehouses/WarehousesAlerts.js b/src/containers/Preferences/Warehouses/WarehousesAlerts.js
new file mode 100644
index 000000000..7e19d865a
--- /dev/null
+++ b/src/containers/Preferences/Warehouses/WarehousesAlerts.js
@@ -0,0 +1,10 @@
+import React from 'react';
+
+const WarehouseDeleteAlert = React.lazy(() =>
+ import('../../Alerts/Warehouses/WarehouseDeleteAlert'),
+);
+
+/**
+ * Warehouses alerts.
+ */
+export default [{ name: 'warehouse-delete', component: WarehouseDeleteAlert }];
diff --git a/src/containers/Preferences/Warehouses/WarehousesGridItems.js b/src/containers/Preferences/Warehouses/WarehousesGridItems.js
index 8ade20f5d..edc33ff22 100644
--- a/src/containers/Preferences/Warehouses/WarehousesGridItems.js
+++ b/src/containers/Preferences/Warehouses/WarehousesGridItems.js
@@ -1,74 +1,56 @@
import React from 'react';
import styled from 'styled-components';
+import { ContextMenu2 } from '@blueprintjs/popover2';
+
+import { WarehouseContextMenu, WarehousesGrid } from './components';
+
+import withAlertsActions from '../../Alert/withAlertActions';
+import withDialogActions from '../../Dialog/withDialogActions';
+import { compose } from 'utils';
+
+/**
+ * Warehouse grid items.
+ * @returns
+ */
+function WarehousesGridItems({
+ // #withAlertsActions
+ openAlert,
+ // #withDialogActions
+ openDialog,
+
+ warehouse,
+}) {
+ // Handle edit warehouse.
+ const handleEditWarehouse = () => {
+ openDialog('warehouse-form', { warehouseId: warehouse.id, action: 'edit' });
+ };
+
+ // Handle delete warehouse.
+ const handleDeleteWarehouse = () => {
+ openAlert('warehouse-delete', { warehouseId: warehouse.id });
+ };
-function WarehousesGrid({ warehouse }) {
return (
-
-
- {warehouse.title}
- {warehouse.code}
-
- {warehouse.city}
- {warehouse.country}
- {warehouse.email}
- {warehouse.phone}
-
+
+ }
+ >
+
+
);
}
-/**
- * Warehouse Grid.
- * @returns
- */
-function WarehousesGridItems({ warehouses }) {
- return warehouses.map((warehouse) => (
-
- ));
-}
-export default WarehousesGridItems;
+export default compose(
+ withAlertsActions,
+ withDialogActions,
+)(WarehousesGridItems);
-const WarehouseGrid = styled.div`
+const WarehouseGridWrap = styled.div`
display: flex;
- flex-direction: column;
- border-radius: 3px;
- width: 300px; // 453px
- height: 160px; //225px
- background: #fff;
- margin: 5px;
- padding: 16px 12px 10px;
- border: 1px solid #c8cad0; //#CFD1D6
- transition: all 0.1s ease-in-out;
-
- &:hover {
- border-color: #0153cc;
- }
-`;
-
-const WarehouseTitle = styled.div`
- font-size: 14px; //22px
- font-style: inherit;
- color: #000;
- white-space: nowrap;
- font-weight: 500;
- line-height: 1;
-`;
-
-const WarehouseHeader = styled.div`
- margin: 4px 0px 15px;
-`;
-
-const WarehouseCode = styled.div`
- display: inline-block;
- font-size: 11px;
- color: #6b7176;
-`;
-
-const WarehouseInfoItem = styled.div`
- display: inline-block;
- font-size: 12px;
- color: #000;
- line-height: 1.3rem;
- overflow: hidden;
- text-overflow: ellipsis;
- margin: 0;
+ flex-wrap: wrap;
+ margin: 15px;
`;
diff --git a/src/containers/Preferences/Warehouses/WarehousesList.js b/src/containers/Preferences/Warehouses/WarehousesList.js
deleted file mode 100644
index 094e0d5d4..000000000
--- a/src/containers/Preferences/Warehouses/WarehousesList.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react';
-import intl from 'react-intl-universal';
-
-import Warehouses from './Warehouses';
-import withDashboardActions from 'containers/Dashboard/withDashboardActions';
-
-import { compose } from 'utils';
-
-/**
- * Warehouses List.
- * @returns
- */
-function WarehousesList({
- // #withDashboardActions
- changePreferencesPageTitle,
-}) {
- React.useEffect(() => {
- changePreferencesPageTitle(intl.get('warehouses.label'));
- }, [changePreferencesPageTitle]);
-
- return ;
-}
-
-export default compose(withDashboardActions)(WarehousesList);
diff --git a/src/containers/Preferences/Warehouses/WarehousesProvider.js b/src/containers/Preferences/Warehouses/WarehousesProvider.js
index c42465b91..3b2320431 100644
--- a/src/containers/Preferences/Warehouses/WarehousesProvider.js
+++ b/src/containers/Preferences/Warehouses/WarehousesProvider.js
@@ -1,7 +1,9 @@
import React from 'react';
+import styled from 'styled-components';
import classNames from 'classnames';
import { CLASSES } from 'common/classes';
-import styled from 'styled-components';
+import { useWarehouses } from 'hooks/query';
+import PreferencesPageLoader from '../PreferencesPageLoader';
const WarehousesContext = React.createContext();
@@ -9,12 +11,24 @@ const WarehousesContext = React.createContext();
* Warehouses data provider.
*/
function WarehousesProvider({ ...props }) {
+ // Fetch warehouses list.
+ const { data: warehouses, isLoading: isWarehouesLoading } = useWarehouses();
+
// Provider state.
- const provider = {};
+ const provider = {
+ warehouses,
+ isWarehouesLoading,
+ };
return (
-
+
+ {isWarehouesLoading ? (
+
+ ) : (
+
+ )}
+
);
}
@@ -22,3 +36,9 @@ function WarehousesProvider({ ...props }) {
const useWarehousesContext = () => React.useContext(WarehousesContext);
export { WarehousesProvider, useWarehousesContext };
+
+const WarehousePreference = styled.div`
+ display: flex;
+ flex-wrap: wrap;
+ margin: 15px;
+`;
diff --git a/src/containers/Preferences/Warehouses/components.js b/src/containers/Preferences/Warehouses/components.js
index 1ab35654b..7027343b5 100644
--- a/src/containers/Preferences/Warehouses/components.js
+++ b/src/containers/Preferences/Warehouses/components.js
@@ -1,5 +1,6 @@
import React from 'react';
import intl from 'react-intl-universal';
+import styled from 'styled-components';
import { Menu, MenuItem, MenuDivider, Intent } from '@blueprintjs/core';
import { If, Icon, Can } from '../../../components';
@@ -35,3 +36,64 @@ export function WarehouseContextMenu({
);
}
+
+export function WarehousesGrid({ warehouse }) {
+ return (
+
+
+ {warehouse.name}
+ {warehouse.code}
+
+ {warehouse.city}
+ {warehouse.country}
+ {warehouse.email}
+ {warehouse.phone_number}
+
+ );
+}
+
+const WarehouseGrid = styled.div`
+ display: flex;
+ flex-direction: column;
+ border-radius: 3px;
+ width: 280px; // 453px
+ height: 160px; //225px
+ background: #fff;
+ margin: 5px;
+ padding: 16px 12px 10px;
+ border: 1px solid #c8cad0; //#CFD1D6
+ transition: all 0.1s ease-in-out;
+
+ &:hover {
+ border-color: #0153cc;
+ }
+`;
+
+const WarehouseTitle = styled.div`
+ font-size: 14px; //22px
+ font-style: inherit;
+ color: #000;
+ white-space: nowrap;
+ font-weight: 500;
+ line-height: 1;
+`;
+
+const WarehouseHeader = styled.div`
+ margin: 4px 0px 15px;
+`;
+
+const WarehouseCode = styled.div`
+ display: inline-block;
+ font-size: 11px;
+ color: #6b7176;
+`;
+
+const WarehouseInfoItem = styled.div`
+ display: inline-block;
+ font-size: 12px;
+ color: #000;
+ line-height: 1.3rem;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin: 0;
+`;
diff --git a/src/containers/Preferences/Warehouses/index.js b/src/containers/Preferences/Warehouses/index.js
index 65ec45d5a..5a7270e10 100644
--- a/src/containers/Preferences/Warehouses/index.js
+++ b/src/containers/Preferences/Warehouses/index.js
@@ -1,6 +1,6 @@
import React from 'react';
import { WarehousesProvider } from './WarehousesProvider';
-import Warehouses from './WarehousesList';
+import Warehouses from './Warehouses';
/**
* Warehouses Preferences.
diff --git a/src/hooks/query/index.js b/src/hooks/query/index.js
index 629f4f1b4..b27ebd2b5 100644
--- a/src/hooks/query/index.js
+++ b/src/hooks/query/index.js
@@ -33,3 +33,4 @@ export * from './roles';
export * from './creditNote';
export * from './vendorCredit';
export * from './transactionsLocking';
+export * from './warehouses'
diff --git a/src/hooks/query/types.js b/src/hooks/query/types.js
index d98f99db8..27d7e3f77 100644
--- a/src/hooks/query/types.js
+++ b/src/hooks/query/types.js
@@ -191,6 +191,11 @@ const TARNSACTIONS_LOCKING = {
TRANSACTIONS_LOCKING: 'TRANSACTIONS_LOCKING',
};
+const WAREHOUSES = {
+ WAREHOUSE: 'WAREHOUSE',
+ WAREHOUSES: 'WAREHOUSES',
+};
+
export default {
...ACCOUNTS,
...BILLS,
@@ -218,4 +223,5 @@ export default {
...CREDIT_NOTES,
...VENDOR_CREDIT_NOTES,
...TARNSACTIONS_LOCKING,
+ ...WAREHOUSES
};
diff --git a/src/hooks/query/warehouses.js b/src/hooks/query/warehouses.js
new file mode 100644
index 000000000..4aea65efe
--- /dev/null
+++ b/src/hooks/query/warehouses.js
@@ -0,0 +1,99 @@
+import { useQueryClient, useMutation } from 'react-query';
+import { useRequestQuery } from '../useQueryRequest';
+import useApiRequest from '../useRequest';
+import t from './types';
+
+// Common invalidate queries.
+const commonInvalidateQueries = (queryClient) => {
+ // Invalidate warehouses.
+ queryClient.invalidateQueries(t.WAREHOUSES);
+ queryClient.invalidateQueries(t.WAREHOUSE);
+};
+
+/**
+ * Create a new warehouse.
+ */
+export function useCreateWarehouse(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation((values) => apiRequest.post('warehouses', values), {
+ onSuccess: (res, values) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ });
+}
+
+/**
+ * Edits the given warehouse.
+ */
+export function useEditWarehouse(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ ([id, values]) => apiRequest.post(`warehouses/${id}`, values),
+ {
+ onSuccess: (res, [id, values]) => {
+ // Invalidate specific sale invoice.
+ queryClient.invalidateQueries([t.WAREHOUSE, id]);
+
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Deletes the given warehouse.
+ */
+export function useDeleteWarehouse(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation((id) => apiRequest.delete(`warehouses/${id}`), {
+ onSuccess: (res, id) => {
+ // Invalidate specific warehoue.
+ queryClient.invalidateQueries([t.WAREHOUSE, id]);
+
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ });
+}
+
+/**
+ * Retrieve Warehoues list.
+ */
+export function useWarehouses(query, props) {
+ return useRequestQuery(
+ [t.WAREHOUSES, query],
+ { method: 'get', url: 'warehouses', params: query },
+ {
+ select: (res) => res.data.warehouses,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve the warehouse details.
+ * @param {number}
+ */
+export function useWarehouse(id, props, requestProps) {
+ return useRequestQuery(
+ [t.WAREHOUSE, id],
+ { method: 'get', url: `warehouses/${id}`, ...requestProps },
+ {
+ select: (res) => res.data.warehouse,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index be431da0b..9ef8af844 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -1751,19 +1751,26 @@
"payment_receive_preview.dialog.title": "Payment Receive PDF Preview",
"warehouses.label": "Warehouses",
"warehouses.label.new_warehouse": "New Warehouse",
- "warehouse.dialog.label":"New Warehouse",
- "warehouse.dialog.label.warehouse_name":"Warehouse Name",
- "warehouse.dialog.label.warehouse_address":"Address",
- "warehouse.dialog.label.warehouse_address_1":"Address 1",
- "warehouse.dialog.label.warehouse_address_2":"Address 2",
- "warehouse.dialog.label.city":"City",
- "warehouse.dialog.label.country":"Country",
- "warehouse.dialog.label.phone_number":"Phone Number",
- "warehouse_locations.label":"Warehouses Locations",
- "warehouse_locations.column.warehouse_name":"Warehouse name",
- "warehouse_locations.column.quantity":"Quantity",
- "warehouse_locations.column.available_for_sale":"Available for sale",
- "warehouses.action.edit_warehouse":"Edit Warehouse",
- "warehouses.action.delete_warehouse":"Delete Warehouse",
- "warehouses.action.make_as_parimary":"Mark as Primary"
+ "warehouse.dialog.label.new_warehouse": "New Warehouse",
+ "warehouse.dialog.label.edit_warehouse": "Edit Warehouse",
+ "warehouse.dialog.label.warehouse_name": "Warehouse Name",
+ "warehouse.dialog.label.warehouse_address": "Address",
+ "warehouse.dialog.label.warehouse_address_1": "Address",
+ "warehouse.dialog.label.warehouse_address_2": "Address 2",
+ "warehouse.dialog.label.city": "City",
+ "warehouse.dialog.label.country": "Country",
+ "warehouse.dialog.label.phone_number": "Phone Number",
+ "warehouse.dialog.label.code": "Code",
+ "warehouse.dialog.label.email": "Email",
+ "warehouse.dialog.label.website": "Website",
+ "warehouse.dialog.success_message": "The warehouse has been created successfully.",
+ "warehouse_locations.label": "Warehouses Locations",
+ "warehouse_locations.column.warehouse_name": "Warehouse name",
+ "warehouse_locations.column.quantity": "Quantity",
+ "warehouse_locations.column.available_for_sale": "Available for sale",
+ "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?"
}
\ No newline at end of file
From 8d2bede3d4e83235935272ca5348718759a9d617 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Tue, 1 Feb 2022 21:07:28 +0200
Subject: [PATCH 10/30] feat(warehouse): add crud warehouse.
---
.../Dialogs/WarehouseFormDialog/WarehouseFormProvider.js | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js
index 901468fbd..4257d1c8f 100644
--- a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js
+++ b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js
@@ -13,9 +13,6 @@ const WarehouseFormContext = React.createContext();
* Warehouse form provider.
*/
function WarehouseFormProvider({ dialogName, warehouseId, ...props }) {
- const { state } = useLocation();
-
- console.log(state, 'XXX');
// Create and edit warehouse mutations.
const { mutateAsync: createWarehouseMutate } = useCreateWarehouse();
const { mutateAsync: editWarehouseMutate } = useEditWarehouse();
From dea4fe0e790503f66cb00995252bbcbab7a2403c Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Tue, 1 Feb 2022 23:18:32 +0200
Subject: [PATCH 11/30] feat(branche): add crud branches.
---
.../Alerts/Branches/BranchDeleteAlert.js | 77 +++++++++++++++
src/containers/AlertsContainer/registered.js | 6 +-
.../Dialogs/BranchFormDialog/BranchForm.js | 54 ++++++++--
.../BranchFormDialog/BranchForm.schema.js | 11 ++-
.../BranchFormDialogContent.js | 3 +-
.../BranchFormDialog/BranchFormFields.js | 46 ++++-----
.../BranchFormDialog/BranchFormProvider.js | 22 ++++-
.../Dialogs/BranchFormDialog/index.js | 16 ++-
.../Preferences/Branches/BranchesActions.js | 2 +-
.../Preferences/Branches/BranchesAlerts.js | 7 ++
.../Preferences/Branches/BranchesDataTable.js | 32 +++++-
.../Preferences/Branches/BranchesProvider.js | 15 ++-
.../Preferences/Branches/components.js | 26 ++---
src/hooks/query/branches.js | 99 +++++++++++++++++++
src/hooks/query/index.js | 1 +
src/hooks/query/types.js | 6 ++
src/lang/en/index.json | 17 ++--
17 files changed, 366 insertions(+), 74 deletions(-)
create mode 100644 src/containers/Alerts/Branches/BranchDeleteAlert.js
create mode 100644 src/containers/Preferences/Branches/BranchesAlerts.js
create mode 100644 src/hooks/query/branches.js
diff --git a/src/containers/Alerts/Branches/BranchDeleteAlert.js b/src/containers/Alerts/Branches/BranchDeleteAlert.js
new file mode 100644
index 000000000..a58bb63ea
--- /dev/null
+++ b/src/containers/Alerts/Branches/BranchDeleteAlert.js
@@ -0,0 +1,77 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
+import { Intent, Alert } from '@blueprintjs/core';
+import { AppToaster } from 'components';
+
+import { useDeleteBranch } from 'hooks/query';
+
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withAlertActions from 'containers/Alert/withAlertActions';
+
+import { compose } from 'utils';
+
+/**
+ * Branch delete alert.
+ */
+function BranchDeleteAlert({
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { branchId },
+
+ // #withAlertActions
+ closeAlert,
+}) {
+
+ const { mutateAsync: deleteBranch, isLoading } = useDeleteBranch();
+
+ // Handle cancel delete alert.
+ const handleCancelDelete = () => {
+ closeAlert(name);
+ };
+
+ // Handle confirm delete branch.
+ const handleConfirmDeleteBranch = () => {
+ deleteBranch(branchId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get('branch.alert.delete_message'),
+ intent: Intent.SUCCESS,
+ });
+ })
+ .catch(
+ ({
+ response: {
+ data: { errors },
+ },
+ }) => {},
+ )
+ .finally(() => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={ }
+ icon="trash"
+ intent={Intent.DANGER}
+ isOpen={isOpen}
+ onCancel={handleCancelDelete}
+ onConfirm={handleConfirmDeleteBranch}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+)(BranchDeleteAlert);
diff --git a/src/containers/AlertsContainer/registered.js b/src/containers/AlertsContainer/registered.js
index 57d66288a..774000282 100644
--- a/src/containers/AlertsContainer/registered.js
+++ b/src/containers/AlertsContainer/registered.js
@@ -19,7 +19,8 @@ import CurrenciesAlerts from '../Preferences/Currencies/CurrenciesAlerts';
import RolesAlerts from '../Preferences/Users/Roles/RolesAlerts';
import CreditNotesAlerts from '../Sales/CreditNotes/CreditNotesAlerts';
import VendorCreditNotesAlerts from '../Purchases/CreditNotes/VendorCreditNotesAlerts';
-import TransactionsLockingAlerts from '../TransactionsLocking/TransactionsLockingAlerts'
+import TransactionsLockingAlerts from '../TransactionsLocking/TransactionsLockingAlerts';
+import BranchesAlerts from '../Preferences/Branches/BranchesAlerts';
export default [
...AccountsAlerts,
@@ -43,5 +44,6 @@ export default [
...RolesAlerts,
...CreditNotesAlerts,
...VendorCreditNotesAlerts,
- ...TransactionsLockingAlerts
+ ...TransactionsLockingAlerts,
+ ...BranchesAlerts,
];
diff --git a/src/containers/Dialogs/BranchFormDialog/BranchForm.js b/src/containers/Dialogs/BranchFormDialog/BranchForm.js
index 99f41f76e..17f2c8504 100644
--- a/src/containers/Dialogs/BranchFormDialog/BranchForm.js
+++ b/src/containers/Dialogs/BranchFormDialog/BranchForm.js
@@ -1,5 +1,8 @@
import React from 'react';
+import intl from 'react-intl-universal';
+
import { Formik } from 'formik';
+import { Intent } from '@blueprintjs/core';
import { AppToaster } from 'components';
import { CreateBranchFormSchema } from './BranchForm.schema';
@@ -8,30 +11,67 @@ import BranchFormContent from './BranchFormContent';
import { useBranchFormContext } from './BranchFormProvider';
import withDialogActions from 'containers/Dialog/withDialogActions';
-import { compose } from 'utils';
+import { compose, transformToForm } from 'utils';
const defaultInitialValues = {
- branch_name: '',
- branch_address_1: '',
- branch_address_2: '',
+ name: '',
+ code: '',
+ address: '',
phone_number: '',
email: '',
website: '',
- branch_address_city: '',
- branch_address_country: '',
+ city: '',
+ country: '',
};
function BranchForm({
// #withDialogActions
closeDialog,
}) {
+ const {
+ dialogName,
+ branch,
+ branchId,
+ createBranchMutate,
+ editBranchMutate,
+ } = useBranchFormContext();
+
// Initial form values.
const initialValues = {
...defaultInitialValues,
+ ...transformToForm(branch, defaultInitialValues),
};
// Handles the form submit.
- const handleFormSubmit = (values, { setSubmitting, setErrors }) => {};
+ const handleFormSubmit = (values, { setSubmitting, setErrors }) => {
+ const form = { ...values };
+
+ // Handle request response success.
+ const onSuccess = (response) => {
+ AppToaster.show({
+ message: intl.get('branch.dialog.success_message'),
+ intent: Intent.SUCCESS,
+ });
+ closeDialog(dialogName);
+ };
+
+ // Handle request response errors.
+ const onError = ({
+ response: {
+ data: { errors },
+ },
+ }) => {
+ if (errors) {
+ }
+ setSubmitting(false);
+ };
+
+ if (branchId) {
+ editBranchMutate([branchId, form]).then(onSuccess).catch(onError);
+ } else {
+ createBranchMutate(form).then(onSuccess).catch(onError);
+ }
+ };
return (
+
);
diff --git a/src/containers/Dialogs/BranchFormDialog/BranchFormFields.js b/src/containers/Dialogs/BranchFormDialog/BranchFormFields.js
index fcebeb72e..6d6a7203e 100644
--- a/src/containers/Dialogs/BranchFormDialog/BranchFormFields.js
+++ b/src/containers/Dialogs/BranchFormDialog/BranchFormFields.js
@@ -20,7 +20,7 @@ function BranchFormFields() {
return (
{/*------------ Branch Name -----------*/}
-
+
{({ form, field, meta: { error, touched } }) => (
}
@@ -34,15 +34,29 @@ function BranchFormFields() {
)}
+ {/*------------ Branch Code -----------*/}
+
+ {({ form, field, meta: { error, touched } }) => (
+ }
+ intent={inputIntent({ error, touched })}
+ inline={true}
+ helperText={ }
+ className={'form-group--branch_name'}
+ >
+
+
+ )}
+
- {/*------------ Branch Address 1 -----------*/}
-
+ {/*------------ Branch Address -----------*/}
+
{({ form, field, meta: { error, touched } }) => (
}
+ helperText={ }
className={'form-group--branch_address'}
>
- {/*------------ Branch Address 2 -----------*/}
-
- {({ form, field, meta: { error, touched } }) => (
- }
- className={'form-group--branch_address'}
- >
-
-
- )}
-
-
{/*------------ Branch Address City & Country-----------*/}
}
>
-
+
{({ field, meta: { error, touched } }) => (
-
+
{({ field, meta: { error, touched } }) => (
}
className={'form-group--phone_number'}
>
-
+
)}
diff --git a/src/containers/Dialogs/BranchFormDialog/BranchFormProvider.js b/src/containers/Dialogs/BranchFormDialog/BranchFormProvider.js
index 18e97bc92..7d9ee8a3d 100644
--- a/src/containers/Dialogs/BranchFormDialog/BranchFormProvider.js
+++ b/src/containers/Dialogs/BranchFormDialog/BranchFormProvider.js
@@ -1,21 +1,33 @@
import React from 'react';
import { DialogContent } from 'components';
-// import {} from 'hooks/query';
+import { useCreateBranch, useEditBranch, useBranch } from 'hooks/query';
const BranchFormContext = React.createContext();
/**
* Branch form dialog provider.
*/
-function BranchFormProvider({ dialogName, ...props }) {
+function BranchFormProvider({ dialogName, branchId, ...props }) {
+ // Create and edit warehouse mutations.
+ const { mutateAsync: createBranchMutate } = useCreateBranch();
+ const { mutateAsync: editBranchMutate } = useEditBranch();
+
+ // Handle fetch branch detail.
+ const { data: branch, isLoading: isBranchLoading } = useBranch(branchId, {
+ enabled: !!branchId,
+ });
+
// State provider.
const provider = {
dialogName,
+ branch,
+ branchId,
+ createBranchMutate,
+ editBranchMutate,
};
+
return (
-
+
);
diff --git a/src/containers/Dialogs/BranchFormDialog/index.js b/src/containers/Dialogs/BranchFormDialog/index.js
index fca572330..f5b611148 100644
--- a/src/containers/Dialogs/BranchFormDialog/index.js
+++ b/src/containers/Dialogs/BranchFormDialog/index.js
@@ -12,18 +12,28 @@ const BranchFormDialogContent = React.lazy(() =>
/**
* Branch form form dialog.
*/
-function BranchFormDialog({ dialogName, payload = {}, isOpen }) {
+function BranchFormDialog({
+ dialogName,
+ payload: { branchId, action },
+ isOpen,
+}) {
return (
}
+ title={
+ action === 'edit' ? (
+
+ ) : (
+
+ )
+ }
isOpen={isOpen}
canEscapeJeyClose={true}
autoFocus={true}
className={'dialog--branch-form'}
>
-
+
);
diff --git a/src/containers/Preferences/Branches/BranchesActions.js b/src/containers/Preferences/Branches/BranchesActions.js
index a73c4bb93..a59309d69 100644
--- a/src/containers/Preferences/Branches/BranchesActions.js
+++ b/src/containers/Preferences/Branches/BranchesActions.js
@@ -20,7 +20,7 @@ function BranchesActions({
onClick={handleClickNewBranche}
intent={Intent.PRIMARY}
>
-
+
);
diff --git a/src/containers/Preferences/Branches/BranchesAlerts.js b/src/containers/Preferences/Branches/BranchesAlerts.js
new file mode 100644
index 000000000..c444030db
--- /dev/null
+++ b/src/containers/Preferences/Branches/BranchesAlerts.js
@@ -0,0 +1,7 @@
+import React from 'react';
+
+const BranchDeleteAlert = React.lazy(() =>
+ import('../../Alerts/Branches/BranchDeleteAlert'),
+);
+
+export default [{ name: 'branch-delete', component: BranchDeleteAlert }];
diff --git a/src/containers/Preferences/Branches/BranchesDataTable.js b/src/containers/Preferences/Branches/BranchesDataTable.js
index 91e992a10..2f238fafa 100644
--- a/src/containers/Preferences/Branches/BranchesDataTable.js
+++ b/src/containers/Preferences/Branches/BranchesDataTable.js
@@ -4,8 +4,11 @@ import styled from 'styled-components';
import { DataTable } from 'components';
import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
import { useBranchesTableColumns, ActionsMenu } from './components';
+import { useBranchesContext } from './BranchesProvider';
import withDialogActions from 'containers/Dialog/withDialogActions';
+import withAlertActions from 'containers/Alert/withAlertActions';
+
import { compose } from 'utils';
/**
@@ -14,23 +17,42 @@ import { compose } from 'utils';
function BranchesDataTable({
// #withDialogAction
openDialog,
+
+ // #withAlertActions
+ openAlert,
}) {
// Table columns.
const columns = useBranchesTableColumns();
+ const { branches, isBranchesLoading, isBranchesFetching } =
+ useBranchesContext();
+
+ const handleEditBranch = ({ id }) => {
+ openDialog('branch-form', { branchId: id, action: 'edit' });
+ };
+
+ const handleDeleteBranch = ({ id }) => {
+ openAlert('branch-delete', { branchId: id });
+ };
+
return (
);
}
-export default compose(withDialogActions)(BranchesDataTable);
+export default compose(withDialogActions, withAlertActions)(BranchesDataTable);
const BranchesTable = styled(DataTable)``;
diff --git a/src/containers/Preferences/Branches/BranchesProvider.js b/src/containers/Preferences/Branches/BranchesProvider.js
index a8fdea708..eb6f47f3a 100644
--- a/src/containers/Preferences/Branches/BranchesProvider.js
+++ b/src/containers/Preferences/Branches/BranchesProvider.js
@@ -3,6 +3,8 @@ import styled from 'styled-components';
import classNames from 'classnames';
import { CLASSES } from 'common/classes';
import { Card } from 'components';
+import { useBranches } from 'hooks/query';
+import PreferencesPageLoader from '../PreferencesPageLoader';
const BranchesContext = React.createContext();
@@ -10,8 +12,19 @@ const BranchesContext = React.createContext();
* Branches data provider.
*/
function BranchesProvider({ ...props }) {
+ // Fetches the branches list.
+ const {
+ isLoading: isBranchesLoading,
+ isFetching: isBranchesFetching,
+ data: branches,
+ } = useBranches();
+
// Provider state.
- const provider = {};
+ const provider = {
+ branches,
+ isBranchesLoading,
+ isBranchesFetching,
+ };
return (
[
{
- id: 'branch_name',
+ id: 'name',
Header: intl.get('branches.column.branch_name'),
- accessor: 'branch_name',
- className: 'branch_name',
+ accessor: 'name',
+ className: 'name',
width: '120',
disableSortBy: true,
textOverview: true,
},
+ {
+ id: 'code',
+ Header: intl.get('branches.column.code'),
+ accessor: 'code',
+ className: 'code',
+ width: '100',
+ disableSortBy: true,
+ textOverview: true,
+ },
{
Header: intl.get('branches.column.address'),
accessor: 'address',
diff --git a/src/hooks/query/branches.js b/src/hooks/query/branches.js
new file mode 100644
index 000000000..b4cbb7daf
--- /dev/null
+++ b/src/hooks/query/branches.js
@@ -0,0 +1,99 @@
+import { useQueryClient, useMutation } from 'react-query';
+import { useRequestQuery } from '../useQueryRequest';
+import useApiRequest from '../useRequest';
+import t from './types';
+
+// Common invalidate queries.
+const commonInvalidateQueries = (queryClient) => {
+ // Invalidate warehouses.
+ queryClient.invalidateQueries(t.BRANCHES);
+ queryClient.invalidateQueries(t.BRANCH);
+};
+
+/**
+ * Create a new branch.
+ */
+export function useCreateBranch(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation((values) => apiRequest.post('branches', values), {
+ onSuccess: (res, values) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ });
+}
+
+/**
+ * Edits the given branch.
+ */
+export function useEditBranch(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ ([id, values]) => apiRequest.post(`branches/${id}`, values),
+ {
+ onSuccess: (res, [id, values]) => {
+ // Invalidate specific branch.
+ queryClient.invalidateQueries([t.BRANCH, id]);
+
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Deletes the given branch.
+ */
+export function useDeleteBranch(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation((id) => apiRequest.delete(`branches/${id}`), {
+ onSuccess: (res, id) => {
+ // Invalidate specific branch.
+ queryClient.invalidateQueries([t.BRANCH, id]);
+
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ });
+}
+
+/**
+ * Retrieve Branches list.
+ */
+export function useBranches(query, props) {
+ return useRequestQuery(
+ [t.BRANCHES, query],
+ { method: 'get', url: 'branches', params: query },
+ {
+ select: (res) => res.data.branches,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve the branch details.
+ * @param {number}
+ */
+export function useBranch(id, props, requestProps) {
+ return useRequestQuery(
+ [t.BRANCH, id],
+ { method: 'get', url: `branches/${id}`, ...requestProps },
+ {
+ select: (res) => res.data.branch,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
diff --git a/src/hooks/query/index.js b/src/hooks/query/index.js
index 629f4f1b4..433717958 100644
--- a/src/hooks/query/index.js
+++ b/src/hooks/query/index.js
@@ -33,3 +33,4 @@ export * from './roles';
export * from './creditNote';
export * from './vendorCredit';
export * from './transactionsLocking';
+export * from './branches';
diff --git a/src/hooks/query/types.js b/src/hooks/query/types.js
index d98f99db8..afa6a21ef 100644
--- a/src/hooks/query/types.js
+++ b/src/hooks/query/types.js
@@ -191,6 +191,11 @@ const TARNSACTIONS_LOCKING = {
TRANSACTIONS_LOCKING: 'TRANSACTIONS_LOCKING',
};
+const BRANCHES = {
+ BRANCHES: 'BRANCHES',
+ BRANCH: 'BRANCH',
+};
+
export default {
...ACCOUNTS,
...BILLS,
@@ -218,4 +223,5 @@ export default {
...CREDIT_NOTES,
...VENDOR_CREDIT_NOTES,
...TARNSACTIONS_LOCKING,
+ ...BRANCHES,
};
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index eb7b674b3..c61dcb604 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -1750,20 +1750,25 @@
"credit_note_preview.dialog.title": "Credit Note PDF Preview",
"payment_receive_preview.dialog.title": "Payment Receive PDF Preview",
"branches.label": "Branches",
- "branches.label.new_branche": "New Branch",
+ "branches.label.new_branch": "New Branch",
"branches.action.edit_branch": "Edit Branch",
- "branches.action.delete_branch": "Edit Branch",
+ "branches.action.delete_branch": "Delete Branch",
"branches.column.branch_name": "Branch name",
"branches.column.address": "Address",
"branches.column.phone_number": "Phone number",
- "branch.dialog.label": "New Branch",
+ "branches.column.code": "Code",
+ "branch.dialog.label_new_branch": "New Branch",
+ "branch.dialog.label_edit_branch": "New Branch",
"branch.dialog.label.branch_name": "Branch Name",
+ "branch.dialog.label.branch_code": "Code",
"branch.dialog.label.branch_address": "Branch Address",
- "branch.dialog.label.address_1": "Address 1",
- "branch.dialog.label.address_2": "Address 2",
+ "branch.dialog.label.address_1": "Address",
"branch.dialog.label.city": "City",
"branch.dialog.label.country": "Country",
"branch.dialog.label.phone_number": "Phone Number",
"branch.dialog.label.email": "Email",
- "branch.dialog.label.website": "Website"
+ "branch.dialog.label.website": "Website",
+ "branch.dialog.success_message": "The branch has been created successfully.",
+ "branch.alert.delete_message":"The branch has been deleted successfully",
+ "branch.once_delete_this_branch":"Once you delete this branch, you won't be able to restore it later. Are you sure you want to delete this branch?"
}
\ No newline at end of file
From dc491281aa93330e9513dd879f0b755f16c321d3 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Wed, 2 Feb 2022 00:46:02 +0200
Subject: [PATCH 12/30] feat(warehousetransfer): add api.
---
.../WarehouseTransferForm.schema.js | 13 +--
.../WarehouseTransferFormHeaderFields.js | 22 ++---
.../WarehouseTransferFormProvider.js | 16 +++-
.../WarehouseTransferForm/utils.js | 23 +----
src/hooks/query/warehouses.js | 95 +++++++++++++++++++
5 files changed, 129 insertions(+), 40 deletions(-)
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.schema.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.schema.js
index efe3afe45..defb8db87 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.schema.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.schema.js
@@ -4,11 +4,11 @@ import { DATATYPES_LENGTH } from 'common/dataTypes';
const Schema = Yup.object().shape({
date: Yup.date().required().label(intl.get('date')),
- transfer_number: Yup.string()
+ transaction_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')),
+ .label(intl.get('transaction_number')),
+ from_warehouse_id: Yup.number().required().label(intl.get('from_warehouse')),
+ to_warehouse_id: Yup.number().required().label(intl.get('from_warehouse')),
reason: Yup.string()
.trim()
.min(1)
@@ -17,8 +17,9 @@ const Schema = Yup.object().shape({
entries: Yup.array().of(
Yup.object().shape({
item_id: Yup.number().nullable(),
- source_warehouse: Yup.number().nullable(),
- destination_warehouse: Yup.number().nullable(),
+ // source_warehouse: Yup.number().nullable(),
+ // destination_warehouse: Yup.number().nullable(),
+ description: Yup.string().nullable().max(DATATYPES_LENGTH.TEXT),
quantity: Yup.number().nullable().max(DATATYPES_LENGTH.INT_10),
}),
),
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeaderFields.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeaderFields.js
index c036eb167..6b7fc9f1b 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeaderFields.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeaderFields.js
@@ -37,7 +37,7 @@ function WarehouseTransferFormHeaderFields({
warehouseTransferNextNumber,
warehouseTransferNumberPrefix,
}) {
- const { accounts } = useWarehouseTransferFormContext();
+ const { warehouses } = useWarehouseTransferFormContext();
// Handle warehouse transfer number changing.
const handleTransferNumberChange = () => {
@@ -92,11 +92,11 @@ function WarehouseTransferFormHeaderFields({
)}
{/* ----------- Transfer number ----------- */}
-
+
{({ form, field, meta: { error, touched } }) => (
}
- labelInfo={ }
+ // labelInfo={ }
inline={true}
className={classNames('form-group--transfer-no', CLASSES.FILL)}
intent={inputIntent({ error, touched })}
@@ -131,7 +131,7 @@ function WarehouseTransferFormHeaderFields({
)}
{/* ----------- Form Warehouse ----------- */}
-
+
{({ form, field: { value }, meta: { error, touched } }) => (
}
@@ -142,12 +142,12 @@ function WarehouseTransferFormHeaderFields({
inline={true}
labelInfo={ }
intent={inputIntent({ error, touched })}
- helperText={ }
+ helperText={ }
>
{
- form.setFieldValue('form_warehouse', account.id);
+ form.setFieldValue('from_warehouse_id', account.id);
}}
defaultSelectText={'Select Warehouse Transfer'}
selectedAccountId={value}
@@ -158,7 +158,7 @@ function WarehouseTransferFormHeaderFields({
)}
{/* ----------- To Warehouse ----------- */}
-
+
{({ form, field: { value }, meta: { error, touched } }) => (
}
@@ -169,12 +169,12 @@ function WarehouseTransferFormHeaderFields({
inline={true}
labelInfo={ }
intent={inputIntent({ error, touched })}
- helperText={ }
+ helperText={ }
>
{
- form.setFieldValue('to_warehouse', account.id);
+ form.setFieldValue('to_warehouse_id', account.id);
}}
defaultSelectText={'Select Warehouse Transfer'}
selectedAccountId={value}
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
index 664262689..2531e9e73 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
@@ -1,6 +1,6 @@
import React from 'react';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
-import { useItems, useAccounts } from 'hooks/query';
+import { useItems, useWarehouses } from 'hooks/query';
import { ITEMS_FILTER_ROLES_QUERY } from './utils.js';
const WarehouseFormContext = React.createContext();
@@ -19,17 +19,23 @@ function WarehouseTransferFormProvider({ warehouseTransferId, ...props }) {
stringified_filter_roles: ITEMS_FILTER_ROLES_QUERY,
});
- // Fetch accounts list.
- const { data: accounts, isLoading: isAccountsLoading } = useAccounts();
+ // Fetch warehouses list.
+ const {
+ data: warehouses,
+ isFetching: isWarehouesFetching,
+ isLoading: isWarehouesLoading,
+ } = useWarehouses();
// Provider payload.
const provider = {
items,
- accounts,
+ warehouses,
+ isItemsFetching,
+ isWarehouesFetching,
};
return (
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/utils.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/utils.js
index 0fac70605..b5aa27d73 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/utils.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/utils.js
@@ -18,28 +18,15 @@ export const MIN_LINES_NUMBER = 4;
export const defaultWarehouseTransfer = {
date: moment(new Date()).format('YYYY-MM-DD'),
- transfer_number: '',
- from_warehouse: '',
- to_warehouse: '',
+ transaction_number: '',
+ from_warehouse_id: '',
+ to_warehouse_id: '',
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',
- },
+ { fieldKey: 'type', comparator: 'is', value: 'inventory', index: 1 },
]);
/**
@@ -50,6 +37,6 @@ export const useObserveTransferNoSettings = (prefix, nextNumber) => {
React.useEffect(() => {
const transferNo = transactionNumber(prefix, nextNumber);
- setFieldValue('transfer_no', transferNo);
+ setFieldValue('transaction_number', transferNo);
}, [setFieldValue, prefix, nextNumber]);
};
diff --git a/src/hooks/query/warehouses.js b/src/hooks/query/warehouses.js
index 4aea65efe..55f7ca9e2 100644
--- a/src/hooks/query/warehouses.js
+++ b/src/hooks/query/warehouses.js
@@ -8,6 +8,10 @@ const commonInvalidateQueries = (queryClient) => {
// Invalidate warehouses.
queryClient.invalidateQueries(t.WAREHOUSES);
queryClient.invalidateQueries(t.WAREHOUSE);
+
+ // Invalidate warehouses transfers.
+ queryClient.invalidateQueries(t.WAREHOUSE_TRANSFERS);
+ queryClient.invalidateQueries(t.WAREHOUSE_TRANSFER);
};
/**
@@ -97,3 +101,94 @@ export function useWarehouse(id, props, requestProps) {
},
);
}
+
+/**
+ * Create a new warehouse transfer.
+ */
+export function useCreateWarehouseTransfer(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (values) => apiRequest.post('warehouses/transfers', values),
+ {
+ onSuccess: (res, values) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Edits the given warehouse transfer.
+ */
+export function useEditWarehouseTransfer(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ ([id, values]) => apiRequest.post(`warehouses/transfers${id}`, values),
+ {
+ onSuccess: (res, [id, values]) => {
+ // Invalidate specific sale invoice.
+ queryClient.invalidateQueries([t.WAREHOUSE_TRANSFER, id]);
+
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Deletes the given warehouse Transfer.
+ */
+export function useDeleteWarehouseTransfer(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation((id) => apiRequest.delete(`warehouses/transfers/${id}`), {
+ onSuccess: (res, id) => {
+ // Invalidate specific warehoue.
+ queryClient.invalidateQueries([t.WAREHOUSE_TRANSFER, id]);
+
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ });
+}
+
+/**
+ * Retrieve Warehoues list.
+ */
+export function useWarehousesTransfers(query, props) {
+ return useRequestQuery(
+ [t.WAREHOUSE_TRANSFERS, query],
+ { method: 'get', url: 'warehouses/transfers', params: query },
+ {
+ select: (res) => res.data,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve the warehouse transfer details.
+ * @param {number}
+ */
+export function useWarehouseTransfer(id, props, requestProps) {
+ return useRequestQuery(
+ [t.WAREHOUSE_TRANSFER, id],
+ { method: 'get', url: `warehouses/transfers/${id}`, ...requestProps },
+ {
+ select: (res) => res.data,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
From 6e7c746d09b6212c8a4590619ec23b84b7744735 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Wed, 2 Feb 2022 15:53:09 +0200
Subject: [PATCH 13/30] feat(warehouseTransfer): add create & delete transfer &
details.
---
src/config/sidebarMenu.js | 4 +-
.../WarehouseTransferDeleteAlert.js | 79 ++++++++++++
src/containers/AlertsContainer/registered.js | 2 +
.../WarehouseFormProvider.js | 1 -
.../WarehouseTransferDetailDrawerProvider.js | 15 ++-
.../WarehouseTransferDetailHeader.js | 27 ++---
.../WarehouseTransferDetailTable.js | 7 +-
.../WarehouseTransferEditorField.js | 9 +-
.../WarehouseTransferFloatingActions.js | 112 ++++++++++++++++++
.../WarehouseTransferForm.js | 60 +++++++++-
.../WarehouseTransferFormEntriesTable.js | 42 +++++--
.../WarehouseTransferFormHeaderFields.js | 5 +-
.../WarehouseTransferFormProvider.js | 27 ++++-
.../WarehouseTransferForm/utils.js | 75 +++++++++++-
.../WarehouseTransfersActionsBar.js | 2 +-
.../WarehouseTransfersDataTable.js | 18 ++-
.../WarehousesTransfersAlerts.js | 15 +++
src/containers/WarehouseTransfers/utils.js | 68 +++++++++--
src/hooks/query/warehouses.js | 2 +-
src/lang/en/index.json | 7 +-
src/routes/dashboard.js | 8 +-
21 files changed, 513 insertions(+), 72 deletions(-)
create mode 100644 src/containers/Alerts/Warehouses/WarehouseTransferDeleteAlert.js
create mode 100644 src/containers/WarehouseTransfers/WarehousesTransfersAlerts.js
diff --git a/src/config/sidebarMenu.js b/src/config/sidebarMenu.js
index 14812dfea..84fece5ab 100644
--- a/src/config/sidebarMenu.js
+++ b/src/config/sidebarMenu.js
@@ -80,7 +80,7 @@ export default [
},
{
text: ,
- href: '/warehouse-transfers',
+ href: '/warehouses-transfers',
},
{
text: ,
@@ -119,7 +119,7 @@ export default [
},
{
text: ,
- href: '/warehouse-transfers/new',
+ href: '/warehouses-transfers/new',
},
{
text: ,
diff --git a/src/containers/Alerts/Warehouses/WarehouseTransferDeleteAlert.js b/src/containers/Alerts/Warehouses/WarehouseTransferDeleteAlert.js
new file mode 100644
index 000000000..936ccc97c
--- /dev/null
+++ b/src/containers/Alerts/Warehouses/WarehouseTransferDeleteAlert.js
@@ -0,0 +1,79 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
+import { Intent, Alert } from '@blueprintjs/core';
+import { AppToaster } from 'components';
+import { useDeleteWarehouseTransfer } from 'hooks/query';
+
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withAlertActions from 'containers/Alert/withAlertActions';
+
+import { compose } from 'utils';
+
+/**
+ * Warehouse transfer delete alert
+ * @returns
+ */
+function WarehouseTransferDeleteAlert({
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { warehouseTransferId },
+
+ // #withAlertActions
+ closeAlert,
+}) {
+ const { mutateAsync: deleteWarehouseTransferMutate, isLoading } =
+ useDeleteWarehouseTransfer();
+
+ // handle cancel delete warehouse alert.
+ const handleCancelDeleteAlert = () => {
+ closeAlert(name);
+ };
+
+ // handleConfirm delete warehouse transfer.
+ const handleConfirmWarehouseTransferDelete = () => {
+ deleteWarehouseTransferMutate(warehouseTransferId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get('warehouse_transfer.alert.delete_message'),
+ intent: Intent.SUCCESS,
+ });
+ })
+ .catch(
+ ({
+ response: {
+ data: { errors },
+ },
+ }) => {},
+ )
+ .finally(() => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={ }
+ icon="trash"
+ intent={Intent.DANGER}
+ isOpen={isOpen}
+ onCancel={handleCancelDeleteAlert}
+ onConfirm={handleConfirmWarehouseTransferDelete}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+)(WarehouseTransferDeleteAlert);
diff --git a/src/containers/AlertsContainer/registered.js b/src/containers/AlertsContainer/registered.js
index c023ebf0c..dfd8f839d 100644
--- a/src/containers/AlertsContainer/registered.js
+++ b/src/containers/AlertsContainer/registered.js
@@ -21,6 +21,7 @@ import CreditNotesAlerts from '../Sales/CreditNotes/CreditNotesAlerts';
import VendorCreditNotesAlerts from '../Purchases/CreditNotes/VendorCreditNotesAlerts';
import TransactionsLockingAlerts from '../TransactionsLocking/TransactionsLockingAlerts';
import WarehousesAlerts from '../Preferences/Warehouses/WarehousesAlerts';
+import WarehousesTransfersAlerts from '../WarehouseTransfers/WarehousesTransfersAlerts'
export default [
...AccountsAlerts,
@@ -46,4 +47,5 @@ export default [
...VendorCreditNotesAlerts,
...TransactionsLockingAlerts,
...WarehousesAlerts,
+ ...WarehousesTransfersAlerts
];
diff --git a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js
index 4257d1c8f..e2fae2805 100644
--- a/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js
+++ b/src/containers/Dialogs/WarehouseFormDialog/WarehouseFormProvider.js
@@ -5,7 +5,6 @@ import {
useEditWarehouse,
useWarehouse,
} from 'hooks/query';
-import { useLocation } from 'react-router-dom';
const WarehouseFormContext = React.createContext();
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js
index 0d1d6525d..371131568 100644
--- a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js
@@ -1,6 +1,6 @@
import React from 'react';
import intl from 'react-intl-universal';
-// import {} from 'hooks/query';
+import { useWarehouseTransfer } from 'hooks/query';
import { DrawerHeaderContent, DrawerLoading } from 'components';
const WarehouseTransferDetailDrawerContext = React.createContext();
@@ -9,17 +9,22 @@ const WarehouseTransferDetailDrawerContext = React.createContext();
* Warehouse transfer detail drawer provider.
*/
function WarehouseTransferDetailDrawerProvider({
- warehouseTransferId,
+ warehouseTransferId = 5,
...props
}) {
+ // Handle fetch invoice detail.
+ const { data: warehouseTransfer, isLoading: isWarehouseTransferLoading } =
+ useWarehouseTransfer(warehouseTransferId, {
+ enabled: !!warehouseTransferId,
+ });
+
const provider = {
+ warehouseTransfer,
warehouseTransferId,
};
return (
-
+
-
-
-
- '$10'
-
-
-
- {/* */}
+
-
);
}
-
-const AmountItem = styled(DetailItem)`
- width: 50%;
-`;
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailTable.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailTable.js
index e85b7014f..47c7d445f 100644
--- a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailTable.js
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailTable.js
@@ -3,6 +3,7 @@ import React from 'react';
import { CommercialDocEntriesTable } from 'components';
import { TableStyle } from '../../../common';
import { useWarehouseTransferReadOnlyEntriesColumns } from './utils';
+import { useWarehouseDetailDrawerContext } from './WarehouseTransferDetailDrawerProvider';
/**
* Warehouse transfer detail table.
@@ -12,10 +13,14 @@ export default function WarehouseTransferDetailTable() {
// Warehouse transfer entries table columns.
const columns = useWarehouseTransferReadOnlyEntriesColumns();
+ const {
+ warehouseTransfer: { entries },
+ } = useWarehouseDetailDrawerContext();
+
return (
);
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferEditorField.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferEditorField.js
index 7c80c21ac..8c39e2dcf 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferEditorField.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferEditorField.js
@@ -3,7 +3,10 @@ import { FastField } from 'formik';
import classNames from 'classnames';
import { CLASSES } from 'common/classes';
import { useWarehouseTransferFormContext } from './WarehouseTransferFormProvider';
-import { entriesFieldShouldUpdate } from './utils';
+import {
+ entriesFieldShouldUpdate,
+ defaultWarehouseTransferEntry,
+} from './utils';
import WarehouseTransferFormEntriesTable from './WarehouseTransferFormEntriesTable';
/**
@@ -11,12 +14,13 @@ import WarehouseTransferFormEntriesTable from './WarehouseTransferFormEntriesTab
*/
export default function WarehouseTransferEditorField() {
const { items } = useWarehouseTransferFormContext();
+
return (
{({
form: { values, setFieldValue },
@@ -29,6 +33,7 @@ export default function WarehouseTransferEditorField() {
setFieldValue('entries', entries);
}}
items={items}
+ defaultEntry={defaultWarehouseTransferEntry}
errors={error}
/>
)}
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFloatingActions.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFloatingActions.js
index e69de29bb..9362a1ce5 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFloatingActions.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFloatingActions.js
@@ -0,0 +1,112 @@
+import React from 'react';
+import { useHistory } from 'react-router-dom';
+import {
+ Intent,
+ Button,
+ ButtonGroup,
+ Popover,
+ PopoverInteractionKind,
+ Position,
+ Menu,
+ MenuItem,
+} from '@blueprintjs/core';
+import { FormattedMessage as T } from 'components';
+import classNames from 'classnames';
+import { useFormikContext } from 'formik';
+import { CLASSES } from 'common/classes';
+
+import { Icon } from 'components';
+import { useWarehouseTransferFormContext } from './WarehouseTransferFormProvider';
+
+/**
+ * Warehouse transfer floating actions bar.
+ */
+export default function WarehouseTransferFloatingActions() {
+ // History context.
+ const history = useHistory();
+
+ // Formik form context.
+ const { isSubmitting, submitForm, resetForm, values, errors } =
+ useFormikContext();
+
+ // Warehouse tansfer form context.
+ const { isNewMode, setSubmitPayload } = useWarehouseTransferFormContext();
+
+ // Handle submit button click.
+ const handleSubmitBtnClick = (event) => {
+ setSubmitPayload({ redirect: true });
+ submitForm();
+ };
+
+ // Handle clear button click.
+ const handleClearBtnClick = (event) => {
+ resetForm();
+ };
+
+ // Handle submit & new button click.
+ const handleSubmitAndNewClick = (event) => {
+ setSubmitPayload({ redirect: false, resetForm: true });
+ submitForm();
+ };
+
+ // Handle cancel button click.
+ const handleCancelBtnClick = (event) => {
+ history.goBack();
+ };
+
+ return (
+
+ {/* ----------- Save and New ----------- */}
+
+ : }
+ />
+
+ }
+ onClick={handleSubmitAndNewClick}
+ />
+ }
+ // onClick={handleSubmitContinueEditingBtnClick}
+ />
+
+ }
+ minimal={true}
+ interactionKind={PopoverInteractionKind.CLICK}
+ position={Position.BOTTOM_LEFT}
+ >
+ }
+ />
+
+
+
+ {/* ----------- Clear & Reset----------- */}
+
:
}
+ />
+
+ {/* ----------- Cancel ----------- */}
+
}
+ />
+
+ );
+}
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js
index 3487ca548..1d172e6c4 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js
@@ -1,6 +1,7 @@
import React from 'react';
import intl from 'react-intl-universal';
import { Formik, Form } from 'formik';
+import { isEmpty } from 'lodash';
import { Intent } from '@blueprintjs/core';
import { useHistory } from 'react-router-dom';
import { CLASSES } from 'common/classes';
@@ -14,11 +15,18 @@ import {
import WarehouseTransferFormHeader from './WarehouseTransferFormHeader';
import WarehouseTransferEditorField from './WarehouseTransferEditorField';
import WarehouseTransferFormFooter from './WarehouseTransferFormFooter';
+import WarehouseTransferFloatingActions from './WarehouseTransferFloatingActions';
import WarehouseTransferFormDialog from './WarehouseTransferFormDialog';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+import { AppToaster } from 'components';
+import { useWarehouseTransferFormContext } from './WarehouseTransferFormProvider';
import { compose, orderingLinesIndexes, transactionNumber } from 'utils';
-import { defaultWareTransferEntry, defaultWarehouseTransfer } from './utils';
+import {
+ defaultWarehouseTransfer,
+ transformValueToRequest,
+ transformToEditForm,
+} from './utils';
function WarehouseTransferForm({
// #withSettings
@@ -28,6 +36,14 @@ function WarehouseTransferForm({
}) {
const history = useHistory();
+ const {
+ isNewMode,
+ warehouseTransfer,
+ createWarehouseTransferMutate,
+ editWarehouseTransferMutate,
+ submitPayload,
+ } = useWarehouseTransferFormContext();
+
// WarehouseTransfer number.
const warehouseTransferNumber = transactionNumber(
warehouseTransferNumberPrefix,
@@ -37,18 +53,43 @@ function WarehouseTransferForm({
// Form initial values.
const initialValues = React.useMemo(
() => ({
- ...defaultWarehouseTransfer,
+ ...(!isEmpty(null)
+ ? { ...transformToEditForm(null) }
+ : {
+ ...defaultWarehouseTransfer,
+ entries: orderingLinesIndexes(defaultWarehouseTransfer.entries),
+ }),
}),
[],
);
// Handles form submit.
const handleSubmit = (values, { setSubmitting, setErrors, resetForm }) => {
+ setSubmitting(true);
// Transformes the values of the form to request.
- const form = {};
+ const form = {
+ ...transformValueToRequest(values),
+ };
// Handle the request success.
- const onSuccess = () => {};
+ const onSuccess = () => {
+ AppToaster.show({
+ message: intl.get(
+ isNewMode
+ ? 'warehouse_transfer.success_message'
+ : 'warehouse_transfer.edit_success_message',
+ ),
+ intent: Intent.SUCCESS,
+ });
+ setSubmitting(false);
+
+ if (submitPayload.redirect) {
+ history.push('/warehouses-transfers');
+ }
+ if (submitPayload.resetForm) {
+ resetForm();
+ }
+ };
// Handle the request error.
const onError = ({
@@ -58,6 +99,14 @@ function WarehouseTransferForm({
}) => {
setSubmitting(false);
};
+
+ if (isNewMode) {
+ createWarehouseTransferMutate(form).then(onSuccess).catch(onError);
+ } else {
+ editWarehouseTransferMutate([warehouseTransfer.id, form])
+ .then(onSuccess)
+ .catch(onError);
+ }
};
return (
@@ -70,7 +119,7 @@ function WarehouseTransferForm({
>
+
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormEntriesTable.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormEntriesTable.js
index 1d1ca8141..8ba567803 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormEntriesTable.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormEntriesTable.js
@@ -2,8 +2,15 @@ import React from 'react';
import { useWarehouseTransferTableColumns } from '../utils';
import { DataTableEditable } from 'components';
-import { compose, saveInvoke, updateTableCell } from 'utils';
-
+import {
+ saveInvoke,
+ compose,
+ updateTableCell,
+ updateMinEntriesLines,
+ updateAutoAddNewLine,
+ updateRemoveLineByIndex,
+ orderingLinesIndexes,
+} from 'utils';
/**
* Warehouse transfer form entries table.
*/
@@ -11,6 +18,7 @@ export default function WarehouseTransferFormEntriesTable({
// #ownProps
items,
entries,
+ defaultEntry,
onUpdateData,
errors,
}) {
@@ -20,12 +28,30 @@ export default function WarehouseTransferFormEntriesTable({
// Handle update data.
const handleUpdateData = React.useCallback(
(rowIndex, columnId, value) => {
- const newRows = compose(updateTableCell(rowIndex, columnId, value))(
- entries,
- );
- onUpdateData(newRows);
+ const newRows = compose(
+ // Update auto-adding new line.
+ updateAutoAddNewLine(defaultEntry, ['item_id']),
+ // Update the row value of the given row index and column id.
+ updateTableCell(rowIndex, columnId, value),
+ )(entries);
+
+ saveInvoke(onUpdateData, newRows);
},
- [onUpdateData, entries],
+ [entries, defaultEntry, onUpdateData],
+ );
+ // Handles click remove datatable row.
+ const handleRemoveRow = React.useCallback(
+ (rowIndex) => {
+ const newRows = compose(
+ // Ensure minimum lines count.
+ updateMinEntriesLines(4, defaultEntry),
+ // Remove the line by the given index.
+ updateRemoveLineByIndex(rowIndex),
+ )(entries);
+
+ saveInvoke(onUpdateData, newRows);
+ },
+ [entries, defaultEntry, onUpdateData],
);
return (
@@ -36,6 +62,8 @@ export default function WarehouseTransferFormEntriesTable({
items,
errors: errors || [],
updateData: handleUpdateData,
+ removeRow: handleRemoveRow,
+ autoFocus: ['item_id', 0],
}}
/>
);
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeaderFields.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeaderFields.js
index 6b7fc9f1b..ee572e8fc 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeaderFields.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormHeaderFields.js
@@ -2,7 +2,6 @@ import React from 'react';
import {
FormGroup,
InputGroup,
- TextArea,
Position,
ControlGroup,
} from '@blueprintjs/core';
@@ -149,7 +148,7 @@ function WarehouseTransferFormHeaderFields({
onAccountSelected={(account) => {
form.setFieldValue('from_warehouse_id', account.id);
}}
- defaultSelectText={'Select Warehouse Transfer'}
+ defaultSelectText={ }
selectedAccountId={value}
popoverFill={true}
allowCreate={true}
@@ -176,7 +175,7 @@ function WarehouseTransferFormHeaderFields({
onAccountSelected={(account) => {
form.setFieldValue('to_warehouse_id', account.id);
}}
- defaultSelectText={'Select Warehouse Transfer'}
+ defaultSelectText={ }
selectedAccountId={value}
popoverFill={true}
allowCreate={true}
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
index 2531e9e73..ad9525558 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
@@ -1,6 +1,11 @@
import React from 'react';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
-import { useItems, useWarehouses } from 'hooks/query';
+import {
+ useItems,
+ useWarehouses,
+ useCreateWarehouseTransfer,
+ useEditWarehouseTransfer,
+} from 'hooks/query';
import { ITEMS_FILTER_ROLES_QUERY } from './utils.js';
const WarehouseFormContext = React.createContext();
@@ -26,12 +31,32 @@ function WarehouseTransferFormProvider({ warehouseTransferId, ...props }) {
isLoading: isWarehouesLoading,
} = useWarehouses();
+ // Create and edit warehouse mutations.
+ const { mutateAsync: createWarehouseTransferMutate } =
+ useCreateWarehouseTransfer();
+ const { mutateAsync: editWarehouseTransferMutate } =
+ useEditWarehouseTransfer();
+
+ // Detarmines whether the form in new mode.
+ const isNewMode = !warehouseTransferId;
+
+ // Form submit payload.
+ const [submitPayload, setSubmitPayload] = React.useState();
+
// Provider payload.
const provider = {
items,
warehouses,
+ warehouseTransfer: [],
+
isItemsFetching,
isWarehouesFetching,
+
+ isNewMode,
+ submitPayload,
+ setSubmitPayload,
+ createWarehouseTransferMutate,
+ editWarehouseTransferMutate,
};
return (
({
+ ...transformToForm(warehouse, defaultWarehouseTransferEntry),
+ })),
+ ...repeatValue(
+ defaultWarehouseTransferEntry,
+ Math.max(MIN_LINES_NUMBER - warehouse.entries.length, 0),
+ ),
+ ];
+ const entries = compose(
+ ensureEntriesHaveEmptyLine(defaultWarehouseTransferEntry),
+ updateItemsEntriesTotal,
+ )(initialEntries);
+
+ return {
+ ...transformToForm(warehouse, defaultWarehouseTransfer),
+ entries,
+ };
+}
+
/**
* Syncs transfer no. settings with form.
*/
@@ -40,3 +80,28 @@ export const useObserveTransferNoSettings = (prefix, nextNumber) => {
setFieldValue('transaction_number', transferNo);
}, [setFieldValue, prefix, nextNumber]);
};
+
+/**
+ * Detarmines warehouse entries field when should update.
+ */
+export const entriesFieldShouldUpdate = (newProps, oldProps) => {
+ return (
+ newProps.items !== oldProps.items ||
+ defaultFastFieldShouldUpdate(newProps, oldProps)
+ );
+};
+
+/**
+ * Transformes the form values to request body values.
+ */
+export function transformValueToRequest(values) {
+ const entries = values.entries.filter(
+ (item) => item.item_id && item.quantity,
+ );
+ return {
+ ...values,
+ entries: entries.map((entry) => ({
+ ...omit(entry, ['destination_warehouse', 'source_warehouse']),
+ })),
+ };
+}
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersActionsBar.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersActionsBar.js
index f3ec0832e..048a7151f 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersActionsBar.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersActionsBar.js
@@ -33,7 +33,7 @@ function WarehouseTransfersActionsBar({
// Handle new warehouse transfer button click.
const handleClickNewWarehouseTransfer = () => {
- history.push('/warehouse-transfers/new');
+ history.push('/warehouses-transfers/new');
};
// Handle click a refresh warehouse transfers
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersDataTable.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersDataTable.js
index 5a571df84..f707d70a3 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersDataTable.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersDataTable.js
@@ -43,18 +43,26 @@ function WarehouseTransfersDataTable({
const columns = useWarehouseTransfersTableColumns();
// Handle view detail.
- const handleViewDetailWarehouseTransfer = () => {
- openDrawer('warehouse-transfer-detail-drawer', {});
+ const handleViewDetailWarehouseTransfer = ({ id }) => {
+ openDrawer('warehouse-transfer-detail-drawer', { warehouseTransferId: id });
};
// Handle edit warehouse transfer.
- const handleEditWarehouseTransfer = () => {};
+ const handleEditWarehouseTransfer = ({ id }) => {
+ history.push(`/warehouses-transfers/${id}/edit`);
+ };
// Handle delete warehouse transfer.
- const handleDeleteWarehouseTransfer = () => {};
+ const handleDeleteWarehouseTransfer = ({ id }) => {
+ openAlert('warehouse-transfer-delete', { warehouseTransferId: id });
+ };
// Handle cell click.
- const handleCellClick = (cell, event) => {};
+ const handleCellClick = (cell, event) => {
+ openDrawer('warehouse-transfer-detail-drawer', {
+ warehouseTransferId: cell.row.original.id,
+ });
+ };
// Local storage memorizing columns widths.
const [initialColumnsWidths, , handleColumnResizing] =
diff --git a/src/containers/WarehouseTransfers/WarehousesTransfersAlerts.js b/src/containers/WarehouseTransfers/WarehousesTransfersAlerts.js
new file mode 100644
index 000000000..c11fabb4d
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehousesTransfersAlerts.js
@@ -0,0 +1,15 @@
+import React from 'react';
+
+const WarehouseTransferDeleteAlert = React.lazy(() =>
+ import('../Alerts/Warehouses/WarehouseTransferDeleteAlert'),
+);
+
+/**
+ * Warehouses alerts.
+ */
+export default [
+ {
+ name: 'warehouse-transfer-delete',
+ component: WarehouseTransferDeleteAlert,
+ },
+];
diff --git a/src/containers/WarehouseTransfers/utils.js b/src/containers/WarehouseTransfers/utils.js
index e3d67946c..1c8713416 100644
--- a/src/containers/WarehouseTransfers/utils.js
+++ b/src/containers/WarehouseTransfers/utils.js
@@ -1,6 +1,14 @@
import React from 'react';
-import { CLASSES } from 'common/classes';
-import { MoneyFieldCell, FormatDateCell, AppToaster, T } from 'components';
+import intl from 'react-intl-universal';
+import { Tooltip, Button, Intent, Position } from '@blueprintjs/core';
+
+import {
+ MoneyFieldCell,
+ FormatDateCell,
+ Icon,
+ AppToaster,
+ T,
+} from 'components';
import { InputGroupCell, ItemsListCell } from 'components/DataTableCells';
// Index table cell.
@@ -8,6 +16,33 @@ export function IndexTableCell({ row: { index } }) {
return {index + 1} ;
}
+/**
+ * Actions cell renderer component.
+ */
+export function ActionsCellRenderer({
+ row: { index },
+ column: { id },
+ cell: { value },
+ data,
+ payload: { removeRow },
+}) {
+ const onRemoveRole = () => {
+ removeRow(index);
+ };
+
+ return (
+ } position={Position.LEFT}>
+ }
+ iconSize={14}
+ className="m12"
+ intent={Intent.DANGER}
+ onClick={onRemoveRole}
+ />
+
+ );
+}
+
/**
* Retrieves warehouse transfer table columns.
* @returns
@@ -26,21 +61,29 @@ export const useWarehouseTransferTableColumns = () => {
},
{
id: 'item_id',
- Header: 'Item Name',
+ Header: intl.get('warehouse_transfer.column.item_name'),
accessor: 'item_id',
Cell: ItemsListCell,
disableSortBy: true,
- width: '120',
+ width: 130,
className: 'item',
fieldProps: { allowCreate: true },
},
+ {
+ Header: intl.get('description'),
+ accessor: 'description',
+ Cell: InputGroupCell,
+ disableSortBy: true,
+ className: 'description',
+ width: 120,
+ },
{
id: 'source_warehouse',
Header: 'Source Warehouse',
accessor: 'source_warehouse',
disableSortBy: true,
align: 'right',
- width: '100',
+ width: 120,
},
{
id: 'destination_warehouse',
@@ -48,15 +91,24 @@ export const useWarehouseTransferTableColumns = () => {
accessor: 'destination_warehouse',
disableSortBy: true,
align: 'right',
- width: '100',
+ width: 120,
},
{
- Header: 'Transfer Quantity',
+ Header: intl.get('warehouse_transfer.column.transfer_quantity'),
accessor: 'quantity',
Cell: MoneyFieldCell,
disableSortBy: true,
align: 'right',
- width: '150',
+ width: 100,
+ },
+ {
+ Header: '',
+ accessor: 'action',
+ Cell: ActionsCellRenderer,
+ className: 'actions',
+ disableSortBy: true,
+ disableResizing: true,
+ width: 45,
},
],
[],
diff --git a/src/hooks/query/warehouses.js b/src/hooks/query/warehouses.js
index 55f7ca9e2..27e052c2f 100644
--- a/src/hooks/query/warehouses.js
+++ b/src/hooks/query/warehouses.js
@@ -186,7 +186,7 @@ export function useWarehouseTransfer(id, props, requestProps) {
[t.WAREHOUSE_TRANSFER, id],
{ method: 'get', url: `warehouses/transfers/${id}`, ...requestProps },
{
- select: (res) => res.data,
+ select: (res) => res.data.warehouse_transfer,
defaultData: {},
...props,
},
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index 340df8545..82695a352 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -1796,5 +1796,10 @@
"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"
+ "warehouse_transfer.label.warehouse_transfer_list": "Warehouse Transfers List",
+ "warehouse_transfer.success_message":"The warehouse transfer transaction has been created successfully.",
+ "warehouse_transfer.edit_success_message":"The warehouse transfer transaction has been created successfully.",
+ "select_warehouse_transfer":"Select Warehouse Transfer",
+ "warehouse_transfer.alert.delete_message":"The warehouse transfer transaction has been deleted successfully",
+ "warehouse_transfer.once_delete_this_warehouse_transfer":"Once you delete this warehouse transfer, you won't be able to restore it later. Are you sure you want to delete this warehouse transfer?"
}
\ No newline at end of file
diff --git a/src/routes/dashboard.js b/src/routes/dashboard.js
index 428fb447b..3afc57e2b 100644
--- a/src/routes/dashboard.js
+++ b/src/routes/dashboard.js
@@ -119,25 +119,25 @@ export const getDashboardRoutes = () => [
},
// Warehouse Transfer.
{
- path: `/warehouse-transfers/:id/edit`,
+ path: `/warehouses-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`,
+ path: `/warehouses-transfers/new`,
component: lazy(() =>
import(
'../containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormPage'
),
),
- name: 'warehouse-transfer-new',
+ name: 'warehouses-transfer-new',
pageTitle: intl.get('warehouse_transfer.label.new_warehouse_transfer'),
backLink: true,
},
{
- path: `/warehouse-transfers`,
+ path: `/warehouses-transfers`,
component: lazy(() =>
import(
'../containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersList'
From a81f1e7a9c09f072b45a8f5c8642ca32bcd255e8 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Wed, 2 Feb 2022 16:09:55 +0200
Subject: [PATCH 14/30] feat(warehouseTransfer): fix warehouse transfer style.
---
.../WarehouseTransferForm/WarehouseTransferFormProvider.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
index ad9525558..5c57d645e 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
@@ -61,7 +61,7 @@ function WarehouseTransferFormProvider({ warehouseTransferId, ...props }) {
return (
From 8bf64c68e0da527a77552076c5dfbb06eacfd373 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Thu, 3 Feb 2022 00:27:42 +0200
Subject: [PATCH 15/30] feat(warehouseTransfer): add crud warehouse transfer.
---
src/common/tables.js | 1 +
.../WarehouseTransferDetailDrawerProvider.js | 4 +-
.../WarehouseTransferForm.js | 4 +-
.../WarehouseTransferFormPage.js | 7 +-
.../WarehouseTransferFormProvider.js | 14 +++-
.../WarehouseTransfersActionsBar.js | 62 ++++++++++++++--
.../WarehouseTransfersDataTable.js | 70 +++++++++++++------
.../WarehouseTransfersEmptyStatus.js | 2 +-
.../WarehouseTransfersList.js | 40 +++++++++--
.../WarehouseTransfersListProvider.js | 58 ++++++++++++++-
.../WarehouseTransfersViewTabs.js | 28 ++++++--
.../WarehouseTransfersLanding/components.js | 31 ++++----
.../withWarehouseTransfers.js | 19 +++++
.../withWarehouseTransfersActions.js | 13 ++++
src/hooks/query/warehouses.js | 33 +++++++--
src/routes/dashboard.js | 7 +-
.../warehouseTransfer.actions.js | 14 ++++
.../warehouseTransfer.reducer.js | 34 +++++++++
.../warehouseTransfer.selector.js | 33 +++++++++
.../warehouseTransfer.type.js | 4 ++
src/store/reducers.js | 2 +
src/store/types.js | 4 +-
22 files changed, 407 insertions(+), 77 deletions(-)
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransfersLanding/withWarehouseTransfers.js
create mode 100644 src/containers/WarehouseTransfers/WarehouseTransfersLanding/withWarehouseTransfersActions.js
create mode 100644 src/store/WarehouseTransfer/warehouseTransfer.actions.js
create mode 100644 src/store/WarehouseTransfer/warehouseTransfer.reducer.js
create mode 100644 src/store/WarehouseTransfer/warehouseTransfer.selector.js
create mode 100644 src/store/WarehouseTransfer/warehouseTransfer.type.js
diff --git a/src/common/tables.js b/src/common/tables.js
index 59d6ca127..59c50dff7 100644
--- a/src/common/tables.js
+++ b/src/common/tables.js
@@ -16,6 +16,7 @@ export const TABLES = {
CASHFLOW_Transactions: 'cashflow_transactions',
CREDIT_NOTES: 'credit_notes',
VENDOR_CREDITS: 'vendor_credits',
+ WAREHOUSE_TRANSFERS:'warehouse_transfers'
};
export const TABLE_SIZE = {
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js
index 371131568..b470c954f 100644
--- a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js
@@ -9,10 +9,10 @@ const WarehouseTransferDetailDrawerContext = React.createContext();
* Warehouse transfer detail drawer provider.
*/
function WarehouseTransferDetailDrawerProvider({
- warehouseTransferId = 5,
+ warehouseTransferId,
...props
}) {
- // Handle fetch invoice detail.
+ // Handle fetch warehouse transfer detail.
const { data: warehouseTransfer, isLoading: isWarehouseTransferLoading } =
useWarehouseTransfer(warehouseTransferId, {
enabled: !!warehouseTransferId,
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js
index 1d172e6c4..760a8e306 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js
@@ -53,8 +53,8 @@ function WarehouseTransferForm({
// Form initial values.
const initialValues = React.useMemo(
() => ({
- ...(!isEmpty(null)
- ? { ...transformToEditForm(null) }
+ ...(!isEmpty(warehouseTransfer)
+ ? { ...transformToEditForm(warehouseTransfer) }
: {
...defaultWarehouseTransfer,
entries: orderingLinesIndexes(defaultWarehouseTransfer.entries),
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormPage.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormPage.js
index b9862488c..e7a622010 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormPage.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormPage.js
@@ -1,6 +1,7 @@
import React from 'react';
+import { useParams } from 'react-router-dom';
-import '../../../style/pages/WarehouseTransfers/PageForm.scss'
+import '../../../style/pages/WarehouseTransfers/PageForm.scss';
import WarehouseTransferForm from './WarehouseTransferForm';
import { WarehouseTransferFormProvider } from './WarehouseTransferFormProvider';
@@ -8,8 +9,10 @@ import { WarehouseTransferFormProvider } from './WarehouseTransferFormProvider';
* WarehouseTransfer form page.
*/
export default function WarehouseTransferFormPage() {
+ const { id } = useParams();
+ const idAsInteger = parseInt(id, 10);
return (
-
+
);
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
index 5c57d645e..1570ad160 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormProvider.js
@@ -3,6 +3,7 @@ import DashboardInsider from 'components/Dashboard/DashboardInsider';
import {
useItems,
useWarehouses,
+ useWarehouseTransfer,
useCreateWarehouseTransfer,
useEditWarehouseTransfer,
} from 'hooks/query';
@@ -24,6 +25,12 @@ function WarehouseTransferFormProvider({ warehouseTransferId, ...props }) {
stringified_filter_roles: ITEMS_FILTER_ROLES_QUERY,
});
+ // Handle fetch warehouse transfer detail.
+ const { data: warehouseTransfer, isLoading: isWarehouseTransferLoading } =
+ useWarehouseTransfer(warehouseTransferId, {
+ enabled: !!warehouseTransferId,
+ });
+
// Fetch warehouses list.
const {
data: warehouses,
@@ -47,7 +54,7 @@ function WarehouseTransferFormProvider({ warehouseTransferId, ...props }) {
const provider = {
items,
warehouses,
- warehouseTransfer: [],
+ warehouseTransfer,
isItemsFetching,
isWarehouesFetching,
@@ -58,9 +65,12 @@ function WarehouseTransferFormProvider({ warehouseTransferId, ...props }) {
createWarehouseTransferMutate,
editWarehouseTransferMutate,
};
+
return (
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersActionsBar.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersActionsBar.js
index 048a7151f..c0ad7a97e 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersActionsBar.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersActionsBar.js
@@ -18,6 +18,11 @@ import {
} from 'components';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
+import { useWarehouseTranfersListContext } from './WarehouseTransfersListProvider';
+
+import withWarehouseTransfers from './withWarehouseTransfers';
+import withWarehouseTransfersActions from './withWarehouseTransfersActions';
+import withSettings from '../../Settings/withSettings';
import withSettingsActions from 'containers/Settings/withSettingsActions';
import { compose } from 'utils';
@@ -26,11 +31,24 @@ import { compose } from 'utils';
* Warehouse Transfers actions bar.
*/
function WarehouseTransfersActionsBar({
+ // #withWarehouseTransfers
+ warehouseTransferFilterRoles,
+
+ // #withWarehouseTransfersActions
+ setWarehouseTransferTableState,
+
+ // #withSettings
+ warehouseTransferTableSize,
+
// #withSettingsActions
addSetting,
}) {
const history = useHistory();
+ // credit note list context.
+ const { WarehouseTransferView, fields, refresh } =
+ useWarehouseTranfersListContext();
+
// Handle new warehouse transfer button click.
const handleClickNewWarehouseTransfer = () => {
history.push('/warehouses-transfers/new');
@@ -38,14 +56,19 @@ function WarehouseTransfersActionsBar({
// Handle click a refresh warehouse transfers
const handleRefreshBtnClick = () => {
- // refresh();
+ refresh();
};
// Handle views tab change.
- const handleTabChange = (view) => {};
+ const handleTabChange = (view) => {
+ setWarehouseTransferTableState({ viewSlug: view ? view.slug : null });
+ };
// Handle table row size change.
- const handleTableRowSizeChange = (size) => {};
+ const handleTableRowSizeChange = (size) => {
+ addSetting('warehouseTransfer', 'tableSize', size);
+ };
+
return (
@@ -63,6 +86,22 @@ function WarehouseTransfersActionsBar({
onClick={handleClickNewWarehouseTransfer}
/>
+
+ {
+ setWarehouseTransferTableState({ filterRoles: filterConditions });
+ },
+ }}
+ >
+
+
+
}
@@ -80,8 +119,8 @@ function WarehouseTransfersActionsBar({
/>
@@ -89,11 +128,20 @@ function WarehouseTransfersActionsBar({
}
- // onClick={handleRefreshBtnClick}
+ onClick={handleRefreshBtnClick}
/>
);
}
-export default compose(withSettingsActions)(WarehouseTransfersActionsBar);
+export default compose(
+ withSettingsActions,
+ withWarehouseTransfersActions,
+ withWarehouseTransfers(({ warehouseTransferTableState }) => ({
+ warehouseTransferFilterRoles: warehouseTransferTableState.filterRoles,
+ })),
+ withSettings(({ warehouseTransferSettings }) => ({
+ warehouseTransferTableSize: warehouseTransferSettings?.tableSize,
+ })),
+)(WarehouseTransfersActionsBar);
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersDataTable.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersDataTable.js
index f707d70a3..a6dd9c907 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersDataTable.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersDataTable.js
@@ -11,6 +11,7 @@ import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+import withWarehouseTransfersActions from './withWarehouseTransfersActions';
import withDrawerActions from 'containers/Drawer/withDrawerActions';
import withDialogActions from 'containers/Dialog/withDialogActions';
import withAlertsActions from 'containers/Alert/withAlertActions';
@@ -25,6 +26,9 @@ import { compose } from 'utils';
* Warehouse transfers datatable.
*/
function WarehouseTransfersDataTable({
+ // #withWarehouseTransfersActions
+ setWarehouseTransferTableState,
+
// #withAlertsActions
openAlert,
@@ -33,15 +37,45 @@ function WarehouseTransfersDataTable({
// #withDialogAction
openDialog,
+
+ // #withSettings
+ warehouseTransferTableSize,
}) {
const history = useHistory();
// Warehouse transfers list context.
- const { isEmptyStatus } = useWarehouseTranfersListContext();
+ const {
+ warehousesTransfers,
+ pagination,
+ isEmptyStatus,
+ isWarehouseTransfersLoading,
+ isWarehouseTransfersFetching,
+ } = useWarehouseTranfersListContext();
// Invoices table columns.
const columns = useWarehouseTransfersTableColumns();
+ // Local storage memorizing columns widths.
+ const [initialColumnsWidths, , handleColumnResizing] =
+ useMemorizedColumnsWidths(TABLES.WAREHOUSE_TRANSFERS);
+
+ // Handles fetch data once the table state change.
+ const handleDataTableFetchData = React.useCallback(
+ ({ pageSize, pageIndex, sortBy }) => {
+ setWarehouseTransferTableState({
+ pageSize,
+ pageIndex,
+ sortBy,
+ });
+ },
+ [setWarehouseTransferTableState],
+ );
+
+ // Display invoice empty status instead of the table.
+ if (isEmptyStatus) {
+ return ;
+ }
+
// Handle view detail.
const handleViewDetailWarehouseTransfer = ({ id }) => {
openDrawer('warehouse-transfer-detail-drawer', { warehouseTransferId: id });
@@ -64,41 +98,31 @@ function WarehouseTransfersDataTable({
});
};
- // 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 (
({
+ warehouseTransferTableSize: warehouseTransferSettings?.tableSize,
+ })),
)(WarehouseTransfersDataTable);
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersEmptyStatus.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersEmptyStatus.js
index 2672f4be0..9cb76ad5a 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersEmptyStatus.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersEmptyStatus.js
@@ -17,7 +17,7 @@ export default function WarehouseTransfersEmptyStatus() {
intent={Intent.PRIMARY}
large={true}
onClick={() => {
- history.push('/warehouse-transfers/new');
+ history.push('/warehouses-transfers/new');
}}
>
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersList.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersList.js
index 8f5eeb3a4..525316331 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersList.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersList.js
@@ -3,16 +3,36 @@ 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';
+import withWarehouseTransfers from './withWarehouseTransfers';
+import withWarehouseTransfersActions from './withWarehouseTransfersActions';
+
+import { WarehouseTransfersListProvider } from './WarehouseTransfersListProvider';
+import { transformTableStateToQuery, compose } from 'utils';
+
+function WarehouseTransfersList({
+ // #withWarehouseTransfers
+ warehouseTransferTableState,
+ warehouseTransferTableStateChanged,
+
+ // #withWarehouseTransfersActions
+ resetWarehouseTransferTableState,
+}) {
+ // Resets the warehouse transfer table state once the page unmount.
+ React.useEffect(
+ () => () => {
+ resetWarehouseTransferTableState();
+ },
+ [resetWarehouseTransferTableState],
+ );
-function WarehouseTransfersList({}) {
return (
-
+
@@ -22,4 +42,12 @@ function WarehouseTransfersList({}) {
);
}
-export default WarehouseTransfersList;
+export default compose(
+ withWarehouseTransfersActions,
+ withWarehouseTransfers(
+ ({ warehouseTransferTableState, warehouseTransferTableStateChanged }) => ({
+ warehouseTransferTableState,
+ warehouseTransferTableStateChanged,
+ }),
+ ),
+)(WarehouseTransfersList);
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersListProvider.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersListProvider.js
index 24714d977..017341b6c 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersListProvider.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersListProvider.js
@@ -2,22 +2,74 @@ import React from 'react';
import { isEmpty } from 'lodash';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
+import {
+ useResourceViews,
+ useResourceMeta,
+ useWarehousesTransfers,
+ useRefreshWarehouseTransfers,
+} from 'hooks/query';
+
+import { getFieldsFromResourceMeta } from 'utils';
const WarehouseTransfersListContext = React.createContext();
/**
* WarehouseTransfer data provider
*/
-function WarehouseTransfersListProvider({ ...props }) {
+function WarehouseTransfersListProvider({
+ query,
+ tableStateChanged,
+ ...props
+}) {
+ // warehouse transfers refresh action.
+ const { refresh } = useRefreshWarehouseTransfers();
+
+ // Fetch warehouse transfers list according to the given custom view id.
+ const {
+ data: { warehousesTransfers, pagination, filterMeta },
+ isFetching: isWarehouseTransfersFetching,
+ isLoading: isWarehouseTransfersLoading,
+ } = useWarehousesTransfers(query, { keepPreviousData: true });
+
// Detarmines the datatable empty status.
- const isEmptyStatus = false;
+ const isEmptyStatus =
+ isEmpty(warehousesTransfers) && !isWarehouseTransfersLoading;
+
+ // Fetch create notes resource views and fields.
+ const { data: WarehouseTransferView, isLoading: isViewsLoading } =
+ useResourceViews('warehouse_transfer');
+
+ // Fetch the accounts resource fields.
+ const {
+ data: resourceMeta,
+ isLoading: isResourceLoading,
+ isFetching: isResourceFetching,
+ } = useResourceMeta('warehouse_transfer');
// Provider payload.
const provider = {
+ warehousesTransfers,
+ pagination,
+
+ WarehouseTransferView,
+ refresh,
+
+ resourceMeta,
+ fields: getFieldsFromResourceMeta(resourceMeta.fields),
+ isResourceLoading,
+ isResourceFetching,
+
+ isWarehouseTransfersLoading,
+ isWarehouseTransfersFetching,
+ isViewsLoading,
isEmptyStatus,
};
+
return (
-
+
);
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersViewTabs.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersViewTabs.js
index 8be06aa31..f0b75af98 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersViewTabs.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersViewTabs.js
@@ -1,23 +1,34 @@
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 withWarehouseTransfers from './withWarehouseTransfers';
+import withWarehouseTransfersActions from './withWarehouseTransfersActions';
-import { compose } from 'utils';
+import { useWarehouseTranfersListContext } from './WarehouseTransfersListProvider';
+import { compose, transfromViewsToTabs } from 'utils';
/**
* Warehouse transfer view tabs.
*/
-function WarehouseTransfersViewTabs() {
+function WarehouseTransfersViewTabs({
+ // #withWarehouseTransfers
+ warehouseTransferCurrentView,
+
+ // #withWarehouseTransfersActions
+ setWarehouseTransferTableState,
+}) {
+ const { WarehouseTransferView } = useWarehouseTranfersListContext();
+
// Handles click a new view tab.
const handleClickNewView = () => {};
// Handles the active tab chaing.
- const handleTabsChange = (customView) => {};
+ const handleTabsChange = (viewSlug) => {
+ setWarehouseTransferTableState({ viewSlug });
+ };
return (
@@ -34,4 +45,9 @@ function WarehouseTransfersViewTabs() {
);
}
-export default WarehouseTransfersViewTabs;
+export default compose(
+ withWarehouseTransfersActions,
+ withWarehouseTransfers(({ warehouseTransferTableState }) => ({
+ warehouseTransferCurrentView: warehouseTransferTableState?.viewSlug,
+ })),
+)(WarehouseTransfersViewTabs);
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/components.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/components.js
index 0a4eb0dab..b7b9ee167 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/components.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/components.js
@@ -58,7 +58,7 @@ export function useWarehouseTransfersTableColumns() {
{
id: 'date',
Header: intl.get('date'),
- accessor: 'date',
+ accessor: 'formatted_date',
Cell: FormatDateCell,
width: 120,
className: 'date',
@@ -66,36 +66,29 @@ export function useWarehouseTransfersTableColumns() {
textOverview: true,
},
{
- id: 'transfer_no',
+ id: 'transaction_number',
Header: intl.get('warehouse_transfer.column.transfer_no'),
- accessor: 'transfer_no',
- width: 120,
- className: 'transfer_no',
+ accessor: 'transaction_number',
+ width: 100,
+ className: 'transaction_number',
clickable: true,
textOverview: true,
},
{
id: 'from_warehouse',
Header: intl.get('warehouse_transfer.column.from_warehouse'),
- accessor: 'from_warehouse',
- width: 150,
+ accessor: 'from_warehouse.name',
+ width: 140,
+ className: 'from_warehouse',
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,
+ accessor: 'to_warehouse.name',
+ width: 140,
+ className: 'to_warehouse',
clickable: true,
textOverview: true,
},
@@ -103,7 +96,7 @@ export function useWarehouseTransfersTableColumns() {
id: 'status',
Header: intl.get('status'),
// accessor: (row) => statusAccessor(row),
- width: 160,
+ width: 140,
className: 'status',
clickable: true,
},
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/withWarehouseTransfers.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/withWarehouseTransfers.js
new file mode 100644
index 000000000..0f1173f68
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/withWarehouseTransfers.js
@@ -0,0 +1,19 @@
+import { connect } from 'react-redux';
+import {
+ getWarehouseTransfersTableStateFactory,
+ isWarehouseTransferTableStateChangedFactory,
+} from '../../../store/WarehouseTransfer/warehouseTransfer.selector';
+
+export default (mapState) => {
+ const getWarehouseTransferTableState = getWarehouseTransfersTableStateFactory();
+ const isWarehouseTransferTableChanged = isWarehouseTransferTableStateChangedFactory();
+
+ const mapStateToProps = (state, props) => {
+ const mapped = {
+ warehouseTransferTableState: getWarehouseTransferTableState(state, props),
+ warehouseTransferTableStateChanged: isWarehouseTransferTableChanged(state, props),
+ };
+ return mapState ? mapState(mapped, state, props) : mapped;
+ };
+ return connect(mapStateToProps);
+};
diff --git a/src/containers/WarehouseTransfers/WarehouseTransfersLanding/withWarehouseTransfersActions.js b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/withWarehouseTransfersActions.js
new file mode 100644
index 000000000..8e0bba3d5
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransfersLanding/withWarehouseTransfersActions.js
@@ -0,0 +1,13 @@
+import { connect } from 'react-redux';
+import {
+ setWarehouseTransferTableState,
+ resetWarehouseTransferTableState,
+} from '../../../store/WarehouseTransfer/warehouseTransfer.actions';
+
+const mapDipatchToProps = (dispatch) => ({
+ setWarehouseTransferTableState: (queries) =>
+ dispatch(setWarehouseTransferTableState(queries)),
+ resetWarehouseTransferTableState: () => dispatch(resetWarehouseTransferTableState()),
+});
+
+export default connect(null, mapDipatchToProps);
\ No newline at end of file
diff --git a/src/hooks/query/warehouses.js b/src/hooks/query/warehouses.js
index 27e052c2f..a095ab87e 100644
--- a/src/hooks/query/warehouses.js
+++ b/src/hooks/query/warehouses.js
@@ -1,4 +1,5 @@
import { useQueryClient, useMutation } from 'react-query';
+import { transformPagination } from 'utils';
import { useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
import t from './types';
@@ -129,7 +130,7 @@ export function useEditWarehouseTransfer(props) {
const apiRequest = useApiRequest();
return useMutation(
- ([id, values]) => apiRequest.post(`warehouses/transfers${id}`, values),
+ ([id, values]) => apiRequest.post(`warehouses/transfers/${id}`, values),
{
onSuccess: (res, [id, values]) => {
// Invalidate specific sale invoice.
@@ -162,6 +163,12 @@ export function useDeleteWarehouseTransfer(props) {
});
}
+const transformWarehousesTransfer = (res) => ({
+ warehousesTransfers: res.data.data,
+ pagination: transformPagination(res.data.pagination),
+ filterMeta: res.data.filter,
+});
+
/**
* Retrieve Warehoues list.
*/
@@ -170,8 +177,16 @@ export function useWarehousesTransfers(query, props) {
[t.WAREHOUSE_TRANSFERS, query],
{ method: 'get', url: 'warehouses/transfers', params: query },
{
- select: (res) => res.data,
- defaultData: [],
+ select: transformWarehousesTransfer,
+ defaultData: {
+ warehousesTransfers: [],
+ pagination: {
+ page: 1,
+ pageSize: 20,
+ total: 0,
+ },
+ filterMeta: {},
+ },
...props,
},
);
@@ -186,9 +201,19 @@ export function useWarehouseTransfer(id, props, requestProps) {
[t.WAREHOUSE_TRANSFER, id],
{ method: 'get', url: `warehouses/transfers/${id}`, ...requestProps },
{
- select: (res) => res.data.warehouse_transfer,
+ select: (res) => res.data.data,
defaultData: {},
...props,
},
);
}
+
+export function useRefreshWarehouseTransfers() {
+ const queryClient = useQueryClient();
+
+ return {
+ refresh: () => {
+ queryClient.invalidateQueries(t.WAREHOUSE_TRANSFERS);
+ },
+ };
+}
diff --git a/src/routes/dashboard.js b/src/routes/dashboard.js
index 3afc57e2b..8877b2396 100644
--- a/src/routes/dashboard.js
+++ b/src/routes/dashboard.js
@@ -117,10 +117,15 @@ export const getDashboardRoutes = () => [
defaultSearchResource: RESOURCES_TYPES.ITEM,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
+
// Warehouse Transfer.
{
path: `/warehouses-transfers/:id/edit`,
- component: lazy(() => import('containers/Items/ItemFormPage')),
+ component: lazy(() =>
+ import(
+ '../containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormPage'
+ ),
+ ),
name: 'warehouse-transfer-edit',
pageTitle: intl.get('warehouse_transfer.label.edit_warehouse_transfer'),
backLink: true,
diff --git a/src/store/WarehouseTransfer/warehouseTransfer.actions.js b/src/store/WarehouseTransfer/warehouseTransfer.actions.js
new file mode 100644
index 000000000..5fa8af202
--- /dev/null
+++ b/src/store/WarehouseTransfer/warehouseTransfer.actions.js
@@ -0,0 +1,14 @@
+import t from 'store/types';
+
+export const setWarehouseTransferTableState = (queries) => {
+ return {
+ type: t.WAREHOUSE_TRANSFERS_TABLE_STATE_SET,
+ payload: { queries },
+ };
+};
+
+export const resetWarehouseTransferTableState = () => {
+ return {
+ type: t.WAREHOUSE_TRANSFERS_TABLE_STATE_RESET,
+ };
+};
diff --git a/src/store/WarehouseTransfer/warehouseTransfer.reducer.js b/src/store/WarehouseTransfer/warehouseTransfer.reducer.js
new file mode 100644
index 000000000..193549eda
--- /dev/null
+++ b/src/store/WarehouseTransfer/warehouseTransfer.reducer.js
@@ -0,0 +1,34 @@
+import { createReducer } from '@reduxjs/toolkit';
+import { persistReducer, purgeStoredState } from 'redux-persist';
+import storage from 'redux-persist/lib/storage';
+import { createTableStateReducers } from 'store/tableState.reducer';
+import t from 'store/types';
+
+export const defaultTableQuery = {
+ pageSize: 20,
+ pageIndex: 0,
+ filterRoles: [],
+ viewSlug: null,
+};
+
+const initialState = {
+ tableState: defaultTableQuery,
+};
+
+const STORAGE_KEY = 'bigcapital:warehouse_transfers';
+
+const CONFIG = {
+ key: STORAGE_KEY,
+ whitelist: [],
+ storage,
+};
+
+const reducerInstance = createReducer(initialState, {
+ ...createTableStateReducers('WAREHOUSE_TRANSFERS', defaultTableQuery),
+
+ [t.RESET]: () => {
+ purgeStoredState(CONFIG);
+ },
+});
+
+export default persistReducer(CONFIG, reducerInstance);
diff --git a/src/store/WarehouseTransfer/warehouseTransfer.selector.js b/src/store/WarehouseTransfer/warehouseTransfer.selector.js
new file mode 100644
index 000000000..ccea3c4df
--- /dev/null
+++ b/src/store/WarehouseTransfer/warehouseTransfer.selector.js
@@ -0,0 +1,33 @@
+import { isEqual } from 'lodash';
+import { paginationLocationQuery } from 'store/selectors';
+import { createDeepEqualSelector } from 'utils';
+import { defaultTableQuery } from './warehouseTransfer.reducer';
+
+const warehouseTransfersTableStateSelector = (state) =>
+ state.warehouseTransfers.tableState;
+
+/**
+ * Retrieve warehouse transfers table state.
+ */
+export const getWarehouseTransfersTableStateFactory = () =>
+ createDeepEqualSelector(
+ paginationLocationQuery,
+ warehouseTransfersTableStateSelector,
+ (locationQuery, tableState) => {
+ return {
+ ...locationQuery,
+ ...tableState,
+ };
+ },
+ );
+
+/**
+ * Retrieve warehouse transfers table state.
+ */
+export const isWarehouseTransferTableStateChangedFactory = () =>
+ createDeepEqualSelector(
+ warehouseTransfersTableStateSelector,
+ (tableState) => {
+ return !isEqual(tableState, defaultTableQuery);
+ },
+ );
diff --git a/src/store/WarehouseTransfer/warehouseTransfer.type.js b/src/store/WarehouseTransfer/warehouseTransfer.type.js
new file mode 100644
index 000000000..280b1cc02
--- /dev/null
+++ b/src/store/WarehouseTransfer/warehouseTransfer.type.js
@@ -0,0 +1,4 @@
+export default {
+ WAREHOUSE_TRANSFERS_TABLE_STATE_SET: 'WAREHOUSE_TRANSFERS/TABLE_STATE_SET',
+ WAREHOUSE_TRANSFERS_TABLE_STATE_RESET: 'WAREHOUSE_TRANSFERS/TABLE_STATE_RESET',
+};
diff --git a/src/store/reducers.js b/src/store/reducers.js
index ad28a32e6..0223270ad 100644
--- a/src/store/reducers.js
+++ b/src/store/reducers.js
@@ -34,6 +34,7 @@ import inventoryAdjustments from './inventoryAdjustments/inventoryAdjustment.red
import plans from './plans/plans.reducer';
import creditNotes from './CreditNote/creditNote.reducer';
import vendorCredit from './VendorCredit/VendorCredit.reducer';
+import warehouseTransfers from './WarehouseTransfer/warehouseTransfer.reducer';
const appReducer = combineReducers({
authentication,
@@ -68,6 +69,7 @@ const appReducer = combineReducers({
plans,
creditNotes,
vendorCredit,
+ warehouseTransfers,
});
// Reset the state of a redux store
diff --git a/src/store/types.js b/src/store/types.js
index 3e509142f..079344984 100644
--- a/src/store/types.js
+++ b/src/store/types.js
@@ -30,6 +30,7 @@ import subscription from './subscription/subscription.types';
import inventoryAdjustments from './inventoryAdjustments/inventoryAdjustment.type';
import creditNote from './CreditNote/creditNote.type';
import vendorCredit from './VendorCredit/vendorCredit.type';
+import WarehouseTransfer from './WarehouseTransfer/warehouseTransfer.type';
import plans from './plans/plans.types';
export default {
@@ -65,5 +66,6 @@ export default {
...inventoryAdjustments,
...plans,
...creditNote,
- ...vendorCredit
+ ...vendorCredit,
+ ...WarehouseTransfer,
};
From e7024955dd056743c3f8787f9a141115b541fece Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Thu, 3 Feb 2022 01:02:31 +0200
Subject: [PATCH 16/30] feat(warehouseTransfer): warehouse transfer detail.
---
.../Alerts/Warehouses/WarehouseTransferDeleteAlert.js | 8 +++++++-
.../WarehouseTransferDetailActionsBar.js | 7 +++++--
.../WarehouseTransferDetailDrawerProvider.js | 4 +++-
.../WarehouseTransferDetailHeader.js | 2 +-
src/lang/en/index.json | 5 +++--
5 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/src/containers/Alerts/Warehouses/WarehouseTransferDeleteAlert.js b/src/containers/Alerts/Warehouses/WarehouseTransferDeleteAlert.js
index 936ccc97c..a602be329 100644
--- a/src/containers/Alerts/Warehouses/WarehouseTransferDeleteAlert.js
+++ b/src/containers/Alerts/Warehouses/WarehouseTransferDeleteAlert.js
@@ -7,6 +7,7 @@ import { useDeleteWarehouseTransfer } from 'hooks/query';
import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
import withAlertActions from 'containers/Alert/withAlertActions';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
import { compose } from 'utils';
@@ -23,9 +24,12 @@ function WarehouseTransferDeleteAlert({
// #withAlertActions
closeAlert,
+
+ // #withDrawerActions
+ closeDrawer,
}) {
const { mutateAsync: deleteWarehouseTransferMutate, isLoading } =
- useDeleteWarehouseTransfer();
+ useDeleteWarehouseTransfer();
// handle cancel delete warehouse alert.
const handleCancelDeleteAlert = () => {
@@ -40,6 +44,7 @@ function WarehouseTransferDeleteAlert({
message: intl.get('warehouse_transfer.alert.delete_message'),
intent: Intent.SUCCESS,
});
+ closeDrawer('warehouse-transfer-detail-drawer');
})
.catch(
({
@@ -76,4 +81,5 @@ function WarehouseTransferDeleteAlert({
export default compose(
withAlertStoreConnect(),
withAlertActions,
+ withDrawerActions,
)(WarehouseTransferDeleteAlert);
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailActionsBar.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailActionsBar.js
index 9202666f4..9a443d5d8 100644
--- a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailActionsBar.js
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailActionsBar.js
@@ -34,15 +34,18 @@ function WarehouseTransferDetailActionsBar({
}) {
const history = useHistory();
+ const { warehouseTransferId, warehouseTransfer } =
+ useWarehouseDetailDrawerContext();
+
// Handle edit warehosue transfer.
const handleEditWarehosueTransfer = () => {
- // history.push(`/warehouse-transfers/${warehouseTransferId}/edit`);
+ history.push(`/warehouses-transfers/${warehouseTransferId}/edit`);
closeDrawer('warehouse-transfer-detail-drawer');
};
// Handle delete warehouse transfer.
const handleDeletetWarehosueTransfer = () => {
- // openAlert('warehouse-transfer-delete', { warehouseTransferId });
+ openAlert('warehouse-transfer-delete', { warehouseTransferId });
};
return (
diff --git a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js
index b470c954f..d6b6572b6 100644
--- a/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js
+++ b/src/containers/Drawers/WarehouseTransferDetailDrawer/WarehouseTransferDetailDrawerProvider.js
@@ -28,7 +28,9 @@ function WarehouseTransferDetailDrawerProvider({
-
+
Date: Thu, 3 Feb 2022 01:03:00 +0200
Subject: [PATCH 17/30] feat(warehouseTransfer): handle error.
---
.../WarehouseTransferForm.js | 4 ++++
.../WarehouseTransferForm/utils.js | 23 ++++++++++++++++---
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js
index 760a8e306..c5990ba34 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferForm.js
@@ -25,6 +25,7 @@ import { compose, orderingLinesIndexes, transactionNumber } from 'utils';
import {
defaultWarehouseTransfer,
transformValueToRequest,
+ transformErrors,
transformToEditForm,
} from './utils';
@@ -97,6 +98,9 @@ function WarehouseTransferForm({
data: { errors },
},
}) => {
+ if (errors) {
+ transformErrors(errors, { setErrors });
+ }
setSubmitting(false);
};
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/utils.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/utils.js
index aad275728..d03dda138 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/utils.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/utils.js
@@ -1,8 +1,9 @@
import React from 'react';
-import intl from 'react-intl-universal';
-import clsx from 'classnames';
-import { useFormikContext } from 'formik';
import moment from 'moment';
+import intl from 'react-intl-universal';
+import { Intent } from '@blueprintjs/core';
+import { useFormikContext } from 'formik';
+import { AppToaster } from 'components';
import { omit } from 'lodash';
import {
@@ -105,3 +106,19 @@ export function transformValueToRequest(values) {
})),
};
}
+
+/**
+ * Transformes the response errors types.
+ */
+export const transformErrors = (errors, { setErrors }) => {
+ if (
+ errors.some(({ type }) => type === 'WAREHOUSES_TRANSFER_SHOULD_NOT_BE_SAME')
+ ) {
+ AppToaster.show({
+ message: intl.get(
+ 'warehouse_transfer.error.could_not_transfer_item_from_source_to_destination',
+ ),
+ intent: Intent.DANGER,
+ });
+ }
+};
From 164eebd6ae6c90881c5dbc14f1e0199c63b993e2 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Thu, 3 Feb 2022 22:47:38 +0200
Subject: [PATCH 18/30] feat(RealizedGainorLoss): add realized gain or loss.
---
src/config/sidebarMenu.js | 4 +
.../RealizedGainOrLoss/RealizedGainOrLoss.js | 67 ++++++++++
.../RealizedGainOrLossActionsBar.js | 122 ++++++++++++++++++
.../RealizedGainOrLossGeneralPanel.js | 17 +++
.../RealizedGainOrLossHeader.js | 108 ++++++++++++++++
.../RealizedGainOrLossProvider.js | 22 ++++
.../RealizedGainOrLossTable.js | 21 +++
.../RealizedGainOrLoss/components.js | 18 +++
.../withRealizedGainOrLoss.js | 12 ++
.../withRealizedGainOrLossActions.js | 9 ++
src/hooks/query/types.js | 5 +-
src/routes/dashboard.js | 14 ++
.../financialStatements.actions.js | 15 ++-
.../financialStatements.reducer.js | 5 +
.../financialStatements.selectors.js | 14 ++
.../financialStatements.types.js | 1 +
16 files changed, 451 insertions(+), 3 deletions(-)
create mode 100644 src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLoss.js
create mode 100644 src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossActionsBar.js
create mode 100644 src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossGeneralPanel.js
create mode 100644 src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossHeader.js
create mode 100644 src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossProvider.js
create mode 100644 src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossTable.js
create mode 100644 src/containers/FinancialStatements/RealizedGainOrLoss/components.js
create mode 100644 src/containers/FinancialStatements/RealizedGainOrLoss/withRealizedGainOrLoss.js
create mode 100644 src/containers/FinancialStatements/RealizedGainOrLoss/withRealizedGainOrLossActions.js
diff --git a/src/config/sidebarMenu.js b/src/config/sidebarMenu.js
index 84fece5ab..bf82e5fe2 100644
--- a/src/config/sidebarMenu.js
+++ b/src/config/sidebarMenu.js
@@ -641,6 +641,10 @@ export default [
ability: ReportsAction.READ_AP_AGING_SUMMARY,
},
},
+ {
+ text: ,
+ href: '/financial-reports/realized-gain-loss',
+ },
{
text: ,
label: true,
diff --git a/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLoss.js b/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLoss.js
new file mode 100644
index 000000000..529f2a376
--- /dev/null
+++ b/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLoss.js
@@ -0,0 +1,67 @@
+import React from 'react';
+
+import { FinancialStatement } from 'components';
+
+import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
+
+import RealizedGainOrLossHeader from './RealizedGainOrLossHeader';
+import RealizedGainOrLossTable from './RealizedGainOrLossTable';
+import RealizedGainOrLossActionsBar from './RealizedGainOrLossActionsBar';
+
+import withCurrentOrganization from '../../Organization/withCurrentOrganization';
+import withRealizedGainOrLossActions from './withRealizedGainOrLossActions';
+import { RealizedGainOrLossProvider } from './RealizedGainOrLossProvider';
+import { RealizedGainOrLossLoadingBar } from './components';
+
+import { compose } from 'utils';
+
+/**
+ * Realized Gain or Loss.
+ */
+function RealizedGainOrLoss({
+ // #withPreferences
+ organizationName,
+
+ //#withRealizedGainOrLossActions
+ toggleRealizedGainOrLossFilterDrawer,
+}) {
+ // Handle refetch realized Gain or Loss after filter change.
+ const handleFilterSubmit = (filter) => {};
+
+ // Handle format number submit.
+ const handleNumberFormatSubmit = (values) => {};
+
+ React.useEffect(
+ () => () => {
+ toggleRealizedGainOrLossFilterDrawer(false);
+ },
+ [toggleRealizedGainOrLossFilterDrawer],
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default compose(
+ withCurrentOrganization(({ organization }) => ({
+ organizationName: organization.name,
+ })),
+ withRealizedGainOrLossActions,
+)(RealizedGainOrLoss);
diff --git a/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossActionsBar.js b/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossActionsBar.js
new file mode 100644
index 000000000..4b9ca3c9e
--- /dev/null
+++ b/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossActionsBar.js
@@ -0,0 +1,122 @@
+import React from 'react';
+import {
+ NavbarGroup,
+ NavbarDivider,
+ Button,
+ Classes,
+ Popover,
+ PopoverInteractionKind,
+ Position,
+} from '@blueprintjs/core';
+import { FormattedMessage as T, Icon } from 'components';
+import classNames from 'classnames';
+
+import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
+import NumberFormatDropdown from 'components/NumberFormatDropdown';
+
+import { useRealizedGainOrLossContext } from './RealizedGainOrLossProvider';
+import withRealizedGainOrLoss from './withRealizedGainOrLoss';
+import withRealizedGainOrLossActions from './withRealizedGainOrLossActions';
+
+import { compose, saveInvoke } from 'utils';
+
+/**
+ * Realized Gain or Loss actions bar.
+ */
+function RealizedGainOrLossActionsBar({
+ //#withRealizedGainOrLoss
+ isFilterDrawerOpen,
+
+ //#withRealizedGainOrLossActions
+ toggleRealizedGainOrLossFilterDrawer,
+
+ //#ownProps
+ numberFormat,
+ onNumberFormatSubmit,
+}) {
+ // Handle filter toggle click.
+ const handleFilterToggleClick = () => {
+ toggleRealizedGainOrLossFilterDrawer();
+ };
+
+ // Handle recalculate report button.
+ const handleRecalculateReport = () => {};
+
+ // handle number format form submit.
+ const handleNumberFormatSubmit = (values) =>
+ saveInvoke(onNumberFormatSubmit, values);
+
+ return (
+
+
+ }
+ onClick={handleRecalculateReport}
+ icon={ }
+ />
+
+
+
+ }
+ text={
+ isFilterDrawerOpen ? (
+
+ ) : (
+
+ )
+ }
+ onClick={handleFilterToggleClick}
+ active={isFilterDrawerOpen}
+ />
+
+
+
+ }
+ minimal={true}
+ interactionKind={PopoverInteractionKind.CLICK}
+ position={Position.BOTTOM_LEFT}
+ >
+ }
+ icon={ }
+ />
+
+
+ }
+ icon={ }
+ />
+
+
+ }
+ text={ }
+ />
+ }
+ text={ }
+ />
+
+
+ );
+}
+
+export default compose(
+ withRealizedGainOrLoss(({ realizedGainOrLossDrawerFilter }) => ({
+ isFilterDrawerOpen: realizedGainOrLossDrawerFilter,
+ })),
+ withRealizedGainOrLossActions,
+)(RealizedGainOrLossActionsBar);
diff --git a/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossGeneralPanel.js b/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossGeneralPanel.js
new file mode 100644
index 000000000..f08938a29
--- /dev/null
+++ b/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossGeneralPanel.js
@@ -0,0 +1,17 @@
+import React from 'react';
+
+import { Row, Col } from '../../../components';
+import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
+import SelectDisplayColumnsBy from '../SelectDisplayColumnsBy';
+
+/**
+ * Realized Gain or Loss header - General panel.
+ */
+export default function RealizedGainOrLossGeneralPanel() {
+ return (
+
+
+
+
+ );
+}
diff --git a/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossHeader.js b/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossHeader.js
new file mode 100644
index 000000000..a13c08166
--- /dev/null
+++ b/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossHeader.js
@@ -0,0 +1,108 @@
+import React from 'react';
+import moment from 'moment';
+import * as Yup from 'yup';
+import intl from 'react-intl-universal';
+import { Formik, Form } from 'formik';
+import { Tabs, Tab, Button, Intent } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'components';
+
+import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
+import RealizedGainOrLossGeneralPanel from './RealizedGainOrLossGeneralPanel';
+
+import withRealizedGainOrLoss from './withRealizedGainOrLoss';
+import withRealizedGainOrLossActions from './withRealizedGainOrLossActions';
+
+import { compose, transformToForm } from 'utils';
+
+/**
+ * Realized Gain or Loss.header.
+ */
+function RealizedGainOrLossHeader({
+ // #ownProps
+ onSubmitFilter,
+ pageFilter,
+
+ //#withRealizedGainOrLoss
+ isFilterDrawerOpen,
+
+ //#withRealizedGainOrLossActions
+ toggleRealizedGainOrLossFilterDrawer,
+}) {
+ // Filter form default values.
+ const defaultValues = {
+ fromDate: moment().toDate(),
+ toDate: moment().toDate(),
+ };
+
+ // Initial form values.
+ const initialValues = transformToForm(
+ {
+ ...pageFilter,
+ fromDate: moment(pageFilter.fromDate).toDate(),
+ toDate: moment(pageFilter.toDate).toDate(),
+ },
+ defaultValues,
+ );
+
+ // Validation schema.
+ const validationSchema = Yup.object().shape({
+ dateRange: Yup.string().optional(),
+ fromDate: Yup.date().required().label(intl.get('fromDate')),
+ toDate: Yup.date()
+ .min(Yup.ref('fromDate'))
+ .required()
+ .label(intl.get('toDate')),
+ displayColumnsType: Yup.string(),
+ });
+
+ // Handle form submit.
+ const handleSubmit = (values, { setSubmitting }) => {
+ onSubmitFilter(values);
+ toggleRealizedGainOrLossFilterDrawer(false);
+ setSubmitting(false);
+ };
+
+ // Handle drawer close action.
+ const handleDrawerClose = () => {
+ toggleRealizedGainOrLossFilterDrawer(false);
+ };
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default compose(
+ withRealizedGainOrLoss(({ realizedGainOrLossDrawerFilter }) => ({
+ isFilterDrawerOpen: realizedGainOrLossDrawerFilter,
+ })),
+ withRealizedGainOrLossActions,
+)(RealizedGainOrLossHeader);
diff --git a/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossProvider.js b/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossProvider.js
new file mode 100644
index 000000000..0c8fb18fc
--- /dev/null
+++ b/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossProvider.js
@@ -0,0 +1,22 @@
+import React from 'react';
+import FinancialReportPage from '../FinancialReportPage';
+
+const RealizedGainOrLossContext = React.createContext();
+
+/**
+ * Realized Gain or Loss provider.
+ */
+function RealizedGainOrLossProvider({ filter, ...props }) {
+ const provider = {};
+
+ return (
+
+
+
+ );
+}
+
+const useRealizedGainOrLossContext = () =>
+ React.useContext(RealizedGainOrLossContext);
+
+export { RealizedGainOrLossProvider, useRealizedGainOrLossContext };
diff --git a/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossTable.js b/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossTable.js
new file mode 100644
index 000000000..426a0997a
--- /dev/null
+++ b/src/containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLossTable.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+
+import { DataTable } from 'components';
+import FinancialSheet from 'components/FinancialSheet';
+
+/**
+ * Realized Gain or Loss table.
+ */
+export default function RealizedGainOrLossTable({
+ // #ownProps
+ companyName,
+}) {
+ return (
+
+ );
+}
diff --git a/src/containers/FinancialStatements/RealizedGainOrLoss/components.js b/src/containers/FinancialStatements/RealizedGainOrLoss/components.js
new file mode 100644
index 000000000..217b440de
--- /dev/null
+++ b/src/containers/FinancialStatements/RealizedGainOrLoss/components.js
@@ -0,0 +1,18 @@
+import React from 'react';
+import { Button } from '@blueprintjs/core';
+import { Icon, If } from 'components';
+import { FormattedMessage as T } from 'components';
+
+import { useRealizedGainOrLossContext } from './RealizedGainOrLossProvider';
+import FinancialLoadingBar from '../FinancialLoadingBar';
+
+/**
+ * Realized Gain or Loss loading bar.
+ */
+export function RealizedGainOrLossLoadingBar() {
+ return (
+
+
+
+ );
+}
diff --git a/src/containers/FinancialStatements/RealizedGainOrLoss/withRealizedGainOrLoss.js b/src/containers/FinancialStatements/RealizedGainOrLoss/withRealizedGainOrLoss.js
new file mode 100644
index 000000000..5f923884a
--- /dev/null
+++ b/src/containers/FinancialStatements/RealizedGainOrLoss/withRealizedGainOrLoss.js
@@ -0,0 +1,12 @@
+import { connect } from 'react-redux';
+import { getRealizedGainOrLossFilterDrawer } from '../../../store/financialStatement/financialStatements.selectors';
+
+export default (mapState) => {
+ const mapStateToProps = (state, props) => {
+ const mapped = {
+ realizedGainOrLossDrawerFilter: getRealizedGainOrLossFilterDrawer(state),
+ };
+ return mapState ? mapState(mapped, state, props) : mapped;
+ };
+ return connect(mapStateToProps);
+};
diff --git a/src/containers/FinancialStatements/RealizedGainOrLoss/withRealizedGainOrLossActions.js b/src/containers/FinancialStatements/RealizedGainOrLoss/withRealizedGainOrLossActions.js
new file mode 100644
index 000000000..95feefac5
--- /dev/null
+++ b/src/containers/FinancialStatements/RealizedGainOrLoss/withRealizedGainOrLossActions.js
@@ -0,0 +1,9 @@
+import { connect } from 'react-redux';
+import { toggleRealizedGainOrLossFilterDrawer } from '../../../store/financialStatement/financialStatements.actions';
+
+const mapDispatchToProps = (dispatch) => ({
+ toggleRealizedGainOrLossFilterDrawer: (toggle) =>
+ dispatch(toggleRealizedGainOrLossFilterDrawer(toggle)),
+});
+
+export default connect(null, mapDispatchToProps);
diff --git a/src/hooks/query/types.js b/src/hooks/query/types.js
index 663ea5679..2950f27c7 100644
--- a/src/hooks/query/types.js
+++ b/src/hooks/query/types.js
@@ -24,6 +24,7 @@ const FINANCIAL_REPORTS = {
CASH_FLOW_STATEMENT: 'CASH_FLOW_STATEMENT',
INVENTORY_ITEM_DETAILS: 'INVENTORY_ITEM_DETAILS',
TRANSACTIONS_BY_REFERENCE: 'TRANSACTIONS_BY_REFERENCE',
+ REALIZED_GAIN_OR_LOSS: 'REALIZED_GAIN_OR_LOSS',
};
const BILLS = {
@@ -195,11 +196,11 @@ const TARNSACTIONS_LOCKING = {
const WAREHOUSES = {
WAREHOUSE: 'WAREHOUSE',
WAREHOUSES: 'WAREHOUSES',
-}
+};
const WAREHOUSE_TRANSFERS = {
WAREHOUSE_TRANSFER: 'WAREHOUSE_TRANSFER',
WAREHOUSE_TRANSFERS: 'WAREHOUSE_TRANSFERS',
-}
+};
const BRANCHES = {
BRANCHES: 'BRANCHES',
BRANCH: 'BRANCH',
diff --git a/src/routes/dashboard.js b/src/routes/dashboard.js
index 8877b2396..866c6d30a 100644
--- a/src/routes/dashboard.js
+++ b/src/routes/dashboard.js
@@ -376,6 +376,20 @@ export const getDashboardRoutes = () => [
sidebarExpand: false,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
+ {
+ path: `/financial-reports/realized-gain-loss`,
+ component: lazy(() =>
+ import(
+ '../containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLoss'
+ ),
+ ),
+
+ breadcrumb: intl.get('realized_gain_or_loss.label'),
+ pageTitle: intl.get('realized_gain_or_loss.label'),
+ backLink: true,
+ sidebarExpand: false,
+ subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
+ },
{
path: '/financial-reports',
component: lazy(() =>
diff --git a/src/store/financialStatement/financialStatements.actions.js b/src/store/financialStatement/financialStatements.actions.js
index 0ef8f9a41..b1229fd9e 100644
--- a/src/store/financialStatement/financialStatements.actions.js
+++ b/src/store/financialStatement/financialStatements.actions.js
@@ -196,7 +196,7 @@ export function toggleCashFlowStatementFilterDrawer(toggle) {
* Toggles display of the inventory item details filter drawer.
* @param {boolean} toggle
*/
- export function toggleInventoryItemDetailsFilterDrawer(toggle) {
+export function toggleInventoryItemDetailsFilterDrawer(toggle) {
return {
type: `${t.INVENTORY_ITEM_DETAILS}/${t.DISPLAY_FILTER_DRAWER_TOGGLE}`,
payload: {
@@ -204,3 +204,16 @@ export function toggleCashFlowStatementFilterDrawer(toggle) {
},
};
}
+
+/**
+ * Toggle display of the Realized Gain or Loss filter drawer.
+ * @param {boolean} toggle
+ */
+export function toggleRealizedGainOrLossCilterDrawer(toggle) {
+ return {
+ type: `${t.REALIZED_GAIN_OR_LOSS}/${t.DISPLAY_FILTER_DRAWER_TOGGLE}`,
+ payload: {
+ toggle,
+ },
+ };
+}
diff --git a/src/store/financialStatement/financialStatements.reducer.js b/src/store/financialStatement/financialStatements.reducer.js
index 63fea46b2..9c6e0a1ff 100644
--- a/src/store/financialStatement/financialStatements.reducer.js
+++ b/src/store/financialStatement/financialStatements.reducer.js
@@ -51,6 +51,9 @@ const initialState = {
inventoryItemDetails: {
displayFilterDrawer: false,
},
+ realizedGainOrLoss: {
+ displayFilterDrawer: false,
+ },
};
/**
@@ -102,4 +105,6 @@ export default createReducer(initialState, {
t.INVENTORY_ITEM_DETAILS,
'inventoryItemDetails',
),
+ ...financialStatementFilterToggle(t.REALIZED_GAIN_OR_LOSS, 'realizedGainOrLoss'),
+
});
diff --git a/src/store/financialStatement/financialStatements.selectors.js b/src/store/financialStatement/financialStatements.selectors.js
index f19337fa2..83de44342 100644
--- a/src/store/financialStatement/financialStatements.selectors.js
+++ b/src/store/financialStatement/financialStatements.selectors.js
@@ -73,6 +73,10 @@ export const inventoryItemDetailsDrawerFilter = (state) => {
return filterDrawerByTypeSelector('inventoryItemDetails')(state);
};
+export const realizedGainOrLossFilterDrawerSelector = (state) => {
+ return filterDrawerByTypeSelector('realizedGainOrLoss')(state);
+};
+
/**
* Retrieve balance sheet filter drawer.
*/
@@ -239,3 +243,13 @@ export const getInventoryItemDetailsFilterDrawer = createSelector(
return isOpen;
},
);
+
+/**
+ * Retrieve Realized Gain or Loss filter drawer.
+ */
+export const getRealizedGainOrLossFilterDrawer = createSelector(
+ realizedGainOrLossFilterDrawerSelector,
+ (isOpen) => {
+ return isOpen;
+ },
+);
diff --git a/src/store/financialStatement/financialStatements.types.js b/src/store/financialStatement/financialStatements.types.js
index ef82d5b92..cdda1f369 100644
--- a/src/store/financialStatement/financialStatements.types.js
+++ b/src/store/financialStatement/financialStatements.types.js
@@ -16,4 +16,5 @@ export default {
VENDORS_TRANSACTIONS: 'VENDORS TRANSACTIONS',
CASH_FLOW_STATEMENT: 'CASH FLOW STATEMENT',
INVENTORY_ITEM_DETAILS: 'INVENTORY ITEM DETAILS',
+ REALIZED_GAIN_OR_LOSS: 'REALIZED GAIN OR LOSS',
};
From 39d0e9c198051854316404c0c161ac1285e973c5 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Thu, 3 Feb 2022 22:47:56 +0200
Subject: [PATCH 19/30] feat(UnrealizedGainorLoss): add Unrealized gain or
loss.
---
src/config/sidebarMenu.js | 4 +
.../UnrealizedGainOrLoss.js | 65 ++++++++++
.../UnrealizedGainOrLossActionsBar.js | 122 ++++++++++++++++++
.../UnrealizedGainOrLossGeneralPanel.js | 17 +++
.../UnrealizedGainOrLossHeader.js | 108 ++++++++++++++++
.../UnrealizedGainOrLossProvider.js | 22 ++++
.../UnrealizedGainOrLossTable.js | 21 +++
.../UnrealizedGainOrLoss/components.js | 18 +++
.../withUnrealizedGainOrLoss.js | 12 ++
.../withUnrealizedGainOrLossActions.js | 9 ++
src/hooks/query/types.js | 1 +
src/lang/en/index.json | 4 +-
src/routes/dashboard.js | 14 +-
.../financialStatements.actions.js | 15 ++-
.../financialStatements.reducer.js | 4 +
.../financialStatements.selectors.js | 13 ++
.../financialStatements.types.js | 1 +
17 files changed, 447 insertions(+), 3 deletions(-)
create mode 100644 src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLoss.js
create mode 100644 src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossActionsBar.js
create mode 100644 src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossGeneralPanel.js
create mode 100644 src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossHeader.js
create mode 100644 src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossProvider.js
create mode 100644 src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossTable.js
create mode 100644 src/containers/FinancialStatements/UnrealizedGainOrLoss/components.js
create mode 100644 src/containers/FinancialStatements/UnrealizedGainOrLoss/withUnrealizedGainOrLoss.js
create mode 100644 src/containers/FinancialStatements/UnrealizedGainOrLoss/withUnrealizedGainOrLossActions.js
diff --git a/src/config/sidebarMenu.js b/src/config/sidebarMenu.js
index bf82e5fe2..480fa72e8 100644
--- a/src/config/sidebarMenu.js
+++ b/src/config/sidebarMenu.js
@@ -645,6 +645,10 @@ export default [
text: ,
href: '/financial-reports/realized-gain-loss',
},
+ {
+ text: ,
+ href: '/financial-reports/unrealized-gain-loss',
+ },
{
text: ,
label: true,
diff --git a/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLoss.js b/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLoss.js
new file mode 100644
index 000000000..a8f20c4ed
--- /dev/null
+++ b/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLoss.js
@@ -0,0 +1,65 @@
+import React from 'react';
+
+import { FinancialStatement } from 'components';
+import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
+
+import UnrealizedGainOrLossHeader from './UnrealizedGainOrLossHeader';
+import UnrealizedGainOrLossTable from './UnrealizedGainOrLossTable';
+import UnrealizedGainOrLossActionsBar from './UnrealizedGainOrLossActionsBar';
+
+import withCurrentOrganization from '../../Organization/withCurrentOrganization';
+import withUnrealizedGainOrLossActions from './withUnrealizedGainOrLossActions';
+import { UnrealizedGainOrLossProvider } from './UnrealizedGainOrLossProvider';
+import { UnrealizedGainOrLossLoadingBar } from './components';
+
+import { compose } from 'utils';
+
+/**
+ * Unrealized Gain or Loss
+ */
+function UnrealizedGainOrLoss({
+ // #withPreferences
+ organizationName,
+
+ //#withUnrealizedGainOrLossActions
+ toggleUnrealizedGainOrLossFilterDrawer,
+}) {
+ // Handle refetch unrealized Gain or Loss after filter change.
+ const handleFilterSubmit = (filter) => {};
+
+ // Handle format number submit.
+ const handleNumberFormatSubmit = (values) => {};
+
+ React.useEffect(
+ () => () => {
+ toggleUnrealizedGainOrLossFilterDrawer(false);
+ },
+ [toggleUnrealizedGainOrLossFilterDrawer],
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default compose(
+ withCurrentOrganization(({ organization }) => ({
+ organizationName: organization.name,
+ })),
+ withUnrealizedGainOrLossActions,
+)(UnrealizedGainOrLoss);
diff --git a/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossActionsBar.js b/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossActionsBar.js
new file mode 100644
index 000000000..7e342ce3e
--- /dev/null
+++ b/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossActionsBar.js
@@ -0,0 +1,122 @@
+import React from 'react';
+import {
+ NavbarGroup,
+ NavbarDivider,
+ Button,
+ Classes,
+ Popover,
+ PopoverInteractionKind,
+ Position,
+} from '@blueprintjs/core';
+import { FormattedMessage as T, Icon } from 'components';
+import classNames from 'classnames';
+
+import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
+import NumberFormatDropdown from 'components/NumberFormatDropdown';
+
+import { useUnrealizedGainOrLossContext } from './UnrealizedGainOrLossProvider';
+import withUnrealizedGainOrLoss from './withUnrealizedGainOrLoss';
+import withUnrealizedGainOrLossActions from './withUnrealizedGainOrLossActions';
+
+import { compose, saveInvoke } from 'utils';
+
+/**
+ * unrealized Gain or Loss actions bar.
+ */
+function UnrealizedGainOrLossActionsBar({
+ //#withRealizedGainOrLoss
+ isFilterDrawerOpen,
+
+ //#withRealizedGainOrLossActions
+ toggleUnrealizedGainOrLossFilterDrawer,
+
+ //#ownProps
+ numberFormat,
+ onNumberFormatSubmit,
+}) {
+ // Handle filter toggle click.
+ const handleFilterToggleClick = () => {
+ toggleUnrealizedGainOrLossFilterDrawer();
+ };
+
+ // Handle recalculate report button.
+ const handleRecalculateReport = () => {};
+
+ // handle number format form submit.
+ const handleNumberFormatSubmit = (values) =>
+ saveInvoke(onNumberFormatSubmit, values);
+
+ return (
+
+
+ }
+ onClick={handleRecalculateReport}
+ icon={ }
+ />
+
+
+
+ }
+ text={
+ isFilterDrawerOpen ? (
+
+ ) : (
+
+ )
+ }
+ onClick={handleFilterToggleClick}
+ active={isFilterDrawerOpen}
+ />
+
+
+
+ }
+ minimal={true}
+ interactionKind={PopoverInteractionKind.CLICK}
+ position={Position.BOTTOM_LEFT}
+ >
+ }
+ icon={ }
+ />
+
+
+ }
+ icon={ }
+ />
+
+
+ }
+ text={ }
+ />
+ }
+ text={ }
+ />
+
+
+ );
+}
+
+export default compose(
+ withUnrealizedGainOrLoss(({ unrealizedGainOrLossDrawerFilter }) => ({
+ isFilterDrawerOpen: unrealizedGainOrLossDrawerFilter,
+ })),
+ withUnrealizedGainOrLossActions,
+)(UnrealizedGainOrLossActionsBar);
diff --git a/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossGeneralPanel.js b/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossGeneralPanel.js
new file mode 100644
index 000000000..7bb912da0
--- /dev/null
+++ b/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossGeneralPanel.js
@@ -0,0 +1,17 @@
+import React from 'react';
+
+import { Row, Col } from '../../../components';
+import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
+import SelectDisplayColumnsBy from '../SelectDisplayColumnsBy';
+
+/**
+ * Unrealized Gain or Loss header - General panel.
+ */
+export default function UnrealizedGainOrLossGeneralPanel() {
+ return (
+
+
+
+
+ );
+}
diff --git a/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossHeader.js b/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossHeader.js
new file mode 100644
index 000000000..a17bce086
--- /dev/null
+++ b/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossHeader.js
@@ -0,0 +1,108 @@
+import React from 'react';
+import moment from 'moment';
+import * as Yup from 'yup';
+import intl from 'react-intl-universal';
+import { Formik, Form } from 'formik';
+import { Tabs, Tab, Button, Intent } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'components';
+
+import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
+import UnrealizedGainOrLossGeneralPanel from './UnrealizedGainOrLossGeneralPanel';
+
+import withUnrealizedGainOrLoss from './withUnrealizedGainOrLoss';
+import withUnrealizedGainOrLossActions from './withUnrealizedGainOrLossActions';
+
+import { compose, transformToForm } from 'utils';
+
+/**
+ * Unrealized Gain or Loss.header.
+ */
+function UnrealizedGainOrLossHeader({
+ // #ownProps
+ onSubmitFilter,
+ pageFilter,
+
+ //#withUnrealizedGainOrLoss
+ isFilterDrawerOpen,
+
+ //#withUnrealizedGainOrLossActions
+ toggleUnrealizedGainOrLossFilterDrawer,
+}) {
+ // Filter form default values.
+ const defaultValues = {
+ fromDate: moment().toDate(),
+ toDate: moment().toDate(),
+ };
+
+ // Initial form values.
+ const initialValues = transformToForm(
+ {
+ ...pageFilter,
+ fromDate: moment(pageFilter.fromDate).toDate(),
+ toDate: moment(pageFilter.toDate).toDate(),
+ },
+ defaultValues,
+ );
+
+ // Validation schema.
+ const validationSchema = Yup.object().shape({
+ dateRange: Yup.string().optional(),
+ fromDate: Yup.date().required().label(intl.get('fromDate')),
+ toDate: Yup.date()
+ .min(Yup.ref('fromDate'))
+ .required()
+ .label(intl.get('toDate')),
+ displayColumnsType: Yup.string(),
+ });
+
+ // Handle form submit.
+ const handleSubmit = (values, { setSubmitting }) => {
+ onSubmitFilter(values);
+ toggleUnrealizedGainOrLossFilterDrawer(false);
+ setSubmitting(false);
+ };
+
+ // Handle drawer close action.
+ const handleDrawerClose = () => {
+ toggleUnrealizedGainOrLossFilterDrawer(false);
+ };
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default compose(
+ withUnrealizedGainOrLoss(({ unrealizedGainOrLossDrawerFilter }) => ({
+ isFilterDrawerOpen: unrealizedGainOrLossDrawerFilter,
+ })),
+ withUnrealizedGainOrLossActions,
+)(UnrealizedGainOrLossHeader);
diff --git a/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossProvider.js b/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossProvider.js
new file mode 100644
index 000000000..a9400489a
--- /dev/null
+++ b/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossProvider.js
@@ -0,0 +1,22 @@
+import React from 'react';
+
+import FinancialReportPage from '../FinancialReportPage';
+
+const UnrealizedGainOrLossContext = React.createContext();
+
+/**
+ * Unrealized Gain or Loss provider.
+ */
+function UnrealizedGainOrLossProvider({ filter, ...props }) {
+ const provider = {};
+ return (
+
+
+
+ );
+}
+
+const useUnrealizedGainOrLossContext = () =>
+ React.useContext(UnrealizedGainOrLossContext);
+
+export { UnrealizedGainOrLossProvider, useUnrealizedGainOrLossContext };
diff --git a/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossTable.js b/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossTable.js
new file mode 100644
index 000000000..a5a99558c
--- /dev/null
+++ b/src/containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLossTable.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+
+import { DataTable } from 'components';
+import FinancialSheet from 'components/FinancialSheet';
+
+/**
+ * Unrealized Gain or Loss table.
+ */
+export default function UnrealizedGainOrLossTable({
+ // #ownProps
+ companyName,
+}) {
+ return (
+
+ );
+}
diff --git a/src/containers/FinancialStatements/UnrealizedGainOrLoss/components.js b/src/containers/FinancialStatements/UnrealizedGainOrLoss/components.js
new file mode 100644
index 000000000..25d754b58
--- /dev/null
+++ b/src/containers/FinancialStatements/UnrealizedGainOrLoss/components.js
@@ -0,0 +1,18 @@
+import React from 'react';
+import { Button } from '@blueprintjs/core';
+import { Icon, If } from 'components';
+import { FormattedMessage as T } from 'components';
+
+import { useUnrealizedGainOrLossContext } from './UnrealizedGainOrLossProvider';
+import FinancialLoadingBar from '../FinancialLoadingBar';
+
+/**
+ * Unrealized Gain or Loss loading bar.
+ */
+export function UnrealizedGainOrLossLoadingBar() {
+ return (
+
+
+
+ );
+}
diff --git a/src/containers/FinancialStatements/UnrealizedGainOrLoss/withUnrealizedGainOrLoss.js b/src/containers/FinancialStatements/UnrealizedGainOrLoss/withUnrealizedGainOrLoss.js
new file mode 100644
index 000000000..4017486dd
--- /dev/null
+++ b/src/containers/FinancialStatements/UnrealizedGainOrLoss/withUnrealizedGainOrLoss.js
@@ -0,0 +1,12 @@
+import { connect } from 'react-redux';
+import { getUnrealizedGainOrLossFilterDrawer } from '../../../store/financialStatement/financialStatements.selectors';
+
+export default (mapState) => {
+ const mapStateToProps = (state, props) => {
+ const mapped = {
+ unrealizedGainOrLossDrawerFilter: getUnrealizedGainOrLossFilterDrawer(state),
+ };
+ return mapState ? mapState(mapped, state, props) : mapped;
+ };
+ return connect(mapStateToProps);
+};
diff --git a/src/containers/FinancialStatements/UnrealizedGainOrLoss/withUnrealizedGainOrLossActions.js b/src/containers/FinancialStatements/UnrealizedGainOrLoss/withUnrealizedGainOrLossActions.js
new file mode 100644
index 000000000..4c51a85dc
--- /dev/null
+++ b/src/containers/FinancialStatements/UnrealizedGainOrLoss/withUnrealizedGainOrLossActions.js
@@ -0,0 +1,9 @@
+import { connect } from 'react-redux';
+import { toggleUnrealizedGainOrLossFilterDrawer } from '../../../store/financialStatement/financialStatements.actions';
+
+const mapDispatchToProps = (dispatch) => ({
+ toggleUnrealizedGainOrLossFilterDrawer: (toggle) =>
+ dispatch(toggleUnrealizedGainOrLossFilterDrawer(toggle)),
+});
+
+export default connect(null, mapDispatchToProps);
diff --git a/src/hooks/query/types.js b/src/hooks/query/types.js
index 2950f27c7..f4c10d1e4 100644
--- a/src/hooks/query/types.js
+++ b/src/hooks/query/types.js
@@ -25,6 +25,7 @@ const FINANCIAL_REPORTS = {
INVENTORY_ITEM_DETAILS: 'INVENTORY_ITEM_DETAILS',
TRANSACTIONS_BY_REFERENCE: 'TRANSACTIONS_BY_REFERENCE',
REALIZED_GAIN_OR_LOSS: 'REALIZED_GAIN_OR_LOSS',
+ UNREALIZED_GAIN_OR_LOSS: 'UNREALIZED_GAIN_OR_LOSS',
};
const BILLS = {
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index b5d16acc1..25e10793f 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -1824,5 +1824,7 @@
"branch.dialog.label.website": "Website",
"branch.dialog.success_message": "The branch has been created successfully.",
"branch.alert.delete_message":"The branch has been deleted successfully",
- "branch.once_delete_this_branch":"Once you delete this branch, you won't be able to restore it later. Are you sure you want to delete this branch?"
+ "branch.once_delete_this_branch":"Once you delete this branch, you won't be able to restore it later. Are you sure you want to delete this branch?",
+ "realized_gain_or_loss.label":"Realized Gain or Loss",
+ "unrealized_gain_or_loss.label":"Unrealized Gain or Loss"
}
\ No newline at end of file
diff --git a/src/routes/dashboard.js b/src/routes/dashboard.js
index 866c6d30a..b68457202 100644
--- a/src/routes/dashboard.js
+++ b/src/routes/dashboard.js
@@ -383,13 +383,25 @@ export const getDashboardRoutes = () => [
'../containers/FinancialStatements/RealizedGainOrLoss/RealizedGainOrLoss'
),
),
-
breadcrumb: intl.get('realized_gain_or_loss.label'),
pageTitle: intl.get('realized_gain_or_loss.label'),
backLink: true,
sidebarExpand: false,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
+ {
+ path: `/financial-reports/unrealized-gain-loss`,
+ component: lazy(() =>
+ import(
+ '../containers/FinancialStatements/UnrealizedGainOrLoss/UnrealizedGainOrLoss'
+ ),
+ ),
+ breadcrumb: intl.get('unrealized_gain_or_loss.label'),
+ pageTitle: intl.get('unrealized_gain_or_loss.label'),
+ backLink: true,
+ sidebarExpand: false,
+ subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
+ },
{
path: '/financial-reports',
component: lazy(() =>
diff --git a/src/store/financialStatement/financialStatements.actions.js b/src/store/financialStatement/financialStatements.actions.js
index b1229fd9e..7e6abef03 100644
--- a/src/store/financialStatement/financialStatements.actions.js
+++ b/src/store/financialStatement/financialStatements.actions.js
@@ -209,7 +209,7 @@ export function toggleInventoryItemDetailsFilterDrawer(toggle) {
* Toggle display of the Realized Gain or Loss filter drawer.
* @param {boolean} toggle
*/
-export function toggleRealizedGainOrLossCilterDrawer(toggle) {
+export function toggleRealizedGainOrLossFilterDrawer(toggle) {
return {
type: `${t.REALIZED_GAIN_OR_LOSS}/${t.DISPLAY_FILTER_DRAWER_TOGGLE}`,
payload: {
@@ -217,3 +217,16 @@ export function toggleRealizedGainOrLossCilterDrawer(toggle) {
},
};
}
+
+/**
+ * Toggle display of the Unrealized Gain or Loss filter drawer.
+ * @param {boolean} toggle
+ */
+export function toggleUnrealizedGainOrLossFilterDrawer(toggle) {
+ return {
+ type: `${t.UNREALIZED_GAIN_OR_LOSS}/${t.DISPLAY_FILTER_DRAWER_TOGGLE}`,
+ payload: {
+ toggle,
+ },
+ };
+}
diff --git a/src/store/financialStatement/financialStatements.reducer.js b/src/store/financialStatement/financialStatements.reducer.js
index 9c6e0a1ff..8f206db6c 100644
--- a/src/store/financialStatement/financialStatements.reducer.js
+++ b/src/store/financialStatement/financialStatements.reducer.js
@@ -54,6 +54,9 @@ const initialState = {
realizedGainOrLoss: {
displayFilterDrawer: false,
},
+ unrealizedGainOrLoss: {
+ displayFilterDrawer: false,
+ },
};
/**
@@ -106,5 +109,6 @@ export default createReducer(initialState, {
'inventoryItemDetails',
),
...financialStatementFilterToggle(t.REALIZED_GAIN_OR_LOSS, 'realizedGainOrLoss'),
+ ...financialStatementFilterToggle(t.UNREALIZED_GAIN_OR_LOSS, 'unrealizedGainOrLoss'),
});
diff --git a/src/store/financialStatement/financialStatements.selectors.js b/src/store/financialStatement/financialStatements.selectors.js
index 83de44342..a554ebb37 100644
--- a/src/store/financialStatement/financialStatements.selectors.js
+++ b/src/store/financialStatement/financialStatements.selectors.js
@@ -77,6 +77,10 @@ export const realizedGainOrLossFilterDrawerSelector = (state) => {
return filterDrawerByTypeSelector('realizedGainOrLoss')(state);
};
+export const unrealizedGainOrLossFilterDrawerSelector = (state) => {
+ return filterDrawerByTypeSelector('unrealizedGainOrLoss')(state);
+};
+
/**
* Retrieve balance sheet filter drawer.
*/
@@ -253,3 +257,12 @@ export const getRealizedGainOrLossFilterDrawer = createSelector(
return isOpen;
},
);
+/**
+ * Retrieve Unrealized Gain or Loss filter drawer.
+ */
+export const getUnrealizedGainOrLossFilterDrawer = createSelector(
+ unrealizedGainOrLossFilterDrawerSelector,
+ (isOpen) => {
+ return isOpen;
+ },
+);
diff --git a/src/store/financialStatement/financialStatements.types.js b/src/store/financialStatement/financialStatements.types.js
index cdda1f369..98d37a1d5 100644
--- a/src/store/financialStatement/financialStatements.types.js
+++ b/src/store/financialStatement/financialStatements.types.js
@@ -17,4 +17,5 @@ export default {
CASH_FLOW_STATEMENT: 'CASH FLOW STATEMENT',
INVENTORY_ITEM_DETAILS: 'INVENTORY ITEM DETAILS',
REALIZED_GAIN_OR_LOSS: 'REALIZED GAIN OR LOSS',
+ UNREALIZED_GAIN_OR_LOSS: 'UNREALIZED GAIN OR LOSS',
};
From a368e5572b371d0fb63a0c7eac9b47cfefc38a2a Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Sun, 6 Feb 2022 09:58:38 +0200
Subject: [PATCH 20/30] Revert "feat(warehouse) add warehouse propover."
This reverts commit 2aa26959e924af32a49bb943f2e5877dfede0ae9.
---
.../DataTableCells/NumericInputCell.js | 4 +-
.../DataTableCells/RadioFieldCell.js | 44 -----------
src/components/DataTableCells/index.js | 2 -
.../WarehouseListPopover/WarehousesList.js | 75 -------------------
.../WarehouseListPopover/components.js | 38 ----------
src/containers/WarehouseListPopover/index.js | 36 ---------
6 files changed, 1 insertion(+), 198 deletions(-)
delete mode 100644 src/components/DataTableCells/RadioFieldCell.js
delete mode 100644 src/containers/WarehouseListPopover/WarehousesList.js
delete mode 100644 src/containers/WarehouseListPopover/components.js
delete mode 100644 src/containers/WarehouseListPopover/index.js
diff --git a/src/components/DataTableCells/NumericInputCell.js b/src/components/DataTableCells/NumericInputCell.js
index 5e6c5d245..eaf933fb8 100644
--- a/src/components/DataTableCells/NumericInputCell.js
+++ b/src/components/DataTableCells/NumericInputCell.js
@@ -2,7 +2,6 @@ import React, { useState, useEffect } from 'react';
import { FormGroup, NumericInput, Intent } from '@blueprintjs/core';
import classNames from 'classnames';
import { CLASSES } from 'common/classes';
-import WarehouseListPopover from '../../containers/WarehouseListPopover';
/**
* Numeric input table cell.
@@ -37,8 +36,7 @@ export default function NumericInputCell({
onValueChange={handleValueChange}
onBlur={onBlur}
fill={true}
- buttonPosition={'none'}
- rightElement={ }
+ buttonPosition={"none"}
/>
);
diff --git a/src/components/DataTableCells/RadioFieldCell.js b/src/components/DataTableCells/RadioFieldCell.js
deleted file mode 100644
index 7471fb56c..000000000
--- a/src/components/DataTableCells/RadioFieldCell.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import React from 'react';
-import classNames from 'classnames';
-import { FormGroup, Intent, Classes, Radio } from '@blueprintjs/core';
-
-const RadioEditableCell = ({
- row: { index, original },
- column: { id, radioProps },
- cell: { value: initialValue },
- payload,
-}) => {
- const [value, setValue] = React.useState(initialValue);
-
- const onChange = (e) => {
- const newValue = e.target.checked;
- debugger;
- setValue(newValue);
- payload.updateData(index, id, newValue);
- };
-
- React.useEffect(() => {
- setValue(initialValue);
- }, [initialValue]);
-
- const error = payload.errors?.[index]?.[id];
-
- return (
-
-
-
- );
-};
-
-export default RadioEditableCell;
diff --git a/src/components/DataTableCells/index.js b/src/components/DataTableCells/index.js
index 4e0a42835..fed349eed 100644
--- a/src/components/DataTableCells/index.js
+++ b/src/components/DataTableCells/index.js
@@ -9,7 +9,6 @@ import NumericInputCell from './NumericInputCell';
import CheckBoxFieldCell from './CheckBoxFieldCell';
import SwitchFieldCell from './SwitchFieldCell';
import TextAreaCell from './TextAreaCell';
-import RadioFieldCell from './RadioFieldCell';
export {
AccountsListFieldCell,
@@ -24,5 +23,4 @@ export {
CheckBoxFieldCell,
SwitchFieldCell,
TextAreaCell,
- RadioFieldCell,
};
diff --git a/src/containers/WarehouseListPopover/WarehousesList.js b/src/containers/WarehouseListPopover/WarehousesList.js
deleted file mode 100644
index 15c85743c..000000000
--- a/src/containers/WarehouseListPopover/WarehousesList.js
+++ /dev/null
@@ -1,75 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-
-import { CLASSES } from 'common/classes';
-import { TableStyle } from '../../common';
-import { DataTableEditable, DataTable } from 'components';
-import { compose, saveInvoke, updateTableCell } from 'utils';
-import { useWarehouseEntriesColumns } from './components';
-
-export default function IntegrateWarehousesTable({
- // #ownProps
- initialWarehouse,
- selectedWarehouseId,
- onUpdateData,
- entries,
- errors,
-}) {
- const [rows, setRows] = React.useState(initialWarehouse);
-
- // warehouses entries columns.
- const columns = useWarehouseEntriesColumns();
-
- // Handle update data.
- const handleUpdateData = React.useCallback(
- (rowIndex, columnId, value) => {
- const newRows = compose(updateTableCell(rowIndex, columnId, value))(
- entries,
- );
- onUpdateData(newRows);
- },
- [onUpdateData, entries],
- );
-
- const DATA = [
- {
- warehouse_name: true,
- quantity: '9,444',
- availiable_for_sale: 0,
- },
- {
- warehouse_name: false,
- quantity: '19,444',
- availiable_for_sale: 0,
- },
- ];
-
- return (
-
- );
-}
-
-const WarehouseDataTableRoot = styled(DataTable)`
- width: 600px;
-
- .table {
- border: 1px solid #000000;
- .thead .th {
- background: transparent;
- color: #222222;
- border-bottom: 1px solid #000000;
- padding: 0.5rem;
- }
- .tbody .tr .td {
- padding: 0.2rem 0.2rem;
- border-bottom: 1px solid #cecbcb;
- }
- }
-`;
diff --git a/src/containers/WarehouseListPopover/components.js b/src/containers/WarehouseListPopover/components.js
deleted file mode 100644
index 1429a87e6..000000000
--- a/src/containers/WarehouseListPopover/components.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from 'react';
-
-import { RadioFieldCell } from 'components/DataTableCells';
-
-/**
- * Retrieve warehouse entries columns.
- */
-export function useWarehouseEntriesColumns() {
- return React.useMemo(
- () => [
- {
- Header: 'Warehouse Name',
- accessor: 'warehouse_name',
- Cell: RadioFieldCell,
- width: 120,
- disableSortBy: true,
- className: 'name',
- },
- {
- id: 'quantity',
- Header: 'Quantity on Hand',
- accessor: 'quantity',
- disableSortBy: true,
- align: 'right',
- width: '100',
- },
- {
- id: 'availiable_for_sale',
- Header: 'Availiable for Sale',
- accessor: 'availiable_for_sale',
- disableSortBy: true,
- align: 'right',
- width: '100',
- },
- ],
- [],
- );
-}
diff --git a/src/containers/WarehouseListPopover/index.js b/src/containers/WarehouseListPopover/index.js
deleted file mode 100644
index d2026f8ec..000000000
--- a/src/containers/WarehouseListPopover/index.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import { PopoverInteractionKind, Position, Button } from '@blueprintjs/core';
-import { Popover2 } from '@blueprintjs/popover2';
-import WarehousesList from './WarehousesList';
-import { Icon, FormattedMessage as T, ButtonLink } from 'components';
-
-export default function IntegrateWarehouseTable() {
- return (
- }
- interactionKind={PopoverInteractionKind.CLICK}
- position={Position.BOTTOM_LEFT}
- modifiers={{
- offset: { offset: '0, 4' },
- }}
- >
- →
-
- );
-}
-
-const PopoverLink = styled.button`
- border: 0;
- cursor: pointer;
- background: transparent;
- margin-top: 18px;
- padding-right: 0px;
- color: #0052cc;
-
- &:hover,
- &:active {
- text-decoration: underline;
- }
-`;
From fe3314b5cb014cd02ff48411b8e67d3df458c5c7 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Mon, 7 Feb 2022 13:16:46 +0200
Subject: [PATCH 21/30] feat(invoice): add branch & warehouse.
---
src/components/CustomSelectList.js | 103 +++++++
src/components/index.js | 2 +
.../Invoices/InvoiceForm/BaseCurrency.js | 34 +++
.../Sales/Invoices/InvoiceForm/FlagKit.js | 20 ++
.../Sales/Invoices/InvoiceForm/InvoiceForm.js | 2 +
.../InvoiceForm/InvoiceFormHeaderFields.js | 275 ++++++++++++------
.../InvoiceForm/InvoiceFormProvider.js | 12 +
.../Invoices/InvoiceForm/InvoiceFormTopBar.js | 55 ++++
src/static/json/icons.js | 12 +
src/static/svg/AD.svg | 35 +++
src/static/svg/AE.svg | 33 +++
src/static/svg/AF.svg | 34 +++
src/static/svg/AG.svg | 44 +++
src/static/svg/AI.svg | 50 ++++
src/static/svg/AL.svg | 27 ++
src/static/svg/AM.svg | 32 ++
src/static/svg/AO.svg | 37 +++
src/static/svg/AR.svg | 26 ++
src/static/svg/AS.svg | 36 +++
src/static/svg/AT.svg | 24 ++
src/static/svg/AU.svg | 36 +++
src/static/svg/AW.svg | 30 ++
src/static/svg/AX.svg | 32 ++
src/static/svg/AZ.svg | 33 +++
src/static/svg/BA.svg | 32 ++
src/static/svg/BB.svg | 38 +++
src/static/svg/BD.svg | 27 ++
src/static/svg/BE.svg | 32 ++
src/static/svg/BF.svg | 28 ++
src/static/svg/BG.svg | 28 ++
src/static/svg/BH.svg | 23 ++
src/static/svg/BI.svg | 36 +++
src/static/svg/BJ.svg | 32 ++
src/static/svg/BL.svg | 42 +++
src/static/svg/BM.svg | 49 ++++
src/static/svg/BN.svg | 28 ++
src/static/svg/BO.svg | 32 ++
src/static/svg/BR.svg | 35 +++
src/static/svg/BS.svg | 33 +++
src/static/svg/BT.svg | 27 ++
src/static/svg/BV.svg | 28 ++
src/static/svg/BW.svg | 29 ++
src/static/svg/BY.svg | 30 ++
src/static/svg/BZ.svg | 30 ++
src/static/svg/CA.svg | 25 ++
src/static/svg/CC.svg | 33 +++
src/static/svg/CD.svg | 31 ++
src/static/svg/CF.svg | 43 +++
src/static/svg/CG.svg | 34 +++
src/static/svg/CH.svg | 23 ++
src/static/svg/CI.svg | 28 ++
src/static/svg/CK.svg | 31 ++
src/static/svg/CL.svg | 29 ++
src/static/svg/CM.svg | 38 +++
src/static/svg/CN.svg | 32 ++
src/static/svg/CO.svg | 32 ++
src/static/svg/CR.svg | 29 ++
src/static/svg/CU.svg | 32 ++
src/static/svg/CV.svg | 30 ++
src/static/svg/CW.svg | 29 ++
src/static/svg/CX.svg | 38 +++
src/static/svg/CY.svg | 24 ++
src/static/svg/CZ.svg | 28 ++
src/static/svg/DE.svg | 32 ++
src/static/svg/DJ.svg | 33 +++
src/static/svg/DK.svg | 23 ++
src/static/svg/DM.svg | 41 +++
src/static/svg/DO.svg | 33 +++
src/static/svg/DZ.svg | 29 ++
src/static/svg/EC.svg | 39 +++
src/static/svg/EE.svg | 28 ++
src/static/svg/EG.svg | 30 ++
src/static/svg/ER.svg | 40 +++
src/static/svg/ES.svg | 34 +++
src/static/svg/ET.svg | 42 +++
src/static/svg/EU.svg | 27 ++
src/static/svg/FI.svg | 22 ++
src/static/svg/FJ.svg | 51 ++++
src/static/svg/FK.svg | 58 ++++
src/static/svg/FM.svg | 23 ++
src/static/svg/FO.svg | 27 ++
src/static/svg/FR.svg | 28 ++
src/static/svg/GA.svg | 32 ++
src/static/svg/GB-ENG.svg | 22 ++
src/static/svg/GB-NIR.svg | 41 +++
src/static/svg/GB-SCT.svg | 23 ++
src/static/svg/GB-WLS.svg | 28 ++
src/static/svg/GB-ZET.svg | 23 ++
src/static/svg/GB.svg | 32 ++
src/static/svg/GD.svg | 49 ++++
src/static/svg/GE.svg | 26 ++
src/static/svg/GF.svg | 32 ++
src/static/svg/GG.svg | 27 ++
src/static/svg/GH.svg | 37 +++
src/static/svg/GI.svg | 38 +++
src/static/svg/GL.svg | 33 +++
src/static/svg/GM.svg | 33 +++
src/static/svg/GN.svg | 32 ++
src/static/svg/GP.svg | 40 +++
src/static/svg/GQ.svg | 34 +++
src/static/svg/GR.svg | 22 ++
src/static/svg/GS.svg | 112 +++++++
src/static/svg/GT.svg | 26 ++
src/static/svg/GU.svg | 65 +++++
src/static/svg/GW.svg | 37 +++
src/static/svg/GY.svg | 42 +++
src/static/svg/HK.svg | 23 ++
src/static/svg/HM.svg | 36 +++
src/static/svg/HN.svg | 33 +++
src/static/svg/HR.svg | 35 +++
src/static/svg/HT.svg | 46 +++
src/static/svg/HU.svg | 28 ++
src/static/svg/ID.svg | 23 ++
src/static/svg/IE.svg | 28 ++
src/static/svg/IL.svg | 26 ++
src/static/svg/IM.svg | 30 ++
src/static/svg/IN.svg | 31 ++
src/static/svg/IO.svg | 33 +++
src/static/svg/IQ.svg | 33 +++
src/static/svg/IR.svg | 31 ++
src/static/svg/IS.svg | 28 ++
src/static/svg/IT.svg | 28 ++
src/static/svg/JE.svg | 32 ++
src/static/svg/JM.svg | 33 +++
src/static/svg/JO.svg | 34 +++
src/static/svg/JP.svg | 22 ++
src/static/svg/KE.svg | 43 +++
src/static/svg/KG.svg | 28 ++
src/static/svg/KH.svg | 29 ++
src/static/svg/KI.svg | 35 +++
src/static/svg/KM.svg | 39 +++
src/static/svg/KN.svg | 39 +++
src/static/svg/KP.svg | 30 ++
src/static/svg/KR.svg | 38 +++
src/static/svg/KW.svg | 33 +++
src/static/svg/KY.svg | 44 +++
src/static/svg/KZ.svg | 29 ++
src/static/svg/LA.svg | 29 ++
src/static/svg/LB.svg | 29 ++
src/static/svg/LC.svg | 33 +++
src/static/svg/LGBT.svg | 42 +++
src/static/svg/LI.svg | 27 ++
src/static/svg/LK.svg | 43 +++
src/static/svg/LR.svg | 36 +++
src/static/svg/LS.svg | 34 +++
src/static/svg/LT.svg | 32 ++
src/static/svg/LU.svg | 28 ++
src/static/svg/LV.svg | 24 ++
src/static/svg/LY.svg | 33 +++
src/static/svg/MA.svg | 23 ++
src/static/svg/MC.svg | 23 ++
src/static/svg/MD.svg | 42 +++
src/static/svg/ME.svg | 29 ++
src/static/svg/MF.svg | 28 ++
src/static/svg/MG.svg | 28 ++
src/static/svg/MH.svg | 29 ++
src/static/svg/MK.svg | 29 ++
src/static/svg/ML.svg | 32 ++
src/static/svg/MM.svg | 33 +++
src/static/svg/MN.svg | 33 +++
src/static/svg/MO.svg | 26 ++
src/static/svg/MP.svg | 29 ++
src/static/svg/MQ.svg | 27 ++
src/static/svg/MR.svg | 27 ++
src/static/svg/MS.svg | 47 +++
src/static/svg/MT.svg | 29 ++
src/static/svg/MU.svg | 37 +++
src/static/svg/MV.svg | 28 ++
src/static/svg/MW.svg | 33 +++
src/static/svg/MX.svg | 30 ++
src/static/svg/MY.svg | 32 ++
src/static/svg/MZ.svg | 43 +++
src/static/svg/NA.svg | 75 +++++
src/static/svg/NC.svg | 42 +++
src/static/svg/NE.svg | 33 +++
src/static/svg/NF.svg | 29 ++
src/static/svg/NG.svg | 24 ++
src/static/svg/NI.svg | 26 ++
src/static/svg/NL.svg | 28 ++
src/static/svg/NO.svg | 28 ++
src/static/svg/NP.svg | 35 +++
src/static/svg/NR.svg | 28 ++
src/static/svg/NU.svg | 41 +++
src/static/svg/NZ.svg | 34 +++
src/static/svg/OM.svg | 29 ++
src/static/svg/PA.svg | 30 ++
src/static/svg/PE.svg | 24 ++
src/static/svg/PF.svg | 52 ++++
src/static/svg/PG.svg | 36 +++
src/static/svg/PH.svg | 33 +++
src/static/svg/PK.svg | 32 ++
src/static/svg/PL.svg | 23 ++
src/static/svg/PM.svg | 66 +++++
src/static/svg/PN.svg | 51 ++++
src/static/svg/PR.svg | 30 ++
src/static/svg/PS.svg | 33 +++
src/static/svg/PT.svg | 38 +++
src/static/svg/PW.svg | 27 ++
src/static/svg/PY.svg | 30 ++
src/static/svg/QA.svg | 23 ++
src/static/svg/RE.svg | 28 ++
src/static/svg/RO.svg | 32 ++
src/static/svg/RS.svg | 39 +++
src/static/svg/RU.svg | 28 ++
src/static/svg/RW.svg | 37 +++
src/static/svg/SA.svg | 26 ++
src/static/svg/SB.svg | 39 +++
src/static/svg/SC.svg | 43 +++
src/static/svg/SD.svg | 33 +++
src/static/svg/SE.svg | 27 ++
src/static/svg/SG.svg | 24 ++
src/static/svg/SH.svg | 53 ++++
src/static/svg/SI.svg | 28 ++
src/static/svg/SJ.svg | 28 ++
src/static/svg/SK.svg | 46 +++
src/static/svg/SL.svg | 28 ++
src/static/svg/SM.svg | 25 ++
src/static/svg/SN.svg | 33 +++
src/static/svg/SO.svg | 23 ++
src/static/svg/SR.svg | 34 +++
src/static/svg/SS.svg | 44 +++
src/static/svg/ST.svg | 39 +++
src/static/svg/SV.svg | 30 ++
src/static/svg/SX.svg | 45 +++
src/static/svg/SY.svg | 34 +++
src/static/svg/SZ.svg | 47 +++
src/static/svg/TC.svg | 40 +++
src/static/svg/TD.svg | 32 ++
src/static/svg/TF.svg | 35 +++
src/static/svg/TG.svg | 33 +++
src/static/svg/TH.svg | 29 ++
src/static/svg/TJ.svg | 29 ++
src/static/svg/TK.svg | 31 ++
src/static/svg/TL.svg | 33 +++
src/static/svg/TM.svg | 74 +++++
src/static/svg/TN.svg | 23 ++
src/static/svg/TO.svg | 28 ++
src/static/svg/TR.svg | 23 ++
src/static/svg/TT.svg | 28 ++
src/static/svg/TV.svg | 36 +++
src/static/svg/TW.svg | 28 ++
src/static/svg/TZ.svg | 37 +++
src/static/svg/UA.svg | 27 ++
src/static/svg/UG.svg | 37 +++
src/static/svg/UM.svg | 28 ++
src/static/svg/US-CA.svg | 33 +++
src/static/svg/US.svg | 28 ++
src/static/svg/UY.svg | 29 ++
src/static/svg/UZ.svg | 29 ++
src/static/svg/VA.svg | 39 +++
src/static/svg/VC.svg | 37 +++
src/static/svg/VE.svg | 33 +++
src/static/svg/VG.svg | 42 +++
src/static/svg/VI.svg | 49 ++++
src/static/svg/VN.svg | 27 ++
src/static/svg/VU.svg | 38 +++
src/static/svg/WF.svg | 28 ++
src/static/svg/WS.svg | 28 ++
src/static/svg/XK.svg | 28 ++
src/static/svg/YE.svg | 28 ++
src/static/svg/YT.svg | 77 +++++
src/static/svg/ZA.svg | 44 +++
src/static/svg/ZM.svg | 42 +++
src/static/svg/ZW.svg | 43 +++
src/style/pages/Dashboard/Dashboard.scss | 36 ++-
src/style/pages/SaleInvoice/PageForm.scss | 22 ++
266 files changed, 9061 insertions(+), 88 deletions(-)
create mode 100644 src/components/CustomSelectList.js
create mode 100644 src/containers/Sales/Invoices/InvoiceForm/BaseCurrency.js
create mode 100644 src/containers/Sales/Invoices/InvoiceForm/FlagKit.js
create mode 100644 src/containers/Sales/Invoices/InvoiceForm/InvoiceFormTopBar.js
create mode 100644 src/static/svg/AD.svg
create mode 100644 src/static/svg/AE.svg
create mode 100644 src/static/svg/AF.svg
create mode 100644 src/static/svg/AG.svg
create mode 100644 src/static/svg/AI.svg
create mode 100644 src/static/svg/AL.svg
create mode 100644 src/static/svg/AM.svg
create mode 100644 src/static/svg/AO.svg
create mode 100644 src/static/svg/AR.svg
create mode 100644 src/static/svg/AS.svg
create mode 100644 src/static/svg/AT.svg
create mode 100644 src/static/svg/AU.svg
create mode 100644 src/static/svg/AW.svg
create mode 100644 src/static/svg/AX.svg
create mode 100644 src/static/svg/AZ.svg
create mode 100644 src/static/svg/BA.svg
create mode 100644 src/static/svg/BB.svg
create mode 100644 src/static/svg/BD.svg
create mode 100644 src/static/svg/BE.svg
create mode 100644 src/static/svg/BF.svg
create mode 100644 src/static/svg/BG.svg
create mode 100644 src/static/svg/BH.svg
create mode 100644 src/static/svg/BI.svg
create mode 100644 src/static/svg/BJ.svg
create mode 100644 src/static/svg/BL.svg
create mode 100644 src/static/svg/BM.svg
create mode 100644 src/static/svg/BN.svg
create mode 100644 src/static/svg/BO.svg
create mode 100644 src/static/svg/BR.svg
create mode 100644 src/static/svg/BS.svg
create mode 100644 src/static/svg/BT.svg
create mode 100644 src/static/svg/BV.svg
create mode 100644 src/static/svg/BW.svg
create mode 100644 src/static/svg/BY.svg
create mode 100644 src/static/svg/BZ.svg
create mode 100644 src/static/svg/CA.svg
create mode 100644 src/static/svg/CC.svg
create mode 100644 src/static/svg/CD.svg
create mode 100644 src/static/svg/CF.svg
create mode 100644 src/static/svg/CG.svg
create mode 100644 src/static/svg/CH.svg
create mode 100644 src/static/svg/CI.svg
create mode 100644 src/static/svg/CK.svg
create mode 100644 src/static/svg/CL.svg
create mode 100644 src/static/svg/CM.svg
create mode 100644 src/static/svg/CN.svg
create mode 100644 src/static/svg/CO.svg
create mode 100644 src/static/svg/CR.svg
create mode 100644 src/static/svg/CU.svg
create mode 100644 src/static/svg/CV.svg
create mode 100644 src/static/svg/CW.svg
create mode 100644 src/static/svg/CX.svg
create mode 100644 src/static/svg/CY.svg
create mode 100644 src/static/svg/CZ.svg
create mode 100644 src/static/svg/DE.svg
create mode 100644 src/static/svg/DJ.svg
create mode 100644 src/static/svg/DK.svg
create mode 100644 src/static/svg/DM.svg
create mode 100644 src/static/svg/DO.svg
create mode 100644 src/static/svg/DZ.svg
create mode 100644 src/static/svg/EC.svg
create mode 100644 src/static/svg/EE.svg
create mode 100644 src/static/svg/EG.svg
create mode 100644 src/static/svg/ER.svg
create mode 100644 src/static/svg/ES.svg
create mode 100644 src/static/svg/ET.svg
create mode 100644 src/static/svg/EU.svg
create mode 100644 src/static/svg/FI.svg
create mode 100644 src/static/svg/FJ.svg
create mode 100644 src/static/svg/FK.svg
create mode 100644 src/static/svg/FM.svg
create mode 100644 src/static/svg/FO.svg
create mode 100644 src/static/svg/FR.svg
create mode 100644 src/static/svg/GA.svg
create mode 100644 src/static/svg/GB-ENG.svg
create mode 100644 src/static/svg/GB-NIR.svg
create mode 100644 src/static/svg/GB-SCT.svg
create mode 100644 src/static/svg/GB-WLS.svg
create mode 100644 src/static/svg/GB-ZET.svg
create mode 100644 src/static/svg/GB.svg
create mode 100644 src/static/svg/GD.svg
create mode 100644 src/static/svg/GE.svg
create mode 100644 src/static/svg/GF.svg
create mode 100644 src/static/svg/GG.svg
create mode 100644 src/static/svg/GH.svg
create mode 100644 src/static/svg/GI.svg
create mode 100644 src/static/svg/GL.svg
create mode 100644 src/static/svg/GM.svg
create mode 100644 src/static/svg/GN.svg
create mode 100644 src/static/svg/GP.svg
create mode 100644 src/static/svg/GQ.svg
create mode 100644 src/static/svg/GR.svg
create mode 100644 src/static/svg/GS.svg
create mode 100644 src/static/svg/GT.svg
create mode 100644 src/static/svg/GU.svg
create mode 100644 src/static/svg/GW.svg
create mode 100644 src/static/svg/GY.svg
create mode 100644 src/static/svg/HK.svg
create mode 100644 src/static/svg/HM.svg
create mode 100644 src/static/svg/HN.svg
create mode 100644 src/static/svg/HR.svg
create mode 100644 src/static/svg/HT.svg
create mode 100644 src/static/svg/HU.svg
create mode 100644 src/static/svg/ID.svg
create mode 100644 src/static/svg/IE.svg
create mode 100644 src/static/svg/IL.svg
create mode 100644 src/static/svg/IM.svg
create mode 100644 src/static/svg/IN.svg
create mode 100644 src/static/svg/IO.svg
create mode 100644 src/static/svg/IQ.svg
create mode 100644 src/static/svg/IR.svg
create mode 100644 src/static/svg/IS.svg
create mode 100644 src/static/svg/IT.svg
create mode 100644 src/static/svg/JE.svg
create mode 100644 src/static/svg/JM.svg
create mode 100644 src/static/svg/JO.svg
create mode 100644 src/static/svg/JP.svg
create mode 100644 src/static/svg/KE.svg
create mode 100644 src/static/svg/KG.svg
create mode 100644 src/static/svg/KH.svg
create mode 100644 src/static/svg/KI.svg
create mode 100644 src/static/svg/KM.svg
create mode 100644 src/static/svg/KN.svg
create mode 100644 src/static/svg/KP.svg
create mode 100644 src/static/svg/KR.svg
create mode 100644 src/static/svg/KW.svg
create mode 100644 src/static/svg/KY.svg
create mode 100644 src/static/svg/KZ.svg
create mode 100644 src/static/svg/LA.svg
create mode 100644 src/static/svg/LB.svg
create mode 100644 src/static/svg/LC.svg
create mode 100644 src/static/svg/LGBT.svg
create mode 100644 src/static/svg/LI.svg
create mode 100644 src/static/svg/LK.svg
create mode 100644 src/static/svg/LR.svg
create mode 100644 src/static/svg/LS.svg
create mode 100644 src/static/svg/LT.svg
create mode 100644 src/static/svg/LU.svg
create mode 100644 src/static/svg/LV.svg
create mode 100644 src/static/svg/LY.svg
create mode 100644 src/static/svg/MA.svg
create mode 100644 src/static/svg/MC.svg
create mode 100644 src/static/svg/MD.svg
create mode 100644 src/static/svg/ME.svg
create mode 100644 src/static/svg/MF.svg
create mode 100644 src/static/svg/MG.svg
create mode 100644 src/static/svg/MH.svg
create mode 100644 src/static/svg/MK.svg
create mode 100644 src/static/svg/ML.svg
create mode 100644 src/static/svg/MM.svg
create mode 100644 src/static/svg/MN.svg
create mode 100644 src/static/svg/MO.svg
create mode 100644 src/static/svg/MP.svg
create mode 100644 src/static/svg/MQ.svg
create mode 100644 src/static/svg/MR.svg
create mode 100644 src/static/svg/MS.svg
create mode 100644 src/static/svg/MT.svg
create mode 100644 src/static/svg/MU.svg
create mode 100644 src/static/svg/MV.svg
create mode 100644 src/static/svg/MW.svg
create mode 100644 src/static/svg/MX.svg
create mode 100644 src/static/svg/MY.svg
create mode 100644 src/static/svg/MZ.svg
create mode 100644 src/static/svg/NA.svg
create mode 100644 src/static/svg/NC.svg
create mode 100644 src/static/svg/NE.svg
create mode 100644 src/static/svg/NF.svg
create mode 100644 src/static/svg/NG.svg
create mode 100644 src/static/svg/NI.svg
create mode 100644 src/static/svg/NL.svg
create mode 100644 src/static/svg/NO.svg
create mode 100644 src/static/svg/NP.svg
create mode 100644 src/static/svg/NR.svg
create mode 100644 src/static/svg/NU.svg
create mode 100644 src/static/svg/NZ.svg
create mode 100644 src/static/svg/OM.svg
create mode 100644 src/static/svg/PA.svg
create mode 100644 src/static/svg/PE.svg
create mode 100644 src/static/svg/PF.svg
create mode 100644 src/static/svg/PG.svg
create mode 100644 src/static/svg/PH.svg
create mode 100644 src/static/svg/PK.svg
create mode 100644 src/static/svg/PL.svg
create mode 100644 src/static/svg/PM.svg
create mode 100644 src/static/svg/PN.svg
create mode 100644 src/static/svg/PR.svg
create mode 100644 src/static/svg/PS.svg
create mode 100644 src/static/svg/PT.svg
create mode 100644 src/static/svg/PW.svg
create mode 100644 src/static/svg/PY.svg
create mode 100644 src/static/svg/QA.svg
create mode 100644 src/static/svg/RE.svg
create mode 100644 src/static/svg/RO.svg
create mode 100644 src/static/svg/RS.svg
create mode 100644 src/static/svg/RU.svg
create mode 100644 src/static/svg/RW.svg
create mode 100644 src/static/svg/SA.svg
create mode 100644 src/static/svg/SB.svg
create mode 100644 src/static/svg/SC.svg
create mode 100644 src/static/svg/SD.svg
create mode 100644 src/static/svg/SE.svg
create mode 100644 src/static/svg/SG.svg
create mode 100644 src/static/svg/SH.svg
create mode 100644 src/static/svg/SI.svg
create mode 100644 src/static/svg/SJ.svg
create mode 100644 src/static/svg/SK.svg
create mode 100644 src/static/svg/SL.svg
create mode 100644 src/static/svg/SM.svg
create mode 100644 src/static/svg/SN.svg
create mode 100644 src/static/svg/SO.svg
create mode 100644 src/static/svg/SR.svg
create mode 100644 src/static/svg/SS.svg
create mode 100644 src/static/svg/ST.svg
create mode 100644 src/static/svg/SV.svg
create mode 100644 src/static/svg/SX.svg
create mode 100644 src/static/svg/SY.svg
create mode 100644 src/static/svg/SZ.svg
create mode 100644 src/static/svg/TC.svg
create mode 100644 src/static/svg/TD.svg
create mode 100644 src/static/svg/TF.svg
create mode 100644 src/static/svg/TG.svg
create mode 100644 src/static/svg/TH.svg
create mode 100644 src/static/svg/TJ.svg
create mode 100644 src/static/svg/TK.svg
create mode 100644 src/static/svg/TL.svg
create mode 100644 src/static/svg/TM.svg
create mode 100644 src/static/svg/TN.svg
create mode 100644 src/static/svg/TO.svg
create mode 100644 src/static/svg/TR.svg
create mode 100644 src/static/svg/TT.svg
create mode 100644 src/static/svg/TV.svg
create mode 100644 src/static/svg/TW.svg
create mode 100644 src/static/svg/TZ.svg
create mode 100644 src/static/svg/UA.svg
create mode 100644 src/static/svg/UG.svg
create mode 100644 src/static/svg/UM.svg
create mode 100644 src/static/svg/US-CA.svg
create mode 100644 src/static/svg/US.svg
create mode 100644 src/static/svg/UY.svg
create mode 100644 src/static/svg/UZ.svg
create mode 100644 src/static/svg/VA.svg
create mode 100644 src/static/svg/VC.svg
create mode 100644 src/static/svg/VE.svg
create mode 100644 src/static/svg/VG.svg
create mode 100644 src/static/svg/VI.svg
create mode 100644 src/static/svg/VN.svg
create mode 100644 src/static/svg/VU.svg
create mode 100644 src/static/svg/WF.svg
create mode 100644 src/static/svg/WS.svg
create mode 100644 src/static/svg/XK.svg
create mode 100644 src/static/svg/YE.svg
create mode 100644 src/static/svg/YT.svg
create mode 100644 src/static/svg/ZA.svg
create mode 100644 src/static/svg/ZM.svg
create mode 100644 src/static/svg/ZW.svg
diff --git a/src/components/CustomSelectList.js b/src/components/CustomSelectList.js
new file mode 100644
index 000000000..2b0ad4bad
--- /dev/null
+++ b/src/components/CustomSelectList.js
@@ -0,0 +1,103 @@
+import React from 'react';
+import {
+ Button,
+ MenuItem,
+ PopoverInteractionKind,
+ Position,
+} from '@blueprintjs/core';
+import { defaultTo } from 'lodash';
+import { Select } from '@blueprintjs/select';
+import { FormattedMessage as T, Icon } from 'components';
+
+/**
+ * warehouse & branches select list.
+ * @returns
+ */
+export default function CustomSelectList({
+ // #ownProps
+ items,
+ initialItemId,
+ selectedItemId,
+ text,
+ onItemSelected,
+ buttonProps,
+}) {
+ const initialItem = React.useMemo(
+ () => items.find((a) => a.id === initialItemId),
+ [initialItemId, items],
+ );
+
+ const [selecetedItem, setSelectedItem] = React.useState(initialItem || null);
+
+ React.useEffect(() => {
+ if (typeof selectedItemId !== 'undefined') {
+ const item = selectedItemId
+ ? items.find((a) => a.id === selectedItemId)
+ : null;
+ setSelectedItem(item);
+ }
+ }, [selectedItemId, items, setSelectedItem]);
+
+ // Menu items renderer.
+ const itemRenderer = (item, { handleClick, modifiers, query }) => (
+
+ );
+
+ // Filters items items.
+ const filterItemsPredicater = (query, item, _index, exactMatch) => {
+ const normalizedTitle = item.name.toLowerCase();
+ const normalizedQuery = query.toLowerCase();
+
+ if (exactMatch) {
+ return normalizedTitle === normalizedQuery;
+ } else {
+ return `${item.code} ${normalizedTitle}`.indexOf(normalizedQuery) >= 0;
+ }
+ };
+
+ const handleItemMenuSelect = React.useCallback(
+ (item) => {
+ if (item.id) {
+ setSelectedItem({ ...item });
+ onItemSelected && onItemSelected(item);
+ }
+ },
+ [onItemSelected, setSelectedItem],
+ );
+
+ return (
+ } />}
+ itemRenderer={itemRenderer}
+ itemPredicate={filterItemsPredicater}
+ onItemSelect={handleItemMenuSelect}
+ popoverProps={{
+ minimal: true,
+ position: Position.BOTTOM_LEFT,
+ interactionKind: PopoverInteractionKind.CLICK,
+ modifiers: {
+ offset: { offset: '0, 4' },
+ },
+ }}
+ >
+
+
+ );
+}
diff --git a/src/components/index.js b/src/components/index.js
index 5e14f2288..a5cde02ec 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -58,6 +58,7 @@ import AvaterCell from './AvaterCell';
import { ItemsMultiSelect } from './Items';
import MoreMenuItems from './MoreMenutItems';
+import CustomSelectList from './CustomSelectList'
export * from './Dialog';
export * from './Menu';
@@ -163,4 +164,5 @@ export {
ItemsMultiSelect,
AvaterCell,
MoreMenuItems,
+ CustomSelectList
};
diff --git a/src/containers/Sales/Invoices/InvoiceForm/BaseCurrency.js b/src/containers/Sales/Invoices/InvoiceForm/BaseCurrency.js
new file mode 100644
index 000000000..c4f72e7cc
--- /dev/null
+++ b/src/containers/Sales/Invoices/InvoiceForm/BaseCurrency.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import * as R from 'ramda';
+import styled from 'styled-components';
+
+import { CurrencyTag } from 'components';
+import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
+
+/**
+ * base currency sign.
+ */
+function BaseCurrency({
+ // #withCurrentOrganization
+ organization: { base_currency = '' },
+}) {
+ // if (base_currency.length <= 0) {
+ // return null;
+ // }
+
+ return (
+
+ {base_currency}
+
+ );
+}
+
+export default R.compose(withCurrentOrganization())(BaseCurrency);
+
+const BaseCurrencySign = styled.div`
+ font-size: 10px;
+ margin-left: 5px;
+ span {
+ background: #5c7080;
+ }
+`;
diff --git a/src/containers/Sales/Invoices/InvoiceForm/FlagKit.js b/src/containers/Sales/Invoices/InvoiceForm/FlagKit.js
new file mode 100644
index 000000000..0a64a8ad6
--- /dev/null
+++ b/src/containers/Sales/Invoices/InvoiceForm/FlagKit.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import styled from 'styled-components';
+
+export default function FlagKit({ flage }) {
+ return (
+
+
+
+ );
+}
+
+const Img = styled.img`
+ display: inline-block;
+ object-fit: cover;
+ object-position: center;
+ margin: 0 5px;
+`;
diff --git a/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.js b/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.js
index 8c2f96c8c..b83f15072 100644
--- a/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.js
+++ b/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.js
@@ -16,6 +16,7 @@ import InvoiceItemsEntriesEditorField from './InvoiceItemsEntriesEditorField';
import InvoiceFloatingActions from './InvoiceFloatingActions';
import InvoiceFormFooter from './InvoiceFormFooter';
import InvoiceFormDialogs from './InvoiceFormDialogs';
+import InvoiceFormTopBar from './InvoiceFormTopBar';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withMediaActions from 'containers/Media/withMediaActions';
@@ -166,6 +167,7 @@ function InvoiceForm({
onSubmit={handleSubmit}
>
);
}
const useBranchesContext = () => React.useContext(BranchesContext);
export { BranchesProvider, useBranchesContext };
-
-const BrachesPreferencesCard = styled(Card)`
- padding: 0;
-`;
diff --git a/src/containers/Preferences/Warehouses/WarehousesList.js b/src/containers/Preferences/Warehouses/WarehousesList.js
index fc6051b3a..d23f20632 100644
--- a/src/containers/Preferences/Warehouses/WarehousesList.js
+++ b/src/containers/Preferences/Warehouses/WarehousesList.js
@@ -1,5 +1,8 @@
import React from 'react';
+import styled from 'styled-components';
import intl from 'react-intl-universal';
+
+import '../../../style/pages/Preferences/warehousesList.scss';
import Warehouses from './Warehouses';
import WarehousesEmptyStatus from './WarehousesEmptyStatus';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
@@ -18,7 +21,17 @@ function WarehousesList({
// return ;
// }
- return ;
+ return (
+
+
+
+ );
}
export default compose(withDashboardActions)(WarehousesList);
+
+const WarehousesListRoot = styled.div`
+ display: flex;
+ flex-wrap: wrap;
+ margin: 15px;
+`;
diff --git a/src/containers/Preferences/Warehouses/WarehousesProvider.js b/src/containers/Preferences/Warehouses/WarehousesProvider.js
index 3b2320431..bbcfdcf38 100644
--- a/src/containers/Preferences/Warehouses/WarehousesProvider.js
+++ b/src/containers/Preferences/Warehouses/WarehousesProvider.js
@@ -21,14 +21,19 @@ function WarehousesProvider({ ...props }) {
};
return (
-
-
+
+
{isWarehouesLoading ? (
) : (
)}
-
+
);
}
@@ -37,8 +42,4 @@ const useWarehousesContext = () => React.useContext(WarehousesContext);
export { WarehousesProvider, useWarehousesContext };
-const WarehousePreference = styled.div`
- display: flex;
- flex-wrap: wrap;
- margin: 15px;
-`;
+const WarehousePreference = styled.div``;
diff --git a/src/style/pages/Preferences/branchesList.scss b/src/style/pages/Preferences/branchesList.scss
new file mode 100644
index 000000000..ffdfaa9a0
--- /dev/null
+++ b/src/style/pages/Preferences/branchesList.scss
@@ -0,0 +1,6 @@
+// Branches List.
+// ---------------------------------
+.preferences-page__inside-content--branches {
+ height: 100%;
+
+}
diff --git a/src/style/pages/Preferences/warehousesList.scss b/src/style/pages/Preferences/warehousesList.scss
new file mode 100644
index 000000000..f80a690a1
--- /dev/null
+++ b/src/style/pages/Preferences/warehousesList.scss
@@ -0,0 +1,5 @@
+// warehouses List.
+// ---------------------------------
+.preferences-page__inside-content--warehouses {
+ height: 100%;
+}
From 09d5771481e0c0e01ad825ae0f16f2db56c17e59 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Tue, 8 Feb 2022 20:16:46 +0200
Subject: [PATCH 27/30] feat(branche & warehouse activate) add api.
---
.../BranchActivateDialogContent.js | 40 ++----------
.../BranchActivateForm.js | 64 +++++++++++++++++++
.../BranchActivateFormContent.js | 21 ++++++
.../BranchActivateFormFloatingActions.js | 47 ++++++++++++++
.../BranchActivateFormProvider.js | 29 +++++++++
.../WarehouseActivateDialogContent.js | 45 ++-----------
.../WarehouseActivateForm.js | 63 ++++++++++++++++++
.../WarehouseActivateFormContent.js | 22 +++++++
.../WarehouseActivateFormFloatingActions.js | 46 +++++++++++++
.../WarehouseActivateFormProvider.js | 31 +++++++++
10 files changed, 335 insertions(+), 73 deletions(-)
create mode 100644 src/containers/Dialogs/BranchActivateDialog/BranchActivateForm.js
create mode 100644 src/containers/Dialogs/BranchActivateDialog/BranchActivateFormContent.js
create mode 100644 src/containers/Dialogs/BranchActivateDialog/BranchActivateFormFloatingActions.js
create mode 100644 src/containers/Dialogs/BranchActivateDialog/BranchActivateFormProvider.js
create mode 100644 src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateForm.js
create mode 100644 src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateFormContent.js
create mode 100644 src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateFormFloatingActions.js
create mode 100644 src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateFormProvider.js
diff --git a/src/containers/Dialogs/BranchActivateDialog/BranchActivateDialogContent.js b/src/containers/Dialogs/BranchActivateDialog/BranchActivateDialogContent.js
index ab0d71c3f..31c1f8a86 100644
--- a/src/containers/Dialogs/BranchActivateDialog/BranchActivateDialogContent.js
+++ b/src/containers/Dialogs/BranchActivateDialog/BranchActivateDialogContent.js
@@ -1,43 +1,15 @@
import React from 'react';
-import { Intent, Button, Callout, Classes } from '@blueprintjs/core';
-import { DialogContent, T } from 'components';
-import withDialogActions from 'containers/Dialog/withDialogActions';
-import { compose } from 'utils';
+import BranchActivateForm from './BranchActivateForm';
+import { BranchActivateFormProvider } from './BranchActivateFormProvider';
-function BranchActivateDialogContent({
+export default function BranchActivateDialogContent({
// #ownProps
dialogName,
- // #withDialogActions
- closeDialog,
}) {
- // Handle close button click.
- const handleCancelBtnClick = () => {
- closeDialog(dialogName);
- };
return (
-
-
-
- Aute esse eiusmod dolore ipsum dolor sint qui proident pariatur
- proident fugiat ea ad aliquip.
-
-
-
-
+
+
+
);
}
-export default compose(withDialogActions)(BranchActivateDialogContent);
diff --git a/src/containers/Dialogs/BranchActivateDialog/BranchActivateForm.js b/src/containers/Dialogs/BranchActivateDialog/BranchActivateForm.js
new file mode 100644
index 000000000..d5f154a40
--- /dev/null
+++ b/src/containers/Dialogs/BranchActivateDialog/BranchActivateForm.js
@@ -0,0 +1,64 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+
+import { Formik } from 'formik';
+import { Intent } from '@blueprintjs/core';
+
+import { AppToaster } from 'components';
+import { useBranchActivateContext } from './BranchActivateFormProvider';
+import BranchActivateFormContent from './BranchActivateFormContent';
+
+import withDialogActions from 'containers/Dialog/withDialogActions';
+
+import { compose } from 'utils';
+
+/**
+ * Branch activate form.
+ */
+function BranchActivateForm({
+ // #withDialogActions
+ closeDialog,
+}) {
+ const { activateBranches, dialogName } = useBranchActivateContext();
+
+ // Initial form values
+ const initialValues = {};
+
+ // Handles the form submit.
+ const handleFormSubmit = (values, { setSubmitting, setErrors }) => {
+ const form = {
+ ...values,
+ };
+ setSubmitting(true);
+ // Handle request response success.
+ const onSuccess = (response) => {
+ AppToaster.show({
+ message: intl.get('branch_activate.dialog_success_message'),
+ intent: Intent.SUCCESS,
+ });
+ closeDialog(dialogName);
+ };
+
+ // Handle request response errors.
+ const onError = ({
+ response: {
+ data: { errors },
+ },
+ }) => {
+ if (errors) {
+ }
+ setSubmitting(false);
+ };
+ activateBranches(form).then(onSuccess).catch(onError);
+ };
+
+ return (
+
+ );
+}
+
+export default compose(withDialogActions)(BranchActivateForm);
diff --git a/src/containers/Dialogs/BranchActivateDialog/BranchActivateFormContent.js b/src/containers/Dialogs/BranchActivateDialog/BranchActivateFormContent.js
new file mode 100644
index 000000000..e6b7d0169
--- /dev/null
+++ b/src/containers/Dialogs/BranchActivateDialog/BranchActivateFormContent.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import { Form } from 'formik';
+import { Intent, Callout, Classes } from '@blueprintjs/core';
+import BranchActivateFormFloatingActions from './BranchActivateFormFloatingActions';
+
+/**
+ * Branch activate form content.
+ */
+export default function BranchActivateFormContent() {
+ return (
+
+ );
+}
diff --git a/src/containers/Dialogs/BranchActivateDialog/BranchActivateFormFloatingActions.js b/src/containers/Dialogs/BranchActivateDialog/BranchActivateFormFloatingActions.js
new file mode 100644
index 000000000..395758d44
--- /dev/null
+++ b/src/containers/Dialogs/BranchActivateDialog/BranchActivateFormFloatingActions.js
@@ -0,0 +1,47 @@
+import React from 'react';
+import { Intent, Button, Classes } from '@blueprintjs/core';
+import { useFormikContext } from 'formik';
+import { FormattedMessage as T } from 'components';
+
+import { useBranchActivateContext } from './BranchActivateFormProvider';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import { compose } from 'utils';
+
+/**
+ * branch activate form floating actions.
+ */
+function BranchActivateFormFloatingActions({
+ // #withDialogActions
+ closeDialog,
+}) {
+ // branch activate dialog context.
+ const { dialogName } = useBranchActivateContext();
+
+ // Formik context.
+ const { isSubmitting } = useFormikContext();
+
+ // Handle close button click.
+ const handleCancelBtnClick = () => {
+ closeDialog(dialogName);
+ };
+
+ return (
+
+ );
+}
+
+export default compose(withDialogActions)(BranchActivateFormFloatingActions);
diff --git a/src/containers/Dialogs/BranchActivateDialog/BranchActivateFormProvider.js b/src/containers/Dialogs/BranchActivateDialog/BranchActivateFormProvider.js
new file mode 100644
index 000000000..5e0299b6f
--- /dev/null
+++ b/src/containers/Dialogs/BranchActivateDialog/BranchActivateFormProvider.js
@@ -0,0 +1,29 @@
+import React from 'react';
+
+import { DialogContent } from 'components';
+import { useActivateBranches } from 'hooks/query';
+
+const BranchActivateContext = React.createContext();
+
+/**
+ * Branch activate form provider.
+ */
+function BranchActivateFormProvider({ dialogName, ...props }) {
+ const { mutateAsync: activateBranches, isLoading } = useActivateBranches();
+
+ // State provider.
+ const provider = {
+ activateBranches,
+ dialogName,
+ };
+
+ return (
+
+
+
+ );
+}
+
+const useBranchActivateContext = () => React.useContext(BranchActivateContext);
+
+export { BranchActivateFormProvider, useBranchActivateContext };
diff --git a/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateDialogContent.js b/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateDialogContent.js
index c5d481e63..b0950d535 100644
--- a/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateDialogContent.js
+++ b/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateDialogContent.js
@@ -1,48 +1,15 @@
import React from 'react';
-import { Intent, Button, Callout, Classes } from '@blueprintjs/core';
-import { DialogContent, T } from 'components';
-import withDialogActions from 'containers/Dialog/withDialogActions';
-import { compose } from 'utils';
+import WarehouseActivateForm from './WarehouseActivateForm';
+import { WarehouseActivateFormProvider } from './WarehouseActivateFormProvider';
-/**
- * Warehouse activate dialog content.
- * @returns
- */
-function WarehouseActivateDialogContent({
+export default function WarehouseActivateDialogContent({
// #ownProps
dialogName,
- // #withDialogActions
- closeDialog,
}) {
- // Handle close button click.
- const handleCancelBtnClick = () => {
- closeDialog(dialogName);
- };
return (
-
-
-
- Aute esse eiusmod dolore ipsum dolor sint qui proident pariatur
- proident fugiat ea ad aliquip.
-
-
-
-
+
+
+
);
}
-
-export default compose(withDialogActions)(WarehouseActivateDialogContent);
diff --git a/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateForm.js b/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateForm.js
new file mode 100644
index 000000000..748023d45
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateForm.js
@@ -0,0 +1,63 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+
+import { Formik } from 'formik';
+import { Intent } from '@blueprintjs/core';
+
+import { AppToaster } from 'components';
+import { useWarehouseActivateContext } from './WarehouseActivateFormProvider';
+import WarehouseActivateFormContent from './WarehouseActivateFormContent';
+
+import withDialogActions from 'containers/Dialog/withDialogActions';
+
+import { compose } from 'utils';
+
+/**
+ * warehouse activate form.
+ */
+function WarehouseActivateForm({
+ // #withDialogActions
+ closeDialog,
+}) {
+ const { activateWarehouses, dialogName } = useWarehouseActivateContext();
+
+ // Initial form values
+ const initialValues = {};
+
+ // Handles the form submit.
+ const handleFormSubmit = (values, { setSubmitting, setErrors }) => {
+ const form = {
+ ...values,
+ };
+ setSubmitting(true);
+ // Handle request response success.
+ const onSuccess = (response) => {
+ AppToaster.show({
+ message: intl.get('warehouse_activate.dialog_success_message'),
+ intent: Intent.SUCCESS,
+ });
+ closeDialog(dialogName);
+ };
+
+ // Handle request response errors.
+ const onError = ({
+ response: {
+ data: { errors },
+ },
+ }) => {
+ if (errors) {
+ }
+ setSubmitting(false);
+ };
+ activateWarehouses(form).then(onSuccess).catch(onError);
+ };
+
+ return (
+
+ );
+}
+export default compose(withDialogActions)(WarehouseActivateForm);
diff --git a/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateFormContent.js b/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateFormContent.js
new file mode 100644
index 000000000..137142a05
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateFormContent.js
@@ -0,0 +1,22 @@
+import React from 'react';
+import { Form } from 'formik';
+import { Intent, Callout, Classes } from '@blueprintjs/core';
+
+import WarehouseActivateFormFloatingActions from './WarehouseActivateFormFloatingActions';
+
+/**
+ * warehouse activate form content.
+ */
+export default function WarehouseActivateFormContent() {
+ return (
+
+ );
+}
diff --git a/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateFormFloatingActions.js b/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateFormFloatingActions.js
new file mode 100644
index 000000000..ab6444268
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateFormFloatingActions.js
@@ -0,0 +1,46 @@
+import React from 'react';
+import { Intent, Button, Classes } from '@blueprintjs/core';
+import { useFormikContext } from 'formik';
+import { FormattedMessage as T } from 'components';
+
+import { useWarehouseActivateContext } from './WarehouseActivateFormProvider';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import { compose } from 'utils';
+
+/**
+ * warehouse activate form floating actions.
+ */
+function WarehouseActivateFormFloatingActions({
+ // #withDialogActions
+ closeDialog,
+}) {
+ // warehouse activate dialog context.
+ const { dialogName } = useWarehouseActivateContext();
+
+ // Formik context.
+ const { isSubmitting } = useFormikContext();
+
+ // Handle close button click.
+ const handleCancelBtnClick = () => {
+ closeDialog(dialogName);
+ };
+
+ return (
+
+ );
+}
+export default compose(withDialogActions)(WarehouseActivateFormFloatingActions);
diff --git a/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateFormProvider.js b/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateFormProvider.js
new file mode 100644
index 000000000..5d8b84a40
--- /dev/null
+++ b/src/containers/Dialogs/WarehouseActivateDialog/WarehouseActivateFormProvider.js
@@ -0,0 +1,31 @@
+import React from 'react';
+
+import { DialogContent } from 'components';
+import { useActivateWarehouses } from 'hooks/query';
+
+const WarehouseActivateContext = React.createContext();
+
+/**
+ * warehouse activate form provider.
+ */
+function WarehouseActivateFormProvider({ dialogName, ...props }) {
+ const { mutateAsync: activateWarehouses, isLoading } =
+ useActivateWarehouses();
+
+ // State provider.
+ const provider = {
+ activateWarehouses,
+ dialogName,
+ };
+
+ return (
+
+
+
+ );
+}
+
+const useWarehouseActivateContext = () =>
+ React.useContext(WarehouseActivateContext);
+
+export { WarehouseActivateFormProvider, useWarehouseActivateContext };
From 49f8cce54b59f29fe16887801249cfef57e93d85 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Tue, 8 Feb 2022 20:31:15 +0200
Subject: [PATCH 28/30] feat(branche & warehouse ) add mark primary alert.
---
.../Alerts/Branches/BranchMarkPrimaryAlert.js | 70 +++++++++++++++++++
.../Warehouses/WarehouseMarkPrimaryAlert.js | 70 +++++++++++++++++++
.../Preferences/Branches/BranchesAlerts.js | 11 ++-
.../Preferences/Branches/BranchesDataTable.js | 16 +++--
.../Preferences/Branches/components.js | 7 +-
.../Warehouses/WarehousesAlerts.js | 11 ++-
.../Warehouses/WarehousesGridItems.js | 6 ++
.../Preferences/Warehouses/WarehousesList.js | 2 +-
.../Warehouses/WarehousesProvider.js | 6 +-
.../Preferences/Warehouses/components.js | 2 +-
src/hooks/query/branches.js | 18 +++++
src/hooks/query/warehouses.js | 18 +++++
src/lang/en/index.json | 32 +++++----
13 files changed, 244 insertions(+), 25 deletions(-)
create mode 100644 src/containers/Alerts/Branches/BranchMarkPrimaryAlert.js
create mode 100644 src/containers/Alerts/Warehouses/WarehouseMarkPrimaryAlert.js
diff --git a/src/containers/Alerts/Branches/BranchMarkPrimaryAlert.js b/src/containers/Alerts/Branches/BranchMarkPrimaryAlert.js
new file mode 100644
index 000000000..e61159587
--- /dev/null
+++ b/src/containers/Alerts/Branches/BranchMarkPrimaryAlert.js
@@ -0,0 +1,70 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { Intent, Alert } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'components';
+
+import { useMarkPrimaryBranches } from 'hooks/query';
+import { AppToaster } from 'components';
+
+import withAlertActions from 'containers/Alert/withAlertActions';
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+
+import { compose } from 'utils';
+
+/**
+ * branch mark primary alert.
+ */
+function BranchMarkPrimaryAlert({
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { branchId },
+
+ // #withAlertActions
+ closeAlert,
+}) {
+ const { mutateAsync: markPrimaryBranchMutate, isLoading } =
+ useMarkPrimaryBranches();
+
+ // Handle cancel mark primary alert.
+ const handleCancelMarkPrimaryAlert = () => {
+ closeAlert(name);
+ };
+
+ // andle cancel mark primary confirm.
+ const handleConfirmMarkPrimaryBranch = () => {
+ markPrimaryBranchMutate(branchId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get('branch.alert.mark_primary_message'),
+ intent: Intent.SUCCESS,
+ });
+ closeAlert(name);
+ })
+ .catch((error) => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={ }
+ intent={Intent.WARNING}
+ isOpen={isOpen}
+ onCancel={handleCancelMarkPrimaryAlert}
+ onConfirm={handleConfirmMarkPrimaryBranch}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+)(BranchMarkPrimaryAlert);
diff --git a/src/containers/Alerts/Warehouses/WarehouseMarkPrimaryAlert.js b/src/containers/Alerts/Warehouses/WarehouseMarkPrimaryAlert.js
new file mode 100644
index 000000000..b51c7fa45
--- /dev/null
+++ b/src/containers/Alerts/Warehouses/WarehouseMarkPrimaryAlert.js
@@ -0,0 +1,70 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { Intent, Alert } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'components';
+
+import { useMarkPrimaryWarehouse } from 'hooks/query';
+import { AppToaster } from 'components';
+
+import withAlertActions from 'containers/Alert/withAlertActions';
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+
+import { compose } from 'utils';
+
+/**
+ * warehouse mark primary alert.
+ */
+function WarehouseMarkPrimaryAlert({
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { warehouseId },
+
+ // #withAlertActions
+ closeAlert,
+}) {
+ const { mutateAsync: markPrimaryWarehouseMutate, isLoading } =
+ useMarkPrimaryWarehouse();
+
+ // Handle cancel mark primary alert.
+ const handleCancelMarkPrimaryAlert = () => {
+ closeAlert(name);
+ };
+
+ // andle cancel mark primary confirm.
+ const handleConfirmMarkPrimaryWarehouse = () => {
+ markPrimaryWarehouseMutate(warehouseId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get('warehouse.alert.mark_primary_message'),
+ intent: Intent.SUCCESS,
+ });
+ closeAlert(name);
+ })
+ .catch((error) => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={ }
+ intent={Intent.WARNING}
+ isOpen={isOpen}
+ onCancel={handleCancelMarkPrimaryAlert}
+ onConfirm={handleConfirmMarkPrimaryWarehouse}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+)(WarehouseMarkPrimaryAlert);
diff --git a/src/containers/Preferences/Branches/BranchesAlerts.js b/src/containers/Preferences/Branches/BranchesAlerts.js
index c444030db..2facc34b8 100644
--- a/src/containers/Preferences/Branches/BranchesAlerts.js
+++ b/src/containers/Preferences/Branches/BranchesAlerts.js
@@ -3,5 +3,14 @@ import React from 'react';
const BranchDeleteAlert = React.lazy(() =>
import('../../Alerts/Branches/BranchDeleteAlert'),
);
+const BranchMarkPrimaryAlert = React.lazy(() =>
+ import('../../Alerts/Branches/BranchMarkPrimaryAlert'),
+);
-export default [{ name: 'branch-delete', component: BranchDeleteAlert }];
+export default [
+ { name: 'branch-delete', component: BranchDeleteAlert },
+ {
+ name: 'branch-mark-primary',
+ component: BranchMarkPrimaryAlert,
+ },
+];
diff --git a/src/containers/Preferences/Branches/BranchesDataTable.js b/src/containers/Preferences/Branches/BranchesDataTable.js
index 1a47a03d8..e34affa54 100644
--- a/src/containers/Preferences/Branches/BranchesDataTable.js
+++ b/src/containers/Preferences/Branches/BranchesDataTable.js
@@ -27,22 +27,27 @@ function BranchesDataTable({
// Table columns.
const columns = useBranchesTableColumns();
- const Time = true;
-
const { branches, isBranchesLoading, isBranchesFetching } =
useBranchesContext();
+ // Handle edit branch.
const handleEditBranch = ({ id }) => {
openDialog('branch-form', { branchId: id, action: 'edit' });
};
+ // Handle delete branch.
const handleDeleteBranch = ({ id }) => {
openAlert('branch-delete', { branchId: id });
};
- if (Time) {
- return ;
- }
+ // Handle mark primary branch.
+ const handleMarkPrimaryBranch = ({ id }) => {
+ openAlert('branch-mark-primary', { branchId: id });
+ };
+
+ // if (type) {
+ // return ;
+ // }
return (
@@ -58,6 +63,7 @@ function BranchesDataTable({
payload={{
onEdit: handleEditBranch,
onDelete: handleDeleteBranch,
+ onMarkPrimary: handleMarkPrimaryBranch,
}}
/>
diff --git a/src/containers/Preferences/Branches/components.js b/src/containers/Preferences/Branches/components.js
index 771681fba..defa408d6 100644
--- a/src/containers/Preferences/Branches/components.js
+++ b/src/containers/Preferences/Branches/components.js
@@ -9,7 +9,7 @@ import { Icon } from 'components';
* Context menu of Branches.
*/
export function ActionsMenu({
- payload: { onEdit, onDelete },
+ payload: { onEdit, onDelete, onMarkPrimary },
row: { original },
}) {
return (
@@ -19,6 +19,11 @@ export function ActionsMenu({
text={intl.get('branches.action.edit_branch')}
onClick={safeCallback(onEdit, original)}
/>
+ }
+ text={intl.get('branches.action.mark_as_primary')}
+ onClick={safeCallback(onMarkPrimary, original)}
+ />
}
diff --git a/src/containers/Preferences/Warehouses/WarehousesAlerts.js b/src/containers/Preferences/Warehouses/WarehousesAlerts.js
index 7e19d865a..bf2ce3883 100644
--- a/src/containers/Preferences/Warehouses/WarehousesAlerts.js
+++ b/src/containers/Preferences/Warehouses/WarehousesAlerts.js
@@ -3,8 +3,17 @@ import React from 'react';
const WarehouseDeleteAlert = React.lazy(() =>
import('../../Alerts/Warehouses/WarehouseDeleteAlert'),
);
+const WarehouseMarkPrimaryAlert = React.lazy(() =>
+ import('../../Alerts/Warehouses/WarehouseMarkPrimaryAlert'),
+);
/**
* Warehouses alerts.
*/
-export default [{ name: 'warehouse-delete', component: WarehouseDeleteAlert }];
+export default [
+ { name: 'warehouse-delete', component: WarehouseDeleteAlert },
+ {
+ name: 'warehouse-mark-primary',
+ component: WarehouseMarkPrimaryAlert,
+ },
+];
diff --git a/src/containers/Preferences/Warehouses/WarehousesGridItems.js b/src/containers/Preferences/Warehouses/WarehousesGridItems.js
index edc33ff22..4668ce10a 100644
--- a/src/containers/Preferences/Warehouses/WarehousesGridItems.js
+++ b/src/containers/Preferences/Warehouses/WarehousesGridItems.js
@@ -30,12 +30,18 @@ function WarehousesGridItems({
openAlert('warehouse-delete', { warehouseId: warehouse.id });
};
+ // Handle mark primary warehouse.
+ const handleMarkPrimaryWarehouse = () => {
+ openAlert('warehouse-mark-primary', { warehouseId: warehouse.id });
+ };
+
return (
}
>
diff --git a/src/containers/Preferences/Warehouses/WarehousesList.js b/src/containers/Preferences/Warehouses/WarehousesList.js
index d23f20632..c2e6c7816 100644
--- a/src/containers/Preferences/Warehouses/WarehousesList.js
+++ b/src/containers/Preferences/Warehouses/WarehousesList.js
@@ -17,7 +17,7 @@ function WarehousesList({
changePreferencesPageTitle(intl.get('warehouses.label'));
}, [changePreferencesPageTitle]);
- // if () {
+ // if (type) {
// return ;
// }
diff --git a/src/containers/Preferences/Warehouses/WarehousesProvider.js b/src/containers/Preferences/Warehouses/WarehousesProvider.js
index bbcfdcf38..69ba03b5f 100644
--- a/src/containers/Preferences/Warehouses/WarehousesProvider.js
+++ b/src/containers/Preferences/Warehouses/WarehousesProvider.js
@@ -28,11 +28,11 @@ function WarehousesProvider({ ...props }) {
)}
>
- {isWarehouesLoading ? (
+ {/* {isWarehouesLoading ? (
- ) : (
+ ) : ( */}
- )}
+ {/* )} */}
);
diff --git a/src/containers/Preferences/Warehouses/components.js b/src/containers/Preferences/Warehouses/components.js
index 7027343b5..bcaf8f419 100644
--- a/src/containers/Preferences/Warehouses/components.js
+++ b/src/containers/Preferences/Warehouses/components.js
@@ -22,7 +22,7 @@ export function WarehouseContextMenu({
onClick={safeCallback(onEditClick)}
/>
}
+ icon={ }
text={intl.get('warehouses.action.make_as_parimary')}
onClick={safeCallback(onPrimary)}
/>
diff --git a/src/hooks/query/branches.js b/src/hooks/query/branches.js
index 2eb95f58c..b9a9e75c7 100644
--- a/src/hooks/query/branches.js
+++ b/src/hooks/query/branches.js
@@ -113,3 +113,21 @@ export function useActivateBranches(props) {
...props,
});
}
+
+/**
+ * Mark primary the given branch.
+ */
+export function useMarkPrimaryBranches(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation((id) => apiRequest.post(`branches/${id}/mark-primary`), {
+ onSuccess: (res, id) => {
+ // Invalidate specific inventory adjustment.
+ queryClient.invalidateQueries([t.BRANCH, id]);
+
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ });
+}
diff --git a/src/hooks/query/warehouses.js b/src/hooks/query/warehouses.js
index 18bca2b04..2499aaed4 100644
--- a/src/hooks/query/warehouses.js
+++ b/src/hooks/query/warehouses.js
@@ -233,3 +233,21 @@ export function useActivateWarehouses(props) {
...props,
});
}
+
+/**
+ * Mark primary the given branch.
+ */
+export function useMarkPrimaryWarehouse(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation((id) => apiRequest.post(`warehouses/${id}/mark-primary`), {
+ onSuccess: (res, id) => {
+ // Invalidate specific inventory adjustment.
+ queryClient.invalidateQueries([t.WAREHOUSE, id]);
+
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ });
+}
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index 25e10793f..fe03fae57 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -1772,8 +1772,8 @@
"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",
@@ -1797,16 +1797,17 @@
"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",
- "warehouse_transfer.success_message":"The warehouse transfer transaction has been created successfully.",
- "warehouse_transfer.edit_success_message":"The warehouse transfer transaction has been created successfully.",
- "select_warehouse_transfer":"Select Warehouse Transfer",
- "warehouse_transfer.alert.delete_message":"The warehouse transfer transaction has been deleted successfully",
- "warehouse_transfer.once_delete_this_warehouse_transfer":"Once you delete this warehouse transfer, you won't be able to restore it later. Are you sure you want to delete this warehouse transfer?",
- "warehouse_transfer.error.could_not_transfer_item_from_source_to_destination":"Could not transfer item from source to destination on the same warehouse",
+ "warehouse_transfer.success_message": "The warehouse transfer transaction has been created successfully.",
+ "warehouse_transfer.edit_success_message": "The warehouse transfer transaction has been created successfully.",
+ "select_warehouse_transfer": "Select Warehouse Transfer",
+ "warehouse_transfer.alert.delete_message": "The warehouse transfer transaction has been deleted successfully",
+ "warehouse_transfer.once_delete_this_warehouse_transfer": "Once you delete this warehouse transfer, you won't be able to restore it later. Are you sure you want to delete this warehouse transfer?",
+ "warehouse_transfer.error.could_not_transfer_item_from_source_to_destination": "Could not transfer item from source to destination on the same warehouse",
"branches.label": "Branches",
"branches.label.new_branch": "New Branch",
"branches.action.edit_branch": "Edit Branch",
"branches.action.delete_branch": "Delete Branch",
+ "branches.action.mark_as_primary": "Make as Primary",
"branches.column.branch_name": "Branch name",
"branches.column.address": "Address",
"branches.column.phone_number": "Phone number",
@@ -1823,8 +1824,15 @@
"branch.dialog.label.email": "Email",
"branch.dialog.label.website": "Website",
"branch.dialog.success_message": "The branch has been created successfully.",
- "branch.alert.delete_message":"The branch has been deleted successfully",
- "branch.once_delete_this_branch":"Once you delete this branch, you won't be able to restore it later. Are you sure you want to delete this branch?",
- "realized_gain_or_loss.label":"Realized Gain or Loss",
- "unrealized_gain_or_loss.label":"Unrealized Gain or Loss"
+ "branch.alert.delete_message": "The branch has been deleted successfully",
+ "branch.once_delete_this_branch": "Once you delete this branch, you won't be able to restore it later. Are you sure you want to delete this branch?",
+ "realized_gain_or_loss.label": "Realized Gain or Loss",
+ "unrealized_gain_or_loss.label": "Unrealized Gain or Loss",
+ "branch_activate.dialog_success_message": "Multi-branches feature has been activated successfully.",
+ "branch.alert.mark_primary_message": "The branch has been marked as primary.",
+ "branch.alert.are_you_sure_you_want_to_make":"Are you sure you want to make a primary branch?",
+ "warehouse_activate.dialog_success_message": "Multi-branches feature has been activated successfully.",
+ "warehouse.alert.mark_primary_message": "The given warehouse has been marked as primary.",
+ "warehouse.alert.are_you_sure_you_want_to_make":"Are you sure you want to make a primary warehouse?",
+ "make_primary":"Make Primary"
}
\ No newline at end of file
From 3e8f281d0c03cb7f9a9d2359b5eb03bf75e8637d Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Tue, 8 Feb 2022 21:18:52 +0200
Subject: [PATCH 29/30] fix(warehouse ) fix mark primary warehouse alert.
---
src/containers/Alerts/Warehouses/WarehouseMarkPrimaryAlert.js | 2 +-
src/containers/Preferences/Warehouses/components.js | 4 ++--
src/lang/en/index.json | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/containers/Alerts/Warehouses/WarehouseMarkPrimaryAlert.js b/src/containers/Alerts/Warehouses/WarehouseMarkPrimaryAlert.js
index b51c7fa45..17f8300f4 100644
--- a/src/containers/Alerts/Warehouses/WarehouseMarkPrimaryAlert.js
+++ b/src/containers/Alerts/Warehouses/WarehouseMarkPrimaryAlert.js
@@ -31,7 +31,7 @@ function WarehouseMarkPrimaryAlert({
const handleCancelMarkPrimaryAlert = () => {
closeAlert(name);
};
-
+ console.log(warehouseId, 'XX');
// andle cancel mark primary confirm.
const handleConfirmMarkPrimaryWarehouse = () => {
markPrimaryWarehouseMutate(warehouseId)
diff --git a/src/containers/Preferences/Warehouses/components.js b/src/containers/Preferences/Warehouses/components.js
index bcaf8f419..0928c8c99 100644
--- a/src/containers/Preferences/Warehouses/components.js
+++ b/src/containers/Preferences/Warehouses/components.js
@@ -12,7 +12,7 @@ import { safeCallback } from 'utils';
export function WarehouseContextMenu({
onEditClick,
onDeleteClick,
- onPrimary,
+ onMarkPrimary,
}) {
return (
@@ -24,7 +24,7 @@ export function WarehouseContextMenu({
}
text={intl.get('warehouses.action.make_as_parimary')}
- onClick={safeCallback(onPrimary)}
+ onClick={safeCallback(onMarkPrimary)}
/>
Date: Wed, 9 Feb 2022 00:23:50 +0200
Subject: [PATCH 30/30] feat(warehouse ): warehouse style.
---
.../Preferences/Warehouses/components.js | 60 ++++++++++++-------
1 file changed, 40 insertions(+), 20 deletions(-)
diff --git a/src/containers/Preferences/Warehouses/components.js b/src/containers/Preferences/Warehouses/components.js
index 0928c8c99..6be10907c 100644
--- a/src/containers/Preferences/Warehouses/components.js
+++ b/src/containers/Preferences/Warehouses/components.js
@@ -39,36 +39,47 @@ export function WarehouseContextMenu({
export function WarehousesGrid({ warehouse }) {
return (
-
+
{warehouse.name}
{warehouse.code}
+
+
+
- {warehouse.city}
- {warehouse.country}
- {warehouse.email}
- {warehouse.phone_number}
-
+
+ {warehouse.city}
+ {warehouse.country}
+ {warehouse.email}
+ {warehouse.phone_number}
+
+
);
}
-const WarehouseGrid = styled.div`
+const WarehouseGridWrapper = styled.div`
display: flex;
flex-direction: column;
+ flex-shrink: 0;
border-radius: 3px;
- width: 280px; // 453px
- height: 160px; //225px
- background: #fff;
- margin: 5px;
- padding: 16px 12px 10px;
border: 1px solid #c8cad0; //#CFD1D6
+ background: #fff;
+ margin: 5px 5px 8px;
+ width: 300px; // 453px
+ height: 160px; //225px
transition: all 0.1s ease-in-out;
+ position: relative;
&:hover {
border-color: #0153cc;
}
`;
+const WarehouseHeader = styled.div`
+ position: relative;
+ padding: 16px 12px 10px;
+`;
+
const WarehouseTitle = styled.div`
font-size: 14px; //22px
font-style: inherit;
@@ -78,22 +89,31 @@ const WarehouseTitle = styled.div`
line-height: 1;
`;
-const WarehouseHeader = styled.div`
- margin: 4px 0px 15px;
-`;
-
const WarehouseCode = styled.div`
display: inline-block;
font-size: 11px;
color: #6b7176;
`;
-const WarehouseInfoItem = styled.div`
+const WarehouseIcon = styled.div`
+ position: absolute;
+ top: 14px;
+ color: #abb3bb;
+ right: 12px;
+`;
+
+const WarehouseContent = styled.div`
display: inline-block;
- font-size: 12px;
+ position: absolute;
+ bottom: 8px;
+ width: 100%;
+ padding: 0 12px 0px;
+`;
+
+const WarehouseItem = styled.div`
+ font-size: 11px;
color: #000;
line-height: 1.3rem;
- overflow: hidden;
text-overflow: ellipsis;
- margin: 0;
+ overflow: hidden;
`;