mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 22:00:31 +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 './FormikObserver';
|
||||
export * from './FormikObserver';
|
||||
export * from './FMoneyInputGroup'
|
||||
export * from './FFormGroup'
|
||||
@@ -98,7 +98,7 @@ export * from './FinancialStatement';
|
||||
export * from './FinancialReport';
|
||||
export * from './FinancialSheet';
|
||||
export * from './FeatureGuard';
|
||||
|
||||
export * from './ExchangeRate'
|
||||
const Hint = FieldHint;
|
||||
|
||||
const T = FormattedMessage;
|
||||
|
||||
@@ -110,7 +110,6 @@ export default function CustomerFinancialPanel() {
|
||||
onCurrencySelected={(currency) => {
|
||||
form.setFieldValue('currency_code', currency.currency_code);
|
||||
}}
|
||||
disabled={true}
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
|
||||
@@ -9,7 +9,6 @@ import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FastField, Field, ErrorMessage } from 'formik';
|
||||
import { FormattedMessage as T, Col, Row, If } from 'components';
|
||||
import { momentFormatter, compose, tansformDateValue } from 'utils';
|
||||
import { upperCase } from 'lodash';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import styled from 'styled-components';
|
||||
@@ -25,8 +24,7 @@ import {
|
||||
ListSelect,
|
||||
Icon,
|
||||
InputPrependButton,
|
||||
MoneyInputGroup,
|
||||
FlagTag,
|
||||
ExchangeRateInputGroup,
|
||||
} from 'components';
|
||||
import { useInvoiceFormContext } from './InvoiceFormProvider';
|
||||
|
||||
@@ -121,42 +119,14 @@ function InvoiceFormHeaderFields({
|
||||
)}
|
||||
</FastField>
|
||||
|
||||
{/* ----------- Exchange reate ----------- */}
|
||||
<If condition={isForeignCustomer}>
|
||||
<ExchangeRateField>
|
||||
<Field name={'exchange_rate'}>
|
||||
{({
|
||||
form: { values, setFieldValue },
|
||||
field,
|
||||
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>
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<If condition={true}>
|
||||
<ExchangeRateInputGroup
|
||||
fromCurrency={'USD'}
|
||||
toCurrency={'LYD'}
|
||||
name={'exchange_rate'}
|
||||
formGroupProps={{ label: ' ', inline: true }}
|
||||
/>
|
||||
</If>
|
||||
|
||||
<Row>
|
||||
@@ -309,25 +279,6 @@ export default compose(
|
||||
})),
|
||||
)(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)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user