Skip to content

Commit

Permalink
Merge pull request #64 from EyeSeeTea/feature/antibiotics-treatment-t…
Browse files Browse the repository at this point in the history
…able

feat: antibiotics treatment episode as table
  • Loading branch information
ifoche authored Aug 14, 2024
2 parents 398aee9 + 2e753e3 commit 1536f66
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export class SurveyTestRepository implements SurveyRepository {
sortOrder: 1,
isAntibioticSection: false,
isSpeciesSection: false,
isAntibioticTreatmentHospitalEpisodeSection: false,
},
],
sortOrder: 1,
Expand Down
9 changes: 9 additions & 0 deletions src/data/utils/surveyFormMappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ import {
import { DataValue } from "@eyeseetea/d2-api";
import { generateUid } from "../../utils/uid";

const AntibioticTreatmentHospitalEpisodeSectionName =
`Antibiotic treatments during hospital episode`.toLowerCase();

export const mapProgramToQuestionnaire = (
program: Program,
event: D2TrackerEvent | undefined,
Expand Down Expand Up @@ -78,6 +81,8 @@ export const mapProgramToQuestionnaire = (
sortOrder: section.sortOrder,
isAntibioticSection: questions.some(isAntibioticQuestion),
isSpeciesSection: questions.some(isSpeciesQuestion),
isAntibioticTreatmentHospitalEpisodeSection:
section.name.toLowerCase() === AntibioticTreatmentHospitalEpisodeSectionName,
};
})
: //If the Program has no sections, create a single section
Expand All @@ -98,6 +103,7 @@ export const mapProgramToQuestionnaire = (
sortOrder: 1,
isAntibioticSection: false,
isSpeciesSection: false,
isAntibioticTreatmentHospitalEpisodeSection: false,
},
];

Expand Down Expand Up @@ -240,6 +246,9 @@ const getRepeatedStageEvents = (
sortOrder: section.sortOrder,
isAntibioticSection: currentRepeatablequestions.some(isAntibioticQuestion),
isSpeciesSection: currentRepeatablequestions.some(isSpeciesQuestion),
isAntibioticTreatmentHospitalEpisodeSection:
section.name.toLowerCase() ===
AntibioticTreatmentHospitalEpisodeSectionName,
};
}) ?? [];

Expand Down
2 changes: 2 additions & 0 deletions src/domain/entities/Questionnaire/QuestionnaireSection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { QuestionnaireRule } from "./QuestionnaireRules";
import _ from "../generic/Collection";

const SPECIES_TITLE = "Specie";
export const AMR_SURVEYS_MORTALITY_DET_SPECIFY_INN = "AMR_SURVEYS_MORTALITY_DET_SPECIFY_INN";
export interface QuestionnaireSection {
title: string;
code: Code;
Expand All @@ -21,6 +22,7 @@ export interface QuestionnaireSection {
stageId: string;
isSpeciesSection: boolean;
isAntibioticSection: boolean;
isAntibioticTreatmentHospitalEpisodeSection: boolean;
}

export interface AntibioticSection {
Expand Down
11 changes: 11 additions & 0 deletions src/webapp/components/survey/SurveyForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { useHistory } from "react-router-dom";
import useReadOnlyAccess from "./hook/useReadOnlyAccess";
import { GridSection } from "./GridSection";
import _c from "../../../domain/entities/generic/Collection";
import { TableSection } from "./TableSection";

export interface SurveyFormProps {
hideForm: () => void;
Expand Down Expand Up @@ -148,6 +149,16 @@ export const SurveyForm: React.FC<SurveyFormProps> = props => {
viewOnly={hasReadOnlyAccess}
/>
);
if (section.isAntibioticTreatmentHospitalEpisodeSection)
return (
<TableSection
section={section}
updateQuestion={question =>
updateQuestion(question, stage.id)
}
viewOnly={hasReadOnlyAccess}
/>
);

return (
<SurveySection
Expand Down
6 changes: 3 additions & 3 deletions src/webapp/components/survey/SurveySection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export const SurveySection: React.FC<SurveySectionProps> = ({
);
};

const PaddedDiv = styled.div`
export const PaddedDiv = styled.div`
padding: 5px;
`;

Expand All @@ -90,10 +90,10 @@ export const StyledTitle = styled.span`
fontweight: "bold" as const;
`;

const StyledWrapper = styled.div`
export const StyledWrapper = styled.div`
display: "flex";
`;

const StyledInput = styled.div`
export const StyledInput = styled.div`
flexgrow: 1;
`;
136 changes: 136 additions & 0 deletions src/webapp/components/survey/TableSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { Typography } from "@material-ui/core";
import { Question } from "../../../domain/entities/Questionnaire/QuestionnaireQuestion";
import { QuestionnaireSection } from "../../../domain/entities/Questionnaire/QuestionnaireSection";
import { QuestionWidget } from "../survey-questions/QuestionWidget";
import { PaddedDiv, StyledInput, StyledTitle, StyledWrapper } from "./SurveySection";
import {
// @ts-ignore
DataTable,
// @ts-ignore
TableHead,
// @ts-ignore
DataTableRow,
// @ts-ignore
DataTableColumnHeader,
// @ts-ignore
DataTableCell,
// @ts-ignore
TableBody,
} from "@dhis2/ui";
import _c from "../../../domain/entities/generic/Collection";
import styled from "styled-components";
import { useTableSection } from "./hook/useTableSection";

interface TableSectionProps {
section: QuestionnaireSection;
viewOnly?: boolean;
updateQuestion: (question: Question) => void;
}

export const TableSection: React.FC<TableSectionProps> = ({
section,
viewOnly,
updateQuestion,
}) => {
const { questionGroups, headerRow } = useTableSection(section);
return (
<div key={section.title}>
<DataTable>
<TableHead>
<DataTableRow>
<DataTableColumnHeader colSpan="6">
<StyledTitle>{section.title}</StyledTitle>
</DataTableColumnHeader>
</DataTableRow>
<DataTableRow>
{headerRow?.map((header, index) => (
<DataTableColumnHeader key={index}>{header}</DataTableColumnHeader>
))}
</DataTableRow>
</TableHead>

<TableBody>
{questionGroups?.map(questionGroup => (
<>
<DataTableRow key={`columns-${questionGroup.groupId}`}>
{questionGroup.columnQuestions.map(
question =>
question.isVisible && (
<DataTableCell key={question.code}>
<StyledDataTableCell key={question.code}>
<QuestionWidget
onChange={updateQuestion}
question={question}
disabled={
question.disabled || viewOnly
? true
: false
}
/>
{question.errors.map((err, index) => (
<div key={index}>
<Typography
variant="body2"
color="error"
>
{err}
</Typography>
</div>
))}
</StyledDataTableCell>
</DataTableCell>
)
)}
</DataTableRow>
<DataTableRow key={`detailQuestion-${questionGroup.groupId}`}>
{questionGroup.detailQuestion &&
questionGroup.detailQuestion.isVisible && (
<>
<DataTableCell>
<span>{questionGroup.detailQuestion.text}</span>
</DataTableCell>

<DataTableCell>
<StyledWrapper>
<StyledInput>
<QuestionWidget
onChange={updateQuestion}
question={questionGroup.detailQuestion}
disabled={
questionGroup.detailQuestion
.disabled || viewOnly
? true
: false
}
/>
{questionGroup.detailQuestion.errors.map(
(err, index) => (
<PaddedDiv key={index}>
<Typography
variant="body2"
color="error"
>
{err}
</Typography>
</PaddedDiv>
)
)}
</StyledInput>
</StyledWrapper>
</DataTableCell>
</>
)}
</DataTableRow>
</>
))}
</TableBody>
</DataTable>
</div>
);
};

const StyledDataTableCell = styled.div`
display: flex;
flex-direction: column;
padding: 0.5rem;
`;
5 changes: 4 additions & 1 deletion src/webapp/components/survey/hook/useSurveyForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ export function useSurveyForm(formType: SURVEY_FORM_TYPES, eventId: string | und
formType === "PrevalenceCentralRefLabForm" ||
formType === "PrevalencePathogenIsolatesLog" ||
formType === "PrevalenceSampleShipTrackForm" ||
formType === "PrevalenceSupranationalRefLabForm"
formType === "PrevalenceSupranationalRefLabForm" ||
formType === "PrevalenceDischarge" ||
formType === "PrevalenceD28FollowUp" ||
formType === "PrevalenceCohortEnrolment"
? currentFacilityLevelForm?.orgUnitId
: undefined;

Expand Down
46 changes: 46 additions & 0 deletions src/webapp/components/survey/hook/useTableSection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useEffect, useState } from "react";
import { Question } from "../../../../domain/entities/Questionnaire/QuestionnaireQuestion";
import {
AMR_SURVEYS_MORTALITY_DET_SPECIFY_INN,
QuestionnaireSection,
} from "../../../../domain/entities/Questionnaire/QuestionnaireSection";
import _c from "../../../../domain/entities/generic/Collection";

type QuestionGroup = {
groupId: string;
columnQuestions: Question[];
detailQuestion?: Question;
}[];

export const useTableSection = (section: QuestionnaireSection) => {
const [questionGroups, setQuestionGroups] = useState<QuestionGroup>();
const [headerRow, setHeaderRow] = useState<string[]>();

useEffect(() => {
const groupedRows: QuestionGroup = _c(section.questions)
.groupBy(q => {
return q.text.charAt(0); //Group by section Id which is the first character of the question text
})
.mapValues(([groupId, questions]) => {
return {
groupId: groupId,
columnQuestions: questions.filter(
question => !question.code.startsWith(AMR_SURVEYS_MORTALITY_DET_SPECIFY_INN)
), // all questions other than the detail question
detailQuestion: questions.find(question =>
question.code.startsWith(AMR_SURVEYS_MORTALITY_DET_SPECIFY_INN)
),
};
})
.values();

const headers =
groupedRows[0]?.columnQuestions
?.filter(q => q.isVisible)
.map(q => q.text.replace("1", "").replace(".", "")) ?? [];
setHeaderRow(headers);
setQuestionGroups(groupedRows);
}, [setQuestionGroups, setHeaderRow, section]);

return { questionGroups, headerRow };
};

0 comments on commit 1536f66

Please sign in to comment.