diff --git a/client/src/common/allocateLandedCostType.js b/client/src/common/allocateLandedCostType.js
new file mode 100644
index 000000000..74bcffacf
--- /dev/null
+++ b/client/src/common/allocateLandedCostType.js
@@ -0,0 +1,6 @@
+import intl from 'react-intl-universal';
+
+export default [
+ { name: intl.get('bills'), value: 'Bill' },
+ { name: intl.get('expenses'), value: 'Expense' },
+];
diff --git a/client/src/common/countries.js b/client/src/common/countries.js
index c86568887..c1bfe5c5a 100644
--- a/client/src/common/countries.js
+++ b/client/src/common/countries.js
@@ -1,3 +1,8 @@
import intl from 'react-intl-universal';
-export default [{ name: intl.get('libya'), value: 'libya' }];
+export const getCountries = () => [
+ {
+ name: intl.get('libya'),
+ value: 'libya',
+ },
+];
diff --git a/client/src/common/currencies.js b/client/src/common/currencies.js
index ae1dbd6d9..b47f16807 100644
--- a/client/src/common/currencies.js
+++ b/client/src/common/currencies.js
@@ -1,6 +1,6 @@
import intl from 'react-intl-universal';
-export default [
+export const getCurrencies = () => [
{ name: intl.get('us_dollar'), code: 'USD' },
{ name: intl.get('euro'), code: 'EUR' },
{ name: intl.get('libyan_diner'), code: 'LYD' },
diff --git a/client/src/common/dateFormatsOptions.js b/client/src/common/dateFormatsOptions.js
index 8c6ed99a2..3a194a790 100644
--- a/client/src/common/dateFormatsOptions.js
+++ b/client/src/common/dateFormatsOptions.js
@@ -1,7 +1,7 @@
import moment from 'moment';
import intl from 'react-intl-universal';
-export default [
+export const getDateFormats =()=> [
{
id: 1,
name: intl.get('mm_dd_yy'),
diff --git a/client/src/common/fiscalYearOptions.js b/client/src/common/fiscalYearOptions.js
index 24043ec80..9fd5c3845 100644
--- a/client/src/common/fiscalYearOptions.js
+++ b/client/src/common/fiscalYearOptions.js
@@ -1,6 +1,6 @@
import intl from 'react-intl-universal';
-export const getFiscalYearOptions = () => [
+export const getFiscalYear = () => [
{
id: 0,
name: `${intl.get('january')} - ${intl.get('december')}`,
diff --git a/client/src/common/languagesOptions.js b/client/src/common/languagesOptions.js
index 77ddb2f6b..76f630e76 100644
--- a/client/src/common/languagesOptions.js
+++ b/client/src/common/languagesOptions.js
@@ -1,6 +1,6 @@
import intl from 'react-intl-universal';
-export default [
+export const getLanguages = () => [
{ name: intl.get('english'), value: 'en' },
{ name: intl.get('arabic'), value: 'ar' },
];
diff --git a/client/src/components/AppIntlLoader.js b/client/src/components/AppIntlLoader.js
index fdd533325..8b1b6690b 100644
--- a/client/src/components/AppIntlLoader.js
+++ b/client/src/components/AppIntlLoader.js
@@ -4,6 +4,7 @@ import { setLocale } from 'yup';
import intl from 'react-intl-universal';
import { find } from 'lodash';
import rtlDetect from 'rtl-detect';
+import { AppIntlProvider } from './AppIntlProvider';
import DashboardLoadingIndicator from 'components/Dashboard/DashboardLoadingIndicator';
const SUPPORTED_LOCALES = [
@@ -40,16 +41,14 @@ function loadYupLocales(currentLocale) {
/**
* Modifies the html document direction to RTl if it was rtl-language.
*/
-function useDocumentDirectionModifier(locale) {
+function useDocumentDirectionModifier(locale, isRTL) {
React.useEffect(() => {
- const isRTL = rtlDetect.isRtlLang(locale);
-
if (isRTL) {
const htmlDocument = document.querySelector('html');
htmlDocument.setAttribute('dir', 'rtl');
htmlDocument.setAttribute('lang', locale);
}
- }, []);
+ }, [isRTL, locale]);
}
/**
@@ -59,8 +58,10 @@ export default function AppIntlLoader({ children }) {
const [isLoading, setIsLoading] = React.useState(true);
const currentLocale = getCurrentLocal();
+ const isRTL = rtlDetect.isRtlLang(currentLocale);
+
// Modifies the html document direction
- useDocumentDirectionModifier(currentLocale);
+ useDocumentDirectionModifier(currentLocale, isRTL);
React.useEffect(() => {
// Lodas the locales data file.
@@ -86,10 +87,12 @@ export default function AppIntlLoader({ children }) {
})
.then(() => {});
}, [currentLocale]);
-
+
return (
-
- {children}
-
+
+
+ {children}
+
+
);
}
diff --git a/client/src/components/AppIntlProvider.js b/client/src/components/AppIntlProvider.js
new file mode 100644
index 000000000..84e2f0638
--- /dev/null
+++ b/client/src/components/AppIntlProvider.js
@@ -0,0 +1,24 @@
+import React, { createContext } from 'react';
+
+const AppIntlContext = createContext();
+
+/**
+ * Application intl provider.
+ */
+function AppIntlProvider({ currentLocale, isRTL, children }) {
+ const provider = {
+ currentLocale,
+ isRTL,
+ isLTR: !isRTL,
+ };
+
+ return (
+
+ {children}
+
+ );
+}
+
+const useAppIntlContext = () => React.useContext(AppIntlContext);
+
+export { AppIntlProvider, useAppIntlContext };
diff --git a/client/src/components/Card.js b/client/src/components/Card.js
new file mode 100644
index 000000000..e28d3816b
--- /dev/null
+++ b/client/src/components/Card.js
@@ -0,0 +1,5 @@
+import React from 'react';
+
+export default function Card({ children }) {
+ return
{children}
;
+}
diff --git a/client/src/components/ContactsMultiSelect.js b/client/src/components/ContactsMultiSelect.js
index 5c8171294..75755ab9a 100644
--- a/client/src/components/ContactsMultiSelect.js
+++ b/client/src/components/ContactsMultiSelect.js
@@ -1,58 +1,57 @@
-import React, { useMemo, useCallback, useState } from 'react';
+import React, { useCallback, useState } from 'react';
import { MenuItem, Button } from '@blueprintjs/core';
-import { omit } from 'lodash';
+import intl from 'react-intl-universal';
import MultiSelect from 'components/MultiSelect';
import { FormattedMessage as T } from 'components';
-import intl from 'react-intl-universal';
+import { safeInvoke } from 'utils';
+/**
+ * Contacts multi-select component.
+ */
export default function ContactsMultiSelect({
contacts,
defaultText = ,
buttonProps,
- onCustomerSelected: onContactSelected,
- ...selectProps
+ onContactSelect,
+ contactsSelected = [],
+ ...multiSelectProps
}) {
- const [selectedContacts, setSelectedContacts] = useState({});
+ const [localSelected, setLocalSelected] = useState([ ...contactsSelected]);
- const isContactSelect = useCallback(
- (id) => typeof selectedContacts[id] !== 'undefined',
- [selectedContacts],
+ // Detarmines the given id is selected.
+ const isItemSelected = useCallback(
+ (id) => localSelected.some(s => s === id),
+ [localSelected],
);
+ // Contact item renderer.
const contactRenderer = useCallback(
(contact, { handleClick }) => (
),
- [isContactSelect],
+ [isItemSelected],
);
- const countSelected = useMemo(
- () => Object.values(selectedContacts).length,
- [selectedContacts],
- );
+ // Count selected items.
+ const countSelected = localSelected.length;
- const onContactSelect = useCallback(
+ // Handle item selected.
+ const handleItemSelect = useCallback(
({ id }) => {
- const selected = {
- ...(isContactSelect(id)
- ? {
- ...omit(selectedContacts, [id]),
- }
- : {
- ...selectedContacts,
- [id]: true,
- }),
- };
- setSelectedContacts({ ...selected });
- onContactSelected && onContactSelected(selected);
+ const selected = isItemSelected(id)
+ ? localSelected.filter(s => s !== id)
+ : [...localSelected, id];
+
+ setLocalSelected([ ...selected ]);
+ safeInvoke(onContactSelect, selected);
},
- [setSelectedContacts, selectedContacts, isContactSelect, onContactSelected],
+ [setLocalSelected, localSelected, isItemSelected, onContactSelect],
);
return (
@@ -62,7 +61,8 @@ export default function ContactsMultiSelect({
itemRenderer={contactRenderer}
popoverProps={{ minimal: true }}
filterable={true}
- onItemSelect={onContactSelect}
+ onItemSelect={handleItemSelect}
+ {...multiSelectProps}
>