diff --git a/packages/twenty-front/src/modules/object-record/record-field/components/FormFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/components/FormFieldInput.tsx index 1b38f7016a00..20f6329c4316 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/components/FormFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/components/FormFieldInput.tsx @@ -12,10 +12,12 @@ 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 { FieldAddressValue, + FieldCurrencyValue, FieldEmailsValue, FieldFullNameValue, FieldLinksValue, @@ -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) ? ( + ) : null; }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormCurrencyFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormCurrencyFieldInput.tsx new file mode 100644 index 000000000000..d69accd6c4b3 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormCurrencyFieldInput.tsx @@ -0,0 +1,76 @@ +import { useMemo } from 'react'; +import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode'; +import { FieldCurrencyValue } 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?: FieldCurrencyValue | null; + onPersist: (value: { + currencyCode: CurrencyCode; + amountMicros: number | string | null; + }) => 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 ?? '') as CurrencyCode, + amountMicros: newAmountMicros ?? '', + }); + }; + + const handleCurrencyCodeChange = (newCurrencyCode: string | null) => { + onPersist({ + currencyCode: (newCurrencyCode ?? '') as CurrencyCode, + amountMicros: defaultValue?.amountMicros ?? null, + }); + }; + + return ( + + {label ? {label} : null} + + + + + + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormCurrencyFieldInput.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormCurrencyFieldInput.stories.tsx new file mode 100644 index 000000000000..d139f5aa0e24 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormCurrencyFieldInput.stories.tsx @@ -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 = { + title: 'UI/Data/Field/Form/Input/FormCurrencyFieldInput', + component: FormCurrencyFieldInput, + args: {}, + argTypes: {}, +}; + +export default meta; + +type Story = StoryObj; + +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'); + }, +};