diff --git a/src/components/RichText/RichTextEditor.tsx b/src/components/RichText/RichTextEditor.tsx index 7ae354f8..a55a3e0d 100644 --- a/src/components/RichText/RichTextEditor.tsx +++ b/src/components/RichText/RichTextEditor.tsx @@ -19,6 +19,7 @@ import { DraftEditorCommand, convertFromHTML, Modifier, + SelectionState, } from 'draft-js'; import { useTranslation } from 'react-i18next'; import { Select } from 'antd'; @@ -56,21 +57,16 @@ const TEXT_STYLES = [ { label: 'rte.h6', value: 'header-six' }, ]; -const TextStyleSelect = ({ setEditorState, editorState }: ToolbarChildrenProps & { editorState: EditorState }) => { +const TextStyleSelect = ({ + setEditorState, + editorState, + selectionState, +}: ToolbarChildrenProps & { editorState: EditorState; selectionState: SelectionState }) => { const { t } = useTranslation(); - const [selectionState, setSelectionState] = useState(() => editorState.getSelection()); - useEffect(() => { - const selection = editorState.getSelection(); - setSelectionState((state) => { - return selection.getHasFocus() ? selection : state; - }); - }, [editorState]); - - const blockType = useMemo( - () => editorState.getCurrentContent().getBlockForKey(selectionState.getStartKey()).getType(), - [editorState, selectionState], - ); + const blockType = useMemo(() => { + return editorState.getCurrentContent().getBlockForKey(selectionState.getStartKey()).getType(); + }, [editorState, selectionState]); const handleToggle = useCallback( (type: string) => { @@ -126,6 +122,7 @@ const RTE = ({ const contentState = ContentState.createFromBlockArray(contentBlocks, entityMap); return EditorState.createWithContent(contentState); }); + const [selectionState, setSelectionState] = useState(() => editorState.getSelection()); useEffect(() => { setEditorState((state) => { @@ -137,6 +134,13 @@ const RTE = ({ }); }, [disabled]); + useEffect(() => { + const selection = editorState.getSelection(); + setSelectionState((state) => { + return selection.getHasFocus() ? selection : state; + }); + }, [editorState]); + const handleChange = useCallback( (edited: EditorState) => { setEditorState(edited); @@ -197,7 +201,11 @@ const RTE = ({ <>
- +
- +
- +
{Object.keys(placeholders || {}).length > 0 && ( )} diff --git a/src/components/TranslatableFormField/index.tsx b/src/components/TranslatableFormField/index.tsx index 4d0f382b..def7491f 100644 --- a/src/components/TranslatableFormField/index.tsx +++ b/src/components/TranslatableFormField/index.tsx @@ -1,6 +1,5 @@ import { Form, Select } from 'antd'; import { FieldContext } from 'rc-field-form'; -import classNames from 'classnames'; import { cloneElement, useContext, useMemo } from 'react'; import { CheckCircleTwoTone, WarningTwoTone } from '@ant-design/icons'; import { useTranslation } from 'react-i18next'; @@ -26,17 +25,15 @@ export const TranslatableFormField = ({ name, children }: TranslatableFormFieldP [tenantData?.settings?.activeLanguages], ); - const errors = formContext - .getFieldsError(languages.map((language) => [...namePath, language])) - .reduce((c, data) => { - const lng = data.name[data.name.length - 1]; - return { - ...c, - [lng]: !fieldData?.[lng] || data.errors.length > 0, - }; - }, {}); + const errors = languages + .map((lng) => { + const fieldErrors = formContext.getFieldError([...namePath, lng]); + const fieldValue = formContext.getFieldValue([...namePath, lng]); + return !fieldValue || fieldErrors.length > 0 ? lng : null; + }) + .filter(Boolean); - const hasErrors = useMemo(() => Object.values(errors).some((e) => e), [errors]); + const hasErrors = useMemo(() => errors.length > 0, [errors]); return ( <> @@ -54,7 +51,7 @@ export const TranslatableFormField = ({ name, children }: TranslatableFormFieldP
{t(`language.${language}`)} - {errors[language] ? ( + {errors.includes(language) ? ( ) : ( @@ -65,16 +62,10 @@ export const TranslatableFormField = ({ name, children }: TranslatableFormFieldP )} - {languages.map((language) => - cloneElement(children, { - name: [...namePath, language], - key: language, - className: classNames({ - [styles.activeLanguage]: fieldData?.translate === language || languages.length === 1, - [styles.notActive]: fieldData?.translate !== language && languages.length !== 1, - }), - }), - )} + {cloneElement(children, { + name: [...namePath, fieldData?.translate || languages[0]], + key: fieldData?.translate || languages[0], + })} ); }; diff --git a/src/components/TranslatableFormField/styles.module.scss b/src/components/TranslatableFormField/styles.module.scss index 87ef31c7..05fcfad7 100644 --- a/src/components/TranslatableFormField/styles.module.scss +++ b/src/components/TranslatableFormField/styles.module.scss @@ -1,11 +1,3 @@ -.activeLanguage { - display: block; -} - -.notActive { - display: none; -} - .containerLabel { display: flex; flex-grow: 1; diff --git a/src/hooks/useAgencyLegalDataMissing.tsx b/src/hooks/useAgencyLegalDataMissing.tsx index cf5ad158..1eb3de67 100644 --- a/src/hooks/useAgencyLegalDataMissing.tsx +++ b/src/hooks/useAgencyLegalDataMissing.tsx @@ -1,33 +1,38 @@ import { useMemo } from 'react'; import { AgencyContact, AgencyData } from '../types/agency'; +import { FeatureFlag } from '../enums/FeatureFlag'; +import { useFeatureContext } from '../context/FeatureContext'; export const useAgencyLegalDataMissing = (agencyData: AgencyData) => { + const { isEnabled } = useFeatureContext(); + return useMemo(() => { - const checkContact = (contact: AgencyContact) => { + const isContactComplete = (contact: AgencyContact) => { return ( - !contact || + contact && ['nameAndLegalForm', 'postcode', 'city', 'phoneNumber'].every((field) => { return !!contact?.[field]; }) ); }; const type = agencyData?.dataProtection?.dataProtectionResponsibleEntity; - const hasMissingAgencyDataProtectionResponsibleContact = !checkContact( + const hasMissingAgencyDataProtectionResponsibleContact = !isContactComplete( agencyData?.dataProtection?.agencyDataProtectionResponsibleContact, ); const hasMissingDataProtectionOfficerContact = type === 'DATA_PROTECTION_OFFICER' && - !checkContact(agencyData?.dataProtection?.dataProtectionOfficerContact); + !isContactComplete(agencyData?.dataProtection?.dataProtectionOfficerContact); const hasMissingAlternativeDataProtectionRepresentativeContact = type === 'ALTERNATIVE_REPRESENTATIVE' && - !checkContact(agencyData?.dataProtection?.alternativeDataProtectionRepresentativeContact); + !isContactComplete(agencyData?.dataProtection?.alternativeDataProtectionRepresentativeContact); - return !( - hasMissingAgencyDataProtectionResponsibleContact || - hasMissingDataProtectionOfficerContact || - hasMissingAlternativeDataProtectionRepresentativeContact + return ( + isEnabled(FeatureFlag.CentralDataProtectionTemplate) && + (hasMissingAgencyDataProtectionResponsibleContact || + hasMissingDataProtectionOfficerContact || + hasMissingAlternativeDataProtectionRepresentativeContact) ); }, [agencyData]); }; diff --git a/src/pages/Agency/EditInitialMeeting/index.tsx b/src/pages/Agency/EditInitialMeeting/index.tsx index 86726d6d..f8b0b2e5 100644 --- a/src/pages/Agency/EditInitialMeeting/index.tsx +++ b/src/pages/Agency/EditInitialMeeting/index.tsx @@ -1,9 +1,10 @@ import { Button, Table, Typography } from 'antd'; import { useTranslation } from 'react-i18next'; import { PlusOutlined } from '@ant-design/icons'; -import { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { ColumnsType } from 'antd/lib/table'; import { useParams } from 'react-router'; +import ErrorOutlinedIcon from '@mui/icons-material/ErrorOutlined'; import EditButtons from '../../../components/EditableTable/EditButtons'; import { ConsultantInterface, AgencyEditData, AgencyEventTypes } from '../../../types/agencyEdit'; import ResizableTitle from '../../../components/Resizable/Resizable'; @@ -17,12 +18,16 @@ import routePathNames from '../../../appConfig'; import { Resource } from '../../../enums/Resource'; import { Page } from '../../../components/Page'; import { useBookingLocations } from './useBookingLocations'; +import { useAgencyData } from '../../../hooks/useAgencyData'; +import { useAgencyLegalDataMissing } from '../../../hooks/useAgencyLegalDataMissing'; const { Paragraph } = Typography; export const AgencyEditInitialMeeting = () => { const { t } = useTranslation(); const { id: agencyId } = useParams(); + const { data: agencyData, isLoading: isLoadingAgency } = useAgencyData({ id: agencyId }); + const legalDataMissing = useAgencyLegalDataMissing(agencyData); const [topics, setTopics] = useState([]); const [showEditModal, setShowEditModal] = useState(false); const [showDeleteModal, setShowDeleteModal] = useState(false); @@ -202,6 +207,7 @@ export const AgencyEditInitialMeeting = () => { { titleKey: 'agency.edit.tab.settings', to: `${routePathNames.agency}/${agencyId}/general`, + icon: !isLoadingAgency && legalDataMissing ? : null, }, { titleKey: 'agency.edit.tab.initialEnquiry', diff --git a/src/utils/draftjs/imagePlugin/Control/Image.tsx b/src/utils/draftjs/imagePlugin/Control/Image.tsx index ccb218ee..88ba186e 100644 --- a/src/utils/draftjs/imagePlugin/Control/Image.tsx +++ b/src/utils/draftjs/imagePlugin/Control/Image.tsx @@ -72,16 +72,13 @@ export const ImageControl = ({ setEditorState, getEditorState, editorState, -}: ToolbarChildrenProps & { editorState: EditorState }) => { + selectionState, +}: ToolbarChildrenProps & { editorState: EditorState; selectionState: SelectionState }) => { const [showTooltip, setShowTooltip] = useState(false); - const [selectionState, setSelectionState] = useState(() => editorState.getSelection()); const [disabled, setDisabled] = useState(!editorState.getSelection().isCollapsed()); useEffect(() => { const selection = editorState.getSelection(); - setSelectionState((state) => { - return selection.getHasFocus() ? selection : state; - }); setDisabled((state) => { return selection.getHasFocus() ? !selection.isCollapsed() : state; }); diff --git a/src/utils/draftjs/linkPlugin/Control/Link.tsx b/src/utils/draftjs/linkPlugin/Control/Link.tsx index 4c8108ac..4c18c600 100644 --- a/src/utils/draftjs/linkPlugin/Control/Link.tsx +++ b/src/utils/draftjs/linkPlugin/Control/Link.tsx @@ -93,16 +93,13 @@ export const LinkControl = ({ setEditorState, getEditorState, editorState, -}: ToolbarChildrenProps & { editorState: EditorState }) => { + selectionState, +}: ToolbarChildrenProps & { editorState: EditorState; selectionState: SelectionState }) => { const [showTooltip, setShowTooltip] = useState(false); - const [selectionState, setSelectionState] = useState(() => editorState.getSelection()); const [disabled, setDisabled] = useState(editorState.getSelection().isCollapsed()); useEffect(() => { const selection = editorState.getSelection(); - setSelectionState((state) => { - return selection.getHasFocus() ? selection : state; - }); setDisabled((state) => { return selection.getHasFocus() ? selection.isCollapsed() : state; }); diff --git a/src/utils/draftjs/placeholderPlugin/Control/Placeholder.tsx b/src/utils/draftjs/placeholderPlugin/Control/Placeholder.tsx index 8f36011b..ec3d24b4 100644 --- a/src/utils/draftjs/placeholderPlugin/Control/Placeholder.tsx +++ b/src/utils/draftjs/placeholderPlugin/Control/Placeholder.tsx @@ -10,16 +10,13 @@ export const PlaceholderControl = ({ setEditorState, getEditorState, editorState, -}: ToolbarChildrenProps & { placeholders: any; editorState: EditorState }) => { + selectionState, +}: ToolbarChildrenProps & { placeholders: any; editorState: EditorState; selectionState: SelectionState }) => { const { t } = useTranslation(); - const [selectionState, setSelectionState] = useState(() => editorState.getSelection()); const [disabled, setDisabled] = useState(!editorState.getSelection().isCollapsed()); useEffect(() => { const selection = editorState.getSelection(); - setSelectionState((state) => { - return selection.getHasFocus() ? selection : state; - }); setDisabled((state) => { return selection.getHasFocus() ? !selection.isCollapsed() : state; });