diff --git a/frontend/src/features/env/PublicFeedbackModal.tsx b/frontend/src/features/env/PublicFeedbackModal.tsx index 4f26e70e8a..6322d4b3c1 100644 --- a/frontend/src/features/env/PublicFeedbackModal.tsx +++ b/frontend/src/features/env/PublicFeedbackModal.tsx @@ -34,6 +34,7 @@ import { ModalCloseButton } from '~components/Modal' import Textarea from '~components/Textarea' import { useEnvMutations, useFeedbackMutation } from '~features/env/mutations' +import { usePublicFormContext } from '~features/public-form/PublicFormContext' import { usePublicFeedbackFormView } from './queries' import { isUsableFeedback } from './utils' @@ -50,6 +51,7 @@ export const PublicFeedbackModal = ({ responseMode?: FormResponseMode authType?: FormAuthType }): JSX.Element => { + const { setBlockNavigation } = usePublicFormContext() const modalSize = useBreakpointValue({ base: 'mobile', xs: 'mobile', @@ -68,7 +70,7 @@ export const PublicFeedbackModal = ({ const url = window.location.href const rumSessionId = datadogRum.getInternalContext()?.session_id - const [showThanksPage, setShowThanksPage] = useState(false) + const [showThanksPage, setShowThanksPage] = useState(true) const { publicSwitchEnvMutation } = useEnvMutations() const { data: feedbackForm, isLoading } = usePublicFeedbackFormView() @@ -88,8 +90,9 @@ export const PublicFeedbackModal = ({ }, [onClose]) const handleChangeEnv = useCallback(() => { + setBlockNavigation(false) publicSwitchEnvMutation.mutate() - }, [publicSwitchEnvMutation]) + }, [publicSwitchEnvMutation, setBlockNavigation]) const checkboxInputName = 'attachmentType' diff --git a/frontend/src/features/public-form/PublicFormContext.tsx b/frontend/src/features/public-form/PublicFormContext.tsx index cb352a9bbf..8021a680f0 100644 --- a/frontend/src/features/public-form/PublicFormContext.tsx +++ b/frontend/src/features/public-form/PublicFormContext.tsx @@ -46,6 +46,8 @@ export interface PublicFormContextProps */ onMobileDrawerOpen: () => void onMobileDrawerClose: () => void + blockNavigation: boolean + setBlockNavigation: (val: boolean) => void } export const PublicFormContext = createContext< diff --git a/frontend/src/features/public-form/PublicFormProvider.tsx b/frontend/src/features/public-form/PublicFormProvider.tsx index 317b55f822..7b60f4835f 100644 --- a/frontend/src/features/public-form/PublicFormProvider.tsx +++ b/frontend/src/features/public-form/PublicFormProvider.tsx @@ -103,6 +103,7 @@ export const PublicFormProvider = ({ }: PublicFormProviderProps): JSX.Element => { // Once form has been submitted, submission data will be set here. const [submissionData, setSubmissionData] = useState() + const [blockNavigation, setBlockNavigation] = useState(false) const { data, isLoading, error, ...rest } = usePublicFormView( formId, @@ -323,6 +324,8 @@ export const PublicFormProvider = ({ captchaContainerId: containerId, expiryInMs, isLoading: isLoading || (!!data?.form.hasCaptcha && !hasLoaded), + blockNavigation, + setBlockNavigation, ...commonFormValues, ...data, ...rest, diff --git a/frontend/src/features/public-form/components/FormFields/FormFields.tsx b/frontend/src/features/public-form/components/FormFields/FormFields.tsx index e6c31b3943..62bc0a07d8 100644 --- a/frontend/src/features/public-form/components/FormFields/FormFields.tsx +++ b/frontend/src/features/public-form/components/FormFields/FormFields.tsx @@ -7,9 +7,11 @@ import { isEmpty, times } from 'lodash' import { BasicField, FormFieldDto } from '~shared/types/field' import { FormColorTheme, LogicDto } from '~shared/types/form' +import { useNativeBlocker } from '~hooks/useNativeBlocker' import InlineMessage from '~components/InlineMessage' import { FormFieldValues } from '~templates/Field' import { createTableRow } from '~templates/Field/Table/utils/createRow' +import { useNavigationPrompt } from '~templates/NavigationPrompt/useNavigationPrompt' import { augmentWithMyInfo, @@ -17,6 +19,7 @@ import { hasExistingFieldValue, } from '~features/myinfo/utils' import { useFetchPrefillQuery } from '~features/public-form/hooks/useFetchPrefillQuery' +import { usePublicFormContext } from '~features/public-form/PublicFormContext' import { PublicFormSubmitButton } from './PublicFormSubmitButton' import { VisibleFormFields } from './VisibleFormFields' @@ -34,6 +37,8 @@ export const FormFields = ({ colorTheme, onSubmit, }: FormFieldsProps): JSX.Element => { + const { blockNavigation, setBlockNavigation } = usePublicFormContext() + useFetchPrefillQuery() const [searchParams] = useSearchParams() @@ -100,6 +105,13 @@ export const FormFields = ({ } }, [defaultFormValues, isDirty, reset]) + useEffect(() => { + if (isDirty) setBlockNavigation(true) + }, [isDirty, setBlockNavigation]) + + // useNavigationPrompt(blockNavigation) + useNativeBlocker(blockNavigation) + return (
diff --git a/frontend/src/hooks/useNativeBlocker.ts b/frontend/src/hooks/useNativeBlocker.ts new file mode 100644 index 0000000000..7cb319ffdd --- /dev/null +++ b/frontend/src/hooks/useNativeBlocker.ts @@ -0,0 +1,17 @@ +import { useCallback, useEffect } from 'react' + +export const useNativeBlocker = (when: boolean) => { + const listener = useCallback( + (e: BeforeUnloadEvent) => { + if (when) e.returnValue = '' + }, + [when], + ) + + useEffect(() => { + window?.addEventListener('beforeunload', listener) + return () => { + window?.removeEventListener('beforeunload', listener) + } + }, [listener]) +}