@ -88,6 +88,7 @@ const mocks = [
|
||||
phones {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
position
|
||||
@ -95,6 +96,7 @@ const mocks = [
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
workPreference
|
||||
@ -246,6 +248,7 @@ const mocks = [
|
||||
phones {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
position
|
||||
@ -253,6 +256,7 @@ const mocks = [
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
workPreference
|
||||
|
||||
@ -246,6 +246,7 @@ mutation UpdateOneFavorite(
|
||||
phones {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
position
|
||||
@ -253,6 +254,7 @@ mutation UpdateOneFavorite(
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
workPreference
|
||||
@ -532,6 +534,7 @@ export const mocks = [
|
||||
phones {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
position
|
||||
@ -539,6 +542,7 @@ export const mocks = [
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
workPreference
|
||||
|
||||
@ -198,6 +198,7 @@ phone
|
||||
{
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
}
|
||||
linkedinLink
|
||||
{
|
||||
|
||||
@ -48,6 +48,7 @@ describe('mapObjectMetadataToGraphQLQuery', () => {
|
||||
{
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
}
|
||||
createdAt
|
||||
avatarUrl
|
||||
|
||||
@ -157,6 +157,7 @@ ${mapObjectMetadataToGraphQLQuery({
|
||||
{
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}`;
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ZERO_RELATIONS = `
|
||||
phones {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
position
|
||||
@ -37,6 +38,7 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ZERO_RELATIONS = `
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
workPreference
|
||||
@ -229,6 +231,7 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = `
|
||||
phones {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
pointOfContactForOpportunities {
|
||||
@ -305,6 +308,7 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = `
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
workPreference
|
||||
|
||||
@ -38,6 +38,7 @@ export const responseData = {
|
||||
},
|
||||
phones: {
|
||||
primaryPhoneCountryCode: '',
|
||||
primaryPhoneCallingCode: '',
|
||||
primaryPhoneNumber: '',
|
||||
},
|
||||
linkedinLink: {
|
||||
|
||||
@ -43,6 +43,7 @@ export const responseData = {
|
||||
},
|
||||
phones: {
|
||||
primaryPhoneCountryCode: '',
|
||||
primaryPhoneCallingCode: '',
|
||||
primaryPhoneNumber: '',
|
||||
},
|
||||
linkedinLink: {
|
||||
|
||||
@ -178,6 +178,7 @@ const mocks: MockedResponse[] = [
|
||||
phones {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
position
|
||||
@ -185,6 +186,7 @@ const mocks: MockedResponse[] = [
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
workPreference
|
||||
@ -332,6 +334,7 @@ const mocks: MockedResponse[] = [
|
||||
phones {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
position
|
||||
@ -339,6 +342,7 @@ const mocks: MockedResponse[] = [
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
workPreference
|
||||
|
||||
@ -39,7 +39,8 @@ const mocks: MockedResponse[] = [
|
||||
input: {
|
||||
phones: {
|
||||
primaryPhoneNumber: '123 456',
|
||||
primaryPhoneCountryCode: '+1',
|
||||
primaryPhoneCountryCode: 'US',
|
||||
primaryPhoneCallingCode: '+1',
|
||||
additionalPhones: [],
|
||||
},
|
||||
},
|
||||
@ -134,7 +135,8 @@ describe('usePersistField', () => {
|
||||
act(() => {
|
||||
result.current.persistField({
|
||||
primaryPhoneNumber: '123 456',
|
||||
primaryPhoneCountryCode: '+1',
|
||||
primaryPhoneCountryCode: 'US',
|
||||
primaryPhoneCallingCode: '+1',
|
||||
additionalPhones: [],
|
||||
});
|
||||
});
|
||||
|
||||
@ -208,6 +208,7 @@ const mocks: MockedResponse[] = [
|
||||
phones {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
position
|
||||
@ -215,6 +216,7 @@ const mocks: MockedResponse[] = [
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
workPreference
|
||||
|
||||
@ -9,12 +9,11 @@ import { TEXT_INPUT_STYLE } from 'twenty-ui';
|
||||
import { MultiItemFieldInput } from './MultiItemFieldInput';
|
||||
|
||||
import { createPhonesFromFieldValue } from '@/object-record/record-field/meta-types/input/utils/phonesUtils';
|
||||
import { useCountries } from '@/ui/input/components/internal/hooks/useCountries';
|
||||
import { PhoneCountryPickerDropdownButton } from '@/ui/input/components/internal/phone/components/PhoneCountryPickerDropdownButton';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { stripSimpleQuotesFromString } from '~/utils/string/stripSimpleQuotesFromString';
|
||||
|
||||
export const DEFAULT_PHONE_COUNTRY_CODE = '1';
|
||||
export const DEFAULT_PHONE_CALLING_CODE = '1';
|
||||
|
||||
const StyledCustomPhoneInput = styled(ReactPhoneNumberInput)`
|
||||
font-family: ${({ theme }) => theme.font.family};
|
||||
@ -60,22 +59,22 @@ export const PhonesFieldInput = ({
|
||||
|
||||
const phones = createPhonesFromFieldValue(fieldValue);
|
||||
|
||||
const defaultCallingCode =
|
||||
stripSimpleQuotesFromString(
|
||||
fieldDefinition?.defaultValue?.primaryPhoneCountryCode,
|
||||
) ?? DEFAULT_PHONE_COUNTRY_CODE;
|
||||
// TODO : improve once we store the real country code
|
||||
const defaultCountry = useCountries().find(
|
||||
(obj) => `+${obj.callingCode}` === defaultCallingCode,
|
||||
)?.countryCode;
|
||||
const defaultCountry = stripSimpleQuotesFromString(
|
||||
fieldDefinition?.defaultValue?.primaryPhoneCountryCode,
|
||||
);
|
||||
|
||||
const handlePersistPhones = (
|
||||
updatedPhones: { number: string; callingCode: string }[],
|
||||
updatedPhones: {
|
||||
number: string;
|
||||
countryCode: string;
|
||||
callingCode: string;
|
||||
}[],
|
||||
) => {
|
||||
const [nextPrimaryPhone, ...nextAdditionalPhones] = updatedPhones;
|
||||
persistPhonesField({
|
||||
primaryPhoneNumber: nextPrimaryPhone?.number ?? '',
|
||||
primaryPhoneCountryCode: nextPrimaryPhone?.callingCode ?? '',
|
||||
primaryPhoneCountryCode: nextPrimaryPhone?.countryCode ?? '',
|
||||
primaryPhoneCallingCode: nextPrimaryPhone?.callingCode ?? '',
|
||||
additionalPhones: nextAdditionalPhones,
|
||||
});
|
||||
};
|
||||
@ -96,11 +95,13 @@ export const PhonesFieldInput = ({
|
||||
return {
|
||||
number: phone.nationalNumber,
|
||||
callingCode: `+${phone.countryCallingCode}`,
|
||||
countryCode: phone.country as string,
|
||||
};
|
||||
}
|
||||
return {
|
||||
number: '',
|
||||
callingCode: '',
|
||||
countryCode: '',
|
||||
};
|
||||
}}
|
||||
renderItem={({
|
||||
|
||||
@ -19,7 +19,8 @@ describe('createPhonesFromFieldValue test suite', () => {
|
||||
it('should return an array with primary phone number if it is defined', () => {
|
||||
const fieldValue: FieldPhonesValue = {
|
||||
primaryPhoneNumber: '123456789',
|
||||
primaryPhoneCountryCode: '+1',
|
||||
primaryPhoneCountryCode: 'US',
|
||||
primaryPhoneCallingCode: '+1',
|
||||
additionalPhones: [],
|
||||
};
|
||||
const result = createPhonesFromFieldValue(fieldValue);
|
||||
@ -27,6 +28,24 @@ describe('createPhonesFromFieldValue test suite', () => {
|
||||
{
|
||||
number: '123456789',
|
||||
callingCode: '+1',
|
||||
countryCode: 'US',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return an array with primary phone number if it is defined, even with incorrect callingCode', () => {
|
||||
const fieldValue: FieldPhonesValue = {
|
||||
primaryPhoneNumber: '123456789',
|
||||
primaryPhoneCountryCode: 'US',
|
||||
primaryPhoneCallingCode: '+33',
|
||||
additionalPhones: [],
|
||||
};
|
||||
const result = createPhonesFromFieldValue(fieldValue);
|
||||
expect(result).toEqual([
|
||||
{
|
||||
number: '123456789',
|
||||
callingCode: '+33',
|
||||
countryCode: 'US',
|
||||
},
|
||||
]);
|
||||
});
|
||||
@ -34,10 +53,11 @@ describe('createPhonesFromFieldValue test suite', () => {
|
||||
it('should return an array with both primary and additional phones if they are defined', () => {
|
||||
const fieldValue: FieldPhonesValue = {
|
||||
primaryPhoneNumber: '123456789',
|
||||
primaryPhoneCountryCode: '+1',
|
||||
primaryPhoneCountryCode: 'US',
|
||||
primaryPhoneCallingCode: '+1',
|
||||
additionalPhones: [
|
||||
{ number: '987654321', callingCode: '+44' },
|
||||
{ number: '555555555', callingCode: '+33' },
|
||||
{ number: '987654321', callingCode: '+44', countryCode: 'GB' },
|
||||
{ number: '555555555', callingCode: '+33', countryCode: 'FR' },
|
||||
],
|
||||
};
|
||||
const result = createPhonesFromFieldValue(fieldValue);
|
||||
@ -45,9 +65,10 @@ describe('createPhonesFromFieldValue test suite', () => {
|
||||
{
|
||||
number: '123456789',
|
||||
callingCode: '+1',
|
||||
countryCode: 'US',
|
||||
},
|
||||
{ number: '987654321', callingCode: '+44' },
|
||||
{ number: '555555555', callingCode: '+33' },
|
||||
{ number: '987654321', callingCode: '+44', countryCode: 'GB' },
|
||||
{ number: '555555555', callingCode: '+33', countryCode: 'FR' },
|
||||
]);
|
||||
});
|
||||
|
||||
@ -56,14 +77,14 @@ describe('createPhonesFromFieldValue test suite', () => {
|
||||
primaryPhoneNumber: '',
|
||||
primaryPhoneCountryCode: '',
|
||||
additionalPhones: [
|
||||
{ number: '987654321', callingCode: '+44' },
|
||||
{ number: '555555555', callingCode: '+33' },
|
||||
{ number: '987654321', callingCode: '+44', countryCode: 'GB' },
|
||||
{ number: '555555555', callingCode: '+33', countryCode: 'FR' },
|
||||
],
|
||||
};
|
||||
const result = createPhonesFromFieldValue(fieldValue);
|
||||
expect(result).toEqual([
|
||||
{ number: '987654321', callingCode: '+44' },
|
||||
{ number: '555555555', callingCode: '+33' },
|
||||
{ number: '987654321', callingCode: '+44', countryCode: 'GB' },
|
||||
{ number: '555555555', callingCode: '+33', countryCode: 'FR' },
|
||||
]);
|
||||
});
|
||||
|
||||
@ -72,22 +93,34 @@ describe('createPhonesFromFieldValue test suite', () => {
|
||||
primaryPhoneNumber: ' ',
|
||||
primaryPhoneCountryCode: '',
|
||||
additionalPhones: [
|
||||
{ number: '987654321', callingCode: '+44' },
|
||||
{ number: '555555555', callingCode: '+33' },
|
||||
{ number: '987654321', callingCode: '+44', countryCode: 'GB' },
|
||||
{ number: '555555555', callingCode: '+33', countryCode: 'FR' },
|
||||
],
|
||||
};
|
||||
const result = createPhonesFromFieldValue(fieldValue);
|
||||
expect(result).toEqual([
|
||||
{ number: ' ', callingCode: '' },
|
||||
{ number: '987654321', callingCode: '+44' },
|
||||
{ number: '555555555', callingCode: '+33' },
|
||||
{ number: ' ', callingCode: '', countryCode: '' },
|
||||
{ number: '987654321', callingCode: '+44', countryCode: 'GB' },
|
||||
{ number: '555555555', callingCode: '+33', countryCode: 'FR' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return an empty array if only country code is defined', () => {
|
||||
it('should return an empty array if only country and calling code are defined', () => {
|
||||
const fieldValue: FieldPhonesValue = {
|
||||
primaryPhoneNumber: '',
|
||||
primaryPhoneCountryCode: '+33',
|
||||
primaryPhoneCountryCode: 'FR',
|
||||
primaryPhoneCallingCode: '+33',
|
||||
additionalPhones: [],
|
||||
};
|
||||
const result = createPhonesFromFieldValue(fieldValue);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return an empty array if only calling code is defined', () => {
|
||||
const fieldValue: FieldPhonesValue = {
|
||||
primaryPhoneNumber: '',
|
||||
primaryPhoneCallingCode: '+33',
|
||||
primaryPhoneCountryCode: '',
|
||||
additionalPhones: [],
|
||||
};
|
||||
const result = createPhonesFromFieldValue(fieldValue);
|
||||
|
||||
@ -8,7 +8,10 @@ export const createPhonesFromFieldValue = (fieldValue: FieldPhonesValue) => {
|
||||
fieldValue.primaryPhoneNumber
|
||||
? {
|
||||
number: fieldValue.primaryPhoneNumber,
|
||||
callingCode: fieldValue.primaryPhoneCountryCode,
|
||||
callingCode: fieldValue.primaryPhoneCallingCode
|
||||
? fieldValue.primaryPhoneCallingCode
|
||||
: fieldValue.primaryPhoneCountryCode,
|
||||
countryCode: fieldValue.primaryPhoneCountryCode,
|
||||
}
|
||||
: null,
|
||||
...(fieldValue.additionalPhones ?? []),
|
||||
|
||||
@ -27,6 +27,7 @@ export type FieldDateTimeDraftValue = string;
|
||||
export type FieldPhonesDraftValue = {
|
||||
primaryPhoneNumber: string;
|
||||
primaryPhoneCountryCode: string;
|
||||
primaryPhoneCallingCode: string;
|
||||
additionalPhones?: PhoneRecord[] | null;
|
||||
};
|
||||
export type FieldEmailsDraftValue = {
|
||||
|
||||
@ -265,10 +265,15 @@ export type FieldActorValue = {
|
||||
|
||||
export type FieldArrayValue = string[];
|
||||
|
||||
export type PhoneRecord = { number: string; callingCode: string };
|
||||
export type PhoneRecord = {
|
||||
number: string;
|
||||
callingCode: string;
|
||||
countryCode: string;
|
||||
};
|
||||
|
||||
export type FieldPhonesValue = {
|
||||
primaryPhoneNumber: string;
|
||||
primaryPhoneCountryCode: string;
|
||||
primaryPhoneCallingCode?: string;
|
||||
additionalPhones?: PhoneRecord[] | null;
|
||||
};
|
||||
|
||||
@ -5,8 +5,15 @@ import { FieldPhonesValue } from '../FieldMetadata';
|
||||
export const phonesSchema = z.object({
|
||||
primaryPhoneNumber: z.string(),
|
||||
primaryPhoneCountryCode: z.string(),
|
||||
primaryPhoneCallingCode: z.string(),
|
||||
additionalPhones: z
|
||||
.array(z.object({ number: z.string(), callingCode: z.string() }))
|
||||
.array(
|
||||
z.object({
|
||||
number: z.string(),
|
||||
callingCode: z.string(),
|
||||
countryCode: z.string(),
|
||||
}),
|
||||
)
|
||||
.nullable(),
|
||||
}) satisfies z.ZodType<FieldPhonesValue>;
|
||||
|
||||
|
||||
@ -71,6 +71,9 @@ export const computeDraftValueFromFieldValue = <FieldValue>({
|
||||
primaryPhoneCountryCode: stripSimpleQuotesFromString(
|
||||
fieldDefinition?.defaultValue?.primaryPhoneCountryCode,
|
||||
),
|
||||
primaryPhoneCallingCode: stripSimpleQuotesFromString(
|
||||
fieldDefinition?.defaultValue?.primaryPhoneCallingCode,
|
||||
),
|
||||
} as unknown as FieldInputDraftValue<FieldValue>;
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@ const mockPerson = {
|
||||
whatsapp: {
|
||||
primaryPhoneNumber: '+1',
|
||||
primaryPhoneCountryCode: '234-567-890',
|
||||
primaryPhoneCallingCode: '+33',
|
||||
additionalPhones: [],
|
||||
},
|
||||
linkedinLink: {
|
||||
|
||||
@ -663,7 +663,8 @@ export const mockPerformance = {
|
||||
id: '20202020-2d40-4e49-8df4-9c6a049191df',
|
||||
email: 'lorie.vladim@google.com',
|
||||
phones: {
|
||||
primaryPhoneCountryCode: '+33',
|
||||
primaryPhoneCountryCode: 'FR',
|
||||
primaryPhoneCallingCode: '+33',
|
||||
primaryPhoneNumber: '788901235',
|
||||
},
|
||||
linkedinLink: {
|
||||
|
||||
@ -207,6 +207,7 @@ const companyMocks = [
|
||||
phones {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
position
|
||||
@ -214,6 +215,7 @@ const companyMocks = [
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
workPreference
|
||||
|
||||
@ -95,6 +95,7 @@ export const generateEmptyFieldValue = (
|
||||
return {
|
||||
primaryPhoneNumber: '',
|
||||
primaryPhoneCountryCode: '',
|
||||
primaryPhoneCallingCode: '',
|
||||
additionalPhones: null,
|
||||
};
|
||||
}
|
||||
|
||||
@ -91,7 +91,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
||||
exampleValue: {
|
||||
primaryPhoneNumber: '234-567-890',
|
||||
primaryPhoneCountryCode: '+1',
|
||||
additionalPhones: [{ number: '234-567-890', callingCode: '+1' }],
|
||||
additionalPhones: [
|
||||
{ number: '234-567-890', callingCode: '+1', countryCode: 'US' },
|
||||
],
|
||||
},
|
||||
subFields: [
|
||||
'primaryPhoneNumber',
|
||||
@ -102,6 +104,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
||||
labelBySubField: {
|
||||
primaryPhoneNumber: 'Primary Phone Number',
|
||||
primaryPhoneCountryCode: 'Primary Phone Country Code',
|
||||
primaryPhoneCallingCode: 'Primary Phone Calling Code',
|
||||
additionalPhones: 'Additional Phones',
|
||||
},
|
||||
category: 'Basic',
|
||||
|
||||
@ -3,8 +3,10 @@ import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { phonesSchema as phonesFieldDefaultValueSchema } from '@/object-record/record-field/types/guards/isFieldPhonesValue';
|
||||
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
|
||||
import { countryCodeToCallingCode } from '@/settings/data-model/fields/preview/utils/getPhonesFieldPreviewValue';
|
||||
import { useCountries } from '@/ui/input/components/internal/hooks/useCountries';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import { CountryCode } from 'libphonenumber-js';
|
||||
import { IconMap } from 'twenty-ui';
|
||||
import { z } from 'zod';
|
||||
import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString';
|
||||
@ -27,22 +29,27 @@ export type SettingsDataModelFieldTextFormValues = z.infer<
|
||||
typeof settingsDataModelFieldPhonesFormSchema
|
||||
>;
|
||||
|
||||
export type CountryCodeOrEmpty = CountryCode | '';
|
||||
|
||||
export const SettingsDataModelFieldPhonesForm = ({
|
||||
disabled,
|
||||
fieldMetadataItem,
|
||||
}: SettingsDataModelFieldPhonesFormProps) => {
|
||||
const { control } = useFormContext<SettingsDataModelFieldTextFormValues>();
|
||||
|
||||
const countries = useCountries()
|
||||
.sort((a, b) => a.countryName.localeCompare(b.countryName))
|
||||
.map((country) => ({
|
||||
label: `${country.countryName} (+${country.callingCode})`,
|
||||
value: `+${country.callingCode}`,
|
||||
}));
|
||||
countries.unshift({ label: 'No country', value: '' });
|
||||
const countries = [
|
||||
{ label: 'No country', value: '' },
|
||||
...useCountries()
|
||||
.sort((a, b) => a.countryName.localeCompare(b.countryName))
|
||||
.map((country) => ({
|
||||
label: `${country.countryName} (+${country.callingCode})`,
|
||||
value: country.countryCode as CountryCodeOrEmpty,
|
||||
})),
|
||||
];
|
||||
const defaultDefaultValue = {
|
||||
primaryPhoneNumber: "''",
|
||||
primaryPhoneCountryCode: "''",
|
||||
primaryPhoneCallingCode: "''",
|
||||
additionalPhones: null,
|
||||
};
|
||||
const fieldMetadataItemDefaultValue = fieldMetadataItem?.defaultValue;
|
||||
@ -73,6 +80,9 @@ export const SettingsDataModelFieldPhonesForm = ({
|
||||
...value,
|
||||
primaryPhoneCountryCode:
|
||||
applySimpleQuotesToString(newPhoneCountryCode),
|
||||
primaryPhoneCallingCode: applySimpleQuotesToString(
|
||||
countryCodeToCallingCode(newPhoneCountryCode),
|
||||
),
|
||||
})
|
||||
}
|
||||
disabled={disabled}
|
||||
|
||||
@ -1,9 +1,29 @@
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { DEFAULT_PHONE_CALLING_CODE } from '@/object-record/record-field/meta-types/input/components/PhonesFieldInput';
|
||||
import { FieldPhonesValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { getSettingsFieldTypeConfig } from '@/settings/data-model/utils/getSettingsFieldTypeConfig';
|
||||
import {
|
||||
CountryCode,
|
||||
getCountries,
|
||||
getCountryCallingCode,
|
||||
} from 'libphonenumber-js';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { stripSimpleQuotesFromString } from '~/utils/string/stripSimpleQuotesFromString';
|
||||
|
||||
const isStrCountryCodeGuard = (str: string): str is CountryCode => {
|
||||
return getCountries().includes(str as CountryCode);
|
||||
};
|
||||
|
||||
export const countryCodeToCallingCode = (countryCode: string): string => {
|
||||
if (!countryCode || !isStrCountryCodeGuard(countryCode)) {
|
||||
return `+${DEFAULT_PHONE_CALLING_CODE}`;
|
||||
}
|
||||
|
||||
const callingCode = getCountryCallingCode(countryCode);
|
||||
|
||||
return callingCode ? `+${callingCode}` : `+${DEFAULT_PHONE_CALLING_CODE}`;
|
||||
};
|
||||
|
||||
export const getPhonesFieldPreviewValue = ({
|
||||
fieldMetadataItem,
|
||||
}: {
|
||||
@ -26,8 +46,16 @@ export const getPhonesFieldPreviewValue = ({
|
||||
fieldMetadataItem.defaultValue?.primaryPhoneCountryCode,
|
||||
)
|
||||
: null;
|
||||
const primaryPhoneCallingCode =
|
||||
fieldMetadataItem.defaultValue?.primaryPhoneCallingCode &&
|
||||
fieldMetadataItem.defaultValue.primaryPhoneCallingCode !== ''
|
||||
? stripSimpleQuotesFromString(
|
||||
fieldMetadataItem.defaultValue?.primaryPhoneCallingCode,
|
||||
)
|
||||
: null;
|
||||
return {
|
||||
...placeholderDefaultValue,
|
||||
primaryPhoneCountryCode,
|
||||
primaryPhoneCallingCode,
|
||||
};
|
||||
};
|
||||
|
||||
@ -5,6 +5,7 @@ import { RoundedLink, THEME_COMMON } from 'twenty-ui';
|
||||
import { FieldPhonesValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList';
|
||||
|
||||
import { DEFAULT_PHONE_CALLING_CODE } from '@/object-record/record-field/meta-types/input/components/PhonesFieldInput';
|
||||
import { parsePhoneNumber } from 'libphonenumber-js';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { logError } from '~/utils/logError';
|
||||
@ -36,7 +37,10 @@ export const PhonesDisplay = ({ value, isFocused }: PhonesDisplayProps) => {
|
||||
value?.primaryPhoneNumber
|
||||
? {
|
||||
number: value.primaryPhoneNumber,
|
||||
callingCode: value.primaryPhoneCountryCode,
|
||||
callingCode:
|
||||
value.primaryPhoneCallingCode ||
|
||||
value.primaryPhoneCountryCode ||
|
||||
`+${DEFAULT_PHONE_CALLING_CODE}`,
|
||||
}
|
||||
: null,
|
||||
...parseAdditionalPhones(value?.additionalPhones),
|
||||
@ -50,11 +54,11 @@ export const PhonesDisplay = ({ value, isFocused }: PhonesDisplayProps) => {
|
||||
}),
|
||||
[
|
||||
value?.primaryPhoneNumber,
|
||||
value?.primaryPhoneCallingCode,
|
||||
value?.primaryPhoneCountryCode,
|
||||
value?.additionalPhones,
|
||||
],
|
||||
);
|
||||
|
||||
const parsePhoneNumberOrReturnInvalidValue = (number: string) => {
|
||||
try {
|
||||
return { parsedPhone: parsePhoneNumber(number) };
|
||||
|
||||
Reference in New Issue
Block a user