Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cmdct 4229 - pre-populate drawer with plans #11995

Merged
merged 23 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions services/app-api/forms/naaar.json
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,25 @@
"entityUnfinishedMessage": "Complete the remaining indicators for this access measure by entering details.",
"enterEntityDetailsButtonText": "Enter",
"readOnlyEntityDetailsButtonText": "View",
"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",
Expand Down Expand Up @@ -382,14 +400,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"
"label": "Plans"
}
]
}
Expand Down
2 changes: 1 addition & 1 deletion services/app-api/utils/types/formFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -77,6 +76,7 @@ export type FieldValidationObject =
| NestedDependentFieldValidation;

export interface FormField {
[x: string]: any;
id: string;
type: string;
validation: string | FieldValidationObject;
Expand Down
1 change: 1 addition & 0 deletions services/ui-src/src/components/drawers/Drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const Drawer = ({
}: Props) => {
const mqClasses = makeMediaQueryClasses();
const { isOpen, onClose } = drawerDisclosure;

return (
<ChakraDrawer
isOpen={isOpen}
Expand Down
40 changes: 35 additions & 5 deletions services/ui-src/src/components/reports/DrawerReportPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
import {
entityWasUpdated,
filterFormData,
generateIlosFields,
isIlosCompleted,
getEntriesToClear,
parseCustomHtml,
Expand All @@ -35,10 +34,15 @@ import {
FormField,
isFieldElement,
InputChangeEvent,
ReportType,
} from "types";
// assets
import completedIcon from "assets/icons/icon_check_circle.png";
import unfinishedIcon from "assets/icons/icon_error_circle_bright.png";
import {
generateDrawerItemFields,
parentFieldName,
} from "utils/forms/dynamicItemFields";

export const DrawerReportPage = ({ route, validateOnRender }: Props) => {
const [submitting, setSubmitting] = useState<boolean>(false);
Expand All @@ -59,10 +63,30 @@ export const DrawerReportPage = ({ route, validateOnRender }: Props) => {
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);

const getForm = (reportType: string) => {
let modifiedForm = drawerForm;
switch (reportType) {
case ReportType.NAAAR:
if (isAnalysisMethodsPage && hasPlans) {
modifiedForm = generateDrawerItemFields(drawerForm, plans, "plan");
parentFieldName("plan");
}
break;
case ReportType.MCPAR:
if (ilos && reportingOnIlos) {
modifiedForm = generateDrawerItemFields(drawerForm, ilos, "ilos");
parentFieldName("ilos");
britt-mo marked this conversation as resolved.
Show resolved Hide resolved
}
break;
default:
modifiedForm = drawerForm;
}
return modifiedForm;
britt-mo marked this conversation as resolved.
Show resolved Hide resolved
};

// generate ILOS fields (if applicable)
const form =
ilos && reportingOnIlos ? generateIlosFields(drawerForm, ilos) : drawerForm;
const form = getForm(report?.reportType!);

// on load, get reporting status from store
const reportingOnPriorAuthorization =
Expand Down Expand Up @@ -150,7 +174,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;
Expand Down Expand Up @@ -222,6 +247,11 @@ export const DrawerReportPage = ({ route, validateOnRender }: Props) => {
{parseCustomHtml(verbiage.missingIlosMessage || "")}
</Box>
)}
{isAnalysisMethodsPage && !hasPlans && (
<Box sx={sx.missingIlos}>
{parseCustomHtml(verbiage.missingEntityMessage || "")}
</Box>
)}
{standardForm && (
<Box sx={sx.standardForm}>
<Form
Expand Down
1 change: 1 addition & 0 deletions services/ui-src/src/types/formFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ export interface ChoiceFieldProps {
export interface Choice {
key: string; // choice.name
value: string; // choice.value
id?: string; // choice.id
}

export interface DropdownChoice {
Expand Down
150 changes: 150 additions & 0 deletions services/ui-src/src/utils/forms/dynamicItemFields.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { FormJson, AnyObject } from "types";
import { generateDrawerItemFields } from "./dynamicItemFields";

const mockIlosForm: FormJson = {
id: "mock-id",
fields: [
{
id: "mock-field-id",
props: {
choices: [
{
id: "mock-choice-id-1",
label: "mock label 1",
},
{
id: "mock-choice-id-2",
label: "mock label 2",
children: [
{
id: "mock-child-id",
type: "checkbox",
validation: {
type: "checkbox",
nested: true,
parentFieldName: "mock-field-id",
parentOptionId: "mock-field-id-mock-choice-id-2",
},
props: {
choices: [],
},
},
],
},
],
},
type: "radio",
validation: "radio",
},
],
};

const mockAnalysisMethodsForm: FormJson = {
id: "mock-id",
fields: [
{
id: "mock-field-id",
props: {
choices: [
{
id: "mock-choice-id-1",
label: "mock label 1",
},
{
id: "mock-choice-id-2",
label: "mock label 2",
children: [
{
id: "mock-child-id-0",
type: "radio",
validation: {
type: "radio",
nested: true,
parentFieldName: "analysis_applicable",
},
props: {
label: "Frequency of analysis",
choices: [],
},
},
{
id: "mock-child-id-1",
type: "checkbox",
validation: {
type: "radio",
nested: true,
parentFieldName: "mock-field-id",
parentOptionId: "mock-field-id-mock-choice-id-1",
},
props: {
label: "Plans utilizing this method",
choices: [],
},
},
],
},
],
},
type: "radio",
validation: "radio",
},
],
};

const mockIlos: AnyObject[] = [
{
id: "mock-ilos-1",
name: "ilos 1",
},
{
id: "mock-ilos-2",
name: "ilos 2",
},
];

const mockPlans: AnyObject[] = [
{
id: "mock-plan-1",
name: "Plan 1",
},
{
id: "mock-plan-2",
name: "Plan 2",
},
];

describe("generateDrawerItemFields for ILOS", () => {
const result = generateDrawerItemFields(mockIlosForm, mockIlos, "ilos");
it("should generate checkboxes per each available ILOS", () => {
expect(result.fields[0].props.choices.length).toBe(2);
});

it("each ILOS checkbox should have a nested text field of type number", () => {
result.fields[0].props.choices[1].children[0].props.choices.map(
(choice: AnyObject) => {
expect(choice.children);
expect(choice.children[0].type).toBe("number");
}
);
});
});

describe("generateDrawerItemFields for NAAAR analysis methods", () => {
const result = generateDrawerItemFields(
mockAnalysisMethodsForm,
mockPlans,
"plan"
);
it("should generate checkboxes per each available ILOS", () => {
expect(result.fields[0].props.choices[1].length).toBe(2);
});

it("each ILOS checkbox should have a nested text field of type number", () => {
result.fields[0].props.choices[1].children[1].props.choices.map(
(choice: AnyObject) => {
expect(choice.children);
expect(choice.children[1].type).toBe("number");
}
);
});
});
Loading
Loading