Add idealCustomerProfile to company show page (#1312)
* Add idealCustomerProfile to company show page * remove editMode * add xUrl
This commit is contained in:
@ -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<FieldBooleanMetadata>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
|
||||||
|
<EditableField
|
||||||
|
iconLabel={currentEditableFieldDefinition.icon}
|
||||||
|
displayModeContent={<GenericEditableBooleanFieldDisplayMode />}
|
||||||
|
displayModeContentOnly
|
||||||
|
/>
|
||||||
|
</RecoilScope>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -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<FieldBooleanMetadata>;
|
||||||
|
|
||||||
|
const [fieldValue, setFieldValue] = useRecoilState<boolean>(
|
||||||
|
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 (
|
||||||
|
<StyledEditableBooleanFieldContainer onClick={toggleValue}>
|
||||||
|
<StyledBooleanFieldIcon>
|
||||||
|
{fieldValue ? (
|
||||||
|
<IconCheck size={theme.icon.size.sm} />
|
||||||
|
) : (
|
||||||
|
<IconX size={theme.icon.size.sm} />
|
||||||
|
)}
|
||||||
|
</StyledBooleanFieldIcon>
|
||||||
|
<StyledEditableBooleanFieldValue>
|
||||||
|
{fieldValue ? 'True' : 'False'}
|
||||||
|
</StyledEditableBooleanFieldValue>
|
||||||
|
</StyledEditableBooleanFieldContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
|
|
||||||
import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext';
|
import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext';
|
||||||
|
import { isFieldBoolean } from '../types/guards/isFieldBoolean';
|
||||||
import { isFieldDate } from '../types/guards/isFieldDate';
|
import { isFieldDate } from '../types/guards/isFieldDate';
|
||||||
import { isFieldNumber } from '../types/guards/isFieldNumber';
|
import { isFieldNumber } from '../types/guards/isFieldNumber';
|
||||||
import { isFieldPhone } from '../types/guards/isFieldPhone';
|
import { isFieldPhone } from '../types/guards/isFieldPhone';
|
||||||
@ -9,6 +10,7 @@ import { isFieldRelation } from '../types/guards/isFieldRelation';
|
|||||||
import { isFieldText } from '../types/guards/isFieldText';
|
import { isFieldText } from '../types/guards/isFieldText';
|
||||||
import { isFieldURL } from '../types/guards/isFieldURL';
|
import { isFieldURL } from '../types/guards/isFieldURL';
|
||||||
|
|
||||||
|
import { GenericEditableBooleanField } from './GenericEditableBooleanField';
|
||||||
import { GenericEditableDateField } from './GenericEditableDateField';
|
import { GenericEditableDateField } from './GenericEditableDateField';
|
||||||
import { GenericEditableNumberField } from './GenericEditableNumberField';
|
import { GenericEditableNumberField } from './GenericEditableNumberField';
|
||||||
import { GenericEditablePhoneField } from './GenericEditablePhoneField';
|
import { GenericEditablePhoneField } from './GenericEditablePhoneField';
|
||||||
@ -34,6 +36,8 @@ export function GenericEditableField() {
|
|||||||
return <GenericEditableTextField />;
|
return <GenericEditableTextField />;
|
||||||
} else if (isFieldPhone(fieldDefinition)) {
|
} else if (isFieldPhone(fieldDefinition)) {
|
||||||
return <GenericEditablePhoneField />;
|
return <GenericEditablePhoneField />;
|
||||||
|
} else if (isFieldBoolean(fieldDefinition)) {
|
||||||
|
return <GenericEditableBooleanField />;
|
||||||
} else {
|
} else {
|
||||||
console.warn(
|
console.warn(
|
||||||
`Unknown field metadata type: ${fieldDefinition.type} in GenericEditableField`,
|
`Unknown field metadata type: ${fieldDefinition.type} in GenericEditableField`,
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import { useContext } from 'react';
|
|||||||
import { EditableFieldMutationContext } from '../contexts/EditableFieldMutationContext';
|
import { EditableFieldMutationContext } from '../contexts/EditableFieldMutationContext';
|
||||||
import { FieldDefinition } from '../types/FieldDefinition';
|
import { FieldDefinition } from '../types/FieldDefinition';
|
||||||
import {
|
import {
|
||||||
|
FieldBooleanMetadata,
|
||||||
|
FieldBooleanValue,
|
||||||
FieldChipMetadata,
|
FieldChipMetadata,
|
||||||
FieldChipValue,
|
FieldChipValue,
|
||||||
FieldDateMetadata,
|
FieldDateMetadata,
|
||||||
@ -25,6 +27,8 @@ import {
|
|||||||
FieldURLMetadata,
|
FieldURLMetadata,
|
||||||
FieldURLValue,
|
FieldURLValue,
|
||||||
} from '../types/FieldMetadata';
|
} from '../types/FieldMetadata';
|
||||||
|
import { isFieldBoolean } from '../types/guards/isFieldBoolean';
|
||||||
|
import { isFieldBooleanValue } from '../types/guards/isFieldBooleanValue';
|
||||||
import { isFieldChip } from '../types/guards/isFieldChip';
|
import { isFieldChip } from '../types/guards/isFieldChip';
|
||||||
import { isFieldChipValue } from '../types/guards/isFieldChipValue';
|
import { isFieldChipValue } from '../types/guards/isFieldChipValue';
|
||||||
import { isFieldDate } from '../types/guards/isFieldDate';
|
import { isFieldDate } from '../types/guards/isFieldDate';
|
||||||
@ -72,6 +76,8 @@ export function useUpdateGenericEntityField() {
|
|||||||
? FieldRelationValue
|
? FieldRelationValue
|
||||||
: FieldMetadata extends FieldProbabilityMetadata
|
: FieldMetadata extends FieldProbabilityMetadata
|
||||||
? FieldProbabilityValue
|
? FieldProbabilityValue
|
||||||
|
: FieldMetadata extends FieldBooleanMetadata
|
||||||
|
? FieldBooleanValue
|
||||||
: unknown,
|
: unknown,
|
||||||
>(
|
>(
|
||||||
currentEntityId: string,
|
currentEntityId: string,
|
||||||
@ -215,6 +221,20 @@ export function useUpdateGenericEntityField() {
|
|||||||
) {
|
) {
|
||||||
const newContent = newFieldValueUnknown;
|
const newContent = newFieldValueUnknown;
|
||||||
|
|
||||||
|
updateEntity({
|
||||||
|
variables: {
|
||||||
|
where: { id: currentEntityId },
|
||||||
|
data: { [field.metadata.fieldName]: newContent },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Boolean
|
||||||
|
else if (
|
||||||
|
isFieldBoolean(field) &&
|
||||||
|
isFieldBooleanValue(newFieldValueUnknown)
|
||||||
|
) {
|
||||||
|
const newContent = newFieldValueUnknown;
|
||||||
|
|
||||||
updateEntity({
|
updateEntity({
|
||||||
variables: {
|
variables: {
|
||||||
where: { id: currentEntityId },
|
where: { id: currentEntityId },
|
||||||
|
|||||||
@ -79,6 +79,10 @@ export type FieldProbabilityMetadata = {
|
|||||||
fieldName: string;
|
fieldName: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type FieldBooleanMetadata = {
|
||||||
|
fieldName: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type FieldMetadata =
|
export type FieldMetadata =
|
||||||
| FieldTextMetadata
|
| FieldTextMetadata
|
||||||
| FieldRelationMetadata
|
| FieldRelationMetadata
|
||||||
@ -90,7 +94,8 @@ export type FieldMetadata =
|
|||||||
| FieldNumberMetadata
|
| FieldNumberMetadata
|
||||||
| FieldEmailMetadata
|
| FieldEmailMetadata
|
||||||
| FieldDateMetadata
|
| FieldDateMetadata
|
||||||
| FieldProbabilityMetadata;
|
| FieldProbabilityMetadata
|
||||||
|
| FieldBooleanMetadata;
|
||||||
|
|
||||||
export type FieldTextValue = string;
|
export type FieldTextValue = string;
|
||||||
|
|
||||||
@ -101,6 +106,7 @@ export type FieldURLValue = string;
|
|||||||
export type FieldNumberValue = number | null;
|
export type FieldNumberValue = number | null;
|
||||||
export type FieldEmailValue = string;
|
export type FieldEmailValue = string;
|
||||||
export type FieldProbabilityValue = number;
|
export type FieldProbabilityValue = number;
|
||||||
|
export type FieldBooleanValue = boolean;
|
||||||
|
|
||||||
export type FieldDoubleTextValue = {
|
export type FieldDoubleTextValue = {
|
||||||
firstValue: string;
|
firstValue: string;
|
||||||
|
|||||||
@ -0,0 +1,8 @@
|
|||||||
|
import { FieldDefinition } from '../FieldDefinition';
|
||||||
|
import { FieldBooleanMetadata, FieldMetadata } from '../FieldMetadata';
|
||||||
|
|
||||||
|
export function isFieldBoolean(
|
||||||
|
field: FieldDefinition<FieldMetadata>,
|
||||||
|
): field is FieldDefinition<FieldBooleanMetadata> {
|
||||||
|
return field.type === 'boolean';
|
||||||
|
}
|
||||||
@ -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'
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import { FieldDefinition } from '@/ui/editable-field/types/FieldDefinition';
|
import { FieldDefinition } from '@/ui/editable-field/types/FieldDefinition';
|
||||||
import {
|
import {
|
||||||
|
FieldBooleanMetadata,
|
||||||
FieldDateMetadata,
|
FieldDateMetadata,
|
||||||
FieldMetadata,
|
FieldMetadata,
|
||||||
FieldNumberMetadata,
|
FieldNumberMetadata,
|
||||||
@ -8,9 +9,11 @@ import {
|
|||||||
FieldURLMetadata,
|
FieldURLMetadata,
|
||||||
} from '@/ui/editable-field/types/FieldMetadata';
|
} from '@/ui/editable-field/types/FieldMetadata';
|
||||||
import {
|
import {
|
||||||
|
IconBrandX,
|
||||||
IconCalendar,
|
IconCalendar,
|
||||||
IconLink,
|
IconLink,
|
||||||
IconMap,
|
IconMap,
|
||||||
|
IconTarget,
|
||||||
IconUserCircle,
|
IconUserCircle,
|
||||||
IconUsers,
|
IconUsers,
|
||||||
} from '@/ui/icon';
|
} from '@/ui/icon';
|
||||||
@ -66,4 +69,23 @@ export const companyShowFieldDefinition: FieldDefinition<FieldMetadata>[] = [
|
|||||||
fieldName: 'createdAt',
|
fieldName: 'createdAt',
|
||||||
},
|
},
|
||||||
} satisfies FieldDefinition<FieldDateMetadata>,
|
} satisfies FieldDefinition<FieldDateMetadata>,
|
||||||
|
{
|
||||||
|
id: 'idealCustomerProfile',
|
||||||
|
label: 'ICP',
|
||||||
|
icon: <IconTarget />,
|
||||||
|
type: 'boolean',
|
||||||
|
metadata: {
|
||||||
|
fieldName: 'idealCustomerProfile',
|
||||||
|
},
|
||||||
|
} satisfies FieldDefinition<FieldBooleanMetadata>,
|
||||||
|
{
|
||||||
|
id: 'xUrl',
|
||||||
|
label: 'Twitter',
|
||||||
|
icon: <IconBrandX />,
|
||||||
|
type: 'url',
|
||||||
|
metadata: {
|
||||||
|
fieldName: 'xUrl',
|
||||||
|
placeHolder: 'X',
|
||||||
|
},
|
||||||
|
} satisfies FieldDefinition<FieldURLMetadata>,
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user