diff --git a/src/data/repositories/RiskAssessmentD2Repository.ts b/src/data/repositories/RiskAssessmentD2Repository.ts index d9bd3020..7550fadc 100644 --- a/src/data/repositories/RiskAssessmentD2Repository.ts +++ b/src/data/repositories/RiskAssessmentD2Repository.ts @@ -27,6 +27,8 @@ import { RiskAssessmentQuestionnaireFormData, RiskAssessmentSummaryFormData, } from "../../domain/entities/ConfigurableForm"; +import { SelectedPick } from "@eyeseetea/d2-api/api"; +import { D2DataElementSchema } from "@eyeseetea/d2-api/2.36"; //SNEHA TO DO : Fetch from metadata on app load export const riskAssessmentGradingIds = { @@ -261,51 +263,113 @@ export class RiskAssessmentD2Repository implements RiskAssessmentRepository { | RiskAssessmentQuestionnaireFormData, diseaseOutbreakId: Id ): FutureData { - const programStageId = this.getProgramStageByFormType(formData.type); - return getProgramStage(this.api, programStageId).flatMap(riskResponse => { - const riskDataElements = riskResponse.objects[0]?.programStageDataElements; + if (formData.type === "risk-assessment-questionnaire") { + const { stdQuestionnaireStageId, customQuestionnaireStageId } = + this.getRiskAssessmentQuestionnaireProgramStages(); - if (!riskDataElements) - return Future.error( - new Error(` ${formData.type} Program Stage metadata not found`) - ); - - //Get the enrollment Id for the disease outbreak - return apiToFuture( - this.api.tracker.enrollments.get({ - fields: { - enrollment: true, - }, - trackedEntity: diseaseOutbreakId, - enrolledBefore: new Date().toISOString(), - program: RTSL_ZEBRA_PROGRAM_ID, - orgUnit: RTSL_ZEBRA_ORG_UNIT_ID, - }) - ).flatMap(enrollmentResponse => { - const enrollmentId = enrollmentResponse.instances[0]?.enrollment; - if (!enrollmentId) { - return Future.error(new Error(`Enrollment not found for Disease Outbreak`)); + return getProgramStage(this.api, stdQuestionnaireStageId).flatMap( + stdQuestionnaireRes => { + const stdQuestionnaireDataElements = + stdQuestionnaireRes.objects[0]?.programStageDataElements; + if (!stdQuestionnaireDataElements) + return Future.error( + new Error(` ${formData.type} Program Stage metadata not found`) + ); + return this.postRiskAssessmentQestionnaire( + stdQuestionnaireDataElements, + formData, + diseaseOutbreakId, + stdQuestionnaireStageId + ).flatMap(() => { + return getProgramStage(this.api, customQuestionnaireStageId).flatMap( + customQuestionnaireRes => { + const customQuestionnaireDataElements = + customQuestionnaireRes.objects[0]?.programStageDataElements; + if (!customQuestionnaireDataElements) + return Future.error( + new Error( + ` ${formData.type} Program Stage metadata not found` + ) + ); + return this.postRiskAssessmentQestionnaire( + customQuestionnaireDataElements, + formData, + diseaseOutbreakId, + customQuestionnaireStageId + ); + } + ); + }); } - const events: D2TrackerEvent = mapRiskAssessmentToDataElements( + ); + } else { + const programStageId = this.getProgramStageByFormType(formData.type); + return getProgramStage(this.api, programStageId).flatMap(riskResponse => { + const riskDataElements = riskResponse.objects[0]?.programStageDataElements; + if (!riskDataElements) + return Future.error( + new Error(` ${formData.type} Program Stage metadata not found`) + ); + return this.postRiskAssessmentQestionnaire( + riskDataElements, formData, - programStageId, diseaseOutbreakId, - enrollmentId, - riskDataElements + programStageId ); + }); + } + } - return apiToFuture( - this.api.tracker.post( - { importStrategy: "CREATE_AND_UPDATE" }, - { events: [events] } - ) - ).flatMap(saveResponse => { - if (saveResponse.status === "ERROR" || !diseaseOutbreakId) { - return Future.error(new Error(`Error Risk Assessment Grading`)); - } else { - return Future.success(undefined); - } - }); + private postRiskAssessmentQestionnaire( + riskDataElements: { + dataElement: SelectedPick< + D2DataElementSchema, + { + id: true; + valueType: true; + code: true; + } + >; + }[], + formData: + | RiskAssessmentGradingFormData + | RiskAssessmentSummaryFormData + | RiskAssessmentQuestionnaireFormData, + diseaseOutbreakId: Id, + programStageId: Id + ): FutureData { + //Get the enrollment Id for the disease outbreak + return apiToFuture( + this.api.tracker.enrollments.get({ + fields: { + enrollment: true, + }, + trackedEntity: diseaseOutbreakId, + enrolledBefore: new Date().toISOString(), + program: RTSL_ZEBRA_PROGRAM_ID, + orgUnit: RTSL_ZEBRA_ORG_UNIT_ID, + }) + ).flatMap(enrollmentResponse => { + const enrollmentId = enrollmentResponse.instances[0]?.enrollment; + if (!enrollmentId) { + return Future.error(new Error(`Enrollment not found for Disease Outbreak`)); + } + const events: D2TrackerEvent[] = mapRiskAssessmentToDataElements( + formData, + programStageId, + diseaseOutbreakId, + enrollmentId, + riskDataElements + ); + + return apiToFuture( + this.api.tracker.post({ importStrategy: "CREATE_AND_UPDATE" }, { events: events }) + ).flatMap(saveResponse => { + if (saveResponse.status === "ERROR" || !diseaseOutbreakId) { + return Future.error(new Error(`Error Risk Assessment Grading`)); + } else { + return Future.success(undefined); + } }); }); } @@ -315,10 +379,15 @@ export class RiskAssessmentD2Repository implements RiskAssessmentRepository { return RTSL_ZEBRA_RISK_ASSESSMENT_GRADING_PROGRAM_STAGE_ID; case "risk-assessment-summary": return RTSL_ZEBRA_RISK_ASSESSMENT_SUMMARY_PROGRAM_STAGE_ID; - case "risk-assessment-questionnaire": - return RTSL_ZEBRA_RISK_ASSESSMENT_QUESTIONNAIRE_PROGRAM_STAGE_ID; default: throw new Error("Risk Form type not supported"); } } + private getRiskAssessmentQuestionnaireProgramStages() { + return { + stdQuestionnaireStageId: RTSL_ZEBRA_RISK_ASSESSMENT_QUESTIONNAIRE_PROGRAM_STAGE_ID, + customQuestionnaireStageId: + RTSL_ZEBRA_RISK_ASSESSMENT_QUESTIONNAIRE_CUSTOM_PROGRAM_STAGE_ID, + }; + } } diff --git a/src/data/repositories/TeamMemberD2Repository.ts b/src/data/repositories/TeamMemberD2Repository.ts index acc5f898..169e5f11 100644 --- a/src/data/repositories/TeamMemberD2Repository.ts +++ b/src/data/repositories/TeamMemberD2Repository.ts @@ -6,7 +6,8 @@ import { apiToFuture, FutureData } from "../api-futures"; import { assertOrError } from "./utils/AssertOrError"; import { Future } from "../../domain/entities/generic/Future"; -const RTSL_ZEBRA_INCIDENTMANAGER = "UOd3K79040G"; +const RTSL_ZEBRA_INCIDENTMANAGER = "RTSL_ZEBRA_INCIDENTMANAGER"; +const RTSL_ZEBRA_RISKASSESSOR = "RTSL_ZEBRA_RISKASSESSOR"; export class TeamMemberD2Repository implements TeamMemberRepository { constructor(private api: D2Api) {} @@ -29,11 +30,19 @@ export class TeamMemberD2Repository implements TeamMemberRepository { }); } getIncidentManagers(): FutureData { + return this.getTeamMembersByUserGroup(RTSL_ZEBRA_INCIDENTMANAGER); + } + + getRiskAssessors(): FutureData { + return this.getTeamMembersByUserGroup(RTSL_ZEBRA_RISKASSESSOR); + } + + private getTeamMembersByUserGroup(userGroupCode: string): FutureData { return apiToFuture( this.api.metadata.get({ users: { fields: d2UserFields, - filter: { "userGroups.id": { in: [RTSL_ZEBRA_INCIDENTMANAGER] } }, + filter: { "userGroups.code": { in: [userGroupCode] } }, }, }) ) diff --git a/src/data/repositories/consts/RiskAssessmentConstants.ts b/src/data/repositories/consts/RiskAssessmentConstants.ts index b4d4f919..ca8b316c 100644 --- a/src/data/repositories/consts/RiskAssessmentConstants.ts +++ b/src/data/repositories/consts/RiskAssessmentConstants.ts @@ -4,7 +4,10 @@ import { RiskAssessmentGrading, RiskAssessmentGradingAttrs, } from "../../../domain/entities/risk-assessment/RiskAssessmentGrading"; -import { RiskAssessmentQuestionnaire } from "../../../domain/entities/risk-assessment/RiskAssessmentQuestionnaire"; +import { + RiskAssessmentQuestion, + RiskAssessmentQuestionnaire, +} from "../../../domain/entities/risk-assessment/RiskAssessmentQuestionnaire"; import { RiskAssessmentSummary } from "../../../domain/entities/risk-assessment/RiskAssessmentSummary"; import { GetValue } from "../../../utils/ts-utils"; @@ -68,7 +71,7 @@ export const riskAssessmentSummaryCodes = { } as const; export type RiskAssessmentSummaryCodes = GetValue; -export const riskAssessmentQuestionnaireCodes = { +export const riskAssessmentStdQuestionnaireCodes = { question: "RTSL_ZEB_DET_QUESTION", likelihood1: "RTSL_ZEB_DET_LIKELIHOOD", consequences1: "RTSL_ZEB_DET_CONSEQUENCES", @@ -87,7 +90,22 @@ export const riskAssessmentQuestionnaireCodes = { riskId3: "RTSL_ZEB_DET_RISK_ID_RAQ3", } as const; -export type RiskAssessmentQuestionnaireCodes = GetValue; +export type RiskAssessmentStdQuestionnaireCodes = GetValue< + typeof riskAssessmentStdQuestionnaireCodes +>; + +export const riskAssessmentCustomQuestionnaireCodes = { + question: "RTSL_ZEB_DET_QUESTION", + likelihood4: "RTSL_ZEB_DET_LIKELIHOOD4", + consequences4: "RTSL_ZEB_DET_CONSEQUENCES4", + risk4: "RTSL_ZEB_DET_RISK4", + rational4: "RTSL_ZEB_DET_RATIONALE4", + riskId: "RTSL_ZEB_DET_RISK_ID_RAQ4", +} as const; + +export type RiskAssessmentCustomQuestionnaireCodes = GetValue< + typeof riskAssessmentCustomQuestionnaireCodes +>; export function isStringInRiskAssessmentGradingOptionCodes( code: string @@ -174,9 +192,9 @@ export function isStringInRiskAssessmentSummaryCodes( return (Object.values(riskAssessmentSummaryCodes) as string[]).includes(code); } -export function getValueFromRiskAssessmentQuestionnaire( +export function getValueFromRiskAssessmentStdQuestionnaire( riskAssessmentQuestionnaire: RiskAssessmentQuestionnaire -): Record { +): Record { return { RTSL_ZEB_DET_LIKELIHOOD: riskAssessmentQuestionnaire.potentialRiskForHumanHealth.likelihood.id, @@ -201,11 +219,33 @@ export function getValueFromRiskAssessmentQuestionnaire( RTSL_ZEB_DET_RISK_ID_RAQ3: "", }; } -export type RiskAssessmentQuestionnaireKeyCode = - (typeof riskAssessmentQuestionnaireCodes)[keyof typeof riskAssessmentQuestionnaireCodes]; +export type RiskAssessmentStdQuestionnaireKeyCode = + (typeof riskAssessmentStdQuestionnaireCodes)[keyof typeof riskAssessmentStdQuestionnaireCodes]; + +export function isStringInRiskAssessmentStdQuestionnaireCodes( + code: string +): code is RiskAssessmentStdQuestionnaireKeyCode { + return (Object.values(riskAssessmentStdQuestionnaireCodes) as string[]).includes(code); +} + +export function getValueFromRiskAssessmentCustomQuestionnaire( + riskAssessmentCustomQuestion: RiskAssessmentQuestion +): Record { + return { + RTSL_ZEB_DET_QUESTION: riskAssessmentCustomQuestion.question ?? "", + RTSL_ZEB_DET_LIKELIHOOD4: riskAssessmentCustomQuestion.likelihood.id, + RTSL_ZEB_DET_CONSEQUENCES4: riskAssessmentCustomQuestion.consequences.id, + RTSL_ZEB_DET_RISK4: riskAssessmentCustomQuestion.risk.id, + RTSL_ZEB_DET_RATIONALE4: riskAssessmentCustomQuestion.rational, + RTSL_ZEB_DET_RISK_ID_RAQ4: "", + }; +} + +export type RiskAssessmentCustomQuestionnaireKeyCode = + (typeof riskAssessmentCustomQuestionnaireCodes)[keyof typeof riskAssessmentCustomQuestionnaireCodes]; -export function isStringInRiskAssessmentQuestionnaireCodes( +export function isStringInRiskAssessmentCustomQuestionnaireCodes( code: string -): code is RiskAssessmentQuestionnaireKeyCode { - return (Object.values(riskAssessmentQuestionnaireCodes) as string[]).includes(code); +): code is RiskAssessmentCustomQuestionnaireKeyCode { + return (Object.values(riskAssessmentCustomQuestionnaireCodes) as string[]).includes(code); } diff --git a/src/data/repositories/test/TeamMemberTestRepository.ts b/src/data/repositories/test/TeamMemberTestRepository.ts index cfd50ce1..91c4d178 100644 --- a/src/data/repositories/test/TeamMemberTestRepository.ts +++ b/src/data/repositories/test/TeamMemberTestRepository.ts @@ -19,6 +19,21 @@ export class TeamMemberTestRepository implements TeamMemberRepository { return Future.success([teamMember]); } + getRiskAssessors(): FutureData { + const teamMember: TeamMember = new TeamMember({ + id: "riskAssessor", + username: "riskAssessor", + name: `Team Member Name test`, + email: `email@email.com`, + phone: `121-1234`, + role: { id: "1", name: "role" }, + status: "Available", + photo: new URL("https://www.example.com"), + }); + + return Future.success([teamMember]); + } + getAll(): FutureData { const teamMember: TeamMember = new TeamMember({ id: "test", diff --git a/src/data/repositories/utils/DateTimeHelper.ts b/src/data/repositories/utils/DateTimeHelper.ts index a6aff3b4..552f297b 100644 --- a/src/data/repositories/utils/DateTimeHelper.ts +++ b/src/data/repositories/utils/DateTimeHelper.ts @@ -34,3 +34,12 @@ export function getDateAsLocaleDateTimeString(date: Date): string { return ""; } } + +export function getDateAsLocaleDateString(date: Date): string { + try { + return `${date.toLocaleDateString()}`; + } catch (e) { + console.debug(e); + return ""; + } +} diff --git a/src/data/repositories/utils/RiskAssessmentMapper.ts b/src/data/repositories/utils/RiskAssessmentMapper.ts index 9d0650cf..ae433941 100644 --- a/src/data/repositories/utils/RiskAssessmentMapper.ts +++ b/src/data/repositories/utils/RiskAssessmentMapper.ts @@ -2,21 +2,29 @@ import { SelectedPick } from "@eyeseetea/d2-api/api"; import { RiskAssessmentGrading } from "../../../domain/entities/risk-assessment/RiskAssessmentGrading"; import { D2DataElementSchema } from "@eyeseetea/d2-api/2.36"; import { D2TrackerEvent, DataValue } from "@eyeseetea/d2-api/api/trackerEvents"; -import { RTSL_ZEBRA_ORG_UNIT_ID, RTSL_ZEBRA_PROGRAM_ID } from "../consts/DiseaseOutbreakConstants"; +import { + RTSL_ZEBRA_ORG_UNIT_ID, + RTSL_ZEBRA_PROGRAM_ID, + RTSL_ZEBRA_RISK_ASSESSMENT_QUESTIONNAIRE_PROGRAM_STAGE_ID, +} from "../consts/DiseaseOutbreakConstants"; import { Code, Id } from "../../../domain/entities/Ref"; import { getValueFromRiskAssessmentGrading, - getValueFromRiskAssessmentQuestionnaire, + getValueFromRiskAssessmentStdQuestionnaire, getValueFromRiskAssessmentSummary, isStringInRiskAssessmentGradingCodes, - isStringInRiskAssessmentQuestionnaireCodes, + isStringInRiskAssessmentStdQuestionnaireCodes, isStringInRiskAssessmentSummaryCodes, RiskAssessmentGradingCodes, RiskAssessmentGradingKeyCode, - RiskAssessmentQuestionnaireCodes, - RiskAssessmentQuestionnaireKeyCode, + RiskAssessmentStdQuestionnaireCodes, + RiskAssessmentStdQuestionnaireKeyCode, RiskAssessmentSummaryCodes, RiskAssessmentSummaryKeyCode, + getValueFromRiskAssessmentCustomQuestionnaire, + RiskAssessmentCustomQuestionnaireCodes, + isStringInRiskAssessmentCustomQuestionnaireCodes, + RiskAssessmentCustomQuestionnaireKeyCode, } from "../consts/RiskAssessmentConstants"; import { riskAssessmentCustomQuestionnaireIds, @@ -56,26 +64,30 @@ export function mapRiskAssessmentToDataElements( teiId: Id, enrollmentId: Id, programStageDataElementsMetadata: D2ProgramStageDataElementsMetadata[] -): D2TrackerEvent { +): D2TrackerEvent[] { if (!formData.entity) throw new Error("No form data found"); switch (formData.type) { case "risk-assessment-grading": - return mapRiskAssessmentGradingToDataElements( - programStageId, - teiId, - enrollmentId, - formData.entity, - programStageDataElementsMetadata - ); + return [ + mapRiskAssessmentGradingToDataElements( + programStageId, + teiId, + enrollmentId, + formData.entity, + programStageDataElementsMetadata + ), + ]; case "risk-assessment-summary": if (!formData.entity) throw new Error("No form data found"); - return mapRiskAssessmentSummaryToDataElements( - programStageId, - teiId, - enrollmentId, - formData.entity, - programStageDataElementsMetadata - ); + return [ + mapRiskAssessmentSummaryToDataElements( + programStageId, + teiId, + enrollmentId, + formData.entity, + programStageDataElementsMetadata + ), + ]; case "risk-assessment-questionnaire": return mapRiskAssessmentQuestionnaireToDataElements( programStageId, @@ -149,26 +161,63 @@ function mapRiskAssessmentQuestionnaireToDataElements( enrollmentId: Id, riskAssessmentQuestionnaire: RiskAssessmentQuestionnaire, programStageDataElementsMetadata: D2ProgramStageDataElementsMetadata[] -): D2TrackerEvent { - const dataElementValues: Record = - getValueFromRiskAssessmentQuestionnaire(riskAssessmentQuestionnaire); +): D2TrackerEvent[] { + if (programStageId === RTSL_ZEBRA_RISK_ASSESSMENT_QUESTIONNAIRE_PROGRAM_STAGE_ID) { + const dataElementValues: Record = + getValueFromRiskAssessmentStdQuestionnaire(riskAssessmentQuestionnaire); - const dataValues: DataValue[] = programStageDataElementsMetadata.map(programStage => { - if (!isStringInRiskAssessmentQuestionnaireCodes(programStage.dataElement.code)) { - throw new Error( - `DataElement code ${programStage.dataElement.code} not found in Risk Assessment Questionnaire Codes` + const dataValues: DataValue[] = programStageDataElementsMetadata.map(programStage => { + if (!isStringInRiskAssessmentStdQuestionnaireCodes(programStage.dataElement.code)) { + throw new Error( + `DataElement code ${programStage.dataElement.code} not found in Risk Assessment Questionnaire Codes` + ); + } + const typedCode: RiskAssessmentStdQuestionnaireKeyCode = programStage.dataElement.code; + return getPopulatedDataElement( + programStage.dataElement.id, + dataElementValues[typedCode] ); - } - const typedCode: RiskAssessmentQuestionnaireKeyCode = programStage.dataElement.code; - return getPopulatedDataElement(programStage.dataElement.id, dataElementValues[typedCode]); - }); - return getRiskAssessmentTrackerEvent( - programStageId, - riskAssessmentQuestionnaire.id, - enrollmentId, - dataValues, - teiId - ); + }); + return [ + getRiskAssessmentTrackerEvent( + programStageId, + riskAssessmentQuestionnaire.id, + enrollmentId, + dataValues, + teiId + ), + ]; + } else { + const customEvents = riskAssessmentQuestionnaire.additionalQuestions.map(customQuestion => { + const dataElementValues: Record = + getValueFromRiskAssessmentCustomQuestionnaire(customQuestion); + + const dataValues: DataValue[] = programStageDataElementsMetadata.map(programStage => { + if ( + !isStringInRiskAssessmentCustomQuestionnaireCodes(programStage.dataElement.code) + ) { + throw new Error( + `DataElement code ${programStage.dataElement.code} not found in Custom Risk Assessment Questionnaire Codes` + ); + } + const typedCode: RiskAssessmentCustomQuestionnaireKeyCode = + programStage.dataElement.code; + return getPopulatedDataElement( + programStage.dataElement.id, + dataElementValues[typedCode] + ); + }); + return getRiskAssessmentTrackerEvent( + programStageId, + customQuestion.id, + enrollmentId, + dataValues, + teiId + ); + }); + + return customEvents; + } } function getPopulatedDataElement(dataElement: Id, value: Maybe): DataValue { diff --git a/src/domain/entities/risk-assessment/RiskAssessmentQuestionnaire.ts b/src/domain/entities/risk-assessment/RiskAssessmentQuestionnaire.ts index bbb80495..aa91f862 100644 --- a/src/domain/entities/risk-assessment/RiskAssessmentQuestionnaire.ts +++ b/src/domain/entities/risk-assessment/RiskAssessmentQuestionnaire.ts @@ -2,6 +2,7 @@ import { Id, NamedRef } from "../Ref"; import { Struct } from "../generic/Struct"; export type RiskAssessmentQuestion = { + id?: Id; question?: string; likelihood: NamedRef; consequences: NamedRef; diff --git a/src/domain/repositories/TeamMemberRepository.ts b/src/domain/repositories/TeamMemberRepository.ts index f84191a3..1ff60092 100644 --- a/src/domain/repositories/TeamMemberRepository.ts +++ b/src/domain/repositories/TeamMemberRepository.ts @@ -6,4 +6,5 @@ export interface TeamMemberRepository { getAll(): FutureData; get(id: Id): FutureData; getIncidentManagers(): FutureData; + getRiskAssessors(): FutureData; } diff --git a/src/domain/usecases/utils/risk-assessment/GetRiskAssessmentById.ts b/src/domain/usecases/utils/risk-assessment/GetRiskAssessmentById.ts index f0316a6a..265af61e 100644 --- a/src/domain/usecases/utils/risk-assessment/GetRiskAssessmentById.ts +++ b/src/domain/usecases/utils/risk-assessment/GetRiskAssessmentById.ts @@ -162,6 +162,7 @@ export function getAll( risk, }).flatMap(customQuestionResponse => { const customQuestion: RiskAssessmentQuestion = { + id: customQuestionDataValues.id, question: customQuestionDataValues.question, likelihood: customQuestionResponse.likelihood, diff --git a/src/domain/usecases/utils/risk-assessment/GetRiskAssessmentWithOptions.ts b/src/domain/usecases/utils/risk-assessment/GetRiskAssessmentWithOptions.ts index a49add56..710a4418 100644 --- a/src/domain/usecases/utils/risk-assessment/GetRiskAssessmentWithOptions.ts +++ b/src/domain/usecases/utils/risk-assessment/GetRiskAssessmentWithOptions.ts @@ -97,7 +97,7 @@ export function getRiskAssessmentSummaryWithOptions( return Future.joinObj( { lowMediumHighOptions: optionsRepository.getLowMediumHighOptions(), - riskAssessors: teamMemberRepository.getAll(), + riskAssessors: teamMemberRepository.getRiskAssessors(), }, { concurrency: 2 } ).flatMap(({ lowMediumHighOptions, riskAssessors }) => { diff --git a/src/webapp/pages/event-tracker/EventTrackerPage.tsx b/src/webapp/pages/event-tracker/EventTrackerPage.tsx index 5735fcfd..1cf3565f 100644 --- a/src/webapp/pages/event-tracker/EventTrackerPage.tsx +++ b/src/webapp/pages/event-tracker/EventTrackerPage.tsx @@ -25,6 +25,7 @@ export type VisualizationTypes = //TO DO : Create Risk assessment section export const riskAssessmentColumns: TableColumn[] = [ + { value: "riskAssessmentDate", label: "Assessment Date", type: "text" }, { value: "grade", label: "Grade", type: "text" }, { value: "populationRisk", label: "Population at risk", type: "text" }, { value: "attackRate", label: "Attack rate", type: "text" }, diff --git a/src/webapp/pages/event-tracker/useDiseaseOutbreakEvent.ts b/src/webapp/pages/event-tracker/useDiseaseOutbreakEvent.ts index df3e67a3..ece74f20 100644 --- a/src/webapp/pages/event-tracker/useDiseaseOutbreakEvent.ts +++ b/src/webapp/pages/event-tracker/useDiseaseOutbreakEvent.ts @@ -7,6 +7,7 @@ import { DiseaseOutbreakEvent, } from "../../../domain/entities/disease-outbreak-event/DiseaseOutbreakEvent"; import { + getDateAsLocaleDateString, getDateAsLocaleDateTimeString, getDateAsMonthYearString, } from "../../../data/repositories/utils/DateTimeHelper"; @@ -102,6 +103,7 @@ export function useDiseaseOutbreakEvent(id: Id) { ) => { if (diseaseOutbreakEvent.riskAssessment) { return diseaseOutbreakEvent.riskAssessment.grading.map(riskAssessmentGrading => ({ + riskAssessmentDate: getDateAsLocaleDateString(riskAssessmentGrading.lastUpdated), grade: RiskAssessmentGrading.getTranslatedLabel( riskAssessmentGrading.getGrade().getOrThrow() ), diff --git a/src/webapp/pages/form-page/mapFormStateToEntityData.ts b/src/webapp/pages/form-page/mapFormStateToEntityData.ts index 9fa50f58..546fecbe 100644 --- a/src/webapp/pages/form-page/mapFormStateToEntityData.ts +++ b/src/webapp/pages/form-page/mapFormStateToEntityData.ts @@ -26,7 +26,6 @@ import { Maybe } from "../../../utils/ts-utils"; import { RiskAssessmentGrading } from "../../../domain/entities/risk-assessment/RiskAssessmentGrading"; import { riskAssessmentGradingCodes, - riskAssessmentQuestionnaireCodes, riskAssessmentSummaryCodes, } from "../../../data/repositories/consts/RiskAssessmentConstants"; import { RiskAssessmentSummary } from "../../../domain/entities/risk-assessment/RiskAssessmentSummary"; @@ -409,7 +408,7 @@ function mapFormStateToRiskAssessmentQuestionnaire( const additionalQuestions = formState.sections .filter(section => section.id.startsWith("additionalQuestions")) - .map((_customSection, index): RiskAssessmentQuestion => { + .map((customSection, index): RiskAssessmentQuestion => { const { likelihoodOption, consequencesOption, riskOption } = getRiskAssessmentQuestionsWithOption( "custom", @@ -418,10 +417,13 @@ function mapFormStateToRiskAssessmentQuestionnaire( index.toString() ); return { + id: customSection.id.replace("additionalQuestions", ""), + question: allFields.find(field => field.id.includes(`custom-question${index}`)) + ?.value as string, likelihood: likelihoodOption, consequences: consequencesOption, risk: riskOption, - rational: allFields.find(field => field.id.includes(`rational-custom${index}`)) + rational: allFields.find(field => field.id.includes(`custom-rational${index}`)) ?.value as string, }; }); diff --git a/src/webapp/pages/form-page/risk-assessment/mapRiskAssessmentToInitialFormState.ts b/src/webapp/pages/form-page/risk-assessment/mapRiskAssessmentToInitialFormState.ts index 2b62a241..8b01b708 100644 --- a/src/webapp/pages/form-page/risk-assessment/mapRiskAssessmentToInitialFormState.ts +++ b/src/webapp/pages/form-page/risk-assessment/mapRiskAssessmentToInitialFormState.ts @@ -1,7 +1,6 @@ import i18n from "@eyeseetea/d2-ui-components/locales"; import { riskAssessmentGradingCodes, - riskAssessmentQuestionnaireCodes, riskAssessmentSummaryCodes, } from "../../../../data/repositories/consts/RiskAssessmentConstants"; import { @@ -17,6 +16,7 @@ import { getDateAsLocaleDateTimeString } from "../../../../data/repositories/uti import { FormSectionState } from "../../../components/form/FormSectionsState"; import { RiskAssessmentQuestionnaire } from "../../../../domain/entities/risk-assessment/RiskAssessmentQuestionnaire"; import { Maybe } from "../../../../utils/ts-utils"; +import { Id } from "../../../../domain/entities/Ref"; // TODO: Thinking for the future about generate this FormState by iterating over Object.Keys(diseaseOutbreakEvent) export function mapRiskGradingToInitialFormState( @@ -617,7 +617,12 @@ export function mapRiskAssessmentQuestionnaireToInitialFormState( const customQuestionSections = riskAssessmentQuestionnaire?.additionalQuestions?.map((question, index) => { - return getRiskAssessmentCustomQuestionSection("Custom Question", index, sectionOptions); + return getRiskAssessmentCustomQuestionSection( + "Custom Question", + index, + sectionOptions, + question.id + ); }) ?? []; const addNewOptionSection: FormSectionState = getAnotherOptionSection(); @@ -750,18 +755,19 @@ function getRiskAssessmentCustomQuestionSection( likelihoodOptions: UIOption[]; consequencesOptions: UIOption[]; riskOptions: UIOption[]; - } + }, + questionId?: Id ): FormSectionState { const id = "additionalQuestions"; const { riskAssessmentQuestionnaire, likelihoodOptions, consequencesOptions, riskOptions } = options; const riskAssesssmentQuestionFormSection: FormSectionState = { title: title, - id: `${id}${index}`, + id: questionId ? `${id}${questionId}` : `${id}`, isVisible: true, fields: [ { - id: `question-custom${index}`, + id: `custom-question${index}`, label: "Question", isVisible: true, errors: [],