diff --git a/src/containers/Expenses/ExpenseForm/ExpenseForm.js b/src/containers/Expenses/ExpenseForm/ExpenseForm.js index 33511dc6e..838c7ce44 100644 --- a/src/containers/Expenses/ExpenseForm/ExpenseForm.js +++ b/src/containers/Expenses/ExpenseForm/ExpenseForm.js @@ -11,6 +11,7 @@ import ExpenseFormHeader from './ExpenseFormHeader'; import ExpenseFormBody from './ExpenseFormBody'; import ExpenseFloatingFooter from './ExpenseFloatingActions'; import ExpenseFormFooter from './ExpenseFormFooter'; +import ExpenseFormTopBar from './ExpenseFormTopBar'; import { useExpenseFormContext } from './ExpenseFormPageProvider'; @@ -143,6 +144,7 @@ function ExpenseForm({ onSubmit={handleSubmit} >
+ diff --git a/src/containers/Expenses/ExpenseForm/ExpenseFormHeader.js b/src/containers/Expenses/ExpenseForm/ExpenseFormHeader.js index 609c6d2e4..8b5c81ecc 100644 --- a/src/containers/Expenses/ExpenseForm/ExpenseFormHeader.js +++ b/src/containers/Expenses/ExpenseForm/ExpenseFormHeader.js @@ -11,20 +11,23 @@ import { PageFormBigNumber } from 'components'; // Expense form header. export default function ExpenseFormHeader() { - const { values } = useFormikContext(); + const { + values: { currency_code, categories }, + } = useFormikContext(); // Calculates the expense entries amount. - const totalExpenseAmount = useMemo(() => sumBy(values.categories, 'amount'), [ - values.categories, - ]); + const totalExpenseAmount = useMemo( + () => sumBy(categories, 'amount'), + [categories], + ); return (
} + label={} amount={totalExpenseAmount} - currencyCode={values?.currency_code} + currencyCode={currency_code} />
); diff --git a/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.js b/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.js index 5208759fc..432f0ba29 100644 --- a/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.js +++ b/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.js @@ -1,5 +1,11 @@ import React from 'react'; -import { InputGroup, FormGroup, Position, Classes } from '@blueprintjs/core'; +import { + InputGroup, + FormGroup, + ControlGroup, + Position, + Classes, +} from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; import { FastField, ErrorMessage } from 'formik'; import { FormattedMessage as T } from 'components'; @@ -17,7 +23,9 @@ import { CustomerSelectField, AccountsSelectList, FieldRequiredHint, + ExchangeRateInputGroup, Hint, + If, } from 'components'; import { ACCOUNT_PARENT_TYPE } from 'common/accountTypes'; import { useExpenseFormContext } from './ExpenseFormPageProvider'; @@ -26,7 +34,15 @@ import { useExpenseFormContext } from './ExpenseFormPageProvider'; * Expense form header. */ export default function ExpenseFormHeader() { - const { currencies, accounts, customers } = useExpenseFormContext(); + const { + currencies, + accounts, + customers, + isForeignCustomer, + baseCurrency, + selectCustomer, + setSelectCustomer, + } = useExpenseFormContext(); return (
@@ -102,14 +118,23 @@ export default function ExpenseFormHeader() { selectedCurrencyCode={value} onCurrencySelected={(currencyItem) => { form.setFieldValue('currency_code', currencyItem.currency_code); + setSelectCustomer(currencyItem); }} defaultSelectText={value} - disabled={true} /> )} + + + + {({ form, field, meta: { error, touched } }) => ( )} diff --git a/src/containers/Expenses/ExpenseForm/ExpenseFormPage.js b/src/containers/Expenses/ExpenseForm/ExpenseFormPage.js index 51453b61b..adfaa957f 100644 --- a/src/containers/Expenses/ExpenseForm/ExpenseFormPage.js +++ b/src/containers/Expenses/ExpenseForm/ExpenseFormPage.js @@ -5,18 +5,22 @@ import 'style/pages/Expense/PageForm.scss'; import ExpenseForm from './ExpenseForm'; import { ExpenseFormPageProvider } from './ExpenseFormPageProvider'; - +import withCurrentOrganization from 'containers/Organization/withCurrentOrganization'; +import { compose } from 'utils'; /** * Expense page form. */ -export default function ExpenseFormPage() { +function ExpenseFormPage({ + // #withCurrentOrganization + organization: { base_currency }, +}) { const { id } = useParams(); const expenseId = parseInt(id, 10); return ( - + ); } - \ No newline at end of file +export default compose(withCurrentOrganization())(ExpenseFormPage); diff --git a/src/containers/Expenses/ExpenseForm/ExpenseFormPageProvider.js b/src/containers/Expenses/ExpenseForm/ExpenseFormPageProvider.js index 23b72b704..3d8d69741 100644 --- a/src/containers/Expenses/ExpenseForm/ExpenseFormPageProvider.js +++ b/src/containers/Expenses/ExpenseForm/ExpenseFormPageProvider.js @@ -1,10 +1,14 @@ import React, { createContext } from 'react'; +import { isEqual, isUndefined } from 'lodash'; import DashboardInsider from 'components/Dashboard/DashboardInsider'; +import { Features } from 'common'; +import { useFeatureCan } from 'hooks/state'; import { useCurrencies, useCustomers, useExpense, useAccounts, + useBranches, useCreateExpense, useEditExpense, } from 'hooks/query'; @@ -14,7 +18,11 @@ const ExpenseFormPageContext = createContext(); /** * Accounts chart data provider. */ -function ExpenseFormPageProvider({ expenseId, ...props }) { +function ExpenseFormPageProvider({ query, expenseId, baseCurrency, ...props }) { + // Features guard. + const { featureCan } = useFeatureCan(); + const isBranchFeatureCan = featureCan(Features.Branches); + const { data: currencies, isLoading: isCurrenciesLoading } = useCurrencies(); // Fetches customers list. @@ -24,12 +32,16 @@ function ExpenseFormPageProvider({ expenseId, ...props }) { } = useCustomers(); // Fetch the expense details. - const { data: expense, isLoading: isExpenseLoading } = useExpense( - expenseId, - { - enabled: !!expenseId, - }, - ); + const { data: expense, isLoading: isExpenseLoading } = useExpense(expenseId, { + enabled: !!expenseId, + }); + + // Fetches the branches list. + const { + data: branches, + isLoading: isBranchesLoading, + isSuccess: isBranchesSuccess, + } = useBranches(query, { enabled: isBranchFeatureCan }); // Fetch accounts list. const { data: accounts, isLoading: isAccountsLoading } = useAccounts(); @@ -40,29 +52,40 @@ function ExpenseFormPageProvider({ expenseId, ...props }) { // Submit form payload. const [submitPayload, setSubmitPayload] = React.useState({}); + const [selectCustomer, setSelectCustomer] = React.useState(null); - // + // Detarmines whether the form in new mode. const isNewMode = !expenseId; + // Determines whether the foreign customer. + const isForeignCustomer = + !isEqual(selectCustomer?.currency_code, baseCurrency) && + !isUndefined(selectCustomer?.currency_code); + // Provider payload. const provider = { isNewMode, + isForeignCustomer, expenseId, submitPayload, + selectCustomer, currencies, customers, expense, accounts, + branches, isCurrenciesLoading, isExpenseLoading, isCustomersLoading, isAccountsLoading, + isBranchesSuccess, createExpenseMutate, editExpenseMutate, setSubmitPayload, + setSelectCustomer, }; return ( diff --git a/src/containers/Expenses/ExpenseForm/ExpenseFormTopBar.js b/src/containers/Expenses/ExpenseForm/ExpenseFormTopBar.js new file mode 100644 index 000000000..04ebddacc --- /dev/null +++ b/src/containers/Expenses/ExpenseForm/ExpenseFormTopBar.js @@ -0,0 +1,68 @@ +import React from 'react'; +import intl from 'react-intl-universal'; +import { Button, Alignment, NavbarGroup, Classes } from '@blueprintjs/core'; +import { useSetPrimaryBranchToForm } from './utils'; +import { useFeatureCan } from 'hooks/state'; +import { + Icon, + BranchSelect, + FeatureCan, + FormTopbar, + DetailsBarSkeletonBase, +} from 'components'; +import { useExpenseFormContext } from './ExpenseFormPageProvider'; +import { Features } from 'common'; + +/** + * Expenses form topbar. + * @returns + */ +export default function ExpenseFormTopBar() { + // Features guard. + const { featureCan } = useFeatureCan(); + + // Sets the primary branch to form. + useSetPrimaryBranchToForm(); + + // Can't display the navigation bar if branches feature is not enabled. + if (!featureCan(Features.Branches)) { + return null; + } + + return ( + + + + + + + + ); +} + +function ExpenseFormSelectBranch() { + // Invoice form context. + const { branches, isBranchesLoading } = useExpenseFormContext(); + + return isBranchesLoading ? ( + + ) : ( + + ); +} + +function ExpenseBranchSelectButton({ label }) { + return ( +