Add Currency form field (#9389)

This commit is contained in:
martmull
2025-01-06 16:39:48 +01:00
committed by GitHub
parent 17bf2b6173
commit b22a598d7d
4 changed files with 120 additions and 0 deletions

View File

@ -12,6 +12,7 @@ import { FormRawJsonFieldInput } from '@/object-record/record-field/form-types/c
import { FormSelectFieldInput } from '@/object-record/record-field/form-types/components/FormSelectFieldInput';
import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput';
import { FormUuidFieldInput } from '@/object-record/record-field/form-types/components/FormUuidFieldInput';
import { FormCurrencyFieldInput } from '@/object-record/record-field/form-types/components/FormCurrencyFieldInput';
import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent';
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
import {
@ -22,6 +23,7 @@ import {
FieldMetadata,
FieldMultiSelectValue,
FieldPhonesValue,
FormFieldCurrencyValue,
} from '@/object-record/record-field/types/FieldMetadata';
import { isFieldAddress } from '@/object-record/record-field/types/guards/isFieldAddress';
import { isFieldBoolean } from '@/object-record/record-field/types/guards/isFieldBoolean';
@ -37,6 +39,7 @@ import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFiel
import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect';
import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText';
import { isFieldUuid } from '@/object-record/record-field/types/guards/isFieldUuid';
import { isFieldCurrency } from '@/object-record/record-field/types/guards/isFieldCurrency';
import { JsonValue } from 'type-fest';
type FormFieldInputProps = {
@ -157,5 +160,12 @@ export const FormFieldInput = ({
placeholder={field.label}
VariablePicker={VariablePicker}
/>
) : isFieldCurrency(field) ? (
<FormCurrencyFieldInput
label={field.label}
defaultValue={defaultValue as FormFieldCurrencyValue | null}
onPersist={onPersist}
VariablePicker={VariablePicker}
/>
) : null;
};

View File

@ -0,0 +1,73 @@
import { useMemo } from 'react';
import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode';
import { FormFieldCurrencyValue } from '@/object-record/record-field/types/FieldMetadata';
import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent';
import { FormFieldInputContainer } from '@/object-record/record-field/form-types/components/FormFieldInputContainer';
import { InputLabel } from '@/ui/input/components/InputLabel';
import { FormNestedFieldInputContainer } from '@/object-record/record-field/form-types/components/FormNestedFieldInputContainer';
import { FormNumberFieldInput } from '@/object-record/record-field/form-types/components/FormNumberFieldInput';
import { FormSelectFieldInput } from '@/object-record/record-field/form-types/components/FormSelectFieldInput';
import { SETTINGS_FIELD_CURRENCY_CODES } from '@/settings/data-model/constants/SettingsFieldCurrencyCodes';
type FormCurrencyFieldInputProps = {
label?: string;
defaultValue?: FormFieldCurrencyValue | null;
onPersist: (value: FormFieldCurrencyValue) => void;
VariablePicker?: VariablePickerComponent;
};
export const FormCurrencyFieldInput = ({
label,
defaultValue,
onPersist,
VariablePicker,
}: FormCurrencyFieldInputProps) => {
const currencies = useMemo(() => {
return Object.entries(SETTINGS_FIELD_CURRENCY_CODES).map(
([key, { Icon, label }]) => ({
value: key,
icon: Icon,
label: `${label} (${key})`,
}),
);
}, []);
const handleAmountMicrosChange = (
newAmountMicros: string | number | null,
) => {
onPersist({
currencyCode: defaultValue?.currencyCode ?? null,
amountMicros: newAmountMicros ?? null,
});
};
const handleCurrencyCodeChange = (newCurrencyCode: string | null) => {
onPersist({
currencyCode: (newCurrencyCode as CurrencyCode) ?? null,
amountMicros: defaultValue?.amountMicros ?? null,
});
};
return (
<FormFieldInputContainer>
{label ? <InputLabel>{label}</InputLabel> : null}
<FormNestedFieldInputContainer>
<FormSelectFieldInput
label="Currency Code"
defaultValue={defaultValue?.currencyCode ?? ''}
onPersist={handleCurrencyCodeChange}
options={currencies}
clearLabel={'Currency Code'}
VariablePicker={VariablePicker}
/>
<FormNumberFieldInput
label="Amount Micros"
defaultValue={defaultValue?.amountMicros ?? ''}
onPersist={handleAmountMicrosChange}
VariablePicker={VariablePicker}
placeholder="Set 3210000 for 3.21$"
/>
</FormNestedFieldInputContainer>
</FormFieldInputContainer>
);
};

View File

@ -0,0 +1,33 @@
import { FormCurrencyFieldInput } from '../FormCurrencyFieldInput';
import { Meta, StoryObj } from '@storybook/react';
import { FieldCurrencyValue } from '@/object-record/record-field/types/FieldMetadata';
import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode';
import { within } from '@storybook/test';
const meta: Meta<typeof FormCurrencyFieldInput> = {
title: 'UI/Data/Field/Form/Input/FormCurrencyFieldInput',
component: FormCurrencyFieldInput,
args: {},
argTypes: {},
};
export default meta;
type Story = StoryObj<typeof FormCurrencyFieldInput>;
const defaultSalaryValue: FieldCurrencyValue = {
currencyCode: CurrencyCode.USD,
amountMicros: 44000000,
};
export const Default: Story = {
args: {
label: 'Salary',
defaultValue: defaultSalaryValue,
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await canvas.findByText('Currency Code');
await canvas.findByText('Amount Micros');
},
};

View File

@ -232,6 +232,10 @@ export type FieldCurrencyValue = {
currencyCode: CurrencyCode;
amountMicros: number | null;
};
export type FormFieldCurrencyValue = {
currencyCode: CurrencyCode | null;
amountMicros: number | string | null;
};
export type FieldFullNameValue = { firstName: string; lastName: string };
export type FieldAddressValue = {
addressStreet1: string;