Rename Money/Url to Currency/Link and remove snake_case from composite fields (#2536)
* Rename Money/Url to Currency/Link * regenerate front types * renaming money/url field types * fix double text * fix tests * fix server tests * fix generate-target-column-map * fix currency convert * fix: tests --------- Co-authored-by: Jérémy Magrin <jeremy.magrin@gmail.com>
This commit is contained in:
@ -221,7 +221,7 @@ export type CreateRelationInput = {
|
||||
toObjectMetadataId: Scalars['String']['input'];
|
||||
};
|
||||
|
||||
export enum Currency {
|
||||
export enum CurrencyCode {
|
||||
Aed = 'AED',
|
||||
Afn = 'AFN',
|
||||
All = 'ALL',
|
||||
@ -457,16 +457,16 @@ export type FieldDeleteResponse = {
|
||||
/** Type of the field */
|
||||
export enum FieldMetadataType {
|
||||
Boolean = 'BOOLEAN',
|
||||
Currency = 'CURRENCY',
|
||||
Date = 'DATE',
|
||||
Email = 'EMAIL',
|
||||
Enum = 'ENUM',
|
||||
Money = 'MONEY',
|
||||
Link = 'LINK',
|
||||
Number = 'NUMBER',
|
||||
Phone = 'PHONE',
|
||||
Probability = 'PROBABILITY',
|
||||
Relation = 'RELATION',
|
||||
Text = 'TEXT',
|
||||
Url = 'URL',
|
||||
Uuid = 'UUID'
|
||||
}
|
||||
|
||||
@ -608,7 +608,7 @@ export type Person = {
|
||||
export type Pipeline = {
|
||||
__typename?: 'Pipeline';
|
||||
createdAt: Scalars['DateTime']['output'];
|
||||
currency: Currency;
|
||||
currency: CurrencyCode;
|
||||
icon: Scalars['String']['output'];
|
||||
id: Scalars['ID']['output'];
|
||||
name: Scalars['String']['output'];
|
||||
|
||||
@ -981,7 +981,7 @@ export type CreateRefreshTokenInput = {
|
||||
expiresAt: Scalars['DateTime'];
|
||||
};
|
||||
|
||||
export enum Currency {
|
||||
export enum CurrencyCode {
|
||||
Aed = 'AED',
|
||||
Afn = 'AFN',
|
||||
All = 'ALL',
|
||||
@ -1206,11 +1206,11 @@ export type EnumColorSchemeFilter = {
|
||||
notIn?: InputMaybe<Array<ColorScheme>>;
|
||||
};
|
||||
|
||||
export type EnumCurrencyFilter = {
|
||||
equals?: InputMaybe<Currency>;
|
||||
in?: InputMaybe<Array<Currency>>;
|
||||
not?: InputMaybe<NestedEnumCurrencyFilter>;
|
||||
notIn?: InputMaybe<Array<Currency>>;
|
||||
export type EnumCurrencyCodeFilter = {
|
||||
equals?: InputMaybe<CurrencyCode>;
|
||||
in?: InputMaybe<Array<CurrencyCode>>;
|
||||
not?: InputMaybe<NestedEnumCurrencyCodeFilter>;
|
||||
notIn?: InputMaybe<Array<CurrencyCode>>;
|
||||
};
|
||||
|
||||
export type EnumPipelineProgressableTypeFilter = {
|
||||
@ -1332,16 +1332,16 @@ export type FieldDeleteResponse = {
|
||||
/** Type of the field */
|
||||
export enum FieldMetadataType {
|
||||
Boolean = 'BOOLEAN',
|
||||
Currency = 'CURRENCY',
|
||||
Date = 'DATE',
|
||||
Email = 'EMAIL',
|
||||
Enum = 'ENUM',
|
||||
Money = 'MONEY',
|
||||
Link = 'LINK',
|
||||
Number = 'NUMBER',
|
||||
Phone = 'PHONE',
|
||||
Probability = 'PROBABILITY',
|
||||
Relation = 'RELATION',
|
||||
Text = 'TEXT',
|
||||
Url = 'URL',
|
||||
Uuid = 'UUID'
|
||||
}
|
||||
|
||||
@ -1770,11 +1770,11 @@ export type NestedEnumColorSchemeFilter = {
|
||||
notIn?: InputMaybe<Array<ColorScheme>>;
|
||||
};
|
||||
|
||||
export type NestedEnumCurrencyFilter = {
|
||||
equals?: InputMaybe<Currency>;
|
||||
in?: InputMaybe<Array<Currency>>;
|
||||
not?: InputMaybe<NestedEnumCurrencyFilter>;
|
||||
notIn?: InputMaybe<Array<Currency>>;
|
||||
export type NestedEnumCurrencyCodeFilter = {
|
||||
equals?: InputMaybe<CurrencyCode>;
|
||||
in?: InputMaybe<Array<CurrencyCode>>;
|
||||
not?: InputMaybe<NestedEnumCurrencyCodeFilter>;
|
||||
notIn?: InputMaybe<Array<CurrencyCode>>;
|
||||
};
|
||||
|
||||
export type NestedEnumPipelineProgressableTypeFilter = {
|
||||
@ -2093,7 +2093,7 @@ export type PersonWhereUniqueInput = {
|
||||
export type Pipeline = {
|
||||
__typename?: 'Pipeline';
|
||||
createdAt: Scalars['DateTime'];
|
||||
currency: Currency;
|
||||
currency: CurrencyCode;
|
||||
icon: Scalars['String'];
|
||||
id: Scalars['ID'];
|
||||
name: Scalars['String'];
|
||||
@ -2442,7 +2442,7 @@ export type PipelineWhereInput = {
|
||||
NOT?: InputMaybe<Array<PipelineWhereInput>>;
|
||||
OR?: InputMaybe<Array<PipelineWhereInput>>;
|
||||
createdAt?: InputMaybe<DateTimeFilter>;
|
||||
currency?: InputMaybe<EnumCurrencyFilter>;
|
||||
currency?: InputMaybe<EnumCurrencyCodeFilter>;
|
||||
icon?: InputMaybe<StringFilter>;
|
||||
id?: InputMaybe<StringFilter>;
|
||||
name?: InputMaybe<StringFilter>;
|
||||
|
||||
@ -6,7 +6,14 @@ import { FieldMetadataItem } from '../types/FieldMetadataItem';
|
||||
export const useMapFieldMetadataToGraphQLQuery = () => {
|
||||
const { objectMetadataItems } = useFindManyObjectMetadataItems();
|
||||
|
||||
const mapFieldMetadataToGraphQLQuery = (field: FieldMetadataItem): any => {
|
||||
const mapFieldMetadataToGraphQLQuery = (
|
||||
field: FieldMetadataItem,
|
||||
maxDepthForRelations: number = 1,
|
||||
): any => {
|
||||
if (maxDepthForRelations <= 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// TODO: parse
|
||||
const fieldType = field.type as FieldType;
|
||||
|
||||
@ -22,11 +29,6 @@ export const useMapFieldMetadataToGraphQLQuery = () => {
|
||||
] as FieldType[]
|
||||
).includes(fieldType);
|
||||
|
||||
const fieldIsURL = fieldType === 'URL' || fieldType === 'URL_V2';
|
||||
|
||||
const fieldIsMoneyAmount =
|
||||
fieldType === 'MONEY' || fieldType === 'MONEY_AMOUNT_V2';
|
||||
|
||||
if (fieldIsSimpleValue) {
|
||||
return field.name;
|
||||
} else if (
|
||||
@ -44,7 +46,9 @@ export const useMapFieldMetadataToGraphQLQuery = () => {
|
||||
id
|
||||
${(relationMetadataItem?.fields ?? [])
|
||||
.filter((field) => field.type !== 'RELATION')
|
||||
.map((field) => field.name)
|
||||
.map((field) =>
|
||||
mapFieldMetadataToGraphQLQuery(field, maxDepthForRelations - 1),
|
||||
)
|
||||
.join('\n')}
|
||||
}`;
|
||||
} else if (
|
||||
@ -64,25 +68,27 @@ export const useMapFieldMetadataToGraphQLQuery = () => {
|
||||
id
|
||||
${(relationMetadataItem?.fields ?? [])
|
||||
.filter((field) => field.type !== 'RELATION')
|
||||
.map((field) => field.name)
|
||||
.map((field) =>
|
||||
mapFieldMetadataToGraphQLQuery(field, maxDepthForRelations - 1),
|
||||
)
|
||||
.join('\n')}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
} else if (fieldIsURL) {
|
||||
} else if (fieldType === 'LINK') {
|
||||
return `
|
||||
${field.name}
|
||||
{
|
||||
text
|
||||
link
|
||||
label
|
||||
url
|
||||
}
|
||||
`;
|
||||
} else if (fieldIsMoneyAmount) {
|
||||
} else if (fieldType === 'CURRENCY') {
|
||||
return `
|
||||
${field.name}
|
||||
{
|
||||
amount
|
||||
currency
|
||||
amountMicros
|
||||
currencyCode
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
@ -2,12 +2,12 @@ import { FieldType } from '@/ui/object/field/types/FieldType';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const parseFieldType = (fieldType: FieldMetadataType): FieldType => {
|
||||
if (fieldType === FieldMetadataType.Url) {
|
||||
return 'URL_V2';
|
||||
if (fieldType === FieldMetadataType.Link) {
|
||||
return 'LINK';
|
||||
}
|
||||
|
||||
if (fieldType === FieldMetadataType.Money) {
|
||||
return 'MONEY_AMOUNT_V2';
|
||||
if (fieldType === FieldMetadataType.Currency) {
|
||||
return 'CURRENCY';
|
||||
}
|
||||
|
||||
return fieldType as FieldType;
|
||||
|
||||
@ -4,11 +4,14 @@ import { v4 } from 'uuid';
|
||||
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
|
||||
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
||||
import { Currency, FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { CurrencyCode, FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
const defaultFieldValues: Record<FieldMetadataType, unknown> = {
|
||||
[FieldMetadataType.Money]: { amount: null, currency: Currency.Usd },
|
||||
[FieldMetadataType.Currency]: {
|
||||
amountMicros: null,
|
||||
currencyCode: CurrencyCode.Usd,
|
||||
},
|
||||
[FieldMetadataType.Boolean]: false,
|
||||
[FieldMetadataType.Date]: null,
|
||||
[FieldMetadataType.Email]: '',
|
||||
@ -18,7 +21,7 @@ const defaultFieldValues: Record<FieldMetadataType, unknown> = {
|
||||
[FieldMetadataType.Relation]: null,
|
||||
[FieldMetadataType.Phone]: '',
|
||||
[FieldMetadataType.Text]: '',
|
||||
[FieldMetadataType.Url]: { link: '', text: '' },
|
||||
[FieldMetadataType.Link]: { url: '', label: '' },
|
||||
[FieldMetadataType.Uuid]: '',
|
||||
};
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ export const Currency: Story = {
|
||||
args: {
|
||||
fieldIconKey: 'IconCurrencyDollar',
|
||||
fieldLabel: 'Amount',
|
||||
fieldType: FieldMetadataType.Money,
|
||||
fieldType: FieldMetadataType.Currency,
|
||||
},
|
||||
};
|
||||
|
||||
@ -61,7 +61,7 @@ export const Link: Story = {
|
||||
args: {
|
||||
fieldIconKey: 'IconWorldWww',
|
||||
fieldLabel: 'Website',
|
||||
fieldType: FieldMetadataType.Url,
|
||||
fieldType: FieldMetadataType.Link,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ import {
|
||||
IconTextSize,
|
||||
} from '@/ui/display/icon';
|
||||
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
||||
import { Currency, FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { CurrencyCode, FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
const defaultDateValue = new Date();
|
||||
defaultDateValue.setFullYear(defaultDateValue.getFullYear() + 2);
|
||||
@ -36,10 +36,10 @@ export const dataTypes: Record<
|
||||
Icon: IconNumbers,
|
||||
defaultValue: 2000,
|
||||
},
|
||||
[FieldMetadataType.Url]: {
|
||||
[FieldMetadataType.Link]: {
|
||||
label: 'Link',
|
||||
Icon: IconLink,
|
||||
defaultValue: { link: 'www.twenty.com', text: '' },
|
||||
defaultValue: { url: 'www.twenty.com', label: '' },
|
||||
},
|
||||
[FieldMetadataType.Boolean]: {
|
||||
label: 'True/False',
|
||||
@ -51,10 +51,10 @@ export const dataTypes: Record<
|
||||
Icon: IconCalendarEvent,
|
||||
defaultValue: defaultDateValue.toISOString(),
|
||||
},
|
||||
[FieldMetadataType.Money]: {
|
||||
[FieldMetadataType.Currency]: {
|
||||
label: 'Currency',
|
||||
Icon: IconCoins,
|
||||
defaultValue: { amount: 2000, currency: Currency.Usd },
|
||||
defaultValue: { amount: 2000, currency: CurrencyCode.Usd },
|
||||
},
|
||||
[FieldMetadataType.Relation]: { label: 'Relation', Icon: IconPlug },
|
||||
[FieldMetadataType.Email]: { label: 'Email', Icon: IconMail },
|
||||
|
||||
@ -6,30 +6,30 @@ import { isFieldUuid } from '@/ui/object/field/types/guards/isFieldUuid';
|
||||
|
||||
import { FieldContext } from '../contexts/FieldContext';
|
||||
import { ChipFieldDisplay } from '../meta-types/display/components/ChipFieldDisplay';
|
||||
import { CurrencyFieldDisplay } from '../meta-types/display/components/CurrencyFieldDisplay';
|
||||
import { DateFieldDisplay } from '../meta-types/display/components/DateFieldDisplay';
|
||||
import { DoubleTextChipFieldDisplay } from '../meta-types/display/components/DoubleTextChipFieldDisplay';
|
||||
import { DoubleTextFieldDisplay } from '../meta-types/display/components/DoubleTextFieldDisplay';
|
||||
import { EmailFieldDisplay } from '../meta-types/display/components/EmailFieldDisplay';
|
||||
import { MoneyAmountV2FieldDisplay } from '../meta-types/display/components/MoneyAmountV2FieldDisplay';
|
||||
import { LinkFieldDisplay } from '../meta-types/display/components/LinkFieldDisplay';
|
||||
import { MoneyFieldDisplay } from '../meta-types/display/components/MoneyFieldDisplay';
|
||||
import { NumberFieldDisplay } from '../meta-types/display/components/NumberFieldDisplay';
|
||||
import { PhoneFieldDisplay } from '../meta-types/display/components/PhoneFieldDisplay';
|
||||
import { TextFieldDisplay } from '../meta-types/display/components/TextFieldDisplay';
|
||||
import { URLFieldDisplay } from '../meta-types/display/components/URLFieldDisplay';
|
||||
import { URLV2FieldDisplay } from '../meta-types/display/components/URLV2FieldDisplay';
|
||||
import { isFieldChip } from '../types/guards/isFieldChip';
|
||||
import { isFieldCurrency } from '../types/guards/isFieldCurrency';
|
||||
import { isFieldDate } from '../types/guards/isFieldDate';
|
||||
import { isFieldDoubleText } from '../types/guards/isFieldDoubleText';
|
||||
import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip';
|
||||
import { isFieldEmail } from '../types/guards/isFieldEmail';
|
||||
import { isFieldLink } from '../types/guards/isFieldLink';
|
||||
import { isFieldMoney } from '../types/guards/isFieldMoney';
|
||||
import { isFieldMoneyAmountV2 } from '../types/guards/isFieldMoneyAmountV2';
|
||||
import { isFieldNumber } from '../types/guards/isFieldNumber';
|
||||
import { isFieldPhone } from '../types/guards/isFieldPhone';
|
||||
import { isFieldRelation } from '../types/guards/isFieldRelation';
|
||||
import { isFieldText } from '../types/guards/isFieldText';
|
||||
import { isFieldURL } from '../types/guards/isFieldURL';
|
||||
import { isFieldURLV2 } from '../types/guards/isFieldURLV2';
|
||||
|
||||
export const FieldDisplay = () => {
|
||||
const { fieldDefinition } = useContext(FieldContext);
|
||||
@ -52,10 +52,10 @@ export const FieldDisplay = () => {
|
||||
<MoneyFieldDisplay />
|
||||
) : isFieldURL(fieldDefinition) ? (
|
||||
<URLFieldDisplay />
|
||||
) : isFieldURLV2(fieldDefinition) ? (
|
||||
<URLV2FieldDisplay />
|
||||
) : isFieldMoneyAmountV2(fieldDefinition) ? (
|
||||
<MoneyAmountV2FieldDisplay />
|
||||
) : isFieldLink(fieldDefinition) ? (
|
||||
<LinkFieldDisplay />
|
||||
) : isFieldCurrency(fieldDefinition) ? (
|
||||
<CurrencyFieldDisplay />
|
||||
) : isFieldPhone(fieldDefinition) ? (
|
||||
<PhoneFieldDisplay />
|
||||
) : isFieldChip(fieldDefinition) ? (
|
||||
|
||||
@ -5,11 +5,12 @@ import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'
|
||||
import { FieldContext } from '../contexts/FieldContext';
|
||||
import { BooleanFieldInput } from '../meta-types/input/components/BooleanFieldInput';
|
||||
import { ChipFieldInput } from '../meta-types/input/components/ChipFieldInput';
|
||||
import { CurrencyFieldInput } from '../meta-types/input/components/CurrencyFieldInput';
|
||||
import { DateFieldInput } from '../meta-types/input/components/DateFieldInput';
|
||||
import { DoubleTextChipFieldInput } from '../meta-types/input/components/DoubleTextChipFieldInput';
|
||||
import { DoubleTextFieldInput } from '../meta-types/input/components/DoubleTextFieldInput';
|
||||
import { EmailFieldInput } from '../meta-types/input/components/EmailFieldInput';
|
||||
import { MoneyAmountV2FieldInput } from '../meta-types/input/components/MoneyAmountV2FieldInput';
|
||||
import { LinkFieldInput } from '../meta-types/input/components/LinkFieldInput';
|
||||
import { MoneyFieldInput } from '../meta-types/input/components/MoneyFieldInput';
|
||||
import { NumberFieldInput } from '../meta-types/input/components/NumberFieldInput';
|
||||
import { PhoneFieldInput } from '../meta-types/input/components/PhoneFieldInput';
|
||||
@ -17,23 +18,22 @@ import { ProbabilityFieldInput } from '../meta-types/input/components/Probabilit
|
||||
import { RelationFieldInput } from '../meta-types/input/components/RelationFieldInput';
|
||||
import { TextFieldInput } from '../meta-types/input/components/TextFieldInput';
|
||||
import { URLFieldInput } from '../meta-types/input/components/URLFieldInput';
|
||||
import { URLV2FieldInput } from '../meta-types/input/components/URLV2FieldInput';
|
||||
import { FieldInputEvent } from '../types/FieldInputEvent';
|
||||
import { isFieldBoolean } from '../types/guards/isFieldBoolean';
|
||||
import { isFieldChip } from '../types/guards/isFieldChip';
|
||||
import { isFieldCurrency } from '../types/guards/isFieldCurrency';
|
||||
import { isFieldDate } from '../types/guards/isFieldDate';
|
||||
import { isFieldDoubleText } from '../types/guards/isFieldDoubleText';
|
||||
import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip';
|
||||
import { isFieldEmail } from '../types/guards/isFieldEmail';
|
||||
import { isFieldLink } from '../types/guards/isFieldLink';
|
||||
import { isFieldMoney } from '../types/guards/isFieldMoney';
|
||||
import { isFieldMoneyAmountV2 } from '../types/guards/isFieldMoneyAmountV2';
|
||||
import { isFieldNumber } from '../types/guards/isFieldNumber';
|
||||
import { isFieldPhone } from '../types/guards/isFieldPhone';
|
||||
import { isFieldProbability } from '../types/guards/isFieldProbability';
|
||||
import { isFieldRelation } from '../types/guards/isFieldRelation';
|
||||
import { isFieldText } from '../types/guards/isFieldText';
|
||||
import { isFieldURL } from '../types/guards/isFieldURL';
|
||||
import { isFieldURLV2 } from '../types/guards/isFieldURLV2';
|
||||
|
||||
type FieldInputProps = {
|
||||
onSubmit?: FieldInputEvent;
|
||||
@ -102,16 +102,16 @@ export const FieldInput = ({
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : isFieldURLV2(fieldDefinition) ? (
|
||||
<URLV2FieldInput
|
||||
) : isFieldLink(fieldDefinition) ? (
|
||||
<LinkFieldInput
|
||||
onEnter={onEnter}
|
||||
onEscape={onEscape}
|
||||
onClickOutside={onClickOutside}
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : isFieldMoneyAmountV2(fieldDefinition) ? (
|
||||
<MoneyAmountV2FieldInput
|
||||
) : isFieldCurrency(fieldDefinition) ? (
|
||||
<CurrencyFieldInput
|
||||
onEnter={onEnter}
|
||||
onEscape={onEscape}
|
||||
onClickOutside={onClickOutside}
|
||||
|
||||
@ -7,6 +7,8 @@ import { isFieldBoolean } from '../types/guards/isFieldBoolean';
|
||||
import { isFieldBooleanValue } from '../types/guards/isFieldBooleanValue';
|
||||
import { isFieldChip } from '../types/guards/isFieldChip';
|
||||
import { isFieldChipValue } from '../types/guards/isFieldChipValue';
|
||||
import { isFieldCurrency } from '../types/guards/isFieldCurrency';
|
||||
import { isFieldCurrencyValue } from '../types/guards/isFieldCurrencyValue';
|
||||
import { isFieldDate } from '../types/guards/isFieldDate';
|
||||
import { isFieldDateValue } from '../types/guards/isFieldDateValue';
|
||||
import { isFieldDoubleText } from '../types/guards/isFieldDoubleText';
|
||||
@ -15,9 +17,9 @@ import { isFieldDoubleTextChipValue } from '../types/guards/isFieldDoubleTextChi
|
||||
import { isFieldDoubleTextValue } from '../types/guards/isFieldDoubleTextValue';
|
||||
import { isFieldEmail } from '../types/guards/isFieldEmail';
|
||||
import { isFieldEmailValue } from '../types/guards/isFieldEmailValue';
|
||||
import { isFieldLink } from '../types/guards/isFieldLink';
|
||||
import { isFieldLinkValue } from '../types/guards/isFieldLinkValue';
|
||||
import { isFieldMoney } from '../types/guards/isFieldMoney';
|
||||
import { isFieldMoneyAmountV2 } from '../types/guards/isFieldMoneyAmountV2';
|
||||
import { isFieldMoneyAmountV2Value } from '../types/guards/isFieldMoneyAmountV2Value';
|
||||
import { isFieldMoneyValue } from '../types/guards/isFieldMoneyValue';
|
||||
import { isFieldNumber } from '../types/guards/isFieldNumber';
|
||||
import { isFieldNumberValue } from '../types/guards/isFieldNumberValue';
|
||||
@ -30,8 +32,6 @@ import { isFieldRelationValue } from '../types/guards/isFieldRelationValue';
|
||||
import { isFieldText } from '../types/guards/isFieldText';
|
||||
import { isFieldTextValue } from '../types/guards/isFieldTextValue';
|
||||
import { isFieldURL } from '../types/guards/isFieldURL';
|
||||
import { isFieldURLV2 } from '../types/guards/isFieldURLV2';
|
||||
import { isFieldURLV2Value } from '../types/guards/isFieldURLV2Value';
|
||||
import { isFieldURLValue } from '../types/guards/isFieldURLValue';
|
||||
|
||||
export const usePersistField = () => {
|
||||
@ -73,8 +73,8 @@ export const usePersistField = () => {
|
||||
const fieldIsURL =
|
||||
isFieldURL(fieldDefinition) && isFieldURLValue(valueToPersist);
|
||||
|
||||
const fieldIsURLV2 =
|
||||
isFieldURLV2(fieldDefinition) && isFieldURLV2Value(valueToPersist);
|
||||
const fieldIsLink =
|
||||
isFieldLink(fieldDefinition) && isFieldLinkValue(valueToPersist);
|
||||
|
||||
const fieldIsBoolean =
|
||||
isFieldBoolean(fieldDefinition) &&
|
||||
@ -90,9 +90,9 @@ export const usePersistField = () => {
|
||||
const fieldIsMoney =
|
||||
isFieldMoney(fieldDefinition) && isFieldMoneyValue(valueToPersist);
|
||||
|
||||
const fieldIsMoneyAmountV2 =
|
||||
isFieldMoneyAmountV2(fieldDefinition) &&
|
||||
isFieldMoneyAmountV2Value(valueToPersist);
|
||||
const fieldIsCurrency =
|
||||
isFieldCurrency(fieldDefinition) &&
|
||||
isFieldCurrencyValue(valueToPersist);
|
||||
|
||||
const fieldIsPhone =
|
||||
isFieldPhone(fieldDefinition) && isFieldPhoneValue(valueToPersist);
|
||||
@ -169,8 +169,8 @@ export const usePersistField = () => {
|
||||
fieldIsMoney ||
|
||||
fieldIsDate ||
|
||||
fieldIsPhone ||
|
||||
fieldIsURLV2 ||
|
||||
fieldIsMoneyAmountV2
|
||||
fieldIsLink ||
|
||||
fieldIsCurrency
|
||||
) {
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
import { useCurrencyField } from '../../hooks/useCurrencyField';
|
||||
import { CurrencyDisplay } from '../content-display/components/CurrencyDisplay';
|
||||
|
||||
export const CurrencyFieldDisplay = () => {
|
||||
const { fieldValue } = useCurrencyField();
|
||||
|
||||
return <CurrencyDisplay value={fieldValue} />;
|
||||
};
|
||||
@ -0,0 +1,8 @@
|
||||
import { useLinkField } from '../../hooks/useLinkField';
|
||||
import { LinkDisplay } from '../content-display/components/LinkDisplay';
|
||||
|
||||
export const LinkFieldDisplay = () => {
|
||||
const { fieldValue } = useLinkField();
|
||||
|
||||
return <LinkDisplay value={fieldValue} />;
|
||||
};
|
||||
@ -1,8 +0,0 @@
|
||||
import { useMoneyAmountV2Field } from '../../hooks/useMoneyAmountV2Field';
|
||||
import { MoneyAmountV2Display } from '../content-display/components/MoneyAmountV2Display';
|
||||
|
||||
export const MoneyAmountV2FieldDisplay = () => {
|
||||
const { fieldValue } = useMoneyAmountV2Field();
|
||||
|
||||
return <MoneyAmountV2Display value={fieldValue} />;
|
||||
};
|
||||
@ -1,8 +0,0 @@
|
||||
import { useURLV2Field } from '../../hooks/useURLV2Field';
|
||||
import { URLV2Display } from '../content-display/components/URLDisplayV2';
|
||||
|
||||
export const URLV2FieldDisplay = () => {
|
||||
const { fieldValue } = useURLV2Field();
|
||||
|
||||
return <URLV2Display value={fieldValue} />;
|
||||
};
|
||||
@ -0,0 +1,18 @@
|
||||
import { FieldCurrencyValue } from '@/ui/object/field/types/FieldMetadata';
|
||||
import { convertCurrencyMicrosToCurrency } from '~/utils/convert-currency-amount';
|
||||
|
||||
import { EllipsisDisplay } from './EllipsisDisplay';
|
||||
|
||||
type CurrencyDisplayProps = {
|
||||
value?: FieldCurrencyValue;
|
||||
};
|
||||
|
||||
// TODO: convert currencyCode to currency symbol
|
||||
export const CurrencyDisplay = ({ value }: CurrencyDisplayProps) => {
|
||||
return (
|
||||
<EllipsisDisplay>
|
||||
{convertCurrencyMicrosToCurrency(value?.amountMicros)}{' '}
|
||||
{value?.currencyCode}
|
||||
</EllipsisDisplay>
|
||||
);
|
||||
};
|
||||
@ -6,7 +6,7 @@ import {
|
||||
LinkType,
|
||||
SocialLink,
|
||||
} from '@/ui/navigation/link/components/SocialLink';
|
||||
import { FieldURLV2Value } from '@/ui/object/field/types/FieldMetadata';
|
||||
import { FieldLinkValue } from '@/ui/object/field/types/FieldMetadata';
|
||||
|
||||
import { EllipsisDisplay } from './EllipsisDisplay';
|
||||
|
||||
@ -20,8 +20,8 @@ const StyledRawLink = styled(RoundedLink)`
|
||||
}
|
||||
`;
|
||||
|
||||
type URLV2DisplayProps = {
|
||||
value?: FieldURLV2Value;
|
||||
type LinkDisplayProps = {
|
||||
value?: FieldLinkValue;
|
||||
};
|
||||
|
||||
const checkUrlType = (url: string) => {
|
||||
@ -39,18 +39,18 @@ const checkUrlType = (url: string) => {
|
||||
return LinkType.Url;
|
||||
};
|
||||
|
||||
export const URLV2Display = ({ value }: URLV2DisplayProps) => {
|
||||
export const LinkDisplay = ({ value }: LinkDisplayProps) => {
|
||||
const handleClick = (event: MouseEvent<HTMLElement>) => {
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
const absoluteUrl = value?.link
|
||||
? value.link.startsWith('http')
|
||||
? value.link
|
||||
: 'https://' + value.link
|
||||
const absoluteUrl = value?.url
|
||||
? value.url.startsWith('http')
|
||||
? value.url
|
||||
: 'https://' + value.url
|
||||
: '';
|
||||
|
||||
const displayedValue = value?.text || value?.link || '';
|
||||
const displayedValue = value?.label || value?.url || '';
|
||||
|
||||
const type = checkUrlType(absoluteUrl);
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
import { FieldMoneyAmountV2Value } from '@/ui/object/field/types/FieldMetadata';
|
||||
|
||||
import { EllipsisDisplay } from './EllipsisDisplay';
|
||||
|
||||
type MoneyAmountV2DisplayProps = {
|
||||
value?: FieldMoneyAmountV2Value;
|
||||
};
|
||||
|
||||
export const MoneyAmountV2Display = ({ value }: MoneyAmountV2DisplayProps) => {
|
||||
return (
|
||||
<EllipsisDisplay>
|
||||
{value?.amount} {value?.currency}
|
||||
</EllipsisDisplay>
|
||||
);
|
||||
};
|
||||
@ -5,19 +5,19 @@ import { FieldContext } from '../../contexts/FieldContext';
|
||||
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
|
||||
import { usePersistField } from '../../hooks/usePersistField';
|
||||
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
|
||||
import { FieldMoneyAmountV2Value } from '../../types/FieldMetadata';
|
||||
import { FieldCurrencyValue } from '../../types/FieldMetadata';
|
||||
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
|
||||
import { isFieldMoneyAmountV2 } from '../../types/guards/isFieldMoneyAmountV2';
|
||||
import { isFieldMoneyAmountV2Value } from '../../types/guards/isFieldMoneyAmountV2Value';
|
||||
import { isFieldCurrency } from '../../types/guards/isFieldCurrency';
|
||||
import { isFieldCurrencyValue } from '../../types/guards/isFieldCurrencyValue';
|
||||
|
||||
export const useMoneyAmountV2Field = () => {
|
||||
export const useCurrencyField = () => {
|
||||
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
|
||||
|
||||
assertFieldMetadata('MONEY_AMOUNT_V2', isFieldMoneyAmountV2, fieldDefinition);
|
||||
assertFieldMetadata('CURRENCY', isFieldCurrency, fieldDefinition);
|
||||
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
|
||||
const [fieldValue, setFieldValue] = useRecoilState<FieldMoneyAmountV2Value>(
|
||||
const [fieldValue, setFieldValue] = useRecoilState<FieldCurrencyValue>(
|
||||
entityFieldsFamilySelector({
|
||||
entityId: entityId,
|
||||
fieldName: fieldName,
|
||||
@ -26,8 +26,8 @@ export const useMoneyAmountV2Field = () => {
|
||||
|
||||
const persistField = usePersistField();
|
||||
|
||||
const persistMoneyAmountV2Field = (newValue: FieldMoneyAmountV2Value) => {
|
||||
if (!isFieldMoneyAmountV2Value(newValue)) {
|
||||
const persistCurrencyField = (newValue: FieldCurrencyValue) => {
|
||||
if (!isFieldCurrencyValue(newValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -36,11 +36,11 @@ export const useMoneyAmountV2Field = () => {
|
||||
|
||||
const fieldInitialValue = useFieldInitialValue();
|
||||
|
||||
const initialValue: FieldMoneyAmountV2Value = fieldInitialValue?.isEmpty
|
||||
? { amount: 0, currency: '' }
|
||||
const initialValue: FieldCurrencyValue = fieldInitialValue?.isEmpty
|
||||
? { amountMicros: 0, currencyCode: '' }
|
||||
: !isNaN(Number(fieldInitialValue?.value))
|
||||
? { amount: Number(fieldInitialValue?.value), currency: '' }
|
||||
: { amount: 0, currency: '' } ?? fieldValue;
|
||||
? { amountMicros: Number(fieldInitialValue?.value), currencyCode: '' }
|
||||
: { amountMicros: 0, currencyCode: '' } ?? fieldValue;
|
||||
|
||||
return {
|
||||
fieldDefinition,
|
||||
@ -48,6 +48,6 @@ export const useMoneyAmountV2Field = () => {
|
||||
initialValue,
|
||||
setFieldValue,
|
||||
hotkeyScope,
|
||||
persistMoneyAmountV2Field,
|
||||
persistCurrencyField,
|
||||
};
|
||||
};
|
||||
@ -5,19 +5,19 @@ import { FieldContext } from '../../contexts/FieldContext';
|
||||
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
|
||||
import { usePersistField } from '../../hooks/usePersistField';
|
||||
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
|
||||
import { FieldURLV2Value } from '../../types/FieldMetadata';
|
||||
import { FieldLinkValue } from '../../types/FieldMetadata';
|
||||
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
|
||||
import { isFieldURLV2 } from '../../types/guards/isFieldURLV2';
|
||||
import { isFieldURLV2Value } from '../../types/guards/isFieldURLV2Value';
|
||||
import { isFieldLink } from '../../types/guards/isFieldLink';
|
||||
import { isFieldLinkValue } from '../../types/guards/isFieldLinkValue';
|
||||
|
||||
export const useURLV2Field = () => {
|
||||
export const useLinkField = () => {
|
||||
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
|
||||
|
||||
assertFieldMetadata('URL_V2', isFieldURLV2, fieldDefinition);
|
||||
assertFieldMetadata('LINK', isFieldLink, fieldDefinition);
|
||||
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
|
||||
const [fieldValue, setFieldValue] = useRecoilState<FieldURLV2Value>(
|
||||
const [fieldValue, setFieldValue] = useRecoilState<FieldLinkValue>(
|
||||
entityFieldsFamilySelector({
|
||||
entityId: entityId,
|
||||
fieldName: fieldName,
|
||||
@ -26,16 +26,16 @@ export const useURLV2Field = () => {
|
||||
|
||||
const fieldInitialValue = useFieldInitialValue();
|
||||
|
||||
const initialValue: FieldURLV2Value = fieldInitialValue?.isEmpty
|
||||
? { link: '', text: '' }
|
||||
const initialValue: FieldLinkValue = fieldInitialValue?.isEmpty
|
||||
? { url: '', label: '' }
|
||||
: fieldInitialValue?.value
|
||||
? { link: fieldInitialValue.value, text: '' }
|
||||
? { url: fieldInitialValue.value, label: '' }
|
||||
: fieldValue;
|
||||
|
||||
const persistField = usePersistField();
|
||||
|
||||
const persistURLField = (newValue: FieldURLV2Value) => {
|
||||
if (!isFieldURLV2Value(newValue)) {
|
||||
const persistLinkField = (newValue: FieldLinkValue) => {
|
||||
if (!isFieldLinkValue(newValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -48,6 +48,6 @@ export const useURLV2Field = () => {
|
||||
initialValue,
|
||||
setFieldValue,
|
||||
hotkeyScope,
|
||||
persistURLField,
|
||||
persistLinkField,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,94 @@
|
||||
import { TextInput } from '@/ui/object/field/meta-types/input/components/internal/TextInput';
|
||||
import { convertCurrencyToCurrencyMicros } from '~/utils/convert-currency-amount';
|
||||
|
||||
import { useCurrencyField } from '../../hooks/useCurrencyField';
|
||||
|
||||
import { FieldInputOverlay } from './internal/FieldInputOverlay';
|
||||
import { FieldInputEvent } from './DateFieldInput';
|
||||
|
||||
export type CurrencyFieldInputProps = {
|
||||
onClickOutside?: FieldInputEvent;
|
||||
onEnter?: FieldInputEvent;
|
||||
onEscape?: FieldInputEvent;
|
||||
onTab?: FieldInputEvent;
|
||||
onShiftTab?: FieldInputEvent;
|
||||
};
|
||||
|
||||
export const CurrencyFieldInput = ({
|
||||
onEnter,
|
||||
onEscape,
|
||||
onClickOutside,
|
||||
onTab,
|
||||
onShiftTab,
|
||||
}: CurrencyFieldInputProps) => {
|
||||
const { hotkeyScope, initialValue, persistCurrencyField } =
|
||||
useCurrencyField();
|
||||
|
||||
const handleEnter = (newValue: string) => {
|
||||
onEnter?.(() =>
|
||||
persistCurrencyField({
|
||||
amountMicros:
|
||||
convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0,
|
||||
currencyCode: initialValue.currencyCode,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleEscape = (newValue: string) => {
|
||||
onEscape?.(() =>
|
||||
persistCurrencyField({
|
||||
amountMicros:
|
||||
convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0,
|
||||
currencyCode: initialValue.currencyCode,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleClickOutside = (
|
||||
event: MouseEvent | TouchEvent,
|
||||
newValue: string,
|
||||
) => {
|
||||
onClickOutside?.(() =>
|
||||
persistCurrencyField({
|
||||
amountMicros:
|
||||
convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0,
|
||||
currencyCode: initialValue.currencyCode,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleTab = (newValue: string) => {
|
||||
onTab?.(() =>
|
||||
persistCurrencyField({
|
||||
amountMicros:
|
||||
convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0,
|
||||
currencyCode: initialValue.currencyCode,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleShiftTab = (newValue: string) => {
|
||||
onShiftTab?.(() =>
|
||||
persistCurrencyField({
|
||||
amountMicros:
|
||||
convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0,
|
||||
currencyCode: initialValue.currencyCode,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<FieldInputOverlay>
|
||||
<TextInput
|
||||
value={initialValue.amountMicros?.toString() ?? ''}
|
||||
placeholder="Currency"
|
||||
onClickOutside={handleClickOutside}
|
||||
onEnter={handleEnter}
|
||||
onEscape={handleEscape}
|
||||
onShiftTab={handleShiftTab}
|
||||
onTab={handleTab}
|
||||
hotkeyScope={hotkeyScope}
|
||||
/>
|
||||
</FieldInputOverlay>
|
||||
);
|
||||
};
|
||||
@ -1,11 +1,11 @@
|
||||
import { FieldDoubleText } from '../../../types/FieldDoubleText';
|
||||
import { useURLV2Field } from '../../hooks/useURLV2Field';
|
||||
import { useLinkField } from '../../hooks/useLinkField';
|
||||
|
||||
import { DoubleTextInput } from './internal/DoubleTextInput';
|
||||
import { FieldInputOverlay } from './internal/FieldInputOverlay';
|
||||
import { FieldInputEvent } from './DateFieldInput';
|
||||
|
||||
export type URLV2FieldInputProps = {
|
||||
export type LinkFieldInputProps = {
|
||||
onClickOutside?: FieldInputEvent;
|
||||
onEnter?: FieldInputEvent;
|
||||
onEscape?: FieldInputEvent;
|
||||
@ -13,29 +13,29 @@ export type URLV2FieldInputProps = {
|
||||
onShiftTab?: FieldInputEvent;
|
||||
};
|
||||
|
||||
export const URLV2FieldInput = ({
|
||||
export const LinkFieldInput = ({
|
||||
onEnter,
|
||||
onEscape,
|
||||
onClickOutside,
|
||||
onTab,
|
||||
onShiftTab,
|
||||
}: URLV2FieldInputProps) => {
|
||||
const { initialValue, hotkeyScope, persistURLField } = useURLV2Field();
|
||||
}: LinkFieldInputProps) => {
|
||||
const { initialValue, hotkeyScope, persistLinkField } = useLinkField();
|
||||
|
||||
const handleEnter = (newURL: FieldDoubleText) => {
|
||||
onEnter?.(() =>
|
||||
persistURLField({
|
||||
link: newURL.firstValue,
|
||||
text: newURL.secondValue,
|
||||
persistLinkField({
|
||||
url: newURL.firstValue,
|
||||
label: newURL.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleEscape = (newURL: FieldDoubleText) => {
|
||||
onEscape?.(() =>
|
||||
persistURLField({
|
||||
link: newURL.firstValue,
|
||||
text: newURL.secondValue,
|
||||
persistLinkField({
|
||||
url: newURL.firstValue,
|
||||
label: newURL.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
@ -45,27 +45,27 @@ export const URLV2FieldInput = ({
|
||||
newURL: FieldDoubleText,
|
||||
) => {
|
||||
onClickOutside?.(() =>
|
||||
persistURLField({
|
||||
link: newURL.firstValue,
|
||||
text: newURL.secondValue,
|
||||
persistLinkField({
|
||||
url: newURL.firstValue,
|
||||
label: newURL.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleTab = (newURL: FieldDoubleText) => {
|
||||
onTab?.(() =>
|
||||
persistURLField({
|
||||
link: newURL.firstValue,
|
||||
text: newURL.secondValue,
|
||||
persistLinkField({
|
||||
url: newURL.firstValue,
|
||||
label: newURL.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleShiftTab = (newURL: FieldDoubleText) => {
|
||||
onShiftTab?.(() =>
|
||||
persistURLField({
|
||||
link: newURL.firstValue,
|
||||
text: newURL.secondValue,
|
||||
persistLinkField({
|
||||
url: newURL.firstValue,
|
||||
label: newURL.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
@ -73,9 +73,9 @@ export const URLV2FieldInput = ({
|
||||
return (
|
||||
<FieldInputOverlay>
|
||||
<DoubleTextInput
|
||||
firstValue={initialValue.link}
|
||||
secondValue={initialValue.text}
|
||||
firstValuePlaceholder={'Link'}
|
||||
firstValue={initialValue.url}
|
||||
secondValue={initialValue.label}
|
||||
firstValuePlaceholder={'Url'}
|
||||
secondValuePlaceholder={'Label'}
|
||||
hotkeyScope={hotkeyScope}
|
||||
onClickOutside={handleClickOutside}
|
||||
@ -1,93 +0,0 @@
|
||||
import { DoubleTextInput } from '@/ui/object/field/meta-types/input/components/internal/DoubleTextInput';
|
||||
|
||||
import { usePersistField } from '../../../hooks/usePersistField';
|
||||
import { FieldDoubleText } from '../../../types/FieldDoubleText';
|
||||
import { useMoneyAmountV2Field } from '../../hooks/useMoneyAmountV2Field';
|
||||
|
||||
import { FieldInputOverlay } from './internal/FieldInputOverlay';
|
||||
import { FieldInputEvent } from './DateFieldInput';
|
||||
|
||||
export type MoneyAmountV2FieldInputProps = {
|
||||
onClickOutside?: FieldInputEvent;
|
||||
onEnter?: FieldInputEvent;
|
||||
onEscape?: FieldInputEvent;
|
||||
onTab?: FieldInputEvent;
|
||||
onShiftTab?: FieldInputEvent;
|
||||
};
|
||||
|
||||
export const MoneyAmountV2FieldInput = ({
|
||||
onEnter,
|
||||
onEscape,
|
||||
onClickOutside,
|
||||
onTab,
|
||||
onShiftTab,
|
||||
}: MoneyAmountV2FieldInputProps) => {
|
||||
const { hotkeyScope, initialValue } = useMoneyAmountV2Field();
|
||||
|
||||
const persistField = usePersistField();
|
||||
|
||||
const handleEnter = (newDoubleText: FieldDoubleText) => {
|
||||
onEnter?.(() =>
|
||||
persistField({
|
||||
amount: parseFloat(newDoubleText.firstValue),
|
||||
currency: newDoubleText.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleEscape = (newDoubleText: FieldDoubleText) => {
|
||||
onEscape?.(() =>
|
||||
persistField({
|
||||
amount: parseFloat(newDoubleText.firstValue),
|
||||
currency: newDoubleText.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleClickOutside = (
|
||||
event: MouseEvent | TouchEvent,
|
||||
newDoubleText: FieldDoubleText,
|
||||
) => {
|
||||
onClickOutside?.(() =>
|
||||
persistField({
|
||||
amount: parseFloat(newDoubleText.firstValue),
|
||||
currency: newDoubleText.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleTab = (newDoubleText: FieldDoubleText) => {
|
||||
onTab?.(() =>
|
||||
persistField({
|
||||
amount: parseFloat(newDoubleText.firstValue),
|
||||
currency: newDoubleText.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleShiftTab = (newDoubleText: FieldDoubleText) => {
|
||||
onShiftTab?.(() =>
|
||||
persistField({
|
||||
amount: parseFloat(newDoubleText.firstValue),
|
||||
currency: newDoubleText.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<FieldInputOverlay>
|
||||
<DoubleTextInput
|
||||
firstValue={initialValue.amount?.toString() ?? ''}
|
||||
secondValue={initialValue.currency ?? ''}
|
||||
firstValuePlaceholder="Amount"
|
||||
secondValuePlaceholder="Currency"
|
||||
onClickOutside={handleClickOutside}
|
||||
onEnter={handleEnter}
|
||||
onEscape={handleEscape}
|
||||
onShiftTab={handleShiftTab}
|
||||
onTab={handleTab}
|
||||
hotkeyScope={hotkeyScope}
|
||||
/>
|
||||
</FieldInputOverlay>
|
||||
);
|
||||
};
|
||||
@ -7,12 +7,14 @@ import { FieldDefinition } from '../../types/FieldDefinition';
|
||||
import { FieldMetadata } from '../../types/FieldMetadata';
|
||||
import { isFieldBoolean } from '../../types/guards/isFieldBoolean';
|
||||
import { isFieldChip } from '../../types/guards/isFieldChip';
|
||||
import { isFieldCurrency } from '../../types/guards/isFieldCurrency';
|
||||
import { isFieldCurrencyValue } from '../../types/guards/isFieldCurrencyValue';
|
||||
import { isFieldDate } from '../../types/guards/isFieldDate';
|
||||
import { isFieldDoubleTextChip } from '../../types/guards/isFieldDoubleTextChip';
|
||||
import { isFieldEmail } from '../../types/guards/isFieldEmail';
|
||||
import { isFieldLink } from '../../types/guards/isFieldLink';
|
||||
import { isFieldLinkValue } from '../../types/guards/isFieldLinkValue';
|
||||
import { isFieldMoney } from '../../types/guards/isFieldMoney';
|
||||
import { isFieldMoneyAmountV2 } from '../../types/guards/isFieldMoneyAmountV2';
|
||||
import { isFieldMoneyAmountV2Value } from '../../types/guards/isFieldMoneyAmountV2Value';
|
||||
import { isFieldNumber } from '../../types/guards/isFieldNumber';
|
||||
import { isFieldPhone } from '../../types/guards/isFieldPhone';
|
||||
import { isFieldProbability } from '../../types/guards/isFieldProbability';
|
||||
@ -20,8 +22,6 @@ import { isFieldRelation } from '../../types/guards/isFieldRelation';
|
||||
import { isFieldRelationValue } from '../../types/guards/isFieldRelationValue';
|
||||
import { isFieldText } from '../../types/guards/isFieldText';
|
||||
import { isFieldURL } from '../../types/guards/isFieldURL';
|
||||
import { isFieldURLV2 } from '../../types/guards/isFieldURLV2';
|
||||
import { isFieldURLV2Value } from '../../types/guards/isFieldURLV2Value';
|
||||
import { entityFieldsFamilyState } from '../entityFieldsFamilyState';
|
||||
|
||||
const isValueEmpty = (value: unknown) => !assertNotNull(value) || value === '';
|
||||
@ -98,21 +98,21 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({
|
||||
);
|
||||
}
|
||||
|
||||
if (isFieldMoneyAmountV2(fieldDefinition)) {
|
||||
if (isFieldCurrency(fieldDefinition)) {
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
const fieldValue = get(entityFieldsFamilyState(entityId))?.[fieldName];
|
||||
|
||||
return (
|
||||
!isFieldMoneyAmountV2Value(fieldValue) ||
|
||||
isValueEmpty(fieldValue?.amount)
|
||||
!isFieldCurrencyValue(fieldValue) ||
|
||||
isValueEmpty(fieldValue?.amountMicros)
|
||||
);
|
||||
}
|
||||
|
||||
if (isFieldURLV2(fieldDefinition)) {
|
||||
if (isFieldLink(fieldDefinition)) {
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
const fieldValue = get(entityFieldsFamilyState(entityId))?.[fieldName];
|
||||
|
||||
return !isFieldURLV2Value(fieldValue) || isValueEmpty(fieldValue?.link);
|
||||
return !isFieldLinkValue(fieldValue) || isValueEmpty(fieldValue?.url);
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
|
||||
@ -21,7 +21,7 @@ export type FieldURLMetadata = {
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldURLV2Metadata = {
|
||||
export type FieldLinkMetadata = {
|
||||
placeHolder: string;
|
||||
fieldName: string;
|
||||
};
|
||||
@ -42,7 +42,7 @@ export type FieldMoneyMetadata = {
|
||||
isPositive?: boolean;
|
||||
};
|
||||
|
||||
export type FieldMoneyAmountV2Metadata = {
|
||||
export type FieldCurrencyMetadata = {
|
||||
fieldName: string;
|
||||
placeHolder: string;
|
||||
isPositive?: boolean;
|
||||
@ -91,22 +91,22 @@ export type FieldBooleanMetadata = {
|
||||
};
|
||||
|
||||
export type FieldMetadata =
|
||||
| FieldUuidMetadata
|
||||
| FieldTextMetadata
|
||||
| FieldRelationMetadata
|
||||
| FieldBooleanMetadata
|
||||
| FieldChipMetadata
|
||||
| FieldCurrencyMetadata
|
||||
| FieldDateMetadata
|
||||
| FieldDoubleTextChipMetadata
|
||||
| FieldDoubleTextMetadata
|
||||
| FieldPhoneMetadata
|
||||
| FieldURLMetadata
|
||||
| FieldURLV2Metadata
|
||||
| FieldNumberMetadata
|
||||
| FieldMoneyMetadata
|
||||
| FieldMoneyAmountV2Metadata
|
||||
| FieldEmailMetadata
|
||||
| FieldDateMetadata
|
||||
| FieldLinkMetadata
|
||||
| FieldMoneyMetadata
|
||||
| FieldNumberMetadata
|
||||
| FieldPhoneMetadata
|
||||
| FieldProbabilityMetadata
|
||||
| FieldBooleanMetadata;
|
||||
| FieldRelationMetadata
|
||||
| FieldTextMetadata
|
||||
| FieldURLMetadata
|
||||
| FieldUuidMetadata;
|
||||
|
||||
export type FieldTextValue = string;
|
||||
export type FieldUUidValue = string;
|
||||
@ -115,10 +115,10 @@ export type FieldChipValue = string;
|
||||
export type FieldDateValue = string | null;
|
||||
export type FieldPhoneValue = string;
|
||||
export type FieldURLValue = string;
|
||||
export type FieldURLV2Value = { link: string; text: string };
|
||||
export type FieldLinkValue = { url: string; label: string };
|
||||
export type FieldNumberValue = number | null;
|
||||
export type FieldMoneyValue = number | null;
|
||||
export type FieldMoneyAmountV2Value = { currency: string; amount: number };
|
||||
export type FieldCurrencyValue = { currencyCode: string; amountMicros: number };
|
||||
|
||||
export type FieldEmailValue = string;
|
||||
export type FieldProbabilityValue = number;
|
||||
|
||||
@ -11,8 +11,8 @@ export type FieldType =
|
||||
| 'DATE'
|
||||
| 'PHONE'
|
||||
| 'URL'
|
||||
| 'URL_V2'
|
||||
| 'LINK'
|
||||
| 'PROBABILITY'
|
||||
| 'MONEY_AMOUNT_V2'
|
||||
| 'CURRENCY'
|
||||
| 'MONEY_AMOUNT'
|
||||
| 'MONEY';
|
||||
|
||||
@ -2,12 +2,13 @@ import { FieldDefinition } from '../FieldDefinition';
|
||||
import {
|
||||
FieldBooleanMetadata,
|
||||
FieldChipMetadata,
|
||||
FieldCurrencyMetadata,
|
||||
FieldDateMetadata,
|
||||
FieldDoubleTextChipMetadata,
|
||||
FieldDoubleTextMetadata,
|
||||
FieldEmailMetadata,
|
||||
FieldLinkMetadata,
|
||||
FieldMetadata,
|
||||
FieldMoneyAmountV2Metadata,
|
||||
FieldMoneyMetadata,
|
||||
FieldNumberMetadata,
|
||||
FieldPhoneMetadata,
|
||||
@ -15,45 +16,44 @@ import {
|
||||
FieldRelationMetadata,
|
||||
FieldTextMetadata,
|
||||
FieldURLMetadata,
|
||||
FieldURLV2Metadata,
|
||||
FieldUuidMetadata,
|
||||
} from '../FieldMetadata';
|
||||
import { FieldType } from '../FieldType';
|
||||
|
||||
type AssertFieldMetadataFunction = <
|
||||
E extends FieldType,
|
||||
T extends E extends 'TEXT'
|
||||
? FieldTextMetadata
|
||||
: E extends 'UUID'
|
||||
? FieldUuidMetadata
|
||||
: E extends 'RELATION'
|
||||
? FieldRelationMetadata
|
||||
T extends E extends 'BOOLEAN'
|
||||
? FieldBooleanMetadata
|
||||
: E extends 'CHIP'
|
||||
? FieldChipMetadata
|
||||
: E extends 'DOUBLE_TEXT_CHIP'
|
||||
? FieldDoubleTextChipMetadata
|
||||
: E extends 'DOUBLE_TEXT'
|
||||
? FieldDoubleTextMetadata
|
||||
: E extends 'NUMBER'
|
||||
? FieldNumberMetadata
|
||||
: E extends 'EMAIL'
|
||||
? FieldEmailMetadata
|
||||
: E extends 'BOOLEAN'
|
||||
? FieldBooleanMetadata
|
||||
: E extends 'CURRENCY'
|
||||
? FieldCurrencyMetadata
|
||||
: E extends 'DATE'
|
||||
? FieldDateMetadata
|
||||
: E extends 'PHONE'
|
||||
? FieldPhoneMetadata
|
||||
: E extends 'URL'
|
||||
? FieldURLMetadata
|
||||
: E extends 'URL_V2'
|
||||
? FieldURLV2Metadata
|
||||
: E extends 'PROBABILITY'
|
||||
? FieldProbabilityMetadata
|
||||
: E extends 'DOUBLE_TEXT'
|
||||
? FieldDoubleTextMetadata
|
||||
: E extends 'DOUBLE_TEXT_CHIP'
|
||||
? FieldDoubleTextChipMetadata
|
||||
: E extends 'EMAIL'
|
||||
? FieldEmailMetadata
|
||||
: E extends 'LINK'
|
||||
? FieldLinkMetadata
|
||||
: E extends 'MONEY_AMOUNT'
|
||||
? FieldMoneyMetadata
|
||||
: E extends 'MONEY_AMOUNT_V2'
|
||||
? FieldMoneyAmountV2Metadata
|
||||
: E extends 'NUMBER'
|
||||
? FieldNumberMetadata
|
||||
: E extends 'PHONE'
|
||||
? FieldPhoneMetadata
|
||||
: E extends 'PROBABILITY'
|
||||
? FieldProbabilityMetadata
|
||||
: E extends 'RELATION'
|
||||
? FieldRelationMetadata
|
||||
: E extends 'TEXT'
|
||||
? FieldTextMetadata
|
||||
: E extends 'URL'
|
||||
? FieldURLMetadata
|
||||
: E extends 'UUID'
|
||||
? FieldUuidMetadata
|
||||
: never,
|
||||
>(
|
||||
fieldType: E,
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldCurrencyMetadata, FieldMetadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldCurrency = (
|
||||
field: FieldDefinition<FieldMetadata>,
|
||||
): field is FieldDefinition<FieldCurrencyMetadata> => field.type === 'CURRENCY';
|
||||
@ -0,0 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { FieldCurrencyValue } from '../FieldMetadata';
|
||||
|
||||
const currencySchema = z.object({
|
||||
currencyCode: z.string(),
|
||||
amountMicros: z.number(),
|
||||
});
|
||||
|
||||
export const isFieldCurrencyValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldCurrencyValue =>
|
||||
currencySchema.safeParse(fieldValue).success;
|
||||
@ -0,0 +1,6 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldLinkMetadata, FieldMetadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldLink = (
|
||||
field: FieldDefinition<FieldMetadata>,
|
||||
): field is FieldDefinition<FieldLinkMetadata> => field.type === 'LINK';
|
||||
@ -0,0 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { FieldLinkValue } from '../FieldMetadata';
|
||||
|
||||
const linkSchema = z.object({
|
||||
url: z.string(),
|
||||
label: z.string(),
|
||||
});
|
||||
|
||||
// TODO: add zod
|
||||
export const isFieldLinkValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldLinkValue => linkSchema.safeParse(fieldValue).success;
|
||||
@ -1,7 +0,0 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldMetadata, FieldMoneyAmountV2Metadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldMoneyAmountV2 = (
|
||||
field: FieldDefinition<FieldMetadata>,
|
||||
): field is FieldDefinition<FieldMoneyAmountV2Metadata> =>
|
||||
field.type === 'MONEY_AMOUNT_V2';
|
||||
@ -1,13 +0,0 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { FieldMoneyAmountV2Value } from '../FieldMetadata';
|
||||
|
||||
const moneyAmountV2Schema = z.object({
|
||||
currency: z.string(),
|
||||
amount: z.number(),
|
||||
});
|
||||
|
||||
export const isFieldMoneyAmountV2Value = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldMoneyAmountV2Value =>
|
||||
moneyAmountV2Schema.safeParse(fieldValue).success;
|
||||
@ -1,6 +0,0 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldMetadata, FieldURLV2Metadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldURLV2 = (
|
||||
field: FieldDefinition<FieldMetadata>,
|
||||
): field is FieldDefinition<FieldURLV2Metadata> => field.type === 'URL_V2';
|
||||
@ -1,13 +0,0 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { FieldURLV2Value } from '../FieldMetadata';
|
||||
|
||||
const urlV2Schema = z.object({
|
||||
link: z.string(),
|
||||
text: z.string(),
|
||||
});
|
||||
|
||||
// TODO: add zod
|
||||
export const isFieldURLV2Value = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldURLV2Value => urlV2Schema.safeParse(fieldValue).success;
|
||||
30
front/src/utils/convert-currency-amount.ts
Normal file
30
front/src/utils/convert-currency-amount.ts
Normal file
@ -0,0 +1,30 @@
|
||||
export const convertCurrencyToCurrencyMicros = (
|
||||
currencyAmount: number | undefined,
|
||||
) => {
|
||||
if (!currencyAmount) {
|
||||
return undefined;
|
||||
}
|
||||
const currencyAmountAsNumber = +currencyAmount;
|
||||
if (isNaN(currencyAmountAsNumber)) {
|
||||
throw new Error(`Cannot convert ${currencyAmount} to micros`);
|
||||
}
|
||||
const currencyAmountAsMicros = currencyAmountAsNumber * 1000000;
|
||||
if (currencyAmountAsMicros % 1 !== 0) {
|
||||
throw new Error(`Cannot convert ${currencyAmount} to micros`);
|
||||
}
|
||||
return currencyAmountAsMicros;
|
||||
};
|
||||
|
||||
export const convertCurrencyMicrosToCurrency = (
|
||||
currencyAmountMicros: number | undefined,
|
||||
) => {
|
||||
if (!currencyAmountMicros) {
|
||||
return undefined;
|
||||
}
|
||||
const currencyAmountMicrosAsNumber = +currencyAmountMicros;
|
||||
if (isNaN(currencyAmountMicrosAsNumber)) {
|
||||
throw new Error(`Cannot convert ${currencyAmountMicros} to currency`);
|
||||
}
|
||||
const currencyAmount = currencyAmountMicrosAsNumber / 1000000;
|
||||
return currencyAmount;
|
||||
};
|
||||
Reference in New Issue
Block a user