diff --git a/src/components/Contexts/FormContext.tsx b/src/components/Contexts/FormContext.tsx index af225fafa..1759a4583 100644 --- a/src/components/Contexts/FormContext.tsx +++ b/src/components/Contexts/FormContext.tsx @@ -22,6 +22,7 @@ import { SaveAppInput, } from "../../graphql"; import { InitialApplication, InitialQuestionnaire } from "../../config/InitialValues"; +import { Logger } from "../../utils"; export type SetDataReturnType = | { status: "success"; id: string } @@ -171,11 +172,13 @@ export const FormProvider: FC = ({ children, id }: ProviderProps) if (errors || !d?.saveApplication?.["_id"]) { const errorMessage = errors?.[0]?.message || "An unknown GraphQL Error occurred"; + Logger.error("Unable to save application", errors); setState({ ...newState, status: Status.ERROR, error: errorMessage, }); + return { status: "failed", errorMessage, diff --git a/src/components/Questionnaire/FundingAgency.tsx b/src/components/Questionnaire/FundingAgency.tsx index 85614faa4..02da68be0 100644 --- a/src/components/Questionnaire/FundingAgency.tsx +++ b/src/components/Questionnaire/FundingAgency.tsx @@ -53,7 +53,7 @@ const FundingAgency: FC = ({ idPrefix = "", index, funding, readOnly, onD label="Grant or Contract Number(s)" name={`study[funding][${index}][grantNumbers]`} value={grantNumbers} - maxLength={50} + maxLength={250} placeholder="Enter Grant or Contract Number(s)" tooltipText={ <> diff --git a/src/components/Questionnaire/hooks/useConditionalWrapper.tsx b/src/components/Questionnaire/hooks/useConditionalWrapper.tsx deleted file mode 100644 index 7601073a9..000000000 --- a/src/components/Questionnaire/hooks/useConditionalWrapper.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { useState, useEffect, ReactNode, ComponentType, ComponentProps } from "react"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type WrapperProps> = ComponentProps & { - children: ReactNode; -}; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type Props = >( - condition: () => boolean, - wrapper: T -) => ComponentType>; - -export const useConditionalWrapper: Props = (condition, wrapper) => { - const [renderWrapper, setRenderWrapper] = useState(false); - - useEffect(() => { - setRenderWrapper(condition()); - }, []); - - return renderWrapper ? wrapper : ({ children }: WrapperProps) => children; -}; diff --git a/src/config/CellLineModelSystemConfig.ts b/src/config/CellLineModelSystemConfig.ts index fcc4d3a62..9143e5e21 100644 --- a/src/config/CellLineModelSystemConfig.ts +++ b/src/config/CellLineModelSystemConfig.ts @@ -1,6 +1,5 @@ /** - * Configuration for Questionnaire Section C Cell Line Model System - * + * Configuration for Questionnaire Section D Cell Line Model System */ const options: FormGroupCheckboxOption[] = [ { diff --git a/src/config/ClinicalDataConfig.tsx b/src/config/ClinicalDataConfig.tsx deleted file mode 100644 index dbcbadbec..000000000 --- a/src/config/ClinicalDataConfig.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Configuration for Questionnaire Section D Clinical Data - * - */ -const options: string[] = [ - "Demographic Data", - "Diagnosis Data", - "Treatment Data", - "Relapse/Recurrence data", - "Outcome Data", -]; - -export default options; diff --git a/src/config/PreCancerTypesConfig.ts b/src/config/PreCancerTypesConfig.ts deleted file mode 100644 index 87ddf155f..000000000 --- a/src/config/PreCancerTypesConfig.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Configuration for Questionnaire Section C Pre-Cancer Types - * - */ -const options: string[] = ["Lung Cancer", "Breast Cancer"]; - -export default options; diff --git a/src/config/SectionMetadata.tsx b/src/config/SectionMetadata.tsx index 89c3364f7..3e47de9b1 100644 --- a/src/config/SectionMetadata.tsx +++ b/src/config/SectionMetadata.tsx @@ -44,10 +44,6 @@ const sectionMetadata = { title: "FUNDING AGENCY/ORGANIZATION", description: "List the agency(s) and/or organization(s) that funded this study.", }, - DBGAP_REGISTRATION: { - title: "dbGaP REGISTRATION", - description: "Please indicate if your study is currently registered with dbGaP.", - }, EXISTING_PUBLICATIONS: { title: "EXISTING PUBLICATIONS", description: @@ -88,6 +84,10 @@ const sectionMetadata = { ), }, + DBGAP_REGISTRATION: { + title: "dbGaP REGISTRATION", + description: "Please indicate if your study is currently registered with dbGaP.", + }, CANCER_TYPES: { title: "CANCER TYPES", description: diff --git a/src/content/questionnaire/FormView.tsx b/src/content/questionnaire/FormView.tsx index b6c4836fb..1544c38df 100644 --- a/src/content/questionnaire/FormView.tsx +++ b/src/content/questionnaire/FormView.tsx @@ -397,12 +397,9 @@ const FormView: FC = ({ section }: Props) => { if (!isEqual(data.questionnaireData, newData)) { const res = await setData(newData); if (res?.status === "failed" && !!res?.errorMessage) { - enqueueSnackbar( - `An error occurred while saving the ${map[activeSection].title} section. ${res.errorMessage}`, - { - variant: "error", - } - ); + enqueueSnackbar(`An error occurred while saving the ${map[activeSection].title} section.`, { + variant: "error", + }); } else { enqueueSnackbar( `Your changes for the ${map[activeSection].title} section have been successfully saved.`, diff --git a/src/content/questionnaire/sections/B.tsx b/src/content/questionnaire/sections/B.tsx index f6eaefba1..edd305867 100644 --- a/src/content/questionnaire/sections/B.tsx +++ b/src/content/questionnaire/sections/B.tsx @@ -1,6 +1,6 @@ -import React, { FC, useEffect, useMemo, useRef, useState } from "react"; +import { FC, useEffect, useMemo, useRef, useState } from "react"; import { parseForm } from "@jalik/form-parser"; -import { cloneDeep } from "lodash"; +import { cloneDeep, merge } from "lodash"; import AddCircleIcon from "@mui/icons-material/AddCircle"; import dayjs from "dayjs"; import { Status as FormStatus, useFormContext } from "../../../components/Contexts/FormContext"; @@ -20,7 +20,6 @@ import AddRemoveButton from "../../../components/AddRemoveButton"; import PlannedPublication from "../../../components/Questionnaire/PlannedPublication"; import { InitialQuestionnaire } from "../../../config/InitialValues"; import TransitionGroupWrapper from "../../../components/Questionnaire/TransitionGroupWrapper"; -import SwitchInput from "../../../components/Questionnaire/SwitchInput"; import useFormMode from "../../../hooks/useFormMode"; import FundingAgency from "../../../components/Questionnaire/FundingAgency"; import SelectInput from "../../../components/Questionnaire/SelectInput"; @@ -73,10 +72,6 @@ const FormSectionB: FC = ({ SectionOption, refs }: FormSection const [fundings, setFundings] = useState( data.study?.funding?.map(mapObjectWithKey) || [] ); - const [isDbGapRegistered, setIsdbGaPRegistered] = useState( - data.study?.isDbGapRegistered - ); - const [dbGaPPPHSNumber, setDbGaPPPHSNumber] = useState(data.study?.dbGaPPPHSNumber); const customProgramIds: string[] = [NotApplicableProgram._id, OtherProgram._id]; const programKeyRef = useRef(new Date().getTime()); @@ -98,15 +93,12 @@ const FormSectionB: FC = ({ SectionOption, refs }: FormSection } const formObject = parseForm(formRef.current, { nullify: false }); - const combinedData = { ...cloneDeep(data), ...formObject }; + const combinedData: QuestionnaireData = merge(cloneDeep(data), formObject); // Reset study if the data failed to load if (!formObject.study) { combinedData.study = InitialQuestionnaire.study; } - if (!formObject?.study?.dbGaPPPHSNumber) { - combinedData.study.dbGaPPPHSNumber = ""; - } // Reset publications if the user has not entered any publications if (!formObject.study.publications || formObject.study.publications.length === 0) { @@ -118,6 +110,14 @@ const FormSectionB: FC = ({ SectionOption, refs }: FormSection combinedData.study.repositories = []; } + // Reset planned publications if the user has not entered any planned publications + if ( + !formObject.study.plannedPublications || + formObject.study.plannedPublications.length === 0 + ) { + combinedData.study.plannedPublications = []; + } + // Reset planned publications if the user has not entered any planned publications // Also reset expectedDate when invalid to avoid form submission unsaved changes warning combinedData.study.plannedPublications = @@ -170,13 +170,6 @@ const FormSectionB: FC = ({ SectionOption, refs }: FormSection }); }; - const handleIsDbGapRegisteredChange = (e, checked: boolean) => { - setIsdbGaPRegistered(checked); - if (!checked) { - setDbGaPPPHSNumber(""); - } - }; - /** * Add a empty publication to the publications state * @@ -463,35 +456,6 @@ const FormSectionB: FC = ({ SectionOption, refs }: FormSection /> - {/* dbGaP Registration section */} - - - setDbGaPPPHSNumber(e.target.value || "")} - maxLength={50} - placeholder={'Ex/ "phs002529.v1.p1". 50 characters allowed'} - gridWidth={12} - readOnly={readOnlyInputs || !isDbGapRegistered} - required={isDbGapRegistered} - /> - - {/* Existing Publications */} ({ fontWeight: 400, @@ -44,6 +45,10 @@ const FormSectionC: FC = ({ SectionOption, refs }: FormSection ); const [otherSpecies, setOtherSpecies] = useState(data.otherSpeciesOfSubjects); const [otherSpeciesEnabled, setOtherSpeciesEnabled] = useState(data.otherSpeciesEnabled); + const [isDbGapRegistered, setIsdbGaPRegistered] = useState( + data.study?.isDbGapRegistered + ); + const [dbGaPPPHSNumber, setDbGaPPPHSNumber] = useState(data.study?.dbGaPPPHSNumber); const getFormObject = (): FormObject | null => { if (!formRef.current) { @@ -51,7 +56,7 @@ const FormSectionC: FC = ({ SectionOption, refs }: FormSection } const formObject = parseForm(formRef.current, { nullify: false }); - const combinedData = { ...cloneDeep(data), ...formObject }; + const combinedData: QuestionnaireData = merge(cloneDeep(data), formObject); combinedData.numberOfParticipants = parseInt(formObject.numberOfParticipants, 10) || null; @@ -101,6 +106,13 @@ const FormSectionC: FC = ({ SectionOption, refs }: FormSection setOtherSpeciesEnabled(checked); }; + const handleIsDbGapRegisteredChange = (e, checked: boolean) => { + setIsdbGaPRegistered(checked); + if (!checked) { + setDbGaPPPHSNumber(""); + } + }; + useEffect(() => { getFormObjectRef.current = getFormObject; }, [refs]); @@ -132,6 +144,35 @@ const FormSectionC: FC = ({ SectionOption, refs }: FormSection /> + {/* dbGaP Registration section */} + + + setDbGaPPPHSNumber(e.target.value || "")} + maxLength={50} + placeholder={'Ex/ "phs002529.v1.p1". 50 characters allowed'} + gridWidth={12} + readOnly={readOnlyInputs || !isDbGapRegistered} + required={isDbGapRegistered} + /> + + {/* Cancer Types Section */} = ({ SectionOption, refs }: FormSection initialValue={data.targetedSubmissionDate} gridWidth={6} disablePast + required readOnly={readOnlyInputs} /> = ({ SectionOption, refs }: FormSection initialValue={data.targetedReleaseDate} gridWidth={6} disablePast + required readOnly={readOnlyInputs} /> @@ -549,26 +551,20 @@ const FormSectionD: FC = ({ SectionOption, refs }: FormSection - - - {/* Additional Information Section */} - - + + + {/* Additional Information Section */} + = ({ SectionOption, refs }: FormSection gridWidth={12} readOnly={readOnlyInputs} /> - + {SectionDMetadata.sections.ADDITIONAL_COMMENTS.description} + + } + value={data.submitterComment} gridWidth={12} - row - required + maxLength={500} + placeholder="500 characters allowed" + minRows={5} + multiline readOnly={readOnlyInputs} + inputProps={{ + "aria-label": SectionDMetadata.sections.ADDITIONAL_COMMENTS.title, + }} /> diff --git a/src/content/questionnaire/sections/Review.tsx b/src/content/questionnaire/sections/Review.tsx index cbda559fb..8214cc944 100644 --- a/src/content/questionnaire/sections/Review.tsx +++ b/src/content/questionnaire/sections/Review.tsx @@ -18,6 +18,7 @@ import useFormMode from "../../../hooks/useFormMode"; import DataTypes from "../../../config/DataTypesConfig"; import SectionMetadata from "../../../config/SectionMetadata"; import { repositoryDataTypesOptions } from "../../../components/Questionnaire/Repository"; +import { StyledDescription } from "../../../components/Questionnaire/SectionGroup"; const StyledAddress = styled(Stack)(() => ({ display: "flex", @@ -330,25 +331,6 @@ const FormSectionReview: FC = ({ SectionOption, refs }: FormSe ))} - - - - - {publications?.map((publication: KeyedPublication, idx: number) => ( = ({ SectionOption, refs }: FormSe /> + + + + + = ({ SectionOption, refs }: FormSe + + + + - = ({ SectionOption, refs }: FormSe value={data.modelSystems ? "Yes" : "No"} /> + {SectionMetadata.D.sections.ADDITIONAL_COMMENTS.description} + + } + textTransform="none" + valuePlacement="bottom" />