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');
+ },
+};