feat: abstruct exchange rate input group component.

This commit is contained in:
a.bouhuolia
2022-02-14 15:22:07 +02:00
parent bd63e35489
commit 913245d202
8 changed files with 151 additions and 61 deletions

View 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;
`;

View File

@@ -0,0 +1 @@
export * from './ExchangeRateInput';

View 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}
/>
);
}

View 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} />;
}

View File

@@ -1,2 +1,4 @@
export * from './FormObserver';
export * from './FormikObserver';
export * from './FormikObserver';
export * from './FMoneyInputGroup'
export * from './FFormGroup'

View File

@@ -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;

View File

@@ -110,7 +110,6 @@ export default function CustomerFinancialPanel() {
onCurrencySelected={(currency) => {
form.setFieldValue('currency_code', currency.currency_code);
}}
disabled={true}
/>
</FormGroup>
)}

View File

@@ -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;