mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 05:40:31 +00:00
Merge branch 'develop' into abouhuolia/big-29-no-currency-in-amount-field-on-money-inout-dialogs
This commit is contained in:
@@ -1,119 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React, { useCallback, useState, useEffect, useMemo } from 'react';
|
||||
import { FormattedMessage as T } from '@/components';
|
||||
import intl from 'react-intl-universal';
|
||||
import * as R from 'ramda';
|
||||
|
||||
import { MenuItem, Button } from '@blueprintjs/core';
|
||||
import { Select } from '@blueprintjs/select';
|
||||
import classNames from 'classnames';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
|
||||
import {
|
||||
itemPredicate,
|
||||
handleContactRenderer,
|
||||
createNewItemRenderer,
|
||||
createNewItemFromQuery,
|
||||
} from './utils';
|
||||
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
|
||||
function CustomerSelectFieldRoot({
|
||||
// #withDrawerActions
|
||||
openDrawer,
|
||||
|
||||
// #ownProps
|
||||
contacts,
|
||||
initialContactId,
|
||||
selectedContactId,
|
||||
defaultSelectText = <T id={'select_contact'} />,
|
||||
onContactSelected,
|
||||
popoverFill = false,
|
||||
disabled = false,
|
||||
allowCreate,
|
||||
buttonProps,
|
||||
|
||||
...restProps
|
||||
}) {
|
||||
const localContacts = useMemo(
|
||||
() =>
|
||||
contacts.map((contact) => ({
|
||||
...contact,
|
||||
_id: `${contact.id}_${contact.contact_type}`,
|
||||
})),
|
||||
[contacts],
|
||||
);
|
||||
|
||||
const initialContact = useMemo(
|
||||
() => contacts.find((a) => a.id === initialContactId),
|
||||
[initialContactId, contacts],
|
||||
);
|
||||
|
||||
const [selecetedContact, setSelectedContact] = useState(
|
||||
initialContact || null,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof selectedContactId !== 'undefined') {
|
||||
const account = selectedContactId
|
||||
? contacts.find((a) => a.id === selectedContactId)
|
||||
: null;
|
||||
setSelectedContact(account);
|
||||
}
|
||||
}, [selectedContactId, contacts, setSelectedContact]);
|
||||
|
||||
const handleContactSelect = useCallback(
|
||||
(contact) => {
|
||||
if (contact.id) {
|
||||
setSelectedContact({ ...contact });
|
||||
onContactSelected && onContactSelected(contact);
|
||||
} else {
|
||||
openDrawer(DRAWERS.QUICK_CREATE_CUSTOMER);
|
||||
}
|
||||
},
|
||||
[setSelectedContact, onContactSelected, openDrawer],
|
||||
);
|
||||
|
||||
// Maybe inject create new item props to suggest component.
|
||||
const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null;
|
||||
const maybeCreateNewItemFromQuery = allowCreate
|
||||
? createNewItemFromQuery
|
||||
: null;
|
||||
|
||||
return (
|
||||
<Select
|
||||
items={localContacts}
|
||||
noResults={<MenuItem disabled={true} text={<T id={'no_results'} />} />}
|
||||
itemRenderer={handleContactRenderer}
|
||||
itemPredicate={itemPredicate}
|
||||
filterable={true}
|
||||
disabled={disabled}
|
||||
onItemSelect={handleContactSelect}
|
||||
popoverProps={{ minimal: true, usePortal: !popoverFill }}
|
||||
className={classNames(CLASSES.FORM_GROUP_LIST_SELECT, {
|
||||
[CLASSES.SELECT_LIST_FILL_POPOVER]: popoverFill,
|
||||
})}
|
||||
inputProps={{
|
||||
placeholder: intl.get('filter_'),
|
||||
}}
|
||||
createNewItemRenderer={maybeCreateNewItemRenderer}
|
||||
createNewItemFromQuery={maybeCreateNewItemFromQuery}
|
||||
createNewItemPosition={'top'}
|
||||
{...restProps}
|
||||
>
|
||||
<Button
|
||||
disabled={disabled}
|
||||
text={
|
||||
selecetedContact ? selecetedContact.display_name : defaultSelectText
|
||||
}
|
||||
{...buttonProps}
|
||||
/>
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
|
||||
export const CustomerSelectField = R.compose(withDrawerActions)(
|
||||
CustomerSelectFieldRoot,
|
||||
);
|
||||
48
packages/webapp/src/components/Customers/CustomersSelect.tsx
Normal file
48
packages/webapp/src/components/Customers/CustomersSelect.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import * as R from 'ramda';
|
||||
import { createNewItemFromQuery, createNewItemRenderer } from './utils';
|
||||
import { FSelect } from '../Forms';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
|
||||
/**
|
||||
* Customer select field.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
function CustomerSelectRoot({
|
||||
// #withDrawerActions
|
||||
openDrawer,
|
||||
|
||||
// #ownProps
|
||||
items,
|
||||
allowCreate,
|
||||
...props
|
||||
}) {
|
||||
// Maybe inject create new item props to suggest component.
|
||||
const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null;
|
||||
const maybeCreateNewItemFromQuery = allowCreate
|
||||
? createNewItemFromQuery
|
||||
: null;
|
||||
|
||||
// Handles the create item click.
|
||||
const handleCreateItemClick = () => {
|
||||
openDrawer(DRAWERS.QUICK_CREATE_CUSTOMER);
|
||||
};
|
||||
|
||||
return (
|
||||
<FSelect
|
||||
items={items}
|
||||
textAccessor={'display_name'}
|
||||
labelAccessor={'code'}
|
||||
valueAccessor={'id'}
|
||||
popoverProps={{ minimal: true, usePortal: true, inline: false }}
|
||||
createNewItemRenderer={maybeCreateNewItemRenderer}
|
||||
createNewItemFromQuery={maybeCreateNewItemFromQuery}
|
||||
onCreateItemSelect={handleCreateItemClick}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export const CustomersSelect = R.compose(withDrawerActions)(CustomerSelectRoot);
|
||||
@@ -1,3 +1,3 @@
|
||||
// @ts-nocheck
|
||||
export * from './CustomerSelectField';
|
||||
export * from './CustomerDrawerLink';
|
||||
export * from './CustomersSelect';
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React, { useCallback, useState, useEffect, useMemo } from 'react';
|
||||
import { FormattedMessage as T } from '@/components';
|
||||
import intl from 'react-intl-universal';
|
||||
import * as R from 'ramda';
|
||||
|
||||
import { MenuItem, Button } from '@blueprintjs/core';
|
||||
import { Select } from '@blueprintjs/select';
|
||||
import classNames from 'classnames';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
|
||||
import {
|
||||
itemPredicate,
|
||||
handleContactRenderer,
|
||||
createNewItemFromQuery,
|
||||
createNewItemRenderer,
|
||||
} from './utils';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
|
||||
function VendorSelectFieldRoot({
|
||||
// #withDrawerActions
|
||||
openDrawer,
|
||||
|
||||
// #ownProps
|
||||
contacts,
|
||||
initialContactId,
|
||||
selectedContactId,
|
||||
defaultSelectText = <T id={'select_contact'} />,
|
||||
onContactSelected,
|
||||
popoverFill = false,
|
||||
disabled = false,
|
||||
allowCreate,
|
||||
buttonProps,
|
||||
|
||||
...restProps
|
||||
}) {
|
||||
const localContacts = useMemo(
|
||||
() =>
|
||||
contacts.map((contact) => ({
|
||||
...contact,
|
||||
_id: `${contact.id}_${contact.contact_type}`,
|
||||
})),
|
||||
[contacts],
|
||||
);
|
||||
|
||||
const initialContact = useMemo(
|
||||
() => contacts.find((a) => a.id === initialContactId),
|
||||
[initialContactId, contacts],
|
||||
);
|
||||
|
||||
const [selecetedContact, setSelectedContact] = useState(
|
||||
initialContact || null,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof selectedContactId !== 'undefined') {
|
||||
const account = selectedContactId
|
||||
? contacts.find((a) => a.id === selectedContactId)
|
||||
: null;
|
||||
setSelectedContact(account);
|
||||
}
|
||||
}, [selectedContactId, contacts, setSelectedContact]);
|
||||
|
||||
const handleContactSelect = useCallback(
|
||||
(contact) => {
|
||||
if (contact.id) {
|
||||
setSelectedContact({ ...contact });
|
||||
onContactSelected && onContactSelected(contact);
|
||||
} else {
|
||||
openDrawer(DRAWERS.QUICK_WRITE_VENDOR);
|
||||
}
|
||||
},
|
||||
[setSelectedContact, onContactSelected, openDrawer],
|
||||
);
|
||||
|
||||
// Maybe inject create new item props to suggest component.
|
||||
const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null;
|
||||
const maybeCreateNewItemFromQuery = allowCreate
|
||||
? createNewItemFromQuery
|
||||
: null;
|
||||
|
||||
return (
|
||||
<Select
|
||||
items={localContacts}
|
||||
noResults={<MenuItem disabled={true} text={<T id={'no_results'} />} />}
|
||||
itemRenderer={handleContactRenderer}
|
||||
itemPredicate={itemPredicate}
|
||||
filterable={true}
|
||||
disabled={disabled}
|
||||
onItemSelect={handleContactSelect}
|
||||
popoverProps={{ minimal: true, usePortal: !popoverFill }}
|
||||
className={classNames(CLASSES.FORM_GROUP_LIST_SELECT, {
|
||||
[CLASSES.SELECT_LIST_FILL_POPOVER]: popoverFill,
|
||||
})}
|
||||
inputProps={{
|
||||
placeholder: intl.get('filter_'),
|
||||
}}
|
||||
createNewItemRenderer={maybeCreateNewItemRenderer}
|
||||
createNewItemFromQuery={maybeCreateNewItemFromQuery}
|
||||
createNewItemPosition={'top'}
|
||||
{...restProps}
|
||||
>
|
||||
<Button
|
||||
disabled={disabled}
|
||||
text={
|
||||
selecetedContact ? selecetedContact.display_name : defaultSelectText
|
||||
}
|
||||
{...buttonProps}
|
||||
/>
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
|
||||
export const VendorSelectField = R.compose(withDrawerActions)(
|
||||
VendorSelectFieldRoot,
|
||||
);
|
||||
49
packages/webapp/src/components/Vendors/VendorsSelect.tsx
Normal file
49
packages/webapp/src/components/Vendors/VendorsSelect.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import * as R from 'ramda';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import { createNewItemFromQuery, createNewItemRenderer } from './utils';
|
||||
import { FSelect } from '../Forms';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
|
||||
/**
|
||||
* Vendor select.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
function VendorsSelectRoot({
|
||||
// #withDrawerActions
|
||||
openDrawer,
|
||||
|
||||
// #ownProps
|
||||
items,
|
||||
allowCreate,
|
||||
|
||||
...restProps
|
||||
}) {
|
||||
// Maybe inject create new item props to suggest component.
|
||||
const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null;
|
||||
const maybeCreateNewItemFromQuery = allowCreate
|
||||
? createNewItemFromQuery
|
||||
: null;
|
||||
|
||||
// Handles the create item click.
|
||||
const handleCreateItemClick = () => {
|
||||
openDrawer(DRAWERS.QUICK_WRITE_VENDOR);
|
||||
};
|
||||
|
||||
return (
|
||||
<FSelect
|
||||
items={items}
|
||||
textAccessor={'display_name'}
|
||||
labelAccessor={'code'}
|
||||
valueAccessor={'id'}
|
||||
popoverProps={{ minimal: true, usePortal: true, inline: false }}
|
||||
createNewItemRenderer={maybeCreateNewItemRenderer}
|
||||
createNewItemFromQuery={maybeCreateNewItemFromQuery}
|
||||
onCreateItemSelect={handleCreateItemClick}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export const VendorsSelect = R.compose(withDrawerActions)(VendorsSelectRoot);
|
||||
@@ -1,3 +1,3 @@
|
||||
// @ts-nocheck
|
||||
export * from './VendorDrawerLink'
|
||||
export * from './VendorSelectField'
|
||||
export * from './VendorsSelect';
|
||||
@@ -1,14 +1,8 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import {
|
||||
InputGroup,
|
||||
FormGroup,
|
||||
Position,
|
||||
ControlGroup,
|
||||
} from '@blueprintjs/core';
|
||||
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||
import { InputGroup, FormGroup, Position } from '@blueprintjs/core';
|
||||
import { FastField, ErrorMessage } from 'formik';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import * as R from 'ramda';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
@@ -20,99 +14,15 @@ import {
|
||||
} from '@/utils';
|
||||
import {
|
||||
Hint,
|
||||
FieldHint,
|
||||
FieldRequiredHint,
|
||||
Icon,
|
||||
InputPrependButton,
|
||||
CurrencySelectList,
|
||||
FormattedMessage as T,
|
||||
FInputGroup,
|
||||
FFormGroup,
|
||||
} from '@/components';
|
||||
import { useMakeJournalFormContext } from './MakeJournalProvider';
|
||||
import { JournalExchangeRateInputField } from './components';
|
||||
import { currenciesFieldShouldUpdate } from './utils';
|
||||
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
|
||||
/**
|
||||
* Journal number field of make journal form.
|
||||
*/
|
||||
const MakeJournalTransactionNoField = R.compose(
|
||||
withDialogActions,
|
||||
withSettings(({ manualJournalsSettings }) => ({
|
||||
journalAutoIncrement: manualJournalsSettings?.autoIncrement,
|
||||
})),
|
||||
)(
|
||||
({
|
||||
// #withDialog
|
||||
openDialog,
|
||||
|
||||
// #withSettings
|
||||
journalAutoIncrement,
|
||||
}) => {
|
||||
const { setFieldValue, values } = useFormikContext();
|
||||
|
||||
const handleJournalNumberChange = () => {
|
||||
openDialog('journal-number-form');
|
||||
};
|
||||
const handleJournalNoBlur = (event) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
if (values.journal_number !== newValue && journalAutoIncrement) {
|
||||
openDialog('journal-number-form', {
|
||||
initialFormValues: {
|
||||
onceManualNumber: newValue,
|
||||
incrementMode: 'manual-transaction',
|
||||
},
|
||||
});
|
||||
}
|
||||
if (!journalAutoIncrement) {
|
||||
setFieldValue('journal_number', newValue);
|
||||
setFieldValue('journal_number_manually', newValue);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'journal_number'}
|
||||
label={<T id={'journal_no'} />}
|
||||
labelInfo={
|
||||
<>
|
||||
<FieldRequiredHint />
|
||||
<FieldHint />
|
||||
</>
|
||||
}
|
||||
fill={true}
|
||||
inline={true}
|
||||
fastField={true}
|
||||
>
|
||||
<ControlGroup fill={true}>
|
||||
<FInputGroup
|
||||
name={'journal_number'}
|
||||
fill={true}
|
||||
asyncControl={true}
|
||||
onBlur={handleJournalNoBlur}
|
||||
fastField={true}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<InputPrependButton
|
||||
buttonProps={{
|
||||
onClick: handleJournalNumberChange,
|
||||
icon: <Icon icon={'settings-18'} />,
|
||||
}}
|
||||
tooltip={true}
|
||||
tooltipProps={{
|
||||
content: <T id={'setting_your_auto_generated_journal_number'} />,
|
||||
position: Position.BOTTOM_LEFT,
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FFormGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
import { MakeJournalTransactionNoField } from './MakeJournalTransactionNoField';
|
||||
|
||||
/**
|
||||
* Make journal entries header.
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { Position, ControlGroup } from '@blueprintjs/core';
|
||||
import { useFormikContext } from 'formik';
|
||||
import * as R from 'ramda';
|
||||
import {
|
||||
FieldHint,
|
||||
FieldRequiredHint,
|
||||
Icon,
|
||||
InputPrependButton,
|
||||
FormattedMessage as T,
|
||||
FInputGroup,
|
||||
FFormGroup,
|
||||
} from '@/components';
|
||||
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
|
||||
/**
|
||||
* Journal number field of make journal form.
|
||||
*/
|
||||
export const MakeJournalTransactionNoField = R.compose(
|
||||
withDialogActions,
|
||||
withSettings(({ manualJournalsSettings }) => ({
|
||||
journalAutoIncrement: manualJournalsSettings?.autoIncrement,
|
||||
})),
|
||||
)(
|
||||
({
|
||||
// #withDialog
|
||||
openDialog,
|
||||
|
||||
// #withSettings
|
||||
journalAutoIncrement,
|
||||
}) => {
|
||||
const { setFieldValue, values } = useFormikContext();
|
||||
|
||||
const handleJournalNumberChange = () => {
|
||||
openDialog('journal-number-form');
|
||||
};
|
||||
const handleJournalNoBlur = (event) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
if (values.journal_number !== newValue && journalAutoIncrement) {
|
||||
openDialog('journal-number-form', {
|
||||
initialFormValues: {
|
||||
onceManualNumber: newValue,
|
||||
incrementMode: 'manual-transaction',
|
||||
},
|
||||
});
|
||||
}
|
||||
if (!journalAutoIncrement) {
|
||||
setFieldValue('journal_number', newValue);
|
||||
setFieldValue('journal_number_manually', newValue);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'journal_number'}
|
||||
label={<T id={'journal_no'} />}
|
||||
labelInfo={
|
||||
<>
|
||||
<FieldRequiredHint />
|
||||
<FieldHint />
|
||||
</>
|
||||
}
|
||||
fill={true}
|
||||
inline={true}
|
||||
fastField={true}
|
||||
>
|
||||
<ControlGroup fill={true}>
|
||||
<FInputGroup
|
||||
name={'journal_number'}
|
||||
fill={true}
|
||||
asyncControl={true}
|
||||
onBlur={handleJournalNoBlur}
|
||||
fastField={true}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<InputPrependButton
|
||||
buttonProps={{
|
||||
onClick: handleJournalNumberChange,
|
||||
icon: <Icon icon={'settings-18'} />,
|
||||
}}
|
||||
tooltip={true}
|
||||
tooltipProps={{
|
||||
content: <T id={'setting_your_auto_generated_journal_number'} />,
|
||||
position: Position.BOTTOM_LEFT,
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FFormGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
MakeJournalTransactionNoField.displayName = 'MakeJournalTransactionNoField';
|
||||
@@ -99,6 +99,7 @@ export default function OtherIncomeFormFields() {
|
||||
)}
|
||||
</FastField>
|
||||
</Col>
|
||||
|
||||
<Col xs={5}>
|
||||
{/*------------ Transaction number -----------*/}
|
||||
<MoneyInOutTransactionNoField />
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Intent } from '@blueprintjs/core';
|
||||
import { AppToaster } from '@/components';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { useQuickPaymentMadeContext } from './QuickPaymentMadeFormProvider';
|
||||
import { PAYMENT_MADE_ERRORS } from '@/containers/Purchases/PaymentMades/constants';
|
||||
|
||||
// Default initial values of payment made.
|
||||
export const defaultPaymentMade = {
|
||||
@@ -24,16 +25,16 @@ export const defaultPaymentMade = {
|
||||
export const transformErrors = (errors, { setFieldError }) => {
|
||||
const getError = (errorType) => errors.find((e) => e.type === errorType);
|
||||
|
||||
if (getError('PAYMENT.NUMBER.NOT.UNIQUE')) {
|
||||
if (getError(PAYMENT_MADE_ERRORS.PAYMENT_NUMBER_NOT_UNIQUE)) {
|
||||
setFieldError('payment_number', intl.get('payment_number_is_not_unique'));
|
||||
}
|
||||
if (getError('INVALID_BILL_PAYMENT_AMOUNT')) {
|
||||
if (getError(PAYMENT_MADE_ERRORS.INVALID_BILL_PAYMENT_AMOUNT)) {
|
||||
setFieldError(
|
||||
'payment_amount',
|
||||
intl.get('the_payment_amount_bigger_than_invoice_due_amount'),
|
||||
);
|
||||
}
|
||||
if (getError('WITHDRAWAL_ACCOUNT_CURRENCY_INVALID')) {
|
||||
if (getError(PAYMENT_MADE_ERRORS.WITHDRAWAL_ACCOUNT_CURRENCY_INVALID)) {
|
||||
AppToaster.show({
|
||||
message: intl.get(
|
||||
'payment_made.error.withdrawal_account_currency_invalid',
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
|
||||
import { Card } from '@/components';
|
||||
import { Card, CommercialDocBox } from '@/components';
|
||||
|
||||
import CashflowTransactionDrawerActionBar from './CashflowTransactionDrawerActionBar';
|
||||
import CashflowTransactionDrawerHeader from './CashflowTransactionDrawerHeader';
|
||||
import CashflowTransactionDrawerTable from './CashflowTransactionDrawerTable';
|
||||
import CashflowTransactionDrawerFooter from './CashflowTransactionDrawerFooter';
|
||||
import CashflowTransactionDrawerTableFooter from './CashflowTransactionDrawerTableFooter';
|
||||
import { CashflowTransactionDrawerFooter } from './CashflowTransactionDrawerFooter';
|
||||
/**
|
||||
* Cashflow transaction view details.
|
||||
*/
|
||||
@@ -16,11 +17,12 @@ export default function CashflowTransactionDrawerDetails() {
|
||||
<CashflowTransactionDrawerActionBar />
|
||||
|
||||
<div className="cashflow-drawer__content">
|
||||
<Card>
|
||||
<CommercialDocBox>
|
||||
<CashflowTransactionDrawerHeader />
|
||||
<CashflowTransactionDrawerTable />
|
||||
<CashflowTransactionDrawerTableFooter />
|
||||
<CashflowTransactionDrawerFooter />
|
||||
</Card>
|
||||
</CommercialDocBox>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,35 +1,18 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { CommercialDocFooter, DetailsMenu, DetailItem, T } from '@/components';
|
||||
import { useCashflowTransactionDrawerContext } from './CashflowTransactionDrawerProvider';
|
||||
import { T, FormatNumber } from '@/components';
|
||||
|
||||
export default function CashflowTransactionDrawerFooter() {
|
||||
const {
|
||||
cashflowTransaction: { formatted_amount },
|
||||
} = useCashflowTransactionDrawerContext();
|
||||
export function CashflowTransactionDrawerFooter() {
|
||||
const { cashflowTransaction } = useCashflowTransactionDrawerContext();
|
||||
|
||||
return (
|
||||
<div className="cashflow-drawer__content-footer">
|
||||
<div class="total-lines">
|
||||
<div class="total-lines__line total-lines__line--subtotal">
|
||||
<div class="title">
|
||||
<T id={'manual_journal.details.subtotal'} />
|
||||
</div>
|
||||
<div class="debit">
|
||||
<FormatNumber value={formatted_amount} />
|
||||
</div>
|
||||
<div class="credit">
|
||||
<FormatNumber value={formatted_amount} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="total-lines__line total-lines__line--total">
|
||||
<div class="title">
|
||||
<T id={'manual_journal.details.total'} />
|
||||
</div>
|
||||
<div class="debit">{formatted_amount}</div>
|
||||
<div class="credit">{formatted_amount}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<CommercialDocFooter>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||
<DetailItem label={<T id={'cash_flow.drawer.label.statement'} />}>
|
||||
{cashflowTransaction.description}
|
||||
</DetailItem>
|
||||
</DetailsMenu>
|
||||
</CommercialDocFooter>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { useCashflowTransactionDrawerContext } from './CashflowTransactionDrawerProvider';
|
||||
import { T, FormatNumber } from '@/components';
|
||||
|
||||
export default function CashflowTransactionDrawerTableFooter() {
|
||||
const {
|
||||
cashflowTransaction: { formatted_amount },
|
||||
} = useCashflowTransactionDrawerContext();
|
||||
|
||||
return (
|
||||
<div className="cashflow-drawer__content-footer">
|
||||
<div class="total-lines">
|
||||
<div class="total-lines__line total-lines__line--subtotal">
|
||||
<div class="title">
|
||||
<T id={'manual_journal.details.subtotal'} />
|
||||
</div>
|
||||
<div class="debit">
|
||||
<FormatNumber value={formatted_amount} />
|
||||
</div>
|
||||
<div class="credit">
|
||||
<FormatNumber value={formatted_amount} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="total-lines__line total-lines__line--total">
|
||||
<div class="title">
|
||||
<T id={'manual_journal.details.total'} />
|
||||
</div>
|
||||
<div class="debit">{formatted_amount}</div>
|
||||
<div class="credit">{formatted_amount}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
CommercialDocFooter,
|
||||
T,
|
||||
|
||||
@@ -17,16 +17,6 @@ import withDashboardActions from '@/containers/Dashboard/withDashboardActions';
|
||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
|
||||
/**
|
||||
* Drawer item form loading.
|
||||
* @returns {JSX}
|
||||
*/
|
||||
function DrawerItemFormLoading({ children }) {
|
||||
const { isFormLoading } = useItemFormContext();
|
||||
|
||||
return <DrawerLoading loading={isFormLoading}>{children}</DrawerLoading>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick create/edit item drawer form.
|
||||
*/
|
||||
@@ -72,6 +62,16 @@ function QuickCreateItemDrawerForm({
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drawer item form loading.
|
||||
* @returns {JSX}
|
||||
*/
|
||||
function DrawerItemFormLoading({ children }) {
|
||||
const { isFormLoading } = useItemFormContext();
|
||||
|
||||
return <DrawerLoading loading={isFormLoading}>{children}</DrawerLoading>;
|
||||
}
|
||||
|
||||
export default R.compose(
|
||||
withDrawerActions,
|
||||
withDashboardActions,
|
||||
@@ -79,10 +79,15 @@ export default R.compose(
|
||||
|
||||
const ItemFormCard = styled(Card)`
|
||||
margin: 15px;
|
||||
padding: 25px;
|
||||
margin-bottom: calc(15px + 65px);
|
||||
|
||||
.page-form__floating-actions {
|
||||
margin-left: -36px;
|
||||
margin-right: -36px;
|
||||
.page-form {
|
||||
padding: 0;
|
||||
|
||||
&__floating-actions {
|
||||
margin-left: -41px;
|
||||
margin-right: -41px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from 'react';
|
||||
import { InputGroup, FormGroup, Position, Classes } from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FastField, ErrorMessage } from 'formik';
|
||||
import { FormattedMessage as T } from '@/components';
|
||||
import { CustomersSelect, FormattedMessage as T } from '@/components';
|
||||
import classNames from 'classnames';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import {
|
||||
@@ -121,33 +121,39 @@ export default function ExpenseFormHeader() {
|
||||
)}
|
||||
</FastField>
|
||||
|
||||
<FastField
|
||||
name={'customer_id'}
|
||||
customers={customers}
|
||||
shouldUpdate={customersFieldShouldUpdate}
|
||||
>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'customer'} />}
|
||||
className={classNames('form-group--select-list', Classes.FILL)}
|
||||
labelInfo={<Hint />}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name={'assign_to_customer'} />}
|
||||
inline={true}
|
||||
>
|
||||
<CustomerSelectField
|
||||
contacts={customers}
|
||||
selectedContactId={value}
|
||||
defaultSelectText={<T id={'select_customer_account'} />}
|
||||
onContactSelected={(customer) => {
|
||||
form.setFieldValue('customer_id', customer.id);
|
||||
}}
|
||||
allowCreate={true}
|
||||
popoverFill={true}
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
{/* ----------- Customer ----------- */}
|
||||
<ExpenseFormCustomerSelect />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Customer select field of expense form.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
function ExpenseFormCustomerSelect() {
|
||||
const { customers } = useExpenseFormContext();
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
label={<T id={'customer'} />}
|
||||
labelInfo={<Hint />}
|
||||
inline={true}
|
||||
name={'customer_id'}
|
||||
fastField={true}
|
||||
shouldUpdateDeps={{ items: customers }}
|
||||
shouldUpdate={customersFieldShouldUpdate}
|
||||
>
|
||||
<CustomersSelect
|
||||
name={'customer_id'}
|
||||
items={customers}
|
||||
placeholder={<T id={'select_customer_account'} />}
|
||||
allowCreate={true}
|
||||
popoverFill={true}
|
||||
fastField={true}
|
||||
shouldUpdateDeps={{ items: customers }}
|
||||
shouldUpdate={customersFieldShouldUpdate}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ export const transformToEditForm = (
|
||||
*/
|
||||
export const customersFieldShouldUpdate = (newProps, oldProps) => {
|
||||
return (
|
||||
newProps.customers !== oldProps.customers ||
|
||||
newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items ||
|
||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -90,7 +90,9 @@ export default function ItemFormFormik({
|
||||
};
|
||||
|
||||
return (
|
||||
<div class={classNames(CLASSES.PAGE_FORM_ITEM, className)}>
|
||||
<div
|
||||
class={classNames(CLASSES.PAGE_FORM, CLASSES.PAGE_FORM_ITEM, className)}
|
||||
>
|
||||
<Formik
|
||||
enableReinitialize={true}
|
||||
validationSchema={isNewMode ? CreateItemFormSchema : EditItemFormSchema}
|
||||
|
||||
@@ -15,11 +15,10 @@ import {
|
||||
FMoneyInputGroup,
|
||||
InputPrependText,
|
||||
FormattedMessage as T,
|
||||
FieldRequiredHint,
|
||||
CustomerSelectField,
|
||||
Stack,
|
||||
CustomersSelect,
|
||||
} from '@/components';
|
||||
import { inputIntent, momentFormatter } from '@/utils';
|
||||
import { momentFormatter } from '@/utils';
|
||||
import { useProjectFormContext } from './ProjectFormProvider';
|
||||
|
||||
/**
|
||||
@@ -27,9 +26,6 @@ import { useProjectFormContext } from './ProjectFormProvider';
|
||||
* @returns
|
||||
*/
|
||||
function ProjectFormFields() {
|
||||
// project form dialog context.
|
||||
const { customers } = useProjectFormContext();
|
||||
|
||||
// Formik context.
|
||||
const { values } = useFormikContext();
|
||||
|
||||
@@ -37,26 +33,7 @@ function ProjectFormFields() {
|
||||
<div className={Classes.DIALOG_BODY}>
|
||||
<Stack spacing={25}>
|
||||
{/*------------ Contact -----------*/}
|
||||
<FastField name={'contact_id'}>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={intl.get('projects.dialog.contact')}
|
||||
className={classNames('form-group--select-list', Classes.FILL)}
|
||||
intent={inputIntent({ error, touched })}
|
||||
>
|
||||
<CustomerSelectField
|
||||
contacts={customers}
|
||||
selectedContactId={value}
|
||||
defaultSelectText={'Find or create a customer'}
|
||||
onContactSelected={(customer) => {
|
||||
form.setFieldValue('contact_id', customer.id);
|
||||
}}
|
||||
allowCreate={true}
|
||||
popoverFill={true}
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
<ProjectFormCustomerSelect />
|
||||
|
||||
{/*------------ Project Name -----------*/}
|
||||
<FFormGroup
|
||||
@@ -113,4 +90,21 @@ function ProjectFormFields() {
|
||||
);
|
||||
}
|
||||
|
||||
function ProjectFormCustomerSelect() {
|
||||
// project form dialog context.
|
||||
const { customers } = useProjectFormContext();
|
||||
|
||||
return (
|
||||
<FormGroup name={'contact_id'} label={intl.get('projects.dialog.contact')}>
|
||||
<CustomersSelect
|
||||
name={'contact_id'}
|
||||
items={customers}
|
||||
placeholder={'Find or create a customer'}
|
||||
allowCreate={true}
|
||||
popoverFill={true}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProjectFormFields;
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import classNames from 'classnames';
|
||||
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||
import { FormGroup, InputGroup, Classes, Position } from '@blueprintjs/core';
|
||||
import { FastField, ErrorMessage } from 'formik';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
|
||||
import { FeatureCan, FormattedMessage as T } from '@/components';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
|
||||
import {
|
||||
FFormGroup,
|
||||
VendorSelectField,
|
||||
FieldRequiredHint,
|
||||
Icon,
|
||||
VendorDrawerLink,
|
||||
VendorsSelect,
|
||||
} from '@/components';
|
||||
|
||||
import { useBillFormContext } from './BillFormProvider';
|
||||
@@ -43,43 +43,7 @@ function BillFormHeader() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
{/* ------- Vendor name ------ */}
|
||||
<FastField
|
||||
name={'vendor_id'}
|
||||
vendors={vendors}
|
||||
shouldUpdate={vendorsFieldShouldUpdate}
|
||||
>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FFormGroup
|
||||
name={'vendor_id'}
|
||||
label={<T id={'vendor_name'} />}
|
||||
inline={true}
|
||||
className={classNames(
|
||||
'form-group--vendor-name',
|
||||
'form-group--select-list',
|
||||
CLASSES.FILL,
|
||||
)}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
>
|
||||
<VendorSelectField
|
||||
contacts={vendors}
|
||||
selectedContactId={value}
|
||||
defaultSelectText={<T id={'select_vender_account'} />}
|
||||
onContactSelected={(contact) => {
|
||||
form.setFieldValue('vendor_id', contact.id);
|
||||
form.setFieldValue('currency_code', contact?.currency_code);
|
||||
}}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
/>
|
||||
|
||||
{value && (
|
||||
<VendorButtonLink vendorId={value}>
|
||||
<T id={'view_vendor_details'} />
|
||||
</VendorButtonLink>
|
||||
)}
|
||||
</FFormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
<BillFormVendorField />
|
||||
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<BillExchangeRateInputField
|
||||
@@ -190,6 +154,46 @@ function BillFormHeader() {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vendor select field of bill form.
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
function BillFormVendorField() {
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
const { vendors } = useBillFormContext();
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'vendor_id'}
|
||||
label={<T id={'vendor_name'} />}
|
||||
inline={true}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
fastField={true}
|
||||
shouldUpdate={vendorsFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: vendors }}
|
||||
>
|
||||
<VendorsSelect
|
||||
name={'vendor_id'}
|
||||
items={vendors}
|
||||
placeholder={<T id={'select_vender_account'} />}
|
||||
onItemChange={(contact) => {
|
||||
setFieldValue('vendor_id', contact.id);
|
||||
setFieldValue('currency_code', contact?.currency_code);
|
||||
}}
|
||||
allowCreate={true}
|
||||
fastField={true}
|
||||
shouldUpdate={vendorsFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: vendors }}
|
||||
/>
|
||||
{values.vendor_id && (
|
||||
<VendorButtonLink vendorId={values.vendor_id}>
|
||||
<T id={'view_vendor_details'} />
|
||||
</VendorButtonLink>
|
||||
)}
|
||||
</FFormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(withDialogActions)(BillFormHeader);
|
||||
|
||||
const VendorButtonLink = styled(VendorDrawerLink)`
|
||||
|
||||
@@ -19,7 +19,10 @@ import {
|
||||
ensureEntriesHaveEmptyLine,
|
||||
} from '@/containers/Entries/utils';
|
||||
import { useCurrentOrganization } from '@/hooks/state';
|
||||
import { isLandedCostDisabled, getEntriesTotal } from '@/containers/Entries/utils';
|
||||
import {
|
||||
isLandedCostDisabled,
|
||||
getEntriesTotal,
|
||||
} from '@/containers/Entries/utils';
|
||||
import { useBillFormContext } from './BillFormProvider';
|
||||
|
||||
export const MIN_LINES_NUMBER = 1;
|
||||
@@ -153,7 +156,7 @@ export const handleDeleteErrors = (errors) => {
|
||||
*/
|
||||
export const vendorsFieldShouldUpdate = (newProps, oldProps) => {
|
||||
return (
|
||||
newProps.vendors !== oldProps.vendors ||
|
||||
newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items ||
|
||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,17 +9,17 @@ import {
|
||||
ControlGroup,
|
||||
} from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FastField, ErrorMessage } from 'formik';
|
||||
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
|
||||
import {
|
||||
FFormGroup,
|
||||
VendorSelectField,
|
||||
FieldRequiredHint,
|
||||
InputPrependButton,
|
||||
Icon,
|
||||
FormattedMessage as T,
|
||||
VendorDrawerLink,
|
||||
VendorsSelect,
|
||||
} from '@/components';
|
||||
import {
|
||||
vendorsFieldShouldUpdate,
|
||||
@@ -51,9 +51,6 @@ function VendorCreditNoteFormHeaderFields({
|
||||
vendorcreditNumberPrefix,
|
||||
vendorcreditNextNumber,
|
||||
}) {
|
||||
// Vendor Credit form context.
|
||||
const { vendors } = useVendorCreditNoteFormContext();
|
||||
|
||||
// Handle vendor credit number changing.
|
||||
const handleVendorCreditNumberChange = () => {
|
||||
openDialog('vendor-credit-form');
|
||||
@@ -81,39 +78,7 @@ function VendorCreditNoteFormHeaderFields({
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
{/* ----------- Vendor name ----------- */}
|
||||
<FastField
|
||||
name={'vendor_id'}
|
||||
vendors={vendors}
|
||||
shouldUpdate={vendorsFieldShouldUpdate}
|
||||
>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FFormGroup
|
||||
name={'vendor_id'}
|
||||
label={<T id={'vendor_name'} />}
|
||||
inline={true}
|
||||
className={classNames(CLASSES.FILL, 'form-group--vendor')}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
>
|
||||
<VendorSelectField
|
||||
contacts={vendors}
|
||||
selectedContactId={value}
|
||||
defaultSelectText={<T id={'select_vender_account'} />}
|
||||
onContactSelected={(contact) => {
|
||||
form.setFieldValue('vendor_id', contact.id);
|
||||
form.setFieldValue('currency_code', contact?.currency_code);
|
||||
}}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
/>
|
||||
|
||||
{value && (
|
||||
<VendorButtonLink vendorId={value}>
|
||||
<T id={'view_vendor_details'} />
|
||||
</VendorButtonLink>
|
||||
)}
|
||||
</FFormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
<VendorCreditFormVendorSelect />
|
||||
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<VendorCreditNoteExchangeRateInputField
|
||||
@@ -205,6 +170,49 @@ function VendorCreditNoteFormHeaderFields({
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vendor select field of vendor credit form.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
function VendorCreditFormVendorSelect() {
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
// Vendor Credit form context.
|
||||
const { vendors } = useVendorCreditNoteFormContext();
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'vendor_id'}
|
||||
label={<T id={'vendor_name'} />}
|
||||
inline={true}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
fastField={true}
|
||||
shouldUpdate={vendorsFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: vendors }}
|
||||
>
|
||||
<VendorsSelect
|
||||
name={'vendor_id'}
|
||||
items={vendors}
|
||||
placeholder={<T id={'select_vender_account'} />}
|
||||
onItemChange={(contact) => {
|
||||
setFieldValue('vendor_id', contact.id);
|
||||
setFieldValue('currency_code', contact?.currency_code);
|
||||
}}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
fastField={true}
|
||||
shouldUpdate={vendorsFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: vendors }}
|
||||
/>
|
||||
{values.vendor_id && (
|
||||
<VendorButtonLink vendorId={values.vendor_id}>
|
||||
<T id={'view_vendor_details'} />
|
||||
</VendorButtonLink>
|
||||
)}
|
||||
</FFormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withDialogActions,
|
||||
withSettings(({ vendorsCreditNoteSetting }) => ({
|
||||
|
||||
@@ -113,7 +113,7 @@ export const transformFormValuesToRequest = (values) => {
|
||||
*/
|
||||
export const vendorsFieldShouldUpdate = (newProps, oldProps) => {
|
||||
return (
|
||||
newProps.vendors !== oldProps.vendors ||
|
||||
newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items ||
|
||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,12 +13,14 @@ export function PaymentMadeFormFooterLeft() {
|
||||
<React.Fragment>
|
||||
{/* --------- Internal Note--------- */}
|
||||
<InternalNoteFormGroup
|
||||
name={'internal_note'}
|
||||
name={'statement'}
|
||||
label={<T id={'payment_made.form.internal_note.label'} />}
|
||||
fastField={true}
|
||||
>
|
||||
<FEditableText
|
||||
name={'internal_note'}
|
||||
name={'statement'}
|
||||
placeholder={intl.get('payment_made.form.internal_note.placeholder')}
|
||||
fastField={true}
|
||||
/>
|
||||
</InternalNoteFormGroup>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -12,14 +12,13 @@ import {
|
||||
} from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FastField, Field, useFormikContext, ErrorMessage } from 'formik';
|
||||
import { FormattedMessage as T } from '@/components';
|
||||
import { FormattedMessage as T, VendorsSelect } from '@/components';
|
||||
import { toSafeInteger } from 'lodash';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
|
||||
import {
|
||||
FFormGroup,
|
||||
AccountsSelect,
|
||||
VendorSelectField,
|
||||
FieldRequiredHint,
|
||||
InputPrependText,
|
||||
Money,
|
||||
@@ -55,8 +54,7 @@ function PaymentMadeFormHeaderFields({ organization: { base_currency } }) {
|
||||
} = useFormikContext();
|
||||
|
||||
// Payment made form context.
|
||||
const { vendors, accounts, isNewMode, setPaymentVendorId } =
|
||||
usePaymentMadeFormContext();
|
||||
const { accounts } = usePaymentMadeFormContext();
|
||||
|
||||
// Sumation of payable full-amount.
|
||||
const payableFullAmount = useMemo(
|
||||
@@ -82,41 +80,7 @@ function PaymentMadeFormHeaderFields({ organization: { base_currency } }) {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
{/* ------------ Vendor name ------------ */}
|
||||
<FastField
|
||||
name={'vendor_id'}
|
||||
vendors={vendors}
|
||||
shouldUpdate={vendorsFieldShouldUpdate}
|
||||
>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FFormGroup
|
||||
name={'vendor_id'}
|
||||
label={<T id={'vendor_name'} />}
|
||||
inline={true}
|
||||
className={classNames('form-group--select-list', Classes.FILL)}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
>
|
||||
<VendorSelectField
|
||||
contacts={vendors}
|
||||
selectedContactId={value}
|
||||
defaultSelectText={<T id={'select_vender_account'} />}
|
||||
onContactSelected={(contact) => {
|
||||
form.setFieldValue('vendor_id', contact.id);
|
||||
form.setFieldValue('currency_code', contact?.currency_code);
|
||||
setPaymentVendorId(contact.id);
|
||||
}}
|
||||
disabled={!isNewMode}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
/>
|
||||
|
||||
{value && (
|
||||
<VendorButtonLink vendorId={value}>
|
||||
<T id={'view_vendor_details'} />
|
||||
</VendorButtonLink>
|
||||
)}
|
||||
</FFormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
<PaymentFormVendorSelect />
|
||||
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<PaymentMadeExchangeRateInputField
|
||||
@@ -258,6 +222,52 @@ function PaymentMadeFormHeaderFields({ organization: { base_currency } }) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vendor select field of payment receive form.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
function PaymentFormVendorSelect() {
|
||||
// Formik form context.
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
// Payment made form context.
|
||||
const { vendors, isNewMode, setPaymentVendorId } =
|
||||
usePaymentMadeFormContext();
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'vendor_id'}
|
||||
label={<T id={'vendor_name'} />}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
inline={true}
|
||||
fastField={true}
|
||||
shouldUpdate={vendorsFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: vendors }}
|
||||
>
|
||||
<VendorsSelect
|
||||
name={'vendor_id'}
|
||||
items={vendors}
|
||||
placeholder={<T id={'select_vender_account'} />}
|
||||
onItemChange={(contact) => {
|
||||
setFieldValue('vendor_id', contact.id);
|
||||
setFieldValue('currency_code', contact?.currency_code);
|
||||
setPaymentVendorId(contact.id);
|
||||
}}
|
||||
disabled={!isNewMode}
|
||||
allowCreate={true}
|
||||
fastField={true}
|
||||
shouldUpdate={vendorsFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: vendors }}
|
||||
/>
|
||||
{values.vendor_id && (
|
||||
<VendorButtonLink vendorId={values.vendor_id}>
|
||||
<T id={'view_vendor_details'} />
|
||||
</VendorButtonLink>
|
||||
)}
|
||||
</FFormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(withCurrentOrganization())(PaymentMadeFormHeaderFields);
|
||||
|
||||
const VendorButtonLink = styled(VendorDrawerLink)`
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
formattedAmount,
|
||||
} from '@/utils';
|
||||
import { useCurrentOrganization } from '@/hooks/state';
|
||||
import { PAYMENT_MADE_ERRORS } from '../constants';
|
||||
|
||||
export const ERRORS = {
|
||||
PAYMENT_NUMBER_NOT_UNIQUE: 'PAYMENT.NUMBER.NOT.UNIQUE',
|
||||
@@ -74,7 +75,7 @@ export const transformToNewPageEntries = (entries) => {
|
||||
*/
|
||||
export const vendorsFieldShouldUpdate = (newProps, oldProps) => {
|
||||
return (
|
||||
newProps.vendors !== oldProps.vendors ||
|
||||
newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items ||
|
||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||
);
|
||||
};
|
||||
@@ -124,10 +125,10 @@ export const useSetPrimaryBranchToForm = () => {
|
||||
export const transformErrors = (errors, { setFieldError }) => {
|
||||
const getError = (errorType) => errors.find((e) => e.type === errorType);
|
||||
|
||||
if (getError('PAYMENT_NUMBER_NOT_UNIQUE')) {
|
||||
if (getError(PAYMENT_MADE_ERRORS.PAYMENT_NUMBER_NOT_UNIQUE)) {
|
||||
setFieldError('payment_number', intl.get('payment_number_is_not_unique'));
|
||||
}
|
||||
if (getError('WITHDRAWAL_ACCOUNT_CURRENCY_INVALID')) {
|
||||
if (getError(PAYMENT_MADE_ERRORS.WITHDRAWAL_ACCOUNT_CURRENCY_INVALID)) {
|
||||
AppToaster.show({
|
||||
message: intl.get(
|
||||
'payment_made.error.withdrawal_account_currency_invalid',
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export const PAYMENT_MADE_ERRORS = {
|
||||
PAYMENT_NUMBER_NOT_UNIQUE: 'PAYMENT.NUMBER.NOT.UNIQUE',
|
||||
WITHDRAWAL_ACCOUNT_CURRENCY_INVALID: 'WITHDRAWAL_ACCOUNT_CURRENCY_INVALID',
|
||||
INVALID_BILL_PAYMENT_AMOUNT: 'INVALID_BILL_PAYMENT_AMOUNT'
|
||||
};
|
||||
@@ -1,34 +1,25 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import * as R from 'ramda';
|
||||
import classNames from 'classnames';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
FormGroup,
|
||||
InputGroup,
|
||||
Position,
|
||||
ControlGroup,
|
||||
} from '@blueprintjs/core';
|
||||
import { FormGroup, InputGroup, Position } from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import {
|
||||
CustomerSelectField,
|
||||
FieldRequiredHint,
|
||||
InputPrependButton,
|
||||
Icon,
|
||||
FormattedMessage as T,
|
||||
CustomerDrawerLink,
|
||||
FFormGroup,
|
||||
FInputGroup,
|
||||
CustomersSelect,
|
||||
} from '@/components';
|
||||
import { customerNameFieldShouldUpdate } from './utils';
|
||||
|
||||
import { useCreditNoteFormContext } from './CreditNoteFormProvider';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
import { CreditNoteExchangeRateInputField } from './components';
|
||||
import { CreditNoteTransactionNoField } from './CreditNoteTransactionNoField';
|
||||
import {
|
||||
momentFormatter,
|
||||
tansformDateValue,
|
||||
@@ -36,134 +27,14 @@ import {
|
||||
handleDateChange,
|
||||
} from '@/utils';
|
||||
|
||||
/**
|
||||
* Credit note transaction number field.
|
||||
*/
|
||||
const CreditNoteTransactionNoField = R.compose(
|
||||
withDialogActions,
|
||||
withSettings(({ creditNoteSettings }) => ({
|
||||
creditAutoIncrement: creditNoteSettings?.autoIncrement,
|
||||
creditNextNumber: creditNoteSettings?.nextNumber,
|
||||
creditNumberPrefix: creditNoteSettings?.numberPrefix,
|
||||
})),
|
||||
)(
|
||||
({
|
||||
// #withDialogActions
|
||||
openDialog,
|
||||
|
||||
// #withSettings
|
||||
creditAutoIncrement,
|
||||
}) => {
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
// Handle credit number changing.
|
||||
const handleCreditNumberChange = () => {
|
||||
openDialog('credit-number-form');
|
||||
};
|
||||
// Handle credit note no. field blur.
|
||||
const handleCreditNoBlur = (event) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
// Show the confirmation dialog if the value has changed and auto-increment
|
||||
// mode is enabled.
|
||||
if (values.credit_note_no !== newValue && creditAutoIncrement) {
|
||||
openDialog('credit-number-form', {
|
||||
initialFormValues: {
|
||||
onceManualNumber: newValue,
|
||||
incrementMode: 'manual-transaction',
|
||||
},
|
||||
});
|
||||
}
|
||||
// Setting the credit note number to the form will be manually in case
|
||||
// auto-increment is disable.
|
||||
if (!creditAutoIncrement) {
|
||||
setFieldValue('credit_note_number', newValue);
|
||||
setFieldValue('credit_note_number_manually', newValue);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'credit_note_number'}
|
||||
label={<T id={'credit_note.label_credit_note'} />}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
inline={true}
|
||||
>
|
||||
<ControlGroup fill={true}>
|
||||
<FInputGroup
|
||||
name={'credit_note_number'}
|
||||
minimal={true}
|
||||
value={values.credit_note_number}
|
||||
asyncControl={true}
|
||||
onBlur={handleCreditNoBlur}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<InputPrependButton
|
||||
buttonProps={{
|
||||
onClick: handleCreditNumberChange,
|
||||
icon: <Icon icon={'settings-18'} />,
|
||||
}}
|
||||
tooltip={true}
|
||||
tooltipProps={{
|
||||
content: (
|
||||
<T id={'setting_your_auto_generated_credit_note_number'} />
|
||||
),
|
||||
position: Position.BOTTOM_LEFT,
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FFormGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Credit note form header fields.
|
||||
*/
|
||||
export default function CreditNoteFormHeaderFields({}) {
|
||||
// Credit note form context.
|
||||
const { customers } = useCreditNoteFormContext();
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
{/* ----------- Customer name ----------- */}
|
||||
<FastField
|
||||
name={'customer_id'}
|
||||
customers={customers}
|
||||
shouldUpdate={customerNameFieldShouldUpdate}
|
||||
>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'customer_name'} />}
|
||||
inline={true}
|
||||
className={classNames(
|
||||
'form-group--customer-name',
|
||||
'form-group--select-list',
|
||||
CLASSES.FILL,
|
||||
)}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name={'customer_id'} />}
|
||||
>
|
||||
<CustomerSelectField
|
||||
contacts={customers}
|
||||
selectedContactId={value}
|
||||
defaultSelectText={<T id={'select_customer_account'} />}
|
||||
onContactSelected={(customer) => {
|
||||
form.setFieldValue('customer_id', customer.id);
|
||||
form.setFieldValue('currency_code', customer?.currency_code);
|
||||
}}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
/>
|
||||
{value && (
|
||||
<CustomerButtonLink customerId={value}>
|
||||
<T id={'view_customer_details'} />
|
||||
</CustomerButtonLink>
|
||||
)}
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
<CreditNoteCustomersSelect />
|
||||
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<CreditNoteExchangeRateInputField
|
||||
@@ -216,6 +87,48 @@ export default function CreditNoteFormHeaderFields({}) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Customer select field of credit note form.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
function CreditNoteCustomersSelect() {
|
||||
// Credit note form context.
|
||||
const { customers } = useCreditNoteFormContext();
|
||||
const { setFieldValue, values } = useFormikContext();
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'customer_id'}
|
||||
label={<T id={'customer_name'} />}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
inline={true}
|
||||
fastField={true}
|
||||
shouldUpdate={customerNameFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: customers }}
|
||||
>
|
||||
<CustomersSelect
|
||||
name={'customer_id'}
|
||||
items={customers}
|
||||
placeholder={<T id={'select_customer_account'} />}
|
||||
onItemChange={(customer) => {
|
||||
setFieldValue('customer_id', customer.id);
|
||||
setFieldValue('currency_code', customer?.currency_code);
|
||||
}}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
fastField={true}
|
||||
shouldUpdate={customerNameFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: customers }}
|
||||
/>
|
||||
{values.customer_id && (
|
||||
<CustomerButtonLink customerId={values.customer_id}>
|
||||
<T id={'view_customer_details'} />
|
||||
</CustomerButtonLink>
|
||||
)}
|
||||
</FFormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
const CustomerButtonLink = styled(CustomerDrawerLink)`
|
||||
font-size: 11px;
|
||||
margin-top: 6px;
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import * as R from 'ramda';
|
||||
import { Position, ControlGroup } from '@blueprintjs/core';
|
||||
import { useFormikContext } from 'formik';
|
||||
import {
|
||||
FieldRequiredHint,
|
||||
InputPrependButton,
|
||||
Icon,
|
||||
FormattedMessage as T,
|
||||
FFormGroup,
|
||||
FInputGroup,
|
||||
} from '@/components';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
|
||||
/**
|
||||
* Credit note transaction number field.
|
||||
*/
|
||||
export const CreditNoteTransactionNoField = R.compose(
|
||||
withDialogActions,
|
||||
withSettings(({ creditNoteSettings }) => ({
|
||||
creditAutoIncrement: creditNoteSettings?.autoIncrement,
|
||||
creditNextNumber: creditNoteSettings?.nextNumber,
|
||||
creditNumberPrefix: creditNoteSettings?.numberPrefix,
|
||||
})),
|
||||
)(
|
||||
({
|
||||
// #withDialogActions
|
||||
openDialog,
|
||||
|
||||
// #withSettings
|
||||
creditAutoIncrement,
|
||||
}) => {
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
// Handle credit number changing.
|
||||
const handleCreditNumberChange = () => {
|
||||
openDialog('credit-number-form');
|
||||
};
|
||||
// Handle credit note no. field blur.
|
||||
const handleCreditNoBlur = (event) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
// Show the confirmation dialog if the value has changed and auto-increment
|
||||
// mode is enabled.
|
||||
if (values.credit_note_no !== newValue && creditAutoIncrement) {
|
||||
openDialog('credit-number-form', {
|
||||
initialFormValues: {
|
||||
onceManualNumber: newValue,
|
||||
incrementMode: 'manual-transaction',
|
||||
},
|
||||
});
|
||||
}
|
||||
// Setting the credit note number to the form will be manually in case
|
||||
// auto-increment is disable.
|
||||
if (!creditAutoIncrement) {
|
||||
setFieldValue('credit_note_number', newValue);
|
||||
setFieldValue('credit_note_number_manually', newValue);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'credit_note_number'}
|
||||
label={<T id={'credit_note.label_credit_note'} />}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
inline={true}
|
||||
>
|
||||
<ControlGroup fill={true}>
|
||||
<FInputGroup
|
||||
name={'credit_note_number'}
|
||||
minimal={true}
|
||||
value={values.credit_note_number}
|
||||
asyncControl={true}
|
||||
onBlur={handleCreditNoBlur}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<InputPrependButton
|
||||
buttonProps={{
|
||||
onClick: handleCreditNumberChange,
|
||||
icon: <Icon icon={'settings-18'} />,
|
||||
}}
|
||||
tooltip={true}
|
||||
tooltipProps={{
|
||||
content: (
|
||||
<T id={'setting_your_auto_generated_credit_note_number'} />
|
||||
),
|
||||
position: Position.BOTTOM_LEFT,
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FFormGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
CreditNoteTransactionNoField.displayName = 'CreditNoteTransactionNoField';
|
||||
@@ -116,7 +116,7 @@ export const transformFormValuesToRequest = (values) => {
|
||||
*/
|
||||
export const customerNameFieldShouldUpdate = (newProps, oldProps) => {
|
||||
return (
|
||||
newProps.customers !== oldProps.customers ||
|
||||
newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items ||
|
||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import * as R from 'ramda';
|
||||
import { Position, ControlGroup } from '@blueprintjs/core';
|
||||
import { useFormikContext } from 'formik';
|
||||
import {
|
||||
FFormGroup,
|
||||
FInputGroup,
|
||||
FormattedMessage as T,
|
||||
Icon,
|
||||
InputPrependButton,
|
||||
} from '@/components';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
|
||||
/**
|
||||
* Estimate number field of estimate form.
|
||||
*/
|
||||
export const EstimateFormEstimateNumberField = R.compose(
|
||||
withDialogActions,
|
||||
withSettings(({ estimatesSettings }) => ({
|
||||
estimateNextNumber: estimatesSettings?.nextNumber,
|
||||
estimateNumberPrefix: estimatesSettings?.numberPrefix,
|
||||
estimateAutoIncrement: estimatesSettings?.autoIncrement,
|
||||
})),
|
||||
)(
|
||||
({
|
||||
// #withDialogActions
|
||||
openDialog,
|
||||
|
||||
// #withSettings
|
||||
estimateAutoIncrement,
|
||||
}) => {
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
const handleEstimateNumberBtnClick = () => {
|
||||
openDialog('estimate-number-form', {});
|
||||
};
|
||||
// Handle estimate no. field blur.
|
||||
const handleEstimateNoBlur = (event) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
// Show the confirmation dialog if the value has changed and auto-increment
|
||||
// mode is enabled.
|
||||
if (values.estimate_number !== newValue && estimateAutoIncrement) {
|
||||
openDialog('estimate-number-form', {
|
||||
initialFormValues: {
|
||||
onceManualNumber: newValue,
|
||||
incrementMode: 'manual-transaction',
|
||||
},
|
||||
});
|
||||
}
|
||||
// Setting the estimate number to the form will be manually in case
|
||||
// auto-increment is disable.
|
||||
if (!estimateAutoIncrement) {
|
||||
setFieldValue('estimate_number', newValue);
|
||||
setFieldValue('estimate_number_manually', newValue);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'estimate_number'}
|
||||
label={<T id={'estimate'} />}
|
||||
inline={true}
|
||||
>
|
||||
<ControlGroup fill={true}>
|
||||
<FInputGroup
|
||||
name={'estimate_number'}
|
||||
minimal={true}
|
||||
asyncControl={true}
|
||||
onBlur={handleEstimateNoBlur}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<InputPrependButton
|
||||
buttonProps={{
|
||||
onClick: handleEstimateNumberBtnClick,
|
||||
icon: <Icon icon={'settings-18'} />,
|
||||
}}
|
||||
tooltip={true}
|
||||
tooltipProps={{
|
||||
content: <T id={'setting_your_auto_generated_estimate_number'} />,
|
||||
position: Position.BOTTOM_LEFT,
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FFormGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
EstimateFormEstimateNumberField.displayName = 'EstimateFormEstimateNumberField';
|
||||
@@ -1,28 +1,19 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import * as R from 'ramda';
|
||||
import styled from 'styled-components';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
FormGroup,
|
||||
InputGroup,
|
||||
Position,
|
||||
Classes,
|
||||
ControlGroup,
|
||||
} from '@blueprintjs/core';
|
||||
import { FormGroup, InputGroup, Position, Classes } from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||
|
||||
import {
|
||||
FeatureCan,
|
||||
FFormGroup,
|
||||
FInputGroup,
|
||||
FormattedMessage as T,
|
||||
CustomerSelectField,
|
||||
FieldRequiredHint,
|
||||
Icon,
|
||||
InputPrependButton,
|
||||
CustomerDrawerLink,
|
||||
CustomersSelect,
|
||||
} from '@/components';
|
||||
import {
|
||||
momentFormatter,
|
||||
@@ -34,92 +25,14 @@ import { customersFieldShouldUpdate } from './utils';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { Features } from '@/constants';
|
||||
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
|
||||
import { ProjectsSelect } from '@/containers/Projects/components';
|
||||
import {
|
||||
EstimateExchangeRateInputField,
|
||||
EstimateProjectSelectButton,
|
||||
} from './components';
|
||||
import { EstimateFormEstimateNumberField } from './EstimateFormEstimateNumberField';
|
||||
import { useEstimateFormContext } from './EstimateFormProvider';
|
||||
|
||||
/**
|
||||
* Estimate number field of estimate form.
|
||||
*/
|
||||
const EstimateFormEstimateNumberField = R.compose(
|
||||
withDialogActions,
|
||||
withSettings(({ estimatesSettings }) => ({
|
||||
estimateNextNumber: estimatesSettings?.nextNumber,
|
||||
estimateNumberPrefix: estimatesSettings?.numberPrefix,
|
||||
estimateAutoIncrement: estimatesSettings?.autoIncrement,
|
||||
})),
|
||||
)(
|
||||
({
|
||||
// #withDialogActions
|
||||
openDialog,
|
||||
|
||||
// #withSettings
|
||||
estimateAutoIncrement,
|
||||
}) => {
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
const handleEstimateNumberBtnClick = () => {
|
||||
openDialog('estimate-number-form', {});
|
||||
};
|
||||
// Handle estimate no. field blur.
|
||||
const handleEstimateNoBlur = (event) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
// Show the confirmation dialog if the value has changed and auto-increment
|
||||
// mode is enabled.
|
||||
if (values.estimate_number !== newValue && estimateAutoIncrement) {
|
||||
openDialog('estimate-number-form', {
|
||||
initialFormValues: {
|
||||
onceManualNumber: newValue,
|
||||
incrementMode: 'manual-transaction',
|
||||
},
|
||||
});
|
||||
}
|
||||
// Setting the estimate number to the form will be manually in case
|
||||
// auto-increment is disable.
|
||||
if (!estimateAutoIncrement) {
|
||||
setFieldValue('estimate_number', newValue);
|
||||
setFieldValue('estimate_number_manually', newValue);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'estimate_number'}
|
||||
label={<T id={'estimate'} />}
|
||||
inline={true}
|
||||
>
|
||||
<ControlGroup fill={true}>
|
||||
<FInputGroup
|
||||
name={'estimate_number'}
|
||||
minimal={true}
|
||||
asyncControl={true}
|
||||
onBlur={handleEstimateNoBlur}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<InputPrependButton
|
||||
buttonProps={{
|
||||
onClick: handleEstimateNumberBtnClick,
|
||||
icon: <Icon icon={'settings-18'} />,
|
||||
}}
|
||||
tooltip={true}
|
||||
tooltipProps={{
|
||||
content: <T id={'setting_your_auto_generated_estimate_number'} />,
|
||||
position: Position.BOTTOM_LEFT,
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FFormGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Estimate form header.
|
||||
*/
|
||||
@@ -129,41 +42,7 @@ export default function EstimateFormHeader() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
{/* ----------- Customer name ----------- */}
|
||||
<FastField
|
||||
name={'customer_id'}
|
||||
customers={customers}
|
||||
shouldUpdate={customersFieldShouldUpdate}
|
||||
>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'customer_name'} />}
|
||||
inline={true}
|
||||
className={classNames(CLASSES.FILL, 'form-group--customer')}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name={'customer_id'} />}
|
||||
>
|
||||
<CustomerSelectField
|
||||
contacts={customers}
|
||||
selectedContactId={value}
|
||||
defaultSelectText={<T id={'select_customer_account'} />}
|
||||
onContactSelected={(customer) => {
|
||||
form.setFieldValue('customer_id', customer.id);
|
||||
form.setFieldValue('currency_code', customer?.currency_code);
|
||||
}}
|
||||
popoverFill={true}
|
||||
intent={inputIntent({ error, touched })}
|
||||
allowCreate={true}
|
||||
/>
|
||||
|
||||
{value && (
|
||||
<CustomerButtonLink customerId={value}>
|
||||
<T id={'view_customer_details'} />
|
||||
</CustomerButtonLink>
|
||||
)}
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
<EstimateFormCustomerSelect />
|
||||
|
||||
{/* ----------- Exchange Rate ----------- */}
|
||||
<EstimateExchangeRateInputField
|
||||
@@ -264,6 +143,47 @@ export default function EstimateFormHeader() {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Customer select field of estimate form.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
function EstimateFormCustomerSelect() {
|
||||
const { setFieldValue, values } = useFormikContext();
|
||||
const { customers } = useEstimateFormContext();
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
label={<T id={'customer_name'} />}
|
||||
inline={true}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
name={'customer_id'}
|
||||
fastField={true}
|
||||
shouldUpdate={customersFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: customers }}
|
||||
>
|
||||
<CustomersSelect
|
||||
name={'customer_id'}
|
||||
items={customers}
|
||||
placeholder={<T id={'select_customer_account'} />}
|
||||
onItemChange={(customer) => {
|
||||
setFieldValue('customer_id', customer.id);
|
||||
setFieldValue('currency_code', customer?.currency_code);
|
||||
}}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
fastField={true}
|
||||
shouldUpdate={customersFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: customers }}
|
||||
/>
|
||||
{values.customer_id && (
|
||||
<CustomerButtonLink customerId={values.customer_id}>
|
||||
<T id={'view_customer_details'} />
|
||||
</CustomerButtonLink>
|
||||
)}
|
||||
</FFormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
const CustomerButtonLink = styled(CustomerDrawerLink)`
|
||||
font-size: 11px;
|
||||
margin-top: 6px;
|
||||
|
||||
@@ -80,7 +80,7 @@ export const transformToEditForm = (estimate) => {
|
||||
*/
|
||||
export const customersFieldShouldUpdate = (newProps, oldProps) => {
|
||||
return (
|
||||
newProps.customers !== oldProps.customers ||
|
||||
newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items ||
|
||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,16 +2,9 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
FormGroup,
|
||||
InputGroup,
|
||||
Position,
|
||||
Classes,
|
||||
ControlGroup,
|
||||
} from '@blueprintjs/core';
|
||||
import { FormGroup, InputGroup, Position, Classes } from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||
import * as R from 'ramda';
|
||||
|
||||
import {
|
||||
FFormGroup,
|
||||
@@ -19,12 +12,9 @@ import {
|
||||
Col,
|
||||
Row,
|
||||
CustomerDrawerLink,
|
||||
CustomerSelectField,
|
||||
FieldRequiredHint,
|
||||
Icon,
|
||||
InputPrependButton,
|
||||
FeatureCan,
|
||||
FInputGroup,
|
||||
CustomersSelect,
|
||||
} from '@/components';
|
||||
import {
|
||||
momentFormatter,
|
||||
@@ -40,143 +30,25 @@ import {
|
||||
InvoiceExchangeRateInputField,
|
||||
InvoiceProjectSelectButton,
|
||||
} from './components';
|
||||
import { InvoiceFormInvoiceNumberField } from './InvoiceFormInvoiceNumberField';
|
||||
import {
|
||||
ProjectsSelect,
|
||||
ProjectBillableEntriesLink,
|
||||
} from '@/containers/Projects/components';
|
||||
import { Features } from '@/constants';
|
||||
import { DialogsName } from '@/constants/dialogs';
|
||||
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
|
||||
/**
|
||||
* Invoice number field of invoice form.
|
||||
*/
|
||||
const InvoiceFormInvoiceNumberField = R.compose(
|
||||
withDialogActions,
|
||||
withSettings(({ invoiceSettings }) => ({
|
||||
invoiceAutoIncrement: invoiceSettings?.autoIncrement,
|
||||
})),
|
||||
)(
|
||||
({
|
||||
// #withDialogActions
|
||||
openDialog,
|
||||
|
||||
// #withSettings
|
||||
invoiceAutoIncrement,
|
||||
}) => {
|
||||
// Formik context.
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
// Handle invoice number changing.
|
||||
const handleInvoiceNumberChange = () => {
|
||||
openDialog(DialogsName.InvoiceNumberSettings);
|
||||
};
|
||||
// Handle invoice no. field blur.
|
||||
const handleInvoiceNoBlur = (event) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
// Show the confirmation dialog if the value has changed and auto-increment
|
||||
// mode is enabled.
|
||||
if (values.invoice_no !== newValue && invoiceAutoIncrement) {
|
||||
openDialog(DialogsName.InvoiceNumberSettings, {
|
||||
initialFormValues: {
|
||||
onceManualNumber: newValue,
|
||||
incrementMode: 'manual-transaction',
|
||||
},
|
||||
});
|
||||
}
|
||||
// Setting the invoice number to the form will be manually in case
|
||||
// auto-increment is disable.
|
||||
if (!invoiceAutoIncrement) {
|
||||
setFieldValue('invoice_no', newValue);
|
||||
setFieldValue('invoice_no_manually', newValue);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'invoice_no'}
|
||||
label={<T id={'invoice_no'} />}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
inline={true}
|
||||
fastField={true}
|
||||
>
|
||||
<ControlGroup fill={true}>
|
||||
<FInputGroup
|
||||
name={'invoice_no'}
|
||||
minimal={true}
|
||||
asyncControl={true}
|
||||
onBlur={handleInvoiceNoBlur}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<InputPrependButton
|
||||
buttonProps={{
|
||||
onClick: handleInvoiceNumberChange,
|
||||
icon: <Icon icon={'settings-18'} />,
|
||||
}}
|
||||
tooltip={true}
|
||||
tooltipProps={{
|
||||
content: <T id={'setting_your_auto_generated_invoice_number'} />,
|
||||
position: Position.BOTTOM_LEFT,
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FFormGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
InvoiceFormInvoiceNumberField.displayName = 'InvoiceFormInvoiceNumberField';
|
||||
|
||||
/**
|
||||
* Invoice form header fields.
|
||||
*/
|
||||
export default function InvoiceFormHeaderFields() {
|
||||
// Invoice form context.
|
||||
const { customers, projects } = useInvoiceFormContext();
|
||||
const { projects } = useInvoiceFormContext();
|
||||
const { values } = useFormikContext();
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
{/* ----------- Customer name ----------- */}
|
||||
<FastField
|
||||
name={'customer_id'}
|
||||
customers={customers}
|
||||
shouldUpdate={customerNameFieldShouldUpdate}
|
||||
>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FFormGroup
|
||||
name={'customer_id'}
|
||||
label={<T id={'customer_name'} />}
|
||||
inline={true}
|
||||
className={classNames(
|
||||
'form-group--customer-name',
|
||||
'form-group--select-list',
|
||||
CLASSES.FILL,
|
||||
)}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
>
|
||||
<CustomerSelectField
|
||||
contacts={customers}
|
||||
selectedContactId={value}
|
||||
defaultSelectText={<T id={'select_customer_account'} />}
|
||||
onContactSelected={(customer) => {
|
||||
form.setFieldValue('customer_id', customer.id);
|
||||
form.setFieldValue('currency_code', customer?.currency_code);
|
||||
}}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
/>
|
||||
|
||||
{value && (
|
||||
<CustomerButtonLink customerId={value}>
|
||||
<T id={'view_customer_details'} />
|
||||
</CustomerButtonLink>
|
||||
)}
|
||||
</FFormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
<InvoiceFormCustomerSelect />
|
||||
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<InvoiceExchangeRateInputField
|
||||
@@ -284,6 +156,46 @@ export default function InvoiceFormHeaderFields() {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Customer select field of the invoice form.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
function InvoiceFormCustomerSelect() {
|
||||
const { customers } = useInvoiceFormContext();
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'customer_id'}
|
||||
label={<T id={'customer_name'} />}
|
||||
inline={true}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
fastField={true}
|
||||
shouldUpdate={customerNameFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: customers }}
|
||||
>
|
||||
<CustomersSelect
|
||||
name={'customer_id'}
|
||||
items={customers}
|
||||
placeholder={<T id={'select_customer_account'} />}
|
||||
onItemChange={(customer) => {
|
||||
setFieldValue('customer_id', customer.id);
|
||||
setFieldValue('currency_code', customer?.currency_code);
|
||||
}}
|
||||
allowCreate={true}
|
||||
fastField={true}
|
||||
shouldUpdate={customerNameFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: customers }}
|
||||
/>
|
||||
{values.customer_id && (
|
||||
<CustomerButtonLink customerId={values.customer_id}>
|
||||
<T id={'view_customer_details'} />
|
||||
</CustomerButtonLink>
|
||||
)}
|
||||
</FFormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
const CustomerButtonLink = styled(CustomerDrawerLink)`
|
||||
font-size: 11px;
|
||||
margin-top: 6px;
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { Position, ControlGroup } from '@blueprintjs/core';
|
||||
import { useFormikContext } from 'formik';
|
||||
import * as R from 'ramda';
|
||||
import {
|
||||
FFormGroup,
|
||||
FormattedMessage as T,
|
||||
FieldRequiredHint,
|
||||
Icon,
|
||||
InputPrependButton,
|
||||
FInputGroup,
|
||||
} from '@/components';
|
||||
import { DialogsName } from '@/constants/dialogs';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
|
||||
/**
|
||||
* Invoice number field of invoice form.
|
||||
*/
|
||||
export const InvoiceFormInvoiceNumberField = R.compose(
|
||||
withDialogActions,
|
||||
withSettings(({ invoiceSettings }) => ({
|
||||
invoiceAutoIncrement: invoiceSettings?.autoIncrement,
|
||||
})),
|
||||
)(
|
||||
({
|
||||
// #withDialogActions
|
||||
openDialog,
|
||||
|
||||
// #withSettings
|
||||
invoiceAutoIncrement,
|
||||
}) => {
|
||||
// Formik context.
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
// Handle invoice number changing.
|
||||
const handleInvoiceNumberChange = () => {
|
||||
openDialog(DialogsName.InvoiceNumberSettings);
|
||||
};
|
||||
// Handle invoice no. field blur.
|
||||
const handleInvoiceNoBlur = (event) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
// Show the confirmation dialog if the value has changed and auto-increment
|
||||
// mode is enabled.
|
||||
if (values.invoice_no !== newValue && invoiceAutoIncrement) {
|
||||
openDialog(DialogsName.InvoiceNumberSettings, {
|
||||
initialFormValues: {
|
||||
onceManualNumber: newValue,
|
||||
incrementMode: 'manual-transaction',
|
||||
},
|
||||
});
|
||||
}
|
||||
// Setting the invoice number to the form will be manually in case
|
||||
// auto-increment is disable.
|
||||
if (!invoiceAutoIncrement) {
|
||||
setFieldValue('invoice_no', newValue);
|
||||
setFieldValue('invoice_no_manually', newValue);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'invoice_no'}
|
||||
label={<T id={'invoice_no'} />}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
inline={true}
|
||||
fastField={true}
|
||||
>
|
||||
<ControlGroup fill={true}>
|
||||
<FInputGroup
|
||||
name={'invoice_no'}
|
||||
minimal={true}
|
||||
asyncControl={true}
|
||||
onBlur={handleInvoiceNoBlur}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<InputPrependButton
|
||||
buttonProps={{
|
||||
onClick: handleInvoiceNumberChange,
|
||||
icon: <Icon icon={'settings-18'} />,
|
||||
}}
|
||||
tooltip={true}
|
||||
tooltipProps={{
|
||||
content: <T id={'setting_your_auto_generated_invoice_number'} />,
|
||||
position: Position.BOTTOM_LEFT,
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FFormGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
InvoiceFormInvoiceNumberField.displayName = 'InvoiceFormInvoiceNumberField';
|
||||
@@ -114,7 +114,7 @@ export const transformErrors = (errors, { setErrors }) => {
|
||||
*/
|
||||
export const customerNameFieldShouldUpdate = (newProps, oldProps) => {
|
||||
return (
|
||||
newProps.customers !== oldProps.customers ||
|
||||
newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items||
|
||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -7,25 +7,18 @@ import { FFormGroup, FEditableText, FormattedMessage as T } from '@/components';
|
||||
export function PaymentReceiveFormFootetLeft() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{/* --------- Statement--------- */}
|
||||
<PaymentMsgFormGroup
|
||||
name={'message'}
|
||||
label={<T id={'payment_receive_form.message.label'} />}
|
||||
>
|
||||
<FEditableText
|
||||
name={'message'}
|
||||
placeholder={intl.get('payment_receive_form.message.placeholder')}
|
||||
/>
|
||||
</PaymentMsgFormGroup>
|
||||
|
||||
{/* --------- Internal Note--------- */}
|
||||
<TermsConditsFormGroup
|
||||
name={'internal_note'}
|
||||
name={'statement'}
|
||||
label={<T id={'payment_receive_form.label.note'} />}
|
||||
fastField={true}
|
||||
>
|
||||
<FEditableText
|
||||
name={'internal_note'}
|
||||
placeholder={intl.get('payment_receive_form.internal_note.placeholder')}
|
||||
name={'statement'}
|
||||
placeholder={intl.get(
|
||||
'payment_receive_form.internal_note.placeholder',
|
||||
)}
|
||||
fastField={true}
|
||||
/>
|
||||
</TermsConditsFormGroup>
|
||||
</React.Fragment>
|
||||
@@ -43,17 +36,3 @@ const TermsConditsFormGroup = styled(FFormGroup)`
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const PaymentMsgFormGroup = styled(FFormGroup)`
|
||||
&.bp3-form-group {
|
||||
margin-bottom: 40px;
|
||||
|
||||
.bp3-label {
|
||||
font-size: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.bp3-form-content {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -13,10 +13,12 @@ import {
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { toSafeInteger } from 'lodash';
|
||||
import { FastField, Field, useFormikContext, ErrorMessage } from 'formik';
|
||||
import * as R from 'ramda';
|
||||
|
||||
import { FInputGroup, FeatureCan, FormattedMessage as T } from '@/components';
|
||||
import { useAutofocus } from '@/hooks';
|
||||
import {
|
||||
FeatureCan,
|
||||
CustomersSelect,
|
||||
FormattedMessage as T,
|
||||
} from '@/components';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import {
|
||||
safeSumBy,
|
||||
@@ -28,10 +30,8 @@ import {
|
||||
import {
|
||||
FFormGroup,
|
||||
AccountsSelect,
|
||||
CustomerSelectField,
|
||||
FieldRequiredHint,
|
||||
Icon,
|
||||
InputPrependButton,
|
||||
MoneyInputGroup,
|
||||
InputPrependText,
|
||||
CustomerDrawerLink,
|
||||
@@ -46,9 +46,6 @@ import {
|
||||
PaymentReceiveProjectSelectButton,
|
||||
} from './components';
|
||||
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
|
||||
import {
|
||||
amountPaymentEntries,
|
||||
fullAmountPaymentEntries,
|
||||
@@ -56,95 +53,14 @@ import {
|
||||
accountsFieldShouldUpdate,
|
||||
} from './utils';
|
||||
import { Features } from '@/constants';
|
||||
|
||||
/**
|
||||
* Payment receive number field.
|
||||
*/
|
||||
const PaymentReceivePaymentNoField = R.compose(
|
||||
withSettings(({ paymentReceiveSettings }) => ({
|
||||
paymentReceiveAutoIncrement: paymentReceiveSettings?.autoIncrement,
|
||||
})),
|
||||
withDialogActions,
|
||||
)(
|
||||
({
|
||||
// #withDialogActions
|
||||
openDialog,
|
||||
|
||||
// #withSettings
|
||||
paymentReceiveAutoIncrement,
|
||||
}) => {
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
// Handle click open payment receive number dialog.
|
||||
const handleClickOpenDialog = () => {
|
||||
openDialog('payment-receive-number-form');
|
||||
};
|
||||
// Handle payment number field blur.
|
||||
const handlePaymentNoBlur = (event) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
// Show the confirmation dialog if the value has changed and auto-increment
|
||||
// mode is enabled.
|
||||
if (
|
||||
values.payment_receive_no !== newValue &&
|
||||
paymentReceiveAutoIncrement
|
||||
) {
|
||||
openDialog('payment-receive-number-form', {
|
||||
initialFormValues: {
|
||||
onceManualNumber: newValue,
|
||||
incrementMode: 'manual-transaction',
|
||||
},
|
||||
});
|
||||
}
|
||||
// Setting the payment number to the form will be manually in case
|
||||
// auto-increment is disable.
|
||||
if (!paymentReceiveAutoIncrement) {
|
||||
setFieldValue('payment_receive_no', newValue);
|
||||
setFieldValue('payment_receive_no_manually', newValue);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'payment_receive_no'}
|
||||
label={<T id={'payment_receive_no'} />}
|
||||
inline={true}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
>
|
||||
<ControlGroup fill={true}>
|
||||
<FInputGroup
|
||||
name={'payment_receive_no'}
|
||||
minimal={true}
|
||||
value={values.payment_receive_no}
|
||||
asyncControl={true}
|
||||
onBlur={handlePaymentNoBlur}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<InputPrependButton
|
||||
buttonProps={{
|
||||
onClick: handleClickOpenDialog,
|
||||
icon: <Icon icon={'settings-18'} />,
|
||||
}}
|
||||
tooltip={true}
|
||||
tooltipProps={{
|
||||
content: (
|
||||
<T id={'setting_your_auto_generated_payment_receive_number'} />
|
||||
),
|
||||
position: Position.BOTTOM_LEFT,
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FFormGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
import { PaymentReceivePaymentNoField } from './PaymentReceivePaymentNoField';
|
||||
|
||||
/**
|
||||
* Payment receive header fields.
|
||||
*/
|
||||
export default function PaymentReceiveHeaderFields() {
|
||||
// Payment receive form context.
|
||||
const { customers, accounts, projects, isNewMode } =
|
||||
usePaymentReceiveFormContext();
|
||||
const { accounts, projects } = usePaymentReceiveFormContext();
|
||||
|
||||
// Formik form context.
|
||||
const {
|
||||
@@ -152,8 +68,6 @@ export default function PaymentReceiveHeaderFields() {
|
||||
setFieldValue,
|
||||
} = useFormikContext();
|
||||
|
||||
const customerFieldRef = useAutofocus();
|
||||
|
||||
// Calculates the full-amount received.
|
||||
const totalDueAmount = useMemo(
|
||||
() => safeSumBy(entries, 'due_amount'),
|
||||
@@ -176,45 +90,7 @@ export default function PaymentReceiveHeaderFields() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
{/* ------------- Customer name ------------- */}
|
||||
<FastField
|
||||
name={'customer_id'}
|
||||
customers={customers}
|
||||
shouldUpdate={customersFieldShouldUpdate}
|
||||
>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'customer_name'} />}
|
||||
inline={true}
|
||||
className={classNames('form-group--select-list', CLASSES.FILL)}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name={'customer_id'} />}
|
||||
>
|
||||
<CustomerSelectField
|
||||
contacts={customers}
|
||||
selectedContactId={value}
|
||||
defaultSelectText={<T id={'select_customer_account'} />}
|
||||
onContactSelected={(customer) => {
|
||||
form.setFieldValue('customer_id', customer.id);
|
||||
form.setFieldValue('full_amount', '');
|
||||
form.setFieldValue('currency_code', customer?.currency_code);
|
||||
}}
|
||||
popoverFill={true}
|
||||
disabled={!isNewMode}
|
||||
buttonProps={{
|
||||
elementRef: (ref) => (customerFieldRef.current = ref),
|
||||
}}
|
||||
allowCreate={true}
|
||||
/>
|
||||
|
||||
{value && (
|
||||
<CustomerButtonLink customerId={value}>
|
||||
<T id={'view_customer_details'} />
|
||||
</CustomerButtonLink>
|
||||
)}
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
<PaymentReceiveCustomerSelect />
|
||||
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<PaymentReceiveExchangeRateInputField
|
||||
@@ -361,3 +237,49 @@ const CustomerButtonLink = styled(CustomerDrawerLink)`
|
||||
font-size: 11px;
|
||||
margin-top: 6px;
|
||||
`;
|
||||
|
||||
/**
|
||||
* Customer select field of payment receive form.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
function PaymentReceiveCustomerSelect() {
|
||||
// Payment receive form context.
|
||||
const { customers, isNewMode } = usePaymentReceiveFormContext();
|
||||
|
||||
// Formik form context.
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
label={<T id={'customer_name'} />}
|
||||
inline={true}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
name={'customer_id'}
|
||||
fastField={true}
|
||||
shouldUpdate={customersFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: customers }}
|
||||
>
|
||||
<CustomersSelect
|
||||
name={'customer_id'}
|
||||
items={customers}
|
||||
placeholder={<T id={'select_customer_account'} />}
|
||||
onItemChange={(customer) => {
|
||||
setFieldValue('customer_id', customer.id);
|
||||
setFieldValue('full_amount', '');
|
||||
setFieldValue('currency_code', customer?.currency_code);
|
||||
}}
|
||||
popoverFill={true}
|
||||
disabled={!isNewMode}
|
||||
allowCreate={true}
|
||||
fastField={true}
|
||||
shouldUpdate={customersFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: customers }}
|
||||
/>
|
||||
{values.customer_id && (
|
||||
<CustomerButtonLink customerId={values.customer_id}>
|
||||
<T id={'view_customer_details'} />
|
||||
</CustomerButtonLink>
|
||||
)}
|
||||
</FFormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// @ts-nocheck
|
||||
import React, { useMemo } from 'react';
|
||||
import { Position, ControlGroup } from '@blueprintjs/core';
|
||||
import { useFormikContext } from 'formik';
|
||||
import * as R from 'ramda';
|
||||
|
||||
import { FInputGroup, FormattedMessage as T } from '@/components';
|
||||
import {
|
||||
FFormGroup,
|
||||
FieldRequiredHint,
|
||||
Icon,
|
||||
InputPrependButton,
|
||||
} from '@/components';
|
||||
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
|
||||
/**
|
||||
* Payment receive number field.
|
||||
*/
|
||||
export const PaymentReceivePaymentNoField = R.compose(
|
||||
withSettings(({ paymentReceiveSettings }) => ({
|
||||
paymentReceiveAutoIncrement: paymentReceiveSettings?.autoIncrement,
|
||||
})),
|
||||
withDialogActions,
|
||||
)(
|
||||
({
|
||||
// #withDialogActions
|
||||
openDialog,
|
||||
|
||||
// #withSettings
|
||||
paymentReceiveAutoIncrement,
|
||||
}) => {
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
// Handle click open payment receive number dialog.
|
||||
const handleClickOpenDialog = () => {
|
||||
openDialog('payment-receive-number-form');
|
||||
};
|
||||
// Handle payment number field blur.
|
||||
const handlePaymentNoBlur = (event) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
// Show the confirmation dialog if the value has changed and auto-increment
|
||||
// mode is enabled.
|
||||
if (
|
||||
values.payment_receive_no !== newValue &&
|
||||
paymentReceiveAutoIncrement
|
||||
) {
|
||||
openDialog('payment-receive-number-form', {
|
||||
initialFormValues: {
|
||||
onceManualNumber: newValue,
|
||||
incrementMode: 'manual-transaction',
|
||||
},
|
||||
});
|
||||
}
|
||||
// Setting the payment number to the form will be manually in case
|
||||
// auto-increment is disable.
|
||||
if (!paymentReceiveAutoIncrement) {
|
||||
setFieldValue('payment_receive_no', newValue);
|
||||
setFieldValue('payment_receive_no_manually', newValue);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'payment_receive_no'}
|
||||
label={<T id={'payment_receive_no'} />}
|
||||
inline={true}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
>
|
||||
<ControlGroup fill={true}>
|
||||
<FInputGroup
|
||||
name={'payment_receive_no'}
|
||||
minimal={true}
|
||||
value={values.payment_receive_no}
|
||||
asyncControl={true}
|
||||
onBlur={handlePaymentNoBlur}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<InputPrependButton
|
||||
buttonProps={{
|
||||
onClick: handleClickOpenDialog,
|
||||
icon: <Icon icon={'settings-18'} />,
|
||||
}}
|
||||
tooltip={true}
|
||||
tooltipProps={{
|
||||
content: (
|
||||
<T id={'setting_your_auto_generated_payment_receive_number'} />
|
||||
),
|
||||
position: Position.BOTTOM_LEFT,
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FFormGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
PaymentReceivePaymentNoField.displayName = 'PaymentReceivePaymentNoField';
|
||||
@@ -129,7 +129,7 @@ export const fullAmountPaymentEntries = (entries) => {
|
||||
*/
|
||||
export const customersFieldShouldUpdate = (newProps, oldProps) => {
|
||||
return (
|
||||
newProps.customers !== oldProps.customers ||
|
||||
newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items ||
|
||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,16 +2,9 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
FormGroup,
|
||||
InputGroup,
|
||||
Position,
|
||||
Classes,
|
||||
ControlGroup,
|
||||
} from '@blueprintjs/core';
|
||||
import { FormGroup, InputGroup, Position, Classes } from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||
import * as R from 'ramda';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { ACCOUNT_TYPE } from '@/constants/accountTypes';
|
||||
@@ -19,14 +12,12 @@ import { Features } from '@/constants';
|
||||
import {
|
||||
FFormGroup,
|
||||
AccountsSelect,
|
||||
CustomerSelectField,
|
||||
CustomersSelect,
|
||||
FieldRequiredHint,
|
||||
Icon,
|
||||
InputPrependButton,
|
||||
CustomerDrawerLink,
|
||||
FormattedMessage as T,
|
||||
FeatureCan,
|
||||
FInputGroup,
|
||||
} from '@/components';
|
||||
import { ProjectsSelect } from '@/containers/Projects/components';
|
||||
import {
|
||||
@@ -41,133 +32,18 @@ import {
|
||||
ReceiptExchangeRateInputField,
|
||||
ReceiptProjectSelectButton,
|
||||
} from './components';
|
||||
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
|
||||
/**
|
||||
* Receipt number field of receipt form.
|
||||
*/
|
||||
const ReceiptFormReceiptNumberField = R.compose(
|
||||
withDialogActions,
|
||||
withSettings(({ receiptSettings }) => ({
|
||||
receiptAutoIncrement: receiptSettings?.autoIncrement,
|
||||
})),
|
||||
)(
|
||||
({
|
||||
// #withDialogActions
|
||||
openDialog,
|
||||
|
||||
// #withSettings
|
||||
receiptAutoIncrement,
|
||||
}) => {
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
const handleReceiptNumberChange = () => {
|
||||
openDialog('receipt-number-form', {});
|
||||
};
|
||||
|
||||
const handleReceiptNoBlur = (event) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
// Show the confirmation dialog if the value has changed and auto-increment
|
||||
// mode is enabled.
|
||||
if (values.receipt_number !== newValue && receiptAutoIncrement) {
|
||||
openDialog('receipt-number-form', {
|
||||
initialFormValues: {
|
||||
onceManualNumber: newValue,
|
||||
incrementMode: 'manual-transaction',
|
||||
},
|
||||
});
|
||||
}
|
||||
// Setting the receipt number to the form will be manually in case
|
||||
// auto-increment is disable.
|
||||
if (!receiptAutoIncrement) {
|
||||
setFieldValue('receipt_number', newValue);
|
||||
setFieldValue('receipt_number_manually', newValue);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'receipt_number'}
|
||||
label={<T id={'receipt'} />}
|
||||
inline={true}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
>
|
||||
<ControlGroup fill={true}>
|
||||
<FInputGroup
|
||||
name={'receipt_number'}
|
||||
minimal={true}
|
||||
value={values.receipt_number}
|
||||
asyncControl={true}
|
||||
onBlur={handleReceiptNoBlur}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<InputPrependButton
|
||||
buttonProps={{
|
||||
onClick: handleReceiptNumberChange,
|
||||
icon: <Icon icon={'settings-18'} />,
|
||||
}}
|
||||
tooltip={true}
|
||||
tooltipProps={{
|
||||
content: (
|
||||
<T id={'setting_your_auto_generated_payment_receive_number'} />
|
||||
),
|
||||
position: Position.BOTTOM_LEFT,
|
||||
}}
|
||||
inputProps={{
|
||||
leftIcon: <Icon icon={'date-range'} />,
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FFormGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
import { ReceiptFormReceiptNumberField } from './ReceiptFormReceiptNumberField';
|
||||
|
||||
/**
|
||||
* Receipt form header fields.
|
||||
*/
|
||||
export default function ReceiptFormHeader() {
|
||||
const { accounts, customers, projects } = useReceiptFormContext();
|
||||
const { accounts, projects } = useReceiptFormContext();
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
{/* ----------- Customer name ----------- */}
|
||||
<FastField
|
||||
name={'customer_id'}
|
||||
customers={customers}
|
||||
shouldUpdate={customersFieldShouldUpdate}
|
||||
>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'customer_name'} />}
|
||||
inline={true}
|
||||
className={classNames(CLASSES.FILL, 'form-group--customer')}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name={'customer_id'} />}
|
||||
>
|
||||
<CustomerSelectField
|
||||
contacts={customers}
|
||||
selectedContactId={value}
|
||||
defaultSelectText={<T id={'select_customer_account'} />}
|
||||
onContactSelected={(customer) => {
|
||||
form.setFieldValue('customer_id', customer.id);
|
||||
form.setFieldValue('currency_code', customer?.currency_code);
|
||||
}}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
/>
|
||||
{value && (
|
||||
<CustomerButtonLink customerId={value}>
|
||||
<T id={'view_customer_details'} />
|
||||
</CustomerButtonLink>
|
||||
)}
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
<ReceiptFormCustomerSelect />
|
||||
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<ReceiptExchangeRateInputField
|
||||
@@ -264,6 +140,47 @@ export default function ReceiptFormHeader() {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Customer select field of receipt form.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
function ReceiptFormCustomerSelect() {
|
||||
const { setFieldValue, values } = useFormikContext();
|
||||
const { customers } = useReceiptFormContext();
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'customer_id'}
|
||||
label={<T id={'customer_name'} />}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
inline={true}
|
||||
fastField={true}
|
||||
shouldUpdate={customersFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: customers }}
|
||||
>
|
||||
<CustomersSelect
|
||||
name={'customer_id'}
|
||||
items={customers}
|
||||
placeholder={<T id={'select_customer_account'} />}
|
||||
onItemChange={(customer) => {
|
||||
setFieldValue('customer_id', customer.id);
|
||||
setFieldValue('currency_code', customer?.currency_code);
|
||||
}}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
fastField={true}
|
||||
shouldUpdate={customersFieldShouldUpdate}
|
||||
shouldUpdateDeps={{ items: customers }}
|
||||
/>
|
||||
{values.customer_id && (
|
||||
<CustomerButtonLink customerId={values.customer_id}>
|
||||
<T id={'view_customer_details'} />
|
||||
</CustomerButtonLink>
|
||||
)}
|
||||
</FFormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
const CustomerButtonLink = styled(CustomerDrawerLink)`
|
||||
font-size: 11px;
|
||||
margin-top: 6px;
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { Position, ControlGroup } from '@blueprintjs/core';
|
||||
import { useFormikContext } from 'formik';
|
||||
import * as R from 'ramda';
|
||||
import {
|
||||
FFormGroup,
|
||||
FieldRequiredHint,
|
||||
Icon,
|
||||
InputPrependButton,
|
||||
FormattedMessage as T,
|
||||
FInputGroup,
|
||||
} from '@/components';
|
||||
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
|
||||
/**
|
||||
* Receipt number field of receipt form.
|
||||
*/
|
||||
export const ReceiptFormReceiptNumberField = R.compose(
|
||||
withDialogActions,
|
||||
withSettings(({ receiptSettings }) => ({
|
||||
receiptAutoIncrement: receiptSettings?.autoIncrement,
|
||||
})),
|
||||
)(
|
||||
({
|
||||
// #withDialogActions
|
||||
openDialog,
|
||||
|
||||
// #withSettings
|
||||
receiptAutoIncrement,
|
||||
}) => {
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
const handleReceiptNumberChange = () => {
|
||||
openDialog('receipt-number-form', {});
|
||||
};
|
||||
|
||||
const handleReceiptNoBlur = (event) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
// Show the confirmation dialog if the value has changed and auto-increment
|
||||
// mode is enabled.
|
||||
if (values.receipt_number !== newValue && receiptAutoIncrement) {
|
||||
openDialog('receipt-number-form', {
|
||||
initialFormValues: {
|
||||
onceManualNumber: newValue,
|
||||
incrementMode: 'manual-transaction',
|
||||
},
|
||||
});
|
||||
}
|
||||
// Setting the receipt number to the form will be manually in case
|
||||
// auto-increment is disable.
|
||||
if (!receiptAutoIncrement) {
|
||||
setFieldValue('receipt_number', newValue);
|
||||
setFieldValue('receipt_number_manually', newValue);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'receipt_number'}
|
||||
label={<T id={'receipt'} />}
|
||||
inline={true}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
>
|
||||
<ControlGroup fill={true}>
|
||||
<FInputGroup
|
||||
name={'receipt_number'}
|
||||
minimal={true}
|
||||
value={values.receipt_number}
|
||||
asyncControl={true}
|
||||
onBlur={handleReceiptNoBlur}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<InputPrependButton
|
||||
buttonProps={{
|
||||
onClick: handleReceiptNumberChange,
|
||||
icon: <Icon icon={'settings-18'} />,
|
||||
}}
|
||||
tooltip={true}
|
||||
tooltipProps={{
|
||||
content: (
|
||||
<T id={'setting_your_auto_generated_payment_receive_number'} />
|
||||
),
|
||||
position: Position.BOTTOM_LEFT,
|
||||
}}
|
||||
inputProps={{
|
||||
leftIcon: <Icon icon={'date-range'} />,
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FFormGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
ReceiptFormReceiptNumberField.displayName = 'ReceiptFormReceiptNumberField';
|
||||
@@ -104,7 +104,7 @@ export const accountsFieldShouldUpdate = (newProps, oldProps) => {
|
||||
*/
|
||||
export const customersFieldShouldUpdate = (newProps, oldProps) => {
|
||||
return (
|
||||
newProps.customers !== oldProps.customers ||
|
||||
newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items ||
|
||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -379,7 +379,7 @@
|
||||
"the_expenses_have_been_deleted_successfully": "The expenses have been deleted successfully",
|
||||
"once_delete_these_expenses_you_will_not_able_restore_them": "Once you delete these expenses, you won't be able to retrieve them later. Are you sure you want to delete them?",
|
||||
"the_expense_has_been_published": "The expense has been published",
|
||||
"select_customer": "Select customer",
|
||||
"select_customer": "Select Customer...",
|
||||
"total_amount_equals_zero": "Total amount equals zero",
|
||||
"value": "Value",
|
||||
"you_reached_conditions_limit": "You have reached to conditions limit.",
|
||||
@@ -480,7 +480,7 @@
|
||||
"estimate_date": "Estimate Date",
|
||||
"expiration_date": "Expiration Date",
|
||||
"customer_note": "Customer Note",
|
||||
"select_customer_account": "Select Customer Account",
|
||||
"select_customer_account": "Select Customer Account...",
|
||||
"select_product": "Select Product",
|
||||
"reference": "Reference #",
|
||||
"clear": "Clear",
|
||||
@@ -1452,6 +1452,7 @@
|
||||
"cash_flow.setting_your_auto_generated_transaction_number": "Setting your auto-generated transaction number",
|
||||
"cash_flow_drawer.label_transaction_type": "Transaction type",
|
||||
"cash_flow.drawer.label_transaction_no": "Transaction number",
|
||||
"cash_flow.drawer.label.statement": "Statement",
|
||||
"cash_flow.drawer.label_transaction": "Cash flow Transaction {number}",
|
||||
"cash_flow.account_transactions.no_results": "There are no deposit/withdrawal transactions on the current account.",
|
||||
"cash_flow_balance_in": "Balance in {name}",
|
||||
|
||||
Reference in New Issue
Block a user