From 765dedab0aa8ebc3e9b20ad6eab6738b5c338e08 Mon Sep 17 00:00:00 2001 From: Baptiste Devessier Date: Wed, 15 Jan 2025 11:33:36 +0100 Subject: [PATCH] Ensure users can set the empty value for the FormPhoneFieldInput (#9632) Fixes https://discord.com/channels/1130383047699738754/1328729510547296288 --- .../components/FormCountryCodeSelectInput.tsx | 7 +- .../components/FormPhoneFieldInput.tsx | 18 ++++- .../FormPhoneFieldInput.stories.tsx | 73 ++++++++++++++++++- 3 files changed, 91 insertions(+), 7 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormCountryCodeSelectInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormCountryCodeSelectInput.tsx index 6fc83073c..ca3c8f724 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormCountryCodeSelectInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormCountryCodeSelectInput.tsx @@ -5,6 +5,9 @@ import { FormSelectFieldInput } from '@/object-record/record-field/form-types/co import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent'; import { SelectOption } from '@/spreadsheet-import/types'; import { useCountries } from '@/ui/input/components/internal/hooks/useCountries'; +import { CountryCode } from 'libphonenumber-js'; + +export type FormCountryCodeSelectInputUpdatedValue = CountryCode | ''; export const FormCountryCodeSelectInput = ({ selectedCountryCode, @@ -13,7 +16,7 @@ export const FormCountryCodeSelectInput = ({ VariablePicker, }: { selectedCountryCode: string; - onPersist: (countryCode: string) => void; + onPersist: (countryCode: FormCountryCodeSelectInputUpdatedValue) => void; readonly?: boolean; VariablePicker?: VariablePickerComponent; }) => { @@ -47,7 +50,7 @@ export const FormCountryCodeSelectInput = ({ if (countryCode === null) { onPersist(''); } else { - onPersist(countryCode); + onPersist(countryCode as CountryCode); } }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormPhoneFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormPhoneFieldInput.tsx index 091b0ce53..86f34a2f3 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormPhoneFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormPhoneFieldInput.tsx @@ -1,11 +1,14 @@ -import { FormCountryCodeSelectInput } from '@/object-record/record-field/form-types/components/FormCountryCodeSelectInput'; +import { + FormCountryCodeSelectInput, + FormCountryCodeSelectInputUpdatedValue, +} from '@/object-record/record-field/form-types/components/FormCountryCodeSelectInput'; import { FormFieldInputContainer } from '@/object-record/record-field/form-types/components/FormFieldInputContainer'; import { FormNestedFieldInputContainer } from '@/object-record/record-field/form-types/components/FormNestedFieldInputContainer'; import { FormNumberFieldInput } from '@/object-record/record-field/form-types/components/FormNumberFieldInput'; import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent'; import { FieldPhonesValue } from '@/object-record/record-field/types/FieldMetadata'; import { InputLabel } from '@/ui/input/components/InputLabel'; -import { CountryCode, getCountryCallingCode } from 'libphonenumber-js'; +import { getCountryCallingCode } from 'libphonenumber-js'; type FormPhoneFieldInputProps = { label?: string; @@ -22,8 +25,15 @@ export const FormPhoneFieldInput = ({ readonly, VariablePicker, }: FormPhoneFieldInputProps) => { - const handleCountryChange = (newCountry: string) => { - const newCallingCode = getCountryCallingCode(newCountry as CountryCode); + const handleCountryChange = ( + newCountry: FormCountryCodeSelectInputUpdatedValue, + ) => { + let newCallingCode; + if (newCountry === '') { + newCallingCode = ''; + } else { + newCallingCode = getCountryCallingCode(newCountry); + } onPersist({ primaryPhoneCountryCode: newCountry, diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormPhoneFieldInput.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormPhoneFieldInput.stories.tsx index 64ab42c1e..601dfa47c 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormPhoneFieldInput.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormPhoneFieldInput.stories.tsx @@ -1,5 +1,5 @@ import { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; +import { expect, fn, userEvent, waitFor, within } from '@storybook/test'; import { FieldPhonesValue } from '@/object-record/record-field/types/FieldMetadata'; import { FormPhoneFieldInput } from '../FormPhoneFieldInput'; @@ -33,6 +33,77 @@ export const Default: Story = { }, }; +export const SelectCountryCode: Story = { + args: { + label: 'Phone', + onPersist: fn(), + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + const defaultEmptyOption = await canvas.findByText('No country'); + expect(defaultEmptyOption).toBeVisible(); + + await userEvent.click(defaultEmptyOption); + + const searchInput = await canvas.findByPlaceholderText('Search'); + expect(searchInput).toBeVisible(); + + await userEvent.type(searchInput, 'France'); + + const franceOption = await canvas.findByText(/France/); + + await userEvent.click(franceOption); + + await waitFor(() => { + expect(args.onPersist).toHaveBeenCalledWith({ + primaryPhoneNumber: '', + primaryPhoneCountryCode: 'FR', + primaryPhoneCallingCode: '33', + }); + }); + + expect(args.onPersist).toHaveBeenCalledTimes(1); + }, +}; + +export const SelectEmptyCountryCode: Story = { + args: { + label: 'Phone', + onPersist: fn(), + defaultValue: { + primaryPhoneNumber: '', + primaryPhoneCountryCode: 'FR', + primaryPhoneCallingCode: '33', + }, + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + const defaultSelectedOption = await canvas.findByText(/France/); + expect(defaultSelectedOption).toBeVisible(); + + await userEvent.click(defaultSelectedOption); + + const searchInput = await canvas.findByPlaceholderText('Search'); + expect(searchInput).toBeVisible(); + + const emptyOption = await canvas.findByText('No country'); + + await userEvent.click(emptyOption); + + await waitFor(() => { + expect(args.onPersist).toHaveBeenCalledWith({ + primaryPhoneNumber: '', + primaryPhoneCountryCode: '', + primaryPhoneCallingCode: '', + }); + }); + + expect(args.onPersist).toHaveBeenCalledTimes(1); + }, +}; + export const WithVariables: Story = { args: { label: 'Enter phone...',