From c335d19c97d17754607063ccbb088a1d32fbb802 Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Thu, 26 Oct 2023 12:07:43 +0200 Subject: [PATCH] Feat/add other metadata types v2 (#2224) * Fix view fetch bug * Finished types * Removed console.log * Fixed todo * Reactivate no console * Change no-console to warn --- front/.eslintrc.js | 2 +- .../components/MetadataObjectNavItems.tsx | 5 - .../components/ObjectDataTableEffect.tsx | 2 - .../hooks/useCreateNewTempCustomObject.ts | 154 ++++++++++++------ .../hooks/useFindOneMetadataObject.ts | 6 - .../formatMetadataFieldAsColumnDefinition.ts | 4 + .../generateFindManyCustomObjectsQuery.ts | 21 +-- .../utils/mapFieldMetadataToGraphQLQuery.ts | 44 +++++ .../ui/data/field/components/FieldDisplay.tsx | 4 + .../ui/data/field/components/FieldInput.tsx | 10 ++ .../ui/data/field/hooks/usePersistField.ts | 9 +- .../components/MoneyAmountV2FieldDisplay.tsx | 8 + .../components/MoneyAmountV2Display.tsx | 15 ++ .../meta-types/hooks/useMoneyAmountV2Field.ts | 43 +++++ .../components/MoneyAmountV2FieldInput.tsx | 93 +++++++++++ .../ui/data/field/types/FieldMetadata.ts | 9 + .../modules/ui/data/field/types/FieldType.ts | 4 +- .../field/types/guards/assertFieldMetadata.ts | 3 + .../types/guards/isFieldMoneyAmountV2.ts | 7 + .../types/guards/isFieldMoneyAmountV2Value.ts | 13 ++ 20 files changed, 369 insertions(+), 87 deletions(-) create mode 100644 front/src/modules/metadata/utils/mapFieldMetadataToGraphQLQuery.ts create mode 100644 front/src/modules/ui/data/field/meta-types/display/components/MoneyAmountV2FieldDisplay.tsx create mode 100644 front/src/modules/ui/data/field/meta-types/display/content-display/components/MoneyAmountV2Display.tsx create mode 100644 front/src/modules/ui/data/field/meta-types/hooks/useMoneyAmountV2Field.ts create mode 100644 front/src/modules/ui/data/field/meta-types/input/components/MoneyAmountV2FieldInput.tsx create mode 100644 front/src/modules/ui/data/field/types/guards/isFieldMoneyAmountV2.ts create mode 100644 front/src/modules/ui/data/field/types/guards/isFieldMoneyAmountV2Value.ts diff --git a/front/.eslintrc.js b/front/.eslintrc.js index 9829bbfa8..cb9dc2574 100644 --- a/front/.eslintrc.js +++ b/front/.eslintrc.js @@ -115,7 +115,7 @@ module.exports = { }, ], "@typescript-eslint/consistent-type-imports": ["error", { "prefer": "no-type-imports" }], - 'no-console': ['error', { allow: ['group', 'groupCollapsed', 'groupEnd'] }], + 'no-console': ['warn', { allow: ['group', 'groupCollapsed', 'groupEnd'] }], }, settings: { "react": { diff --git a/front/src/modules/metadata/components/MetadataObjectNavItems.tsx b/front/src/modules/metadata/components/MetadataObjectNavItems.tsx index 179fcfe85..32a43e69b 100644 --- a/front/src/modules/metadata/components/MetadataObjectNavItems.tsx +++ b/front/src/modules/metadata/components/MetadataObjectNavItems.tsx @@ -14,11 +14,6 @@ import { useFindManyMetadataObjects } from '../hooks/useFindManyMetadataObjects' export const MetadataObjectNavItems = () => { const { metadataObjects } = useFindManyMetadataObjects(); - // eslint-disable-next-line no-console - console.log({ - metadataObjects, - }); - const createNewTempCustomObject = useCreateNewTempsCustomObject(); const { deleteOneMetadataObject } = useDeleteOneMetadataObject(); diff --git a/front/src/modules/metadata/components/ObjectDataTableEffect.tsx b/front/src/modules/metadata/components/ObjectDataTableEffect.tsx index 91af7e66d..ebe287084 100644 --- a/front/src/modules/metadata/components/ObjectDataTableEffect.tsx +++ b/front/src/modules/metadata/components/ObjectDataTableEffect.tsx @@ -63,8 +63,6 @@ export const ObjectDataTableEffect = ({ const viewId = searchParams.get('view'); if (viewId) { handleViewSelect(viewId); - } else { - handleViewSelect(objectNamePlural); } }, [handleViewSelect, searchParams, objectNamePlural]); diff --git a/front/src/modules/metadata/hooks/useCreateNewTempCustomObject.ts b/front/src/modules/metadata/hooks/useCreateNewTempCustomObject.ts index ecbcf8242..bb1512525 100644 --- a/front/src/modules/metadata/hooks/useCreateNewTempCustomObject.ts +++ b/front/src/modules/metadata/hooks/useCreateNewTempCustomObject.ts @@ -18,16 +18,55 @@ import { useCreateOneMetadataObject } from './useCreateOneMetadataObject'; import { useUpdateOneMetadataField } from './useUpdateOneMetadataField'; import { useUpdateOneMetadataObject } from './useUpdateOneMetadataObject'; +const useCreateActiveMetadataField = () => { + const { createOneMetadataField } = useCreateOneMetadataField(); + const { updateOneMetadataField } = useUpdateOneMetadataField(); + + return async ({ + objectId, + label, + name, + type, + }: { + objectId: string; + label: string; + name: string; + type: FieldType; + }) => { + const { data: createdField } = await createOneMetadataField({ + objectId: objectId, + label: label, + name: name, + type: type, + description: label, + icon: 'IconMap', + }); + + if (!createdField || !createdField.createOneField.name) { + throw new Error('Could not create metadata field'); + } + + await updateOneMetadataField({ + fieldIdToUpdate: createdField?.createOneField?.id ?? '', + updatePayload: { + isActive: true, + }, + }); + + return createdField.createOneField; + }; +}; + export const useCreateNewTempsCustomObject = () => { const { createOneMetadataObject } = useCreateOneMetadataObject(); - const { createOneMetadataField } = useCreateOneMetadataField(); const { updateOneMetadataObject } = useUpdateOneMetadataObject(); - const { updateOneMetadataField } = useUpdateOneMetadataField(); const [createViewMutation] = useCreateViewMutation(); const [createViewFieldsMutation] = useCreateViewFieldsMutation(); + const createActiveMetadataField = useCreateActiveMetadataField(); + return async () => { const date = new Date().toISOString().replace(/[\/:\.\-\_]/g, ''); @@ -53,64 +92,67 @@ export const useCreateNewTempsCustomObject = () => { }, }); - const { data: nameFieldData } = await createOneMetadataField({ - objectId: supplierObjectId, - name: 'name', - type: 'text', - description: 'Name', + const nameFieldData = await createActiveMetadataField({ label: 'Name', - icon: 'IconBuilding', - }); - - if (!nameFieldData || !nameFieldData.createOneField.name) { - throw new Error('Could not create metadata field'); - } - - await updateOneMetadataField({ - fieldIdToUpdate: nameFieldData?.createOneField?.id ?? '', - updatePayload: { - isActive: true, - }, - }); - - const { data: cityFieldData } = await createOneMetadataField({ + name: 'name', objectId: supplierObjectId, + type: 'text', + }); + + const cityFieldData = await createActiveMetadataField({ label: 'City', name: 'city', - type: 'text', - description: 'City', - icon: 'IconMap', - }); - - if (!cityFieldData || !cityFieldData.createOneField.name) { - throw new Error('Could not create metadata field'); - } - - await updateOneMetadataField({ - fieldIdToUpdate: cityFieldData?.createOneField?.id ?? '', - updatePayload: { - isActive: true, - }, - }); - - const { data: emailFieldData } = await createOneMetadataField({ objectId: supplierObjectId, + type: 'text', + }); + + const emailFieldData = await createActiveMetadataField({ label: 'Email', name: 'email', - type: 'url', - description: 'Email', - icon: 'IconMap', + objectId: supplierObjectId, + type: 'email', }); - if (!emailFieldData || !emailFieldData.createOneField.name) { - throw new Error('Could not create metadata field'); - } + const phoneFieldData = await createActiveMetadataField({ + label: 'Phone', + name: 'phone', + objectId: supplierObjectId, + type: 'phone', + }); - await updateOneMetadataField({ - fieldIdToUpdate: emailFieldData?.createOneField?.id ?? '', - updatePayload: { - isActive: true, - }, + const twitterFieldData = await createActiveMetadataField({ + label: 'Twitter', + name: 'twitter', + objectId: supplierObjectId, + type: 'url', + }); + + const booleanFieldData = await createActiveMetadataField({ + label: 'Boolean example', + name: 'boolexample', + objectId: supplierObjectId, + type: 'boolean', + }); + + const employeesFieldData = await createActiveMetadataField({ + label: 'Employees', + name: 'employees', + objectId: supplierObjectId, + type: 'number', + }); + + const ARRFieldData = await createActiveMetadataField({ + label: 'ARR', + name: 'arr', + objectId: supplierObjectId, + type: 'money', + }); + + const createdAt = await createActiveMetadataField({ + label: 'Created at', + name: 'createdAt', + objectId: supplierObjectId, + type: 'date', }); const objectId = 'suppliers' + date; @@ -127,9 +169,15 @@ export const useCreateNewTempsCustomObject = () => { }); const createdFields = [ - emailFieldData.createOneField, - nameFieldData.createOneField, - cityFieldData.createOneField, + emailFieldData, + nameFieldData, + cityFieldData, + phoneFieldData, + twitterFieldData, + booleanFieldData, + employeesFieldData, + ARRFieldData, + createdAt, ]; const tempColumnDefinitions: ColumnDefinition[] = diff --git a/front/src/modules/metadata/hooks/useFindOneMetadataObject.ts b/front/src/modules/metadata/hooks/useFindOneMetadataObject.ts index 2fba062c4..dc736fc23 100644 --- a/front/src/modules/metadata/hooks/useFindOneMetadataObject.ts +++ b/front/src/modules/metadata/hooks/useFindOneMetadataObject.ts @@ -31,12 +31,6 @@ export const useFindOneMetadataObject = ({ }), ) ?? []; - // eslint-disable-next-line no-console - console.log({ - foundMetadataObject, - columnDefinitions, - }); - const findManyQuery = foundMetadataObject ? generateFindManyCustomObjectsQuery({ metadataObject: foundMetadataObject, diff --git a/front/src/modules/metadata/utils/formatMetadataFieldAsColumnDefinition.ts b/front/src/modules/metadata/utils/formatMetadataFieldAsColumnDefinition.ts index 18558d8da..5cf12e90a 100644 --- a/front/src/modules/metadata/utils/formatMetadataFieldAsColumnDefinition.ts +++ b/front/src/modules/metadata/utils/formatMetadataFieldAsColumnDefinition.ts @@ -10,6 +10,10 @@ const parseFieldType = (fieldType: string): FieldType => { return 'urlV2'; } + if (fieldType === 'money') { + return 'moneyAmountV2'; + } + return fieldType as FieldType; }; diff --git a/front/src/modules/metadata/utils/generateFindManyCustomObjectsQuery.ts b/front/src/modules/metadata/utils/generateFindManyCustomObjectsQuery.ts index f04e19a7b..506ce7c31 100644 --- a/front/src/modules/metadata/utils/generateFindManyCustomObjectsQuery.ts +++ b/front/src/modules/metadata/utils/generateFindManyCustomObjectsQuery.ts @@ -1,9 +1,9 @@ import { gql } from '@apollo/client'; -import { FieldType } from '@/ui/data/field/types/FieldType'; - import { MetadataObject } from '../types/MetadataObject'; +import { mapFieldMetadataToGraphQLQuery } from './mapFieldMetadataToGraphQLQuery'; + export const generateFindManyCustomObjectsQuery = ({ metadataObject, _fromCursor, @@ -18,22 +18,7 @@ export const generateFindManyCustomObjectsQuery = ({ node { id ${metadataObject.fields - .map((field) => { - // TODO: parse - const fieldType = field.type as FieldType; - - if (fieldType === 'text') { - return field.name; - } else if (fieldType === 'url') { - return ` - ${field.name} - { - text - link - } - `; - } - }) + .map(mapFieldMetadataToGraphQLQuery) .join('\n')} } cursor diff --git a/front/src/modules/metadata/utils/mapFieldMetadataToGraphQLQuery.ts b/front/src/modules/metadata/utils/mapFieldMetadataToGraphQLQuery.ts new file mode 100644 index 000000000..a98cee200 --- /dev/null +++ b/front/src/modules/metadata/utils/mapFieldMetadataToGraphQLQuery.ts @@ -0,0 +1,44 @@ +import { FieldType } from '@/ui/data/field/types/FieldType'; +import { Field } from '~/generated/graphql'; + +export const mapFieldMetadataToGraphQLQuery = (field: Field) => { + // TODO: parse + const fieldType = field.type as FieldType; + + const fieldIsSimpleValue = ( + [ + 'text', + 'phone', + 'date', + 'email', + 'number', + 'boolean', + 'date', + ] as FieldType[] + ).includes(fieldType); + + const fieldIsURL = fieldType === 'url' || fieldType === 'urlV2'; + + const fieldIsMoneyAmount = + fieldType === 'money' || fieldType === 'moneyAmountV2'; + + if (fieldIsSimpleValue) { + return field.name; + } else if (fieldIsURL) { + return ` + ${field.name} + { + text + link + } + `; + } else if (fieldIsMoneyAmount) { + return ` + ${field.name} + { + amount + currency + } + `; + } +}; diff --git a/front/src/modules/ui/data/field/components/FieldDisplay.tsx b/front/src/modules/ui/data/field/components/FieldDisplay.tsx index 1b610ba51..b024154d3 100644 --- a/front/src/modules/ui/data/field/components/FieldDisplay.tsx +++ b/front/src/modules/ui/data/field/components/FieldDisplay.tsx @@ -6,6 +6,7 @@ import { DateFieldDisplay } from '../meta-types/display/components/DateFieldDisp 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 { MoneyFieldDisplay } from '../meta-types/display/components/MoneyFieldDisplay'; import { NumberFieldDisplay } from '../meta-types/display/components/NumberFieldDisplay'; import { PhoneFieldDisplay } from '../meta-types/display/components/PhoneFieldDisplay'; @@ -19,6 +20,7 @@ import { isFieldDoubleText } from '../types/guards/isFieldDoubleText'; import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip'; import { isFieldEmail } from '../types/guards/isFieldEmail'; 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'; @@ -47,6 +49,8 @@ export const FieldDisplay = () => { ) : isFieldURLV2(fieldDefinition) ? ( + ) : isFieldMoneyAmountV2(fieldDefinition) ? ( + ) : isFieldPhone(fieldDefinition) ? ( ) : isFieldChip(fieldDefinition) ? ( diff --git a/front/src/modules/ui/data/field/components/FieldInput.tsx b/front/src/modules/ui/data/field/components/FieldInput.tsx index b50f7c0ff..4dbaa933f 100644 --- a/front/src/modules/ui/data/field/components/FieldInput.tsx +++ b/front/src/modules/ui/data/field/components/FieldInput.tsx @@ -9,6 +9,7 @@ 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 { MoneyFieldInput } from '../meta-types/input/components/MoneyFieldInput'; import { NumberFieldInput } from '../meta-types/input/components/NumberFieldInput'; import { PhoneFieldInput } from '../meta-types/input/components/PhoneFieldInput'; @@ -25,6 +26,7 @@ import { isFieldDoubleText } from '../types/guards/isFieldDoubleText'; import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip'; import { isFieldEmail } from '../types/guards/isFieldEmail'; 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'; @@ -108,6 +110,14 @@ export const FieldInput = ({ onTab={onTab} onShiftTab={onShiftTab} /> + ) : isFieldMoneyAmountV2(fieldDefinition) ? ( + ) : isFieldPhone(fieldDefinition) ? ( { const fieldIsMoney = isFieldMoney(fieldDefinition) && isFieldMoneyValue(valueToPersist); + const fieldIsMoneyAmountV2 = + isFieldMoneyAmountV2(fieldDefinition) && + isFieldMoneyAmountV2Value(valueToPersist); + const fieldIsPhone = isFieldPhone(fieldDefinition) && isFieldPhoneValue(valueToPersist); @@ -160,7 +166,8 @@ export const usePersistField = () => { fieldIsMoney || fieldIsDate || fieldIsPhone || - fieldIsURLV2 + fieldIsURLV2 || + fieldIsMoneyAmountV2 ) { const fieldName = fieldDefinition.metadata.fieldName; diff --git a/front/src/modules/ui/data/field/meta-types/display/components/MoneyAmountV2FieldDisplay.tsx b/front/src/modules/ui/data/field/meta-types/display/components/MoneyAmountV2FieldDisplay.tsx new file mode 100644 index 000000000..f0ab589ba --- /dev/null +++ b/front/src/modules/ui/data/field/meta-types/display/components/MoneyAmountV2FieldDisplay.tsx @@ -0,0 +1,8 @@ +import { useMoneyAmountV2Field } from '../../hooks/useMoneyAmountV2Field'; +import { MoneyAmountV2Display } from '../content-display/components/MoneyAmountV2Display'; + +export const MoneyAmountV2FieldDisplay = () => { + const { fieldValue } = useMoneyAmountV2Field(); + + return ; +}; diff --git a/front/src/modules/ui/data/field/meta-types/display/content-display/components/MoneyAmountV2Display.tsx b/front/src/modules/ui/data/field/meta-types/display/content-display/components/MoneyAmountV2Display.tsx new file mode 100644 index 000000000..46749954d --- /dev/null +++ b/front/src/modules/ui/data/field/meta-types/display/content-display/components/MoneyAmountV2Display.tsx @@ -0,0 +1,15 @@ +import { FieldMoneyAmountV2Value } from '@/ui/data/field/types/FieldMetadata'; + +import { EllipsisDisplay } from './EllipsisDisplay'; + +type MoneyAmountV2DisplayProps = { + value?: FieldMoneyAmountV2Value; +}; + +export const MoneyAmountV2Display = ({ value }: MoneyAmountV2DisplayProps) => { + return ( + + {value?.amount} {value?.currency} + + ); +}; diff --git a/front/src/modules/ui/data/field/meta-types/hooks/useMoneyAmountV2Field.ts b/front/src/modules/ui/data/field/meta-types/hooks/useMoneyAmountV2Field.ts new file mode 100644 index 000000000..fb4c01507 --- /dev/null +++ b/front/src/modules/ui/data/field/meta-types/hooks/useMoneyAmountV2Field.ts @@ -0,0 +1,43 @@ +import { useContext } from 'react'; +import { useRecoilState } from 'recoil'; + +import { FieldContext } from '../../contexts/FieldContext'; +import { usePersistField } from '../../hooks/usePersistField'; +import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector'; +import { FieldMoneyAmountV2Value } from '../../types/FieldMetadata'; +import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata'; +import { isFieldMoneyAmountV2 } from '../../types/guards/isFieldMoneyAmountV2'; +import { isFieldMoneyAmountV2Value } from '../../types/guards/isFieldMoneyAmountV2Value'; + +export const useMoneyAmountV2Field = () => { + const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext); + + assertFieldMetadata('moneyAmountV2', isFieldMoneyAmountV2, fieldDefinition); + + const fieldName = fieldDefinition.metadata.fieldName; + + const [fieldValue, setFieldValue] = useRecoilState( + entityFieldsFamilySelector({ + entityId: entityId, + fieldName: fieldName, + }), + ); + + const persistField = usePersistField(); + + const persistMoneyAmountV2Field = (newValue: FieldMoneyAmountV2Value) => { + if (!isFieldMoneyAmountV2Value(newValue)) { + return; + } + + persistField(newValue); + }; + + return { + fieldDefinition, + fieldValue, + setFieldValue, + hotkeyScope, + persistMoneyAmountV2Field, + }; +}; diff --git a/front/src/modules/ui/data/field/meta-types/input/components/MoneyAmountV2FieldInput.tsx b/front/src/modules/ui/data/field/meta-types/input/components/MoneyAmountV2FieldInput.tsx new file mode 100644 index 000000000..e69f0684a --- /dev/null +++ b/front/src/modules/ui/data/field/meta-types/input/components/MoneyAmountV2FieldInput.tsx @@ -0,0 +1,93 @@ +import { DoubleTextInput } from '@/ui/data/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 { fieldValue, hotkeyScope } = 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 ( + + + + ); +}; diff --git a/front/src/modules/ui/data/field/types/FieldMetadata.ts b/front/src/modules/ui/data/field/types/FieldMetadata.ts index 762add033..3efcd46a1 100644 --- a/front/src/modules/ui/data/field/types/FieldMetadata.ts +++ b/front/src/modules/ui/data/field/types/FieldMetadata.ts @@ -37,6 +37,12 @@ export type FieldMoneyMetadata = { isPositive?: boolean; }; +export type FieldMoneyAmountV2Metadata = { + fieldName: string; + placeHolder: string; + isPositive?: boolean; +}; + export type FieldEmailMetadata = { fieldName: string; placeHolder: string; @@ -90,6 +96,7 @@ export type FieldMetadata = | FieldURLV2Metadata | FieldNumberMetadata | FieldMoneyMetadata + | FieldMoneyAmountV2Metadata | FieldEmailMetadata | FieldDateMetadata | FieldProbabilityMetadata @@ -104,6 +111,8 @@ export type FieldURLValue = string; export type FieldURLV2Value = { link: string; text: string }; export type FieldNumberValue = number | null; export type FieldMoneyValue = number | null; +export type FieldMoneyAmountV2Value = { currency: string; amount: number }; + export type FieldEmailValue = string; export type FieldProbabilityValue = number; export type FieldBooleanValue = boolean; diff --git a/front/src/modules/ui/data/field/types/FieldType.ts b/front/src/modules/ui/data/field/types/FieldType.ts index 3fe8ff56a..f3bf440ab 100644 --- a/front/src/modules/ui/data/field/types/FieldType.ts +++ b/front/src/modules/ui/data/field/types/FieldType.ts @@ -12,4 +12,6 @@ export type FieldType = | 'url' | 'urlV2' | 'probability' - | 'moneyAmount'; + | 'moneyAmountV2' + | 'moneyAmount' + | 'money'; diff --git a/front/src/modules/ui/data/field/types/guards/assertFieldMetadata.ts b/front/src/modules/ui/data/field/types/guards/assertFieldMetadata.ts index 7da9696c0..75e2a5f82 100644 --- a/front/src/modules/ui/data/field/types/guards/assertFieldMetadata.ts +++ b/front/src/modules/ui/data/field/types/guards/assertFieldMetadata.ts @@ -7,6 +7,7 @@ import { FieldDoubleTextMetadata, FieldEmailMetadata, FieldMetadata, + FieldMoneyAmountV2Metadata, FieldMoneyMetadata, FieldNumberMetadata, FieldPhoneMetadata, @@ -48,6 +49,8 @@ type AssertFieldMetadataFunction = < ? FieldProbabilityMetadata : E extends 'moneyAmount' ? FieldMoneyMetadata + : E extends 'moneyAmountV2' + ? FieldMoneyAmountV2Metadata : never, >( fieldType: E, diff --git a/front/src/modules/ui/data/field/types/guards/isFieldMoneyAmountV2.ts b/front/src/modules/ui/data/field/types/guards/isFieldMoneyAmountV2.ts new file mode 100644 index 000000000..eb3ab2a41 --- /dev/null +++ b/front/src/modules/ui/data/field/types/guards/isFieldMoneyAmountV2.ts @@ -0,0 +1,7 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldMetadata, FieldMoneyAmountV2Metadata } from '../FieldMetadata'; + +export const isFieldMoneyAmountV2 = ( + field: FieldDefinition, +): field is FieldDefinition => + field.type === 'moneyAmountV2'; diff --git a/front/src/modules/ui/data/field/types/guards/isFieldMoneyAmountV2Value.ts b/front/src/modules/ui/data/field/types/guards/isFieldMoneyAmountV2Value.ts new file mode 100644 index 000000000..66cad2cfa --- /dev/null +++ b/front/src/modules/ui/data/field/types/guards/isFieldMoneyAmountV2Value.ts @@ -0,0 +1,13 @@ +import { z } from 'zod'; + +import { FieldMoneyValue } from '../FieldMetadata'; + +const moneyAmountV2Schema = z.object({ + currency: z.string(), + amount: z.number(), +}); + +export const isFieldMoneyAmountV2Value = ( + fieldValue: unknown, +): fieldValue is FieldMoneyValue => + moneyAmountV2Schema.safeParse(fieldValue).success;