diff --git a/front/src/modules/ui/editable-field/components/GenericEditableRelationField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableRelationField.tsx
index a52f9ecf3..1b2c63220 100644
--- a/front/src/modules/ui/editable-field/components/GenericEditableRelationField.tsx
+++ b/front/src/modules/ui/editable-field/components/GenericEditableRelationField.tsx
@@ -2,30 +2,25 @@ import { useContext } from 'react';
import { useRecoilValue } from 'recoil';
import { PersonChip } from '@/people/components/PersonChip';
-import {
- ViewFieldDefinition,
- ViewFieldRelationMetadata,
-} from '@/ui/editable-field/types/ViewField';
+import { ViewFieldRelationMetadata } from '@/ui/editable-field/types/ViewField';
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
-import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext';
+import { EditableFieldContext } from '../states/EditableFieldContext';
import { FieldContext } from '../states/FieldContext';
import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector';
+import { FieldDefinition } from '../types/FieldDefinition';
+import { FieldRelationMetadata } from '../types/FieldMetadata';
import { EditableField } from './EditableField';
import { GenericEditableRelationFieldEditMode } from './GenericEditableRelationFieldEditMode';
-type OwnProps = {
- viewField: ViewFieldDefinition
;
-};
-
function RelationChip({
fieldDefinition,
fieldValue,
}: {
- fieldDefinition: ViewFieldDefinition;
+ fieldDefinition: FieldDefinition;
fieldValue: any | null;
}) {
switch (fieldDefinition.metadata.relationType) {
@@ -46,13 +41,18 @@ function RelationChip({
}
}
-export function GenericEditableRelationField({ viewField }: OwnProps) {
- const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext);
+export function GenericEditableRelationField() {
+ const currentEditableField = useContext(EditableFieldContext);
+ const currentEditableFieldEntityId = currentEditableField.entityId;
+ const currentEditableFieldDefinition =
+ currentEditableField.fieldDefinition as FieldDefinition;
const fieldValue = useRecoilValue(
genericEntityFieldFamilySelector({
entityId: currentEditableFieldEntityId ?? '',
- fieldName: viewField.metadata.fieldName,
+ fieldName: currentEditableFieldDefinition
+ ? currentEditableFieldDefinition.metadata.fieldName
+ : '',
}),
);
@@ -64,12 +64,13 @@ export function GenericEditableRelationField({ viewField }: OwnProps) {
customEditHotkeyScope={{
scope: RelationPickerHotkeyScope.RelationPicker,
}}
- iconLabel={viewField.columnIcon}
- editModeContent={
-
- }
+ iconLabel={currentEditableFieldDefinition.icon}
+ editModeContent={}
displayModeContent={
-
+
}
isDisplayModeContentEmpty={!fieldValue}
isDisplayModeFixHeight
diff --git a/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldEditMode.tsx
index ce00ba74b..a05303135 100644
--- a/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldEditMode.tsx
+++ b/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldEditMode.tsx
@@ -4,7 +4,6 @@ import { useRecoilState } from 'recoil';
import { PeoplePicker } from '@/people/components/PeoplePicker';
import {
- ViewFieldDefinition,
ViewFieldRelationMetadata,
ViewFieldRelationValue,
} from '@/ui/editable-field/types/ViewField';
@@ -13,8 +12,10 @@ import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
import { useEditableField } from '../hooks/useEditableField';
import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField';
-import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext';
+import { EditableFieldContext } from '../states/EditableFieldContext';
import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector';
+import { FieldDefinition } from '../types/FieldDefinition';
+import { FieldRelationMetadata } from '../types/FieldMetadata';
const RelationPickerContainer = styled.div`
left: 0px;
@@ -22,17 +23,13 @@ const RelationPickerContainer = styled.div`
top: -8px;
`;
-type OwnProps = {
- viewField: ViewFieldDefinition;
-};
-
function RelationPicker({
fieldDefinition,
fieldValue,
handleEntitySubmit,
handleCancel,
}: {
- fieldDefinition: ViewFieldDefinition;
+ fieldDefinition: FieldDefinition;
fieldValue: ViewFieldRelationValue;
handleEntitySubmit: (newRelationId: EntityForSelect | null) => void;
handleCancel: () => void;
@@ -55,14 +52,19 @@ function RelationPicker({
}
}
-export function GenericEditableRelationFieldEditMode({ viewField }: OwnProps) {
- const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext);
+export function GenericEditableRelationFieldEditMode() {
+ const currentEditableField = useContext(EditableFieldContext);
+ const currentEditableFieldEntityId = currentEditableField.entityId;
+ const currentEditableFieldDefinition =
+ currentEditableField.fieldDefinition as FieldDefinition;
// TODO: we could use a hook that would return the field value with the right type
const [fieldValue, setFieldValue] = useRecoilState(
genericEntityFieldFamilySelector({
entityId: currentEditableFieldEntityId ?? '',
- fieldName: viewField.metadata.fieldName,
+ fieldName: currentEditableFieldDefinition
+ ? currentEditableFieldDefinition.metadata.fieldName
+ : '',
}),
);
@@ -79,7 +81,11 @@ export function GenericEditableRelationFieldEditMode({ viewField }: OwnProps) {
});
if (currentEditableFieldEntityId && updateField) {
- updateField(currentEditableFieldEntityId, viewField, newRelation);
+ updateField(
+ currentEditableFieldEntityId,
+ currentEditableFieldDefinition,
+ newRelation,
+ );
}
closeEditableField();
@@ -92,7 +98,7 @@ export function GenericEditableRelationFieldEditMode({ viewField }: OwnProps) {
return (
;
-};
+export function ProbabilityEditableField() {
+ const currentEditableField = useContext(EditableFieldContext);
+ const currentEditableFieldDefinition = currentEditableField.fieldDefinition;
-export function ProbabilityEditableField({ viewField }: OwnProps) {
return (
- }
+ iconLabel={currentEditableFieldDefinition.icon}
+ displayModeContent={}
displayModeContentOnly
disableHoverEffect
/>
diff --git a/front/src/modules/ui/editable-field/components/ProbabilityEditableFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/ProbabilityEditableFieldEditMode.tsx
index e41c01088..03873ecd6 100644
--- a/front/src/modules/ui/editable-field/components/ProbabilityEditableFieldEditMode.tsx
+++ b/front/src/modules/ui/editable-field/components/ProbabilityEditableFieldEditMode.tsx
@@ -5,12 +5,10 @@ import { useRecoilState } from 'recoil';
import { useEditableField } from '@/ui/editable-field/hooks/useEditableField';
import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField';
-import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext';
+import { EditableFieldContext } from '../states/EditableFieldContext';
import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector';
-import {
- ViewFieldDefinition,
- ViewFieldProbabilityMetadata,
-} from '../types/ViewField';
+import { FieldDefinition } from '../types/FieldDefinition';
+import { FieldProbabilityMetadata } from '../types/FieldMetadata';
const StyledContainer = styled.div`
align-items: center;
@@ -60,10 +58,6 @@ const StyledLabel = styled.div`
width: ${({ theme }) => theme.spacing(12)};
`;
-type OwnProps = {
- viewField: ViewFieldDefinition;
-};
-
const PROBABILITY_VALUES = [
{ label: '0%', value: 0 },
{ label: '25%', value: 25 },
@@ -72,28 +66,38 @@ const PROBABILITY_VALUES = [
{ label: '100%', value: 100 },
];
-export function ProbabilityEditableFieldEditMode({ viewField }: OwnProps) {
+export function ProbabilityEditableFieldEditMode() {
const [nextProbabilityIndex, setNextProbabilityIndex] = useState<
number | null
>(null);
- const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext);
+ const currentEditableField = useContext(EditableFieldContext);
+ const currentEditableFieldEntityId = currentEditableField.entityId;
+ const currentEditableFieldDefinition =
+ currentEditableField.fieldDefinition as FieldDefinition;
const [fieldValue, setFieldValue] = useRecoilState(
genericEntityFieldFamilySelector({
entityId: currentEditableFieldEntityId ?? '',
- fieldName: viewField.metadata.fieldName,
+ fieldName: currentEditableFieldDefinition
+ ? currentEditableFieldDefinition.metadata.fieldName
+ : '',
}),
);
- const probabilityIndex = Math.ceil(fieldValue / 25);
const { closeEditableField } = useEditableField();
const updateField = useUpdateGenericEntityField();
+ const probabilityIndex = Math.ceil(fieldValue / 25);
+
function handleChange(newValue: number) {
setFieldValue(newValue);
if (currentEditableFieldEntityId && updateField) {
- updateField(currentEditableFieldEntityId, viewField, newValue);
+ updateField(
+ currentEditableFieldEntityId,
+ currentEditableFieldDefinition,
+ newValue,
+ );
}
closeEditableField();
}
diff --git a/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts b/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts
index 87165dd9f..16a2f903e 100644
--- a/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts
+++ b/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts
@@ -1,100 +1,98 @@
import { useContext } from 'react';
-import { isViewFieldChip } from '@/ui/editable-field/types/guards/isViewFieldChip';
-import { EntityUpdateMutationHookContext } from '@/ui/table/states/EntityUpdateMutationHookContext';
+import { isFieldChip } from '@/ui/editable-field/types/guards/isFieldChip';
-import { isViewFieldChipValue } from '../types/guards/isViewFieldChipValue';
-import { isViewFieldDate } from '../types/guards/isViewFieldDate';
-import { isViewFieldDateValue } from '../types/guards/isViewFieldDateValue';
-import { isViewFieldDoubleText } from '../types/guards/isViewFieldDoubleText';
-import { isViewFieldDoubleTextChip } from '../types/guards/isViewFieldDoubleTextChip';
-import { isViewFieldDoubleTextChipValue } from '../types/guards/isViewFieldDoubleTextChipValue';
-import { isViewFieldDoubleTextValue } from '../types/guards/isViewFieldDoubleTextValue';
-import { isViewFieldNumber } from '../types/guards/isViewFieldNumber';
-import { isViewFieldNumberValue } from '../types/guards/isViewFieldNumberValue';
-import { isViewFieldPhone } from '../types/guards/isViewFieldPhone';
-import { isViewFieldPhoneValue } from '../types/guards/isViewFieldPhoneValue';
-import { isViewFieldProbability } from '../types/guards/isViewFieldProbability';
-import { isViewFieldProbabilityValue } from '../types/guards/isViewFieldProbabilityValue';
-import { isViewFieldRelation } from '../types/guards/isViewFieldRelation';
-import { isViewFieldRelationValue } from '../types/guards/isViewFieldRelationValue';
-import { isViewFieldText } from '../types/guards/isViewFieldText';
-import { isViewFieldTextValue } from '../types/guards/isViewFieldTextValue';
-import { isViewFieldURL } from '../types/guards/isViewFieldURL';
-import { isViewFieldURLValue } from '../types/guards/isViewFieldURLValue';
+import { EditableFieldContext } from '../states/EditableFieldContext';
+import { FieldDefinition } from '../types/FieldDefinition';
import {
- ViewFieldChipMetadata,
- ViewFieldChipValue,
- ViewFieldDateMetadata,
- ViewFieldDateValue,
- ViewFieldDefinition,
- ViewFieldDoubleTextChipMetadata,
- ViewFieldDoubleTextChipValue,
- ViewFieldDoubleTextMetadata,
- ViewFieldDoubleTextValue,
- ViewFieldMetadata,
- ViewFieldNumberMetadata,
- ViewFieldNumberValue,
- ViewFieldPhoneMetadata,
- ViewFieldPhoneValue,
- ViewFieldProbabilityMetadata,
- ViewFieldProbabilityValue,
- ViewFieldRelationMetadata,
- ViewFieldRelationValue,
- ViewFieldTextMetadata,
- ViewFieldTextValue,
- ViewFieldURLMetadata,
- ViewFieldURLValue,
-} from '../types/ViewField';
+ FieldChipMetadata,
+ FieldChipValue,
+ FieldDateMetadata,
+ FieldDateValue,
+ FieldDoubleTextChipMetadata,
+ FieldDoubleTextChipValue,
+ FieldDoubleTextMetadata,
+ FieldDoubleTextValue,
+ FieldMetadata,
+ FieldNumberMetadata,
+ FieldNumberValue,
+ FieldPhoneMetadata,
+ FieldPhoneValue,
+ FieldProbabilityMetadata,
+ FieldProbabilityValue,
+ FieldRelationMetadata,
+ FieldRelationValue,
+ FieldTextMetadata,
+ FieldTextValue,
+ FieldURLMetadata,
+ FieldURLValue,
+} from '../types/FieldMetadata';
+import { isFieldChipValue } from '../types/guards/isFieldChipValue';
+import { isFieldDate } from '../types/guards/isFieldDate';
+import { isFieldDateValue } from '../types/guards/isFieldDateValue';
+import { isFieldDoubleText } from '../types/guards/isFieldDoubleText';
+import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip';
+import { isFieldDoubleTextChipValue } from '../types/guards/isFieldDoubleTextChipValue';
+import { isFieldDoubleTextValue } from '../types/guards/isFieldDoubleTextValue';
+import { isFieldNumber } from '../types/guards/isFieldNumber';
+import { isFieldNumberValue } from '../types/guards/isFieldNumberValue';
+import { isFieldPhone } from '../types/guards/isFieldPhone';
+import { isFieldPhoneValue } from '../types/guards/isFieldPhoneValue';
+import { isFieldProbability } from '../types/guards/isFieldProbability';
+import { isFieldProbabilityValue } from '../types/guards/isFieldProbabilityValue';
+import { isFieldRelation } from '../types/guards/isFieldRelation';
+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 { isFieldURLValue } from '../types/guards/isFieldURLValue';
export function useUpdateGenericEntityField() {
- const useUpdateEntityMutation = useContext(EntityUpdateMutationHookContext);
+ const currentEditableField = useContext(EditableFieldContext);
+ const useUpdateEntityMutation = currentEditableField?.mutation;
const [updateEntity] = useUpdateEntityMutation();
- return function updatePeopleField<
- MetadataType extends ViewFieldMetadata,
- ValueType extends MetadataType extends ViewFieldDoubleTextMetadata
- ? ViewFieldDoubleTextValue
- : MetadataType extends ViewFieldTextMetadata
- ? ViewFieldTextValue
- : MetadataType extends ViewFieldPhoneMetadata
- ? ViewFieldPhoneValue
- : MetadataType extends ViewFieldURLMetadata
- ? ViewFieldURLValue
- : MetadataType extends ViewFieldNumberMetadata
- ? ViewFieldNumberValue
- : MetadataType extends ViewFieldDateMetadata
- ? ViewFieldDateValue
- : MetadataType extends ViewFieldChipMetadata
- ? ViewFieldChipValue
- : MetadataType extends ViewFieldDoubleTextChipMetadata
- ? ViewFieldDoubleTextChipValue
- : MetadataType extends ViewFieldRelationMetadata
- ? ViewFieldRelationValue
- : MetadataType extends ViewFieldProbabilityMetadata
- ? ViewFieldProbabilityValue
+ return function updateEntityField<
+ MetadataType extends FieldMetadata,
+ ValueType extends MetadataType extends FieldDoubleTextMetadata
+ ? FieldDoubleTextValue
+ : MetadataType extends FieldTextMetadata
+ ? FieldTextValue
+ : MetadataType extends FieldPhoneMetadata
+ ? FieldPhoneValue
+ : MetadataType extends FieldURLMetadata
+ ? FieldURLValue
+ : MetadataType extends FieldNumberMetadata
+ ? FieldNumberValue
+ : MetadataType extends FieldDateMetadata
+ ? FieldDateValue
+ : MetadataType extends FieldChipMetadata
+ ? FieldChipValue
+ : MetadataType extends FieldDoubleTextChipMetadata
+ ? FieldDoubleTextChipValue
+ : MetadataType extends FieldRelationMetadata
+ ? FieldRelationValue
+ : MetadataType extends FieldProbabilityMetadata
+ ? FieldProbabilityValue
: unknown,
>(
currentEntityId: string,
- viewField: ViewFieldDefinition,
+ field: FieldDefinition,
newFieldValue: ValueType,
) {
const newFieldValueUnknown = newFieldValue as unknown;
- // TODO: improve type guards organization, maybe with a common typeguard for all view fields
- // taking an object of options as parameter ?
+ // TODO: improve type guards organization, maybe with a common typeguard for all fields
+ // taking an object of options as parameter ?
//
- // The goal would be to check that the view field value not only is valid,
- // but also that it is validated against the corresponding view field type
+ // The goal would be to check that the field value not only is valid,
+ // but also that it is validated against the corresponding field type
// Relation
- if (
- isViewFieldRelation(viewField) &&
- isViewFieldRelationValue(newFieldValueUnknown)
- ) {
+ if (isFieldRelation(field) && isFieldRelationValue(newFieldValueUnknown)) {
const newSelectedEntity = newFieldValueUnknown;
- const fieldName = viewField.metadata.fieldName;
+ const fieldName = field.metadata.fieldName;
if (!newSelectedEntity) {
updateEntity({
@@ -120,35 +118,29 @@ export function useUpdateGenericEntityField() {
});
}
// Chip
- } else if (
- isViewFieldChip(viewField) &&
- isViewFieldChipValue(newFieldValueUnknown)
- ) {
+ } else if (isFieldChip(field) && isFieldChipValue(newFieldValueUnknown)) {
const newContent = newFieldValueUnknown;
updateEntity({
variables: {
where: { id: currentEntityId },
- data: { [viewField.metadata.contentFieldName]: newContent },
+ data: { [field.metadata.contentFieldName]: newContent },
},
});
// Text
- } else if (
- isViewFieldText(viewField) &&
- isViewFieldTextValue(newFieldValueUnknown)
- ) {
+ } else if (isFieldText(field) && isFieldTextValue(newFieldValueUnknown)) {
const newContent = newFieldValueUnknown;
updateEntity({
variables: {
where: { id: currentEntityId },
- data: { [viewField.metadata.fieldName]: newContent },
+ data: { [field.metadata.fieldName]: newContent },
},
});
// Double text
} else if (
- isViewFieldDoubleText(viewField) &&
- isViewFieldDoubleTextValue(newFieldValueUnknown)
+ isFieldDoubleText(field) &&
+ isFieldDoubleTextValue(newFieldValueUnknown)
) {
const newContent = newFieldValueUnknown;
@@ -156,15 +148,15 @@ export function useUpdateGenericEntityField() {
variables: {
where: { id: currentEntityId },
data: {
- [viewField.metadata.firstValueFieldName]: newContent.firstValue,
- [viewField.metadata.secondValueFieldName]: newContent.secondValue,
+ [field.metadata.firstValueFieldName]: newContent.firstValue,
+ [field.metadata.secondValueFieldName]: newContent.secondValue,
},
},
});
// Double Text Chip
} else if (
- isViewFieldDoubleTextChip(viewField) &&
- isViewFieldDoubleTextChipValue(newFieldValueUnknown)
+ isFieldDoubleTextChip(field) &&
+ isFieldDoubleTextChipValue(newFieldValueUnknown)
) {
const newContent = newFieldValueUnknown;
@@ -172,73 +164,64 @@ export function useUpdateGenericEntityField() {
variables: {
where: { id: currentEntityId },
data: {
- [viewField.metadata.firstValueFieldName]: newContent.firstValue,
- [viewField.metadata.secondValueFieldName]: newContent.secondValue,
+ [field.metadata.firstValueFieldName]: newContent.firstValue,
+ [field.metadata.secondValueFieldName]: newContent.secondValue,
},
},
});
// Phone
- } else if (
- isViewFieldPhone(viewField) &&
- isViewFieldPhoneValue(newFieldValueUnknown)
- ) {
+ } else if (isFieldPhone(field) && isFieldPhoneValue(newFieldValueUnknown)) {
const newContent = newFieldValueUnknown;
updateEntity({
variables: {
where: { id: currentEntityId },
- data: { [viewField.metadata.fieldName]: newContent },
+ data: { [field.metadata.fieldName]: newContent },
},
});
// URL
- } else if (
- isViewFieldURL(viewField) &&
- isViewFieldURLValue(newFieldValueUnknown)
- ) {
+ } else if (isFieldURL(field) && isFieldURLValue(newFieldValueUnknown)) {
const newContent = newFieldValueUnknown;
updateEntity({
variables: {
where: { id: currentEntityId },
- data: { [viewField.metadata.fieldName]: newContent },
+ data: { [field.metadata.fieldName]: newContent },
},
});
// Number
} else if (
- isViewFieldNumber(viewField) &&
- isViewFieldNumberValue(newFieldValueUnknown)
+ isFieldNumber(field) &&
+ isFieldNumberValue(newFieldValueUnknown)
) {
const newContent = newFieldValueUnknown;
updateEntity({
variables: {
where: { id: currentEntityId },
- data: { [viewField.metadata.fieldName]: newContent },
+ data: { [field.metadata.fieldName]: newContent },
},
});
// Date
- } else if (
- isViewFieldDate(viewField) &&
- isViewFieldDateValue(newFieldValueUnknown)
- ) {
+ } else if (isFieldDate(field) && isFieldDateValue(newFieldValueUnknown)) {
const newContent = newFieldValueUnknown;
updateEntity({
variables: {
where: { id: currentEntityId },
- data: { [viewField.metadata.fieldName]: newContent },
+ data: { [field.metadata.fieldName]: newContent },
},
});
} else if (
- isViewFieldProbability(viewField) &&
- isViewFieldProbabilityValue(newFieldValueUnknown)
+ isFieldProbability(field) &&
+ isFieldProbabilityValue(newFieldValueUnknown)
) {
const newContent = newFieldValueUnknown;
updateEntity({
variables: {
where: { id: currentEntityId },
- data: { [viewField.metadata.fieldName]: newContent },
+ data: { [field.metadata.fieldName]: newContent },
},
});
}
diff --git a/front/src/modules/ui/editable-field/states/EditableFieldContext.ts b/front/src/modules/ui/editable-field/states/EditableFieldContext.ts
new file mode 100644
index 000000000..818256007
--- /dev/null
+++ b/front/src/modules/ui/editable-field/states/EditableFieldContext.ts
@@ -0,0 +1,16 @@
+import { createContext } from 'react';
+
+import { FieldDefinition } from '../types/FieldDefinition';
+import { ViewFieldMetadata } from '../types/ViewField';
+
+type EditableFieldContextValue = {
+ entityId: string;
+ fieldDefinition: FieldDefinition;
+ mutation: any;
+};
+
+export const EditableFieldContext = createContext({
+ entityId: '',
+ fieldDefinition: {} as FieldDefinition,
+ mutation: undefined,
+});
diff --git a/front/src/modules/ui/editable-field/types/FieldDefinition.ts b/front/src/modules/ui/editable-field/types/FieldDefinition.ts
new file mode 100644
index 000000000..0cb858308
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/FieldDefinition.ts
@@ -0,0 +1,9 @@
+import { FieldMetadata } from './FieldMetadata';
+
+export type FieldDefinition = {
+ id: string;
+ label: string;
+ icon?: JSX.Element;
+ type: string;
+ metadata: T;
+};
diff --git a/front/src/modules/ui/editable-field/types/FieldMetadata.ts b/front/src/modules/ui/editable-field/types/FieldMetadata.ts
new file mode 100644
index 000000000..0b2e598b3
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/FieldMetadata.ts
@@ -0,0 +1,113 @@
+import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
+import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
+
+export type FieldType =
+ | 'text'
+ | 'relation'
+ | 'chip'
+ | 'double-text-chip'
+ | 'double-text'
+ | 'number'
+ | 'date'
+ | 'phone'
+ | 'url'
+ | 'probability';
+
+export type FieldTextMetadata = {
+ type: 'text';
+ placeHolder: string;
+ fieldName: string;
+};
+
+export type FieldPhoneMetadata = {
+ type: 'phone';
+ placeHolder: string;
+ fieldName: string;
+};
+
+export type FieldURLMetadata = {
+ type: 'url';
+ placeHolder: string;
+ fieldName: string;
+};
+
+export type FieldDateMetadata = {
+ type: 'date';
+ fieldName: string;
+};
+
+export type FieldNumberMetadata = {
+ type: 'number';
+ fieldName: string;
+};
+
+export type FieldRelationMetadata = {
+ type: 'relation';
+ relationType: Entity;
+ fieldName: string;
+};
+
+export type FieldChipMetadata = {
+ type: 'chip';
+ relationType: Entity;
+ contentFieldName: string;
+ urlFieldName: string;
+ placeHolder: string;
+};
+
+export type FieldDoubleTextMetadata = {
+ type: 'double-text';
+ firstValueFieldName: string;
+ firstValuePlaceholder: string;
+ secondValueFieldName: string;
+ secondValuePlaceholder: string;
+};
+
+export type FieldDoubleTextChipMetadata = {
+ type: 'double-text-chip';
+ firstValueFieldName: string;
+ firstValuePlaceholder: string;
+ secondValueFieldName: string;
+ secondValuePlaceholder: string;
+ avatarUrlFieldName: string;
+ entityType: Entity;
+};
+
+export type FieldProbabilityMetadata = {
+ type: 'probability';
+ fieldName: string;
+};
+
+export type FieldMetadata = { type: FieldType } & (
+ | FieldTextMetadata
+ | FieldRelationMetadata
+ | FieldChipMetadata
+ | FieldDoubleTextChipMetadata
+ | FieldDoubleTextMetadata
+ | FieldPhoneMetadata
+ | FieldURLMetadata
+ | FieldNumberMetadata
+ | FieldDateMetadata
+ | FieldProbabilityMetadata
+);
+
+export type FieldTextValue = string;
+
+export type FieldChipValue = string;
+export type FieldDateValue = string;
+export type FieldPhoneValue = string;
+export type FieldURLValue = string;
+export type FieldNumberValue = number | null;
+export type FieldProbabilityValue = number;
+
+export type FieldDoubleTextValue = {
+ firstValue: string;
+ secondValue: string;
+};
+
+export type FieldDoubleTextChipValue = {
+ firstValue: string;
+ secondValue: string;
+};
+
+export type FieldRelationValue = EntityForSelect | null;
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldChip.ts b/front/src/modules/ui/editable-field/types/guards/isFieldChip.ts
new file mode 100644
index 000000000..b7e2eac37
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldChip.ts
@@ -0,0 +1,8 @@
+import { FieldDefinition } from '../FieldDefinition';
+import { FieldChipMetadata, FieldMetadata } from '../FieldMetadata';
+
+export function isFieldChip(
+ field: FieldDefinition,
+): field is FieldDefinition {
+ return field.type === 'chip';
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldChipValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldChipValue.ts
new file mode 100644
index 000000000..649a08fa4
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldChipValue.ts
@@ -0,0 +1,12 @@
+import { FieldChipValue } from '../FieldMetadata';
+
+// TODO: add yup
+export function isFieldChipValue(
+ fieldValue: unknown,
+): fieldValue is FieldChipValue {
+ return (
+ fieldValue !== null &&
+ fieldValue !== undefined &&
+ typeof fieldValue === 'string'
+ );
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldDate.ts b/front/src/modules/ui/editable-field/types/guards/isFieldDate.ts
new file mode 100644
index 000000000..e6258847e
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldDate.ts
@@ -0,0 +1,8 @@
+import { FieldDefinition } from '../FieldDefinition';
+import { FieldDateMetadata, FieldMetadata } from '../FieldMetadata';
+
+export function isFieldDate(
+ field: FieldDefinition,
+): field is FieldDefinition {
+ return field.type === 'date';
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldDateValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldDateValue.ts
new file mode 100644
index 000000000..1d7bdfd88
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldDateValue.ts
@@ -0,0 +1,12 @@
+import { FieldDateValue } from '../FieldMetadata';
+
+// TODO: add yup
+export function isFieldDateValue(
+ fieldValue: unknown,
+): fieldValue is FieldDateValue {
+ return (
+ fieldValue !== null &&
+ fieldValue !== undefined &&
+ typeof fieldValue === 'string'
+ );
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldDoubleText.ts b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleText.ts
new file mode 100644
index 000000000..b30c0c6a0
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleText.ts
@@ -0,0 +1,8 @@
+import { FieldDefinition } from '../FieldDefinition';
+import { FieldDoubleTextMetadata, FieldMetadata } from '../FieldMetadata';
+
+export function isFieldDoubleText(
+ field: FieldDefinition,
+): field is FieldDefinition {
+ return field.type === 'double-text';
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChip.ts b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChip.ts
new file mode 100644
index 000000000..73bc0c545
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChip.ts
@@ -0,0 +1,8 @@
+import { FieldDefinition } from '../FieldDefinition';
+import { FieldDoubleTextChipMetadata, FieldMetadata } from '../FieldMetadata';
+
+export function isFieldDoubleTextChip(
+ field: FieldDefinition,
+): field is FieldDefinition {
+ return field.type === 'double-text-chip';
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChipValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChipValue.ts
new file mode 100644
index 000000000..b5d7812a3
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChipValue.ts
@@ -0,0 +1,12 @@
+import { FieldDoubleTextChipValue } from '../FieldMetadata';
+
+// TODO: add yup
+export function isFieldDoubleTextChipValue(
+ fieldValue: unknown,
+): fieldValue is FieldDoubleTextChipValue {
+ return (
+ fieldValue !== null &&
+ fieldValue !== undefined &&
+ typeof fieldValue === 'object'
+ );
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextValue.ts
new file mode 100644
index 000000000..9e5047676
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextValue.ts
@@ -0,0 +1,12 @@
+import { FieldDoubleTextValue } from '../FieldMetadata';
+
+// TODO: add yup
+export function isFieldDoubleTextValue(
+ fieldValue: unknown,
+): fieldValue is FieldDoubleTextValue {
+ return (
+ fieldValue !== null &&
+ fieldValue !== undefined &&
+ typeof fieldValue === 'object'
+ );
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldNumber.ts b/front/src/modules/ui/editable-field/types/guards/isFieldNumber.ts
new file mode 100644
index 000000000..7c23d6167
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldNumber.ts
@@ -0,0 +1,8 @@
+import { FieldDefinition } from '../FieldDefinition';
+import { FieldMetadata, FieldNumberMetadata } from '../FieldMetadata';
+
+export function isFieldNumber(
+ field: FieldDefinition,
+): field is FieldDefinition {
+ return field.type === 'number';
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldNumberValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldNumberValue.ts
new file mode 100644
index 000000000..452bdbede
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldNumberValue.ts
@@ -0,0 +1,12 @@
+import { FieldNumberValue } from '../FieldMetadata';
+
+// TODO: add yup
+export function isFieldNumberValue(
+ fieldValue: unknown,
+): fieldValue is FieldNumberValue {
+ return (
+ fieldValue !== null &&
+ fieldValue !== undefined &&
+ typeof fieldValue === 'number'
+ );
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldPhone.ts b/front/src/modules/ui/editable-field/types/guards/isFieldPhone.ts
new file mode 100644
index 000000000..e886b9bbc
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldPhone.ts
@@ -0,0 +1,8 @@
+import { FieldDefinition } from '../FieldDefinition';
+import { FieldMetadata, FieldPhoneMetadata } from '../FieldMetadata';
+
+export function isFieldPhone(
+ field: FieldDefinition,
+): field is FieldDefinition {
+ return field.type === 'phone';
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldPhoneValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldPhoneValue.ts
new file mode 100644
index 000000000..1337385a7
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldPhoneValue.ts
@@ -0,0 +1,12 @@
+import { FieldPhoneValue } from '../FieldMetadata';
+
+// TODO: add yup
+export function isFieldPhoneValue(
+ fieldValue: unknown,
+): fieldValue is FieldPhoneValue {
+ return (
+ fieldValue !== null &&
+ fieldValue !== undefined &&
+ typeof fieldValue === 'string'
+ );
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldProbability.ts b/front/src/modules/ui/editable-field/types/guards/isFieldProbability.ts
new file mode 100644
index 000000000..97c12661e
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldProbability.ts
@@ -0,0 +1,8 @@
+import { FieldDefinition } from '../FieldDefinition';
+import { FieldMetadata, FieldProbabilityMetadata } from '../FieldMetadata';
+
+export function isFieldProbability(
+ field: FieldDefinition,
+): field is FieldDefinition {
+ return field.type === 'probability';
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldProbabilityValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldProbabilityValue.ts
new file mode 100644
index 000000000..d4dad6eb3
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldProbabilityValue.ts
@@ -0,0 +1,12 @@
+import { FieldProbabilityValue } from '../FieldMetadata';
+
+// TODO: add yup
+export function isFieldProbabilityValue(
+ fieldValue: unknown,
+): fieldValue is FieldProbabilityValue {
+ return (
+ fieldValue !== null &&
+ fieldValue !== undefined &&
+ typeof fieldValue === 'number'
+ );
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldRelation.ts b/front/src/modules/ui/editable-field/types/guards/isFieldRelation.ts
new file mode 100644
index 000000000..bb24ecac2
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldRelation.ts
@@ -0,0 +1,8 @@
+import { FieldDefinition } from '../FieldDefinition';
+import { FieldMetadata, FieldRelationMetadata } from '../FieldMetadata';
+
+export function isFieldRelation(
+ field: FieldDefinition,
+): field is FieldDefinition {
+ return field.type === 'relation';
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldRelationValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldRelationValue.ts
new file mode 100644
index 000000000..5624e0c25
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldRelationValue.ts
@@ -0,0 +1,12 @@
+import { FieldRelationValue } from '../FieldMetadata';
+
+// TODO: add yup
+export function isFieldRelationValue(
+ fieldValue: unknown,
+): fieldValue is FieldRelationValue {
+ return (
+ fieldValue !== null &&
+ fieldValue !== undefined &&
+ typeof fieldValue === 'object'
+ );
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldText.ts b/front/src/modules/ui/editable-field/types/guards/isFieldText.ts
new file mode 100644
index 000000000..d616dd595
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldText.ts
@@ -0,0 +1,8 @@
+import { FieldDefinition } from '../FieldDefinition';
+import { FieldMetadata, FieldTextMetadata } from '../FieldMetadata';
+
+export function isFieldText(
+ field: FieldDefinition,
+): field is FieldDefinition {
+ return field.type === 'text';
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldTextValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldTextValue.ts
new file mode 100644
index 000000000..19f958249
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldTextValue.ts
@@ -0,0 +1,12 @@
+import { FieldTextValue } from '../FieldMetadata';
+
+// TODO: add yup
+export function isFieldTextValue(
+ fieldValue: unknown,
+): fieldValue is FieldTextValue {
+ return (
+ fieldValue !== null &&
+ fieldValue !== undefined &&
+ typeof fieldValue === 'string'
+ );
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldURL.ts b/front/src/modules/ui/editable-field/types/guards/isFieldURL.ts
new file mode 100644
index 000000000..5092c760a
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldURL.ts
@@ -0,0 +1,8 @@
+import { FieldDefinition } from '../FieldDefinition';
+import { FieldMetadata, FieldURLMetadata } from '../FieldMetadata';
+
+export function isFieldURL(
+ field: FieldDefinition,
+): field is FieldDefinition {
+ return field.type === 'url';
+}
diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldURLValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldURLValue.ts
new file mode 100644
index 000000000..96afe4154
--- /dev/null
+++ b/front/src/modules/ui/editable-field/types/guards/isFieldURLValue.ts
@@ -0,0 +1,12 @@
+import { FieldURLValue } from '../FieldMetadata';
+
+// TODO: add yup
+export function isFieldURLValue(
+ fieldValue: unknown,
+): fieldValue is FieldURLValue {
+ return (
+ fieldValue !== null &&
+ fieldValue !== undefined &&
+ typeof fieldValue === 'string'
+ );
+}