mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 15:20:34 +00:00
feat: abstruct exchange rate input group component.
This commit is contained in:
52
src/components/ExchangeRate/ExchangeRateInput.js
Normal file
52
src/components/ExchangeRate/ExchangeRateInput.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { ControlGroup } from '@blueprintjs/core';
|
||||||
|
|
||||||
|
import { FlagTag } from '../Tags';
|
||||||
|
import { FMoneyInputGroup, FFormGroup } from '../Forms';
|
||||||
|
|
||||||
|
export function ExchangeRateInputGroup({
|
||||||
|
fromCurrency,
|
||||||
|
toCurrency,
|
||||||
|
inputGroupProps,
|
||||||
|
formGroupProps,
|
||||||
|
name,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<FFormGroup inline={true} {...formGroupProps} name={name}>
|
||||||
|
<ControlGroup>
|
||||||
|
<ExchangeRatePrepend>
|
||||||
|
<FlagTag flage={'US'} /> 1 {fromCurrency} =
|
||||||
|
</ExchangeRatePrepend>
|
||||||
|
<ExchangeRateField
|
||||||
|
allowDecimals={false}
|
||||||
|
allowNegativeValue={true}
|
||||||
|
{...inputGroupProps}
|
||||||
|
name={name}
|
||||||
|
/>
|
||||||
|
<ExchangeRateAppend>
|
||||||
|
<FlagTag flage={'LY'} /> {toCurrency}
|
||||||
|
</ExchangeRateAppend>
|
||||||
|
</ControlGroup>
|
||||||
|
</FFormGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ExchangeRateField = styled(FMoneyInputGroup)`
|
||||||
|
max-width: 88px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ExchangeRateSideIcon = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ExchangeRatePrepend = styled(ExchangeRateSideIcon)`
|
||||||
|
padding-right: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ExchangeRateAppend = styled(ExchangeRateSideIcon)`
|
||||||
|
padding-left: 8px;
|
||||||
|
`;
|
||||||
1
src/components/ExchangeRate/index.js
Normal file
1
src/components/ExchangeRate/index.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './ExchangeRateInput';
|
||||||
49
src/components/Forms/FFormGroup.tsx
Normal file
49
src/components/Forms/FFormGroup.tsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { FieldMetaProps, FieldInputProps, useField } from 'formik';
|
||||||
|
import {
|
||||||
|
FormGroup as PBFormGroup,
|
||||||
|
Intent,
|
||||||
|
FormGroupProps as PBFormGroupProps,
|
||||||
|
} from '@blueprintjs/core';
|
||||||
|
|
||||||
|
export interface FormGroupProps extends PBFormGroupProps {
|
||||||
|
name: string;
|
||||||
|
children: React.ReactElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transformes field props to form group.
|
||||||
|
* @param {Omit<FormGroupProps, "children">} props
|
||||||
|
* @param {FieldInputProps<any>} field
|
||||||
|
* @param {FieldMetaProps<any>} meta
|
||||||
|
* @returns {PBFormGroupProps}
|
||||||
|
*/
|
||||||
|
const fieldToFormGroup = (
|
||||||
|
props: Omit<FormGroupProps, 'children'>,
|
||||||
|
field: FieldInputProps<any>,
|
||||||
|
meta: FieldMetaProps<any>
|
||||||
|
): PBFormGroupProps => {
|
||||||
|
const showError = meta.touched && meta.error;
|
||||||
|
|
||||||
|
return {
|
||||||
|
intent: showError ? Intent.DANGER : Intent.NONE,
|
||||||
|
helperText: showError ? meta.error : '',
|
||||||
|
...props,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form group.
|
||||||
|
* @param {FormGroupProps}
|
||||||
|
* @returns {React.JSX}
|
||||||
|
*/
|
||||||
|
export function FFormGroup({ children, ...props }: FormGroupProps): JSX.Element {
|
||||||
|
const [field, meta] = useField(props.name);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PBFormGroup
|
||||||
|
{...fieldToFormGroup(props, field, meta)}
|
||||||
|
children={children}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
36
src/components/Forms/FMoneyInputGroup.js
Normal file
36
src/components/Forms/FMoneyInputGroup.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Intent } from '@blueprintjs/core';
|
||||||
|
import { Field, getIn } from 'formik';
|
||||||
|
import { CurrencyInput } from './MoneyInputGroup';
|
||||||
|
|
||||||
|
const fieldToMoneyInputGroup = ({
|
||||||
|
field: { onBlur: onFieldBlur, ...field },
|
||||||
|
form: { setFieldValue, touched, errors },
|
||||||
|
onBlur,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
const fieldError = getIn(errors, field.name);
|
||||||
|
const showError = getIn(touched, field.name) && !!fieldError;
|
||||||
|
|
||||||
|
return {
|
||||||
|
intent: showError ? Intent.DANGER : Intent.NONE,
|
||||||
|
onBlurValue:
|
||||||
|
onBlur ??
|
||||||
|
function (e) {
|
||||||
|
onFieldBlur(e ?? field.name);
|
||||||
|
},
|
||||||
|
...field,
|
||||||
|
onChange: (value) => {
|
||||||
|
setFieldValue(field.name, value);
|
||||||
|
},
|
||||||
|
...props,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function FieldToMoneyInputGroup({ ...props }) {
|
||||||
|
return <CurrencyInput {...fieldToMoneyInputGroup(props)} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FMoneyInputGroup({ ...props }) {
|
||||||
|
return <Field {...props} component={FieldToMoneyInputGroup} />;
|
||||||
|
}
|
||||||
@@ -1,2 +1,4 @@
|
|||||||
export * from './FormObserver';
|
export * from './FormObserver';
|
||||||
export * from './FormikObserver';
|
export * from './FormikObserver';
|
||||||
|
export * from './FMoneyInputGroup'
|
||||||
|
export * from './FFormGroup'
|
||||||
@@ -98,7 +98,7 @@ export * from './FinancialStatement';
|
|||||||
export * from './FinancialReport';
|
export * from './FinancialReport';
|
||||||
export * from './FinancialSheet';
|
export * from './FinancialSheet';
|
||||||
export * from './FeatureGuard';
|
export * from './FeatureGuard';
|
||||||
|
export * from './ExchangeRate'
|
||||||
const Hint = FieldHint;
|
const Hint = FieldHint;
|
||||||
|
|
||||||
const T = FormattedMessage;
|
const T = FormattedMessage;
|
||||||
|
|||||||
@@ -110,7 +110,6 @@ export default function CustomerFinancialPanel() {
|
|||||||
onCurrencySelected={(currency) => {
|
onCurrencySelected={(currency) => {
|
||||||
form.setFieldValue('currency_code', currency.currency_code);
|
form.setFieldValue('currency_code', currency.currency_code);
|
||||||
}}
|
}}
|
||||||
disabled={true}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import { DateInput } from '@blueprintjs/datetime';
|
|||||||
import { FastField, Field, ErrorMessage } from 'formik';
|
import { FastField, Field, ErrorMessage } from 'formik';
|
||||||
import { FormattedMessage as T, Col, Row, If } from 'components';
|
import { FormattedMessage as T, Col, Row, If } from 'components';
|
||||||
import { momentFormatter, compose, tansformDateValue } from 'utils';
|
import { momentFormatter, compose, tansformDateValue } from 'utils';
|
||||||
import { upperCase } from 'lodash';
|
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
@@ -25,8 +24,7 @@ import {
|
|||||||
ListSelect,
|
ListSelect,
|
||||||
Icon,
|
Icon,
|
||||||
InputPrependButton,
|
InputPrependButton,
|
||||||
MoneyInputGroup,
|
ExchangeRateInputGroup,
|
||||||
FlagTag,
|
|
||||||
} from 'components';
|
} from 'components';
|
||||||
import { useInvoiceFormContext } from './InvoiceFormProvider';
|
import { useInvoiceFormContext } from './InvoiceFormProvider';
|
||||||
|
|
||||||
@@ -121,42 +119,14 @@ function InvoiceFormHeaderFields({
|
|||||||
)}
|
)}
|
||||||
</FastField>
|
</FastField>
|
||||||
|
|
||||||
{/* ----------- Exchange reate ----------- */}
|
{/* ----------- Exchange rate ----------- */}
|
||||||
<If condition={isForeignCustomer}>
|
<If condition={true}>
|
||||||
<ExchangeRateField>
|
<ExchangeRateInputGroup
|
||||||
<Field name={'exchange_rate'}>
|
fromCurrency={'USD'}
|
||||||
{({
|
toCurrency={'LYD'}
|
||||||
form: { values, setFieldValue },
|
name={'exchange_rate'}
|
||||||
field,
|
formGroupProps={{ label: ' ', inline: true }}
|
||||||
meta: { error, touched },
|
/>
|
||||||
}) => (
|
|
||||||
<FormGroup
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
inline={true}
|
|
||||||
className={'form-group--exchange_rate'}
|
|
||||||
helperText={<ErrorMessage name="exchange_rate" />}
|
|
||||||
>
|
|
||||||
<ControlGroup>
|
|
||||||
<ExchangeRateTag>
|
|
||||||
<FlagTag flage={'US'} /> 1 USD =
|
|
||||||
</ExchangeRateTag>
|
|
||||||
<MoneyInputGroup
|
|
||||||
value={field.value}
|
|
||||||
allowDecimals={false}
|
|
||||||
allowNegativeValue={true}
|
|
||||||
onChange={(value) => {
|
|
||||||
setFieldValue('exchange_rate', value);
|
|
||||||
}}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
/>
|
|
||||||
<ExchangeRateTag>
|
|
||||||
<FlagTag flage={'LY'} /> LYD
|
|
||||||
</ExchangeRateTag>
|
|
||||||
</ControlGroup>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
</ExchangeRateField>
|
|
||||||
</If>
|
</If>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
@@ -309,25 +279,6 @@ export default compose(
|
|||||||
})),
|
})),
|
||||||
)(InvoiceFormHeaderFields);
|
)(InvoiceFormHeaderFields);
|
||||||
|
|
||||||
const ExchangeRateField = styled.div`
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: center;
|
|
||||||
max-width: 366px;
|
|
||||||
.bp3-input-group .bp3-input {
|
|
||||||
width: 88px;
|
|
||||||
margin: 0 5px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ExchangeRateTag = styled.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: 1.6;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ControlCustomerGroup = styled(ControlGroup)`
|
const ControlCustomerGroup = styled(ControlGroup)`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user