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 cad5be4d3..85c9c26f1 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 dc1d99646..51c53548b 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -1846,5 +1846,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',
};