From 8a3a176571edd3be5f6f1eff87b5d4ffe26fde93 Mon Sep 17 00:00:00 2001 From: Weiko Date: Fri, 25 Aug 2023 21:11:43 +0200 Subject: [PATCH] Add idealCustomerProfile to company show page (#1312) * Add idealCustomerProfile to company show page * remove editMode * add xUrl --- .../GenericEditableBooleanField.tsx | 27 ++++++++ ...GenericEditableBooleanFieldDisplayMode.tsx | 69 +++++++++++++++++++ .../components/GenericEditableField.tsx | 4 ++ .../hooks/useUpdateGenericEntityField.ts | 20 ++++++ .../ui/editable-field/types/FieldMetadata.ts | 8 ++- .../types/guards/isFieldBoolean.ts | 8 +++ .../types/guards/isFieldBooleanValue.ts | 12 ++++ .../constants/companyShowFieldDefinition.tsx | 22 ++++++ 8 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 front/src/modules/ui/editable-field/components/GenericEditableBooleanField.tsx create mode 100644 front/src/modules/ui/editable-field/components/GenericEditableBooleanFieldDisplayMode.tsx create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldBoolean.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldBooleanValue.ts diff --git a/front/src/modules/ui/editable-field/components/GenericEditableBooleanField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableBooleanField.tsx new file mode 100644 index 000000000..2c585ed4c --- /dev/null +++ b/front/src/modules/ui/editable-field/components/GenericEditableBooleanField.tsx @@ -0,0 +1,27 @@ +import { useContext } from 'react'; + +import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; + +import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext'; +import { FieldRecoilScopeContext } from '../states/recoil-scope-contexts/FieldRecoilScopeContext'; +import { FieldDefinition } from '../types/FieldDefinition'; +import { FieldBooleanMetadata } from '../types/FieldMetadata'; + +import { EditableField } from './EditableField'; +import { GenericEditableBooleanFieldDisplayMode } from './GenericEditableBooleanFieldDisplayMode'; + +export function GenericEditableBooleanField() { + const currentEditableFieldDefinition = useContext( + EditableFieldDefinitionContext, + ) as FieldDefinition; + + return ( + + } + displayModeContentOnly + /> + + ); +} diff --git a/front/src/modules/ui/editable-field/components/GenericEditableBooleanFieldDisplayMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableBooleanFieldDisplayMode.tsx new file mode 100644 index 000000000..605e34a71 --- /dev/null +++ b/front/src/modules/ui/editable-field/components/GenericEditableBooleanFieldDisplayMode.tsx @@ -0,0 +1,69 @@ +import { useContext } from 'react'; +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { useRecoilState } from 'recoil'; + +import { IconCheck, IconX } from '@/ui/icon'; + +import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext'; +import { EditableFieldEntityIdContext } from '../contexts/EditableFieldEntityIdContext'; +import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField'; +import { genericEntityFieldFamilySelector } from '../states/selectors/genericEntityFieldFamilySelector'; +import { FieldDefinition } from '../types/FieldDefinition'; +import { FieldBooleanMetadata } from '../types/FieldMetadata'; + +const StyledEditableBooleanFieldContainer = styled.div` + cursor: pointer; + display: flex; +`; +const StyledBooleanFieldIcon = styled.div``; +const StyledEditableBooleanFieldValue = styled.div` + margin-left: ${({ theme }) => theme.spacing(1)}; +`; + +export function GenericEditableBooleanFieldDisplayMode() { + const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); + const currentEditableFieldDefinition = useContext( + EditableFieldDefinitionContext, + ) as FieldDefinition; + + const [fieldValue, setFieldValue] = useRecoilState( + genericEntityFieldFamilySelector({ + entityId: currentEditableFieldEntityId ?? '', + fieldName: currentEditableFieldDefinition + ? currentEditableFieldDefinition.metadata.fieldName + : '', + }), + ); + + const theme = useTheme(); + const updateField = useUpdateGenericEntityField(); + + function toggleValue() { + const newToggledValue = !fieldValue; + setFieldValue(newToggledValue); + + if (currentEditableFieldEntityId && updateField) { + updateField( + currentEditableFieldEntityId, + currentEditableFieldDefinition, + newToggledValue, + ); + } + } + + return ( + + + {fieldValue ? ( + + ) : ( + + )} + + + {fieldValue ? 'True' : 'False'} + + + ); +} diff --git a/front/src/modules/ui/editable-field/components/GenericEditableField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableField.tsx index f258ef241..4ac484d12 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableField.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableField.tsx @@ -1,6 +1,7 @@ import { useContext } from 'react'; import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext'; +import { isFieldBoolean } from '../types/guards/isFieldBoolean'; import { isFieldDate } from '../types/guards/isFieldDate'; import { isFieldNumber } from '../types/guards/isFieldNumber'; import { isFieldPhone } from '../types/guards/isFieldPhone'; @@ -9,6 +10,7 @@ import { isFieldRelation } from '../types/guards/isFieldRelation'; import { isFieldText } from '../types/guards/isFieldText'; import { isFieldURL } from '../types/guards/isFieldURL'; +import { GenericEditableBooleanField } from './GenericEditableBooleanField'; import { GenericEditableDateField } from './GenericEditableDateField'; import { GenericEditableNumberField } from './GenericEditableNumberField'; import { GenericEditablePhoneField } from './GenericEditablePhoneField'; @@ -34,6 +36,8 @@ export function GenericEditableField() { return ; } else if (isFieldPhone(fieldDefinition)) { return ; + } else if (isFieldBoolean(fieldDefinition)) { + return ; } else { console.warn( `Unknown field metadata type: ${fieldDefinition.type} in GenericEditableField`, diff --git a/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts b/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts index b7b636686..de809610f 100644 --- a/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts +++ b/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts @@ -3,6 +3,8 @@ import { useContext } from 'react'; import { EditableFieldMutationContext } from '../contexts/EditableFieldMutationContext'; import { FieldDefinition } from '../types/FieldDefinition'; import { + FieldBooleanMetadata, + FieldBooleanValue, FieldChipMetadata, FieldChipValue, FieldDateMetadata, @@ -25,6 +27,8 @@ import { FieldURLMetadata, FieldURLValue, } from '../types/FieldMetadata'; +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 { isFieldDate } from '../types/guards/isFieldDate'; @@ -72,6 +76,8 @@ export function useUpdateGenericEntityField() { ? FieldRelationValue : FieldMetadata extends FieldProbabilityMetadata ? FieldProbabilityValue + : FieldMetadata extends FieldBooleanMetadata + ? FieldBooleanValue : unknown, >( currentEntityId: string, @@ -215,6 +221,20 @@ export function useUpdateGenericEntityField() { ) { const newContent = newFieldValueUnknown; + updateEntity({ + variables: { + where: { id: currentEntityId }, + data: { [field.metadata.fieldName]: newContent }, + }, + }); + } + // Boolean + else if ( + isFieldBoolean(field) && + isFieldBooleanValue(newFieldValueUnknown) + ) { + const newContent = newFieldValueUnknown; + updateEntity({ variables: { where: { id: currentEntityId }, diff --git a/front/src/modules/ui/editable-field/types/FieldMetadata.ts b/front/src/modules/ui/editable-field/types/FieldMetadata.ts index a5f831222..fdbd9eb76 100644 --- a/front/src/modules/ui/editable-field/types/FieldMetadata.ts +++ b/front/src/modules/ui/editable-field/types/FieldMetadata.ts @@ -79,6 +79,10 @@ export type FieldProbabilityMetadata = { fieldName: string; }; +export type FieldBooleanMetadata = { + fieldName: string; +}; + export type FieldMetadata = | FieldTextMetadata | FieldRelationMetadata @@ -90,7 +94,8 @@ export type FieldMetadata = | FieldNumberMetadata | FieldEmailMetadata | FieldDateMetadata - | FieldProbabilityMetadata; + | FieldProbabilityMetadata + | FieldBooleanMetadata; export type FieldTextValue = string; @@ -101,6 +106,7 @@ export type FieldURLValue = string; export type FieldNumberValue = number | null; export type FieldEmailValue = string; export type FieldProbabilityValue = number; +export type FieldBooleanValue = boolean; export type FieldDoubleTextValue = { firstValue: string; diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldBoolean.ts b/front/src/modules/ui/editable-field/types/guards/isFieldBoolean.ts new file mode 100644 index 000000000..997c81888 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldBoolean.ts @@ -0,0 +1,8 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldBooleanMetadata, FieldMetadata } from '../FieldMetadata'; + +export function isFieldBoolean( + field: FieldDefinition, +): field is FieldDefinition { + return field.type === 'boolean'; +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldBooleanValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldBooleanValue.ts new file mode 100644 index 000000000..f34b727b7 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldBooleanValue.ts @@ -0,0 +1,12 @@ +import { FieldBooleanValue } from '../FieldMetadata'; + +// TODO: add yup +export function isFieldBooleanValue( + fieldValue: unknown, +): fieldValue is FieldBooleanValue { + return ( + fieldValue !== null && + fieldValue !== undefined && + typeof fieldValue === 'boolean' + ); +} diff --git a/front/src/pages/companies/constants/companyShowFieldDefinition.tsx b/front/src/pages/companies/constants/companyShowFieldDefinition.tsx index dc9cd4b47..f8ae3990e 100644 --- a/front/src/pages/companies/constants/companyShowFieldDefinition.tsx +++ b/front/src/pages/companies/constants/companyShowFieldDefinition.tsx @@ -1,5 +1,6 @@ import { FieldDefinition } from '@/ui/editable-field/types/FieldDefinition'; import { + FieldBooleanMetadata, FieldDateMetadata, FieldMetadata, FieldNumberMetadata, @@ -8,9 +9,11 @@ import { FieldURLMetadata, } from '@/ui/editable-field/types/FieldMetadata'; import { + IconBrandX, IconCalendar, IconLink, IconMap, + IconTarget, IconUserCircle, IconUsers, } from '@/ui/icon'; @@ -66,4 +69,23 @@ export const companyShowFieldDefinition: FieldDefinition[] = [ fieldName: 'createdAt', }, } satisfies FieldDefinition, + { + id: 'idealCustomerProfile', + label: 'ICP', + icon: , + type: 'boolean', + metadata: { + fieldName: 'idealCustomerProfile', + }, + } satisfies FieldDefinition, + { + id: 'xUrl', + label: 'Twitter', + icon: , + type: 'url', + metadata: { + fieldName: 'xUrl', + placeHolder: 'X', + }, + } satisfies FieldDefinition, ];