Skip to content

Commit

Permalink
CMDCT-4086: Add / Edit Report Modal (NAAAR) (#11920)
Browse files Browse the repository at this point in the history
  • Loading branch information
karla-vm authored Nov 14, 2024
1 parent f430bd6 commit d271cc3
Show file tree
Hide file tree
Showing 14 changed files with 247 additions and 18 deletions.
2 changes: 1 addition & 1 deletion services/app-api/forms/naaar.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
}
},
{
"id": "stateOrTerritory",
"id": "stateName",
"type": "text",
"validation": "textOptional",
"props": {
Expand Down
4 changes: 3 additions & 1 deletion services/app-api/handlers/reports/submit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
MCPARReportMetadata,
MLRReportMetadata,
UserRoles,
NAAARReportMetadata,
} from "../../utils/types";

export const submitReport = handler(async (event, _context) => {
Expand Down Expand Up @@ -65,7 +66,8 @@ export const submitReport = handler(async (event, _context) => {

const reportMetadata = response.Item as
| MLRReportMetadata
| MCPARReportMetadata;
| MCPARReportMetadata
| NAAARReportMetadata;
const { status, isComplete, fieldDataId, formTemplateId } = reportMetadata;

if (status === "Submitted") {
Expand Down
2 changes: 2 additions & 0 deletions services/app-api/utils/types/reportContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export interface ReportMetadataShape extends ReportKeys {
copyFieldDataSourceId?: string;
programIsPCCM?: Choice[];
previousRevisions: string[];
planTypeIncludedInProgram?: Choice[];
"planTypeIncludedInProgram-otherText"?: string;
novMcparRelease?: boolean;
}

Expand Down
10 changes: 10 additions & 0 deletions services/app-api/utils/types/reports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ export interface MCPARReportMetadata extends ReportMetadata {
novMcparRelease: boolean;
}

export interface NAAARReportMetadata extends ReportMetadata {
programName: string;
reportType: "NAAAR";
reportingPeriodStartDate: number;
reportingPeriodEndDate: number;
dueDate: number;
planTypeIncludedInProgram: Choice[];
"planTypeIncludedInProgram-otherText"?: string;
}

// HELPER FUNCTIONS

/**
Expand Down
4 changes: 3 additions & 1 deletion services/app-api/utils/validation/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as yup from "yup";
import { radioOptional } from "./completionSchemas";
import { radioOptional, textOptional } from "./completionSchemas";

export const metadataValidationSchema = yup.object().shape({
programName: yup.string(),
Expand All @@ -19,4 +19,6 @@ export const metadataValidationSchema = yup.object().shape({
submissionName: yup.string(),
completionStatus: yup.mixed(),
copyFieldDataSourceId: yup.string(),
planTypeIncludedInProgram: radioOptional(),
"planTypeIncludedInProgram-otherText": textOptional(),
});
89 changes: 87 additions & 2 deletions services/ui-src/src/components/modals/AddEditReportModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
mockMlrReport,
mockMlrReportContext,
mockMlrReportStore,
mockNaaarReport,
mockNaaarReportContext,
mockNaaarReportStore,
mockStateUserStore,
Expand Down Expand Up @@ -81,6 +82,22 @@ const mockSelectedMcparReport = {
},
};

// a similar assignment is performed in DashboardPage and is needed here to make sure the modal form hydrates
const mockSelectedNaaarReport = {
...mockNaaarReport,
fieldData: {
programName: mockNaaarReport.programName,
reportingPeriodEndDate: convertDateUtcToEt(
mockNaaarReport.reportingPeriodEndDate
),
reportingPeriodStartDate: convertDateUtcToEt(
mockNaaarReport.reportingPeriodStartDate
),
combinedData: mockNaaarReport.combinedData,
planTypeIncludedInProgram: mockNaaarReport.planTypeIncludedInProgram,
},
};

const modalComponentWithSelectedReport = (
<RouterWrappedComponent>
<ReportContext.Provider value={mockedMcparReportContext}>
Expand Down Expand Up @@ -145,6 +162,22 @@ const naaarModalComponent = (
</RouterWrappedComponent>
);

const naaarModalComponentWithSelectedReport = (
<RouterWrappedComponent>
<ReportContext.Provider value={mockedNaaarReportContext}>
<AddEditReportModal
activeState="AB"
selectedReport={mockSelectedNaaarReport}
reportType={"NAAAR"}
modalDisclosure={{
isOpen: true,
onClose: mockCloseHandler,
}}
/>
</ReportContext.Provider>
</RouterWrappedComponent>
);

describe("Test AddEditProgramModal", () => {
beforeEach(async () => {
mockedUseStore.mockReturnValue({
Expand Down Expand Up @@ -324,8 +357,16 @@ describe("Test AddEditReportModal functionality for NAAAR", () => {
});

const fillForm = async (form: any) => {
const contactNameField = form.querySelector("[name='contactName']")!;
await userEvent.type(contactNameField, "fake contact name");
const programNameField = form.querySelector("[name='programName']")!;
await userEvent.type(programNameField, "fake program name");
const startDateField = form.querySelector(
"[name='reportingPeriodStartDate']"
)!;
await userEvent.type(startDateField, "1/1/2022");
const endDateField = form.querySelector("[name='reportingPeriodEndDate']")!;
await userEvent.type(endDateField, "12/31/2022");
const planTypeField = screen.getByLabelText("MCO") as HTMLInputElement;
await userEvent.click(planTypeField);
const submitButton = screen.getByRole("button", { name: "Save" });
await userEvent.click(submitButton);
};
Expand All @@ -340,6 +381,50 @@ describe("Test AddEditReportModal functionality for NAAAR", () => {
expect(mockCloseHandler).toHaveBeenCalledTimes(1);
});
});

test("Edit modal hydrates with report info and disables fields", async () => {
const result = render(naaarModalComponentWithSelectedReport);
const form = result.getByTestId("add-edit-report-form");
const copyFieldDataSourceId = form.querySelector(
"[name='copyFieldDataSourceId']"
)!;

// yoy copy field is disabled
expect(copyFieldDataSourceId).toHaveProperty("disabled", true);

// hydrated values are in the modal
const programNameField = form.querySelector("[name='programName']")!;
const startDateField = form.querySelector(
"[name='reportingPeriodStartDate']"
)!;
const endDateField = form.querySelector("[name='reportingPeriodEndDate']")!;

expect(programNameField).toHaveProperty(
"value",
mockNaaarReport.programName
);
expect(startDateField).toHaveProperty(
"value",
convertDateUtcToEt(mockNaaarReport.reportingPeriodStartDate)
);
expect(endDateField).toHaveProperty(
"value",
convertDateUtcToEt(mockNaaarReport.reportingPeriodEndDate)
);

await userEvent.click(screen.getByText("Cancel"));
});

test("Editing an existing report", async () => {
const result = render(naaarModalComponentWithSelectedReport);
const form = result.getByTestId("add-edit-report-form");
await fillForm(form);
await waitFor(() => {
expect(mockUpdateReport).toHaveBeenCalledTimes(1);
expect(mockFetchReportsByState).toHaveBeenCalledTimes(1);
expect(mockCloseHandler).toHaveBeenCalledTimes(1);
});
});
});

describe("Test AddEditReportModal accessibility", () => {
Expand Down
23 changes: 20 additions & 3 deletions services/ui-src/src/components/modals/AddEditReportModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,19 +138,35 @@ export const AddEditReportModal = ({

// NAAAR report payload
const prepareNaaarPayload = (formData: any) => {
const contactName = formData["contactName"];
const programName = formData["programName"];
const copyFieldDataSourceId = formData["copyFieldDataSourceId"];
const dueDate = calculateDueDate(formData["reportingPeriodEndDate"]);
const reportingPeriodStartDate = convertDateEtToUtc(
formData["reportingPeriodStartDate"]
);
const reportingPeriodEndDate = convertDateEtToUtc(
formData["reportingPeriodEndDate"]
);
const planTypeIncludedInProgram = formData["planTypeIncludedInProgram"];

return {
metadata: {
contactName,
programName,
reportingPeriodStartDate,
reportingPeriodEndDate,
dueDate,
lastAlteredBy: full_name,
copyFieldDataSourceId: copyFieldDataSourceId?.value,
planTypeIncludedInProgram,
"planTypeIncludedInProgram-otherText":
formData["planTypeIncludedInProgram-otherText"],
locked: false,
submissionCount: 0,
previousRevisions: [],
naaarReport,
},
fieldData: {
contactName,
programName,
},
};
};
Expand Down Expand Up @@ -227,6 +243,7 @@ export const AddEditReportModal = ({
content={{
heading: selectedReport?.id ? form.heading?.edit : form.heading?.add,
subheading: selectedReport?.id ? "" : form.heading?.subheading,
intro: selectedReport?.id ? "" : form.heading?.intro,
actionButtonText: submitting ? <Spinner size="md" /> : "Save",
closeButtonText: "Cancel",
}}
Expand Down
11 changes: 9 additions & 2 deletions services/ui-src/src/components/modals/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ export const Modal = ({
</Heading>
</ModalHeader>
{content.subheading && (
<Box sx={sx.modalSubheader}>{content.subheading}</Box>
<Box sx={sx.modalSubheading}>{content.subheading}</Box>
)}
{content.intro && <Box sx={sx.intro}>{content.intro}</Box>}
<Flex sx={sx.modalCloseContainer}>
<Button
sx={sx.modalClose}
Expand Down Expand Up @@ -95,6 +96,7 @@ interface Props {
content: {
heading: string;
subheading?: string;
intro?: string;
actionButtonText: string | ReactNode;
closeButtonText?: string;
};
Expand All @@ -121,7 +123,12 @@ const sx = {
fontSize: "2xl",
fontWeight: "bold",
},
modalSubheader: {
modalSubheading: {
marginTop: "0.5rem",
fontSize: "xl",
fontWeight: "bold",
},
intro: {
margin: "0.5rem auto -1rem auto",
},
modalCloseContainer: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ export const DashboardPage = ({ reportType }: Props) => {
combinedData: report.combinedData,
copyFieldDataSourceId,
programIsPCCM: report?.programIsPCCM,
planTypeIncludedInProgram: report?.planTypeIncludedInProgram,
"planTypeIncludedInProgram-otherText":
report?.["planTypeIncludedInProgram-otherText"],
},
state: report.state,
id: report.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
},
"heading": {
"add": "Add / Copy a MCPAR",
"subheading": "Complete the form below to generate a MCPAR for your managed care program. You may choose to copy an existing MCPAR report, which will retain many key responses (e.g., plan names, quality measures, etc.). Copied MCPARs will still have several blank fields and all responses can be edited. To create a blank MCPAR form, leave the “copy a report” field as “Select an option”.",
"intro": "Complete the form below to generate a MCPAR for your managed care program. You may choose to copy an existing MCPAR report, which will retain many key responses (e.g., plan names, quality measures, etc.). Copied MCPARs will still have several blank fields and all responses can be edited. To create a blank MCPAR form, leave the “copy a report” field as “Select an option”.",
"edit": "Edit Program"
},
"fields": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,91 @@
"mode": "onChange"
},
"heading": {
"add": "Add new NAAAR submission",
"edit": "Edit NAAAR submission"
"add": "Add / Copy a Program",
"subheading": "State information and reporting scenario",
"intro": "Add a new program to start a blank report or copy an existing report. Copying a program’s NAAAR will retain the structure of your program, including plans and access measures, but allow you to enter updated responses for the new reporting period, saving you time. You can still edit these details within.",
"edit": "Edit Program"
},
"fields": [
{
"id": "contactName",
"id": "programName",
"type": "text",
"validation": "text",
"props": {
"label": "Placeholder",
"hint": "Placeholder"
"label": "Program name"
}
},
{
"id": "copyFieldDataSourceId",
"type": "dropdown",
"props": {
"label": "If you want to copy an existing report, select one (optional)",
"options": "copyEligibleReports"
}
},
{
"id": "reportingPeriodStartDate",
"type": "date",
"validation": "date",
"props": {
"label": "Reporting period (i.e. contract period) start date",
"hint": "Enter start date of the reporting period represented in the report.",
"timetype": "startDate"
}
},
{
"id": "reportingPeriodEndDate",
"type": "date",
"validation": {
"type": "endDate",
"dependentFieldName": "reportingPeriodStartDate"
},
"props": {
"label": "Reporting period (i.e. contract period) end date",
"hint": "Enter end date of the reporting period represented in the report.",
"timetype": "endDate"
}
},
{
"id": "planTypeIncludedInProgram",
"type": "radio",
"validation": "radio",
"props": {
"label": "Plan type included in program",
"hint": "Indicate the managed care plan type (MCO, PIHP, PAHP, or MMP) that contracts with the state in each program.",
"choices": [
{
"id": "NHAbx1VBdvZkHgG2HTfexemq",
"label": "MCO"
},
{
"id": "MiyW1eKfcetIG8k2eyT5dbhw",
"label": "PIHP"
},
{
"id": "QASeuhF5cDBrRpWbmYBndH2v",
"label": "PAHP"
},
{
"id": "U4dg782RHft2Fs53fOpcbocr",
"label": "MMP"
},
{
"id": "ZRH5GgCnJSlnCdieekgh67sv",
"label": "Other, specify",
"children": [
{
"id": "planTypeIncludedInProgram-otherText",
"type": "textarea",
"validation": {
"type": "text",
"nested": true,
"parentFieldName": "planTypeIncludedInProgram"
}
}
]
}
]
}
}
]
Expand Down
2 changes: 2 additions & 0 deletions services/ui-src/src/types/reportContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export interface ReportMetadataShape extends ReportKeys {
copyFieldDataSourceId?: string;
programIsPCCM?: Choice[];
previousRevisions: string[];
planTypeIncludedInProgram?: Choice[];
"planTypeIncludedInProgram-otherText"?: string;
novMcparRelease?: boolean;
}

Expand Down
Loading

0 comments on commit d271cc3

Please sign in to comment.