diff --git a/services/app-api/forms/naaar.json b/services/app-api/forms/naaar.json index d90e05acf..4a752be68 100644 --- a/services/app-api/forms/naaar.json +++ b/services/app-api/forms/naaar.json @@ -290,7 +290,25 @@ "deleteModalTitle": "Are you sure you want to delete this analysis method?", "deleteModalConfirmButtonText": "Yes, delete method", "deleteModalWarning": "Are you sure you want to proceed? You will lose all information entered for this analysis method in the NAAAR. The method will remain in previously submitted NAAAR reports if applicable.", - "drawerTitle": "Analysis method: " + "drawerTitle": "Analysis method: ", + "missingEntityMessage": [ + { + "type": "p", + "children": [ + { + "type": "html", + "content": "This program is missing plans. You won’t be able to complete this section until you’ve added all the plans that participate in this program in section A.7. " + }, + { + "type": "internalLink", + "content": "Add Plans", + "props": { + "to": "/naaar/state-and-program-information/add-plans" + } + } + ] + } + ] }, "drawerForm": { "id": "iam", @@ -374,23 +392,14 @@ "validation": { "type": "checkbox", "nested": true, - "parentFieldName": "analysis_applicable" + "parentFieldName": "analysis_applicable", + "parentOptionId": "analysis_applicable-Br7jPULxsYgbiuHV9zwyIB" }, "props": { "label": "Plans utilizing this method", "choices": [ { - "id": "tvCUw5CcaGUFSIMByAopjF", - "label": "Fill in plans here" - }, - { - "id": "tvCUw5CcaGUFSIMByAopjA", - "label": "Second plan" - } - , - { - "id": "tvCUw5CcaGUFSIMByAopjB", - "label": "Third plan with the absolutest most longest name you ever did see in a plan like this one" + "label": "Plans" } ] } @@ -484,25 +493,13 @@ "id": "analysis_method_applicable_plans", "type": "checkbox", "validation": { - "type": "checkbox", - "nested": true, - "parentFieldName": "analysis_applicable" + "type": "checkbox" }, "props": { "label": "Plans utilizing this method", "choices": [ { - "id": "tvCUw5CcaGUFSIMByAopjF", - "label": "Fill in plans here" - }, - { - "id": "tvCUw5CcaGUFSIMByAopjA", - "label": "Second plan" - } - , - { - "id": "tvCUw5CcaGUFSIMByAopjB", - "label": "Third plan with the absolutest most longest name you ever did see in a plan like this one" + "label": "Plans" } ] } diff --git a/services/app-api/utils/types/formFields.ts b/services/app-api/utils/types/formFields.ts index 28122b2af..d084d9430 100644 --- a/services/app-api/utils/types/formFields.ts +++ b/services/app-api/utils/types/formFields.ts @@ -20,7 +20,6 @@ export const entityTypes = [ /** * This type is a string union type generated by the constant above. */ -export declare type EntityType = typeof entityTypes[number]; export enum ModalDrawerEntityTypes { ACCESS_MEASURES = "accessMeasures", @@ -77,6 +76,7 @@ export type FieldValidationObject = | NestedDependentFieldValidation; export interface FormField { + [x: string]: any; id: string; type: string; validation: string | FieldValidationObject; diff --git a/services/ui-src/src/components/drawers/Drawer.tsx b/services/ui-src/src/components/drawers/Drawer.tsx index 81235fa3b..f0305444b 100644 --- a/services/ui-src/src/components/drawers/Drawer.tsx +++ b/services/ui-src/src/components/drawers/Drawer.tsx @@ -27,6 +27,7 @@ export const Drawer = ({ }: Props) => { const mqClasses = makeMediaQueryClasses(); const { isOpen, onClose } = drawerDisclosure; + return ( { setEntityType: () => {}, setEntities: () => {}, }; - const mockAnalysisMethodsReportPageJson = { - name: "mock-route", - path: "/naaar/analysis-methods", - pageType: "drawer", - entityType: "analysisMethods", - verbiage: { - intro: mockVerbiageIntro, - dashboardTitle: "Mock dashboard title", - drawerTitle: "Mock drawer title", - addEntityButtonText: "Add other analysis method", - }, - drawerForm: { - id: "am", - fields: [ - { - id: "am_default_text", - type: "text", - validation: "text", - props: { - label: "Fill in info on analysis method", - }, - }, - ], - }, - addEntityDrawerForm: { - id: "am_custom", - fields: [ - { - id: "am_custom_text", - type: "text", - validation: "text", - props: { - label: "Fill in info on custom analysis method", - }, - }, - ], - }, - }; const mockNaaarReportContextWithAnalysisMethods: any = mockNaaarReportContext; mockNaaarReportContextWithAnalysisMethods.report.fieldData[ @@ -379,7 +342,7 @@ describe("Test DrawerReportPage with custom entities", () => { const drawerReportPageWithCustomEntities = ( - + ); @@ -394,9 +357,7 @@ describe("Test DrawerReportPage with custom entities", () => { const enterDefaultMethod = screen.getAllByText("Enter")[0]; await userEvent.click(enterDefaultMethod); expect(screen.getByRole("dialog")).toBeVisible(); - const textField = await screen.getByLabelText( - "Fill in info on analysis method" - ); + const textField = await screen.getByLabelText("mock label 1"); expect(textField).toBeVisible(); }); @@ -414,9 +375,7 @@ describe("Test DrawerReportPage with custom entities", () => { const addCustomMethod = screen.getByText("Add other analysis method"); await userEvent.click(addCustomMethod); expect(screen.getByRole("dialog")).toBeVisible(); - const customTextField = await screen.getByLabelText( - "Fill in info on custom analysis method" - ); + const customTextField = await screen.getByLabelText("Analysis method"); expect(customTextField).toBeVisible(); await userEvent.type(customTextField, "new analysis method"); const saveCustomMethod = screen.getByText("Save & close"); @@ -455,7 +414,7 @@ describe("Test DrawerReportPage with custom entities", () => { - + ); diff --git a/services/ui-src/src/components/reports/DrawerReportPage.tsx b/services/ui-src/src/components/reports/DrawerReportPage.tsx index 7e77e546c..3ebb2d679 100644 --- a/services/ui-src/src/components/reports/DrawerReportPage.tsx +++ b/services/ui-src/src/components/reports/DrawerReportPage.tsx @@ -21,7 +21,6 @@ import { import { entityWasUpdated, filterFormData, - generateIlosFields, isIlosCompleted, getEntriesToClear, parseCustomHtml, @@ -38,12 +37,17 @@ import { FormField, isFieldElement, InputChangeEvent, + ReportType, FormJson, } from "types"; // assets import addIcon from "assets/icons/icon_add_blue.png"; import completedIcon from "assets/icons/icon_check_circle.png"; import unfinishedIcon from "assets/icons/icon_error_circle_bright.png"; +import { + generateAddEntityDrawerItemFields, + generateDrawerItemFields, +} from "utils/forms/dynamicItemFields"; export const DrawerReportPage = ({ route, validateOnRender }: Props) => { const [submitting, setSubmitting] = useState(false); @@ -63,14 +67,42 @@ export const DrawerReportPage = ({ route, validateOnRender }: Props) => { // check if there are ILOS and associated plans const isMcparReport = route.path.includes("mcpar"); + const isAnalysisMethodsPage = route.path.includes("analysis-methods"); const reportingOnIlos = route.path === "/mcpar/plan-level-indicators/ilos"; const ilos = report?.fieldData?.["ilos"]; const hasIlos = ilos?.length; const hasPlans = report?.fieldData?.["plans"]?.length > 0; + const plans = report?.fieldData?.plans?.map((plan: { name: string }) => plan); - // generate ILOS fields (if applicable) - const form = - ilos && reportingOnIlos ? generateIlosFields(drawerForm, ilos) : drawerForm; + const getForm = ( + reportType?: string, + isCustomEntityForm: boolean = false + ) => { + let modifiedForm = drawerForm; + switch (reportType) { + case ReportType.NAAAR: + if (isAnalysisMethodsPage && hasPlans) { + modifiedForm = isCustomEntityForm + ? generateAddEntityDrawerItemFields( + addEntityDrawerForm, + plans, + "plan" + ) + : generateDrawerItemFields(drawerForm, plans, "plan"); + } + break; + case ReportType.MCPAR: + if (ilos && reportingOnIlos) { + modifiedForm = generateDrawerItemFields(drawerForm, ilos, "ilos"); + } + break; + default: + } + return modifiedForm; + }; + + const form = getForm(report?.reportType); + const addEntityForm = getForm(report?.reportType, true); // on load, get reporting status from store const reportingOnPriorAuthorization = @@ -121,7 +153,7 @@ export const DrawerReportPage = ({ route, validateOnRender }: Props) => { } let referenceForm = form; if (selectedIsCustomEntity) { - referenceForm = addEntityDrawerForm; + referenceForm = addEntityForm; } const filteredFormData = filterFormData( enteredData, @@ -181,7 +213,8 @@ export const DrawerReportPage = ({ route, validateOnRender }: Props) => { (route.path === "/mcpar/plan-level-indicators/prior-authorization" && priorAuthDisabled) || (route.path === "/mcpar/plan-level-indicators/patient-access-api" && - patientAccessDisabled) + patientAccessDisabled) || + (isAnalysisMethodsPage && !hasPlans) ) { style = sx.disabledButton; disabled = true; @@ -206,7 +239,7 @@ export const DrawerReportPage = ({ route, validateOnRender }: Props) => { const calculateEntityCompletion = () => { let formFields = form.fields; if (isCustomEntity) { - formFields = addEntityDrawerForm.fields; + formFields = addEntityForm.fields; } return formFields ?.filter(isFieldElement) @@ -292,6 +325,11 @@ export const DrawerReportPage = ({ route, validateOnRender }: Props) => { {parseCustomHtml(verbiage.missingIlosMessage || "")} )} + {isAnalysisMethodsPage && !hasPlans && ( + + {parseCustomHtml(verbiage.missingEntityMessage || "")} + + )} {standardForm && (
{ ) : ( entityRows(entities) )} - {canAddEntities && ( + {canAddEntities && hasPlans && (