diff --git a/src/locales/en.json b/src/locales/en.json index 9ce8623f..51eb4e63 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -304,6 +304,8 @@ "reports.preview.area": "Area: {name}", "reports.preview.submittedBy": "Submitted By: {name}", "reports.preview.view": "View Report", + "reports.preview.question.id": "Question {index}:", + "reports.preview.childQuestion.id": "Question {index} More Info:", "reporting.back": "Back to Monitoring", "reporting.tabs.investigation": "Investigation", "reporting.tabs.reports": "Reports", diff --git a/src/pages/reports/report/Report.tsx b/src/pages/reports/report/Report.tsx index 331bacca..2cb5a194 100644 --- a/src/pages/reports/report/Report.tsx +++ b/src/pages/reports/report/Report.tsx @@ -84,7 +84,11 @@ const Report = () => { /> - + ); }; diff --git a/src/pages/reports/report/components/ReportResponse.tsx b/src/pages/reports/report/components/ReportResponse.tsx index 704ee4df..bab94396 100644 --- a/src/pages/reports/report/components/ReportResponse.tsx +++ b/src/pages/reports/report/components/ReportResponse.tsx @@ -10,7 +10,7 @@ import { useIntl } from "react-intl"; export interface IReportResponse { question: string; - response: string; + response: string | null; type: string; } @@ -50,13 +50,13 @@ const Response = (props: ReportResponseProps) => { title="audio.play" onClose={() => setAudioModalOpen(false)} actions={[ - { name: "common.download", onClick: () => download(response) }, + { name: "common.download", onClick: () => download(response || "") }, { name: "common.close", variant: "secondary", onClick: () => setAudioModalOpen(false) } ]} >
{/* eslint-disable-next-line jsx-a11y/media-has-caption */} -
diff --git a/src/pages/reports/report/components/ReportResponses.tsx b/src/pages/reports/report/components/ReportResponses.tsx index f95bd708..2df1e823 100644 --- a/src/pages/reports/report/components/ReportResponses.tsx +++ b/src/pages/reports/report/components/ReportResponses.tsx @@ -2,42 +2,99 @@ import List from "components/extensive/List"; import OptionalWrapper from "components/extensive/OptionalWrapper"; import Button from "components/ui/Button/Button"; import { AnswerResponse, ReportsQuestion } from "generated/forms/formsSchemas"; +import { useAppSelector } from "hooks/useRedux"; import { useMemo, useState } from "react"; -import { FormattedMessage } from "react-intl"; +import { FormattedMessage, useIntl } from "react-intl"; import ReportExportImagesModal from "./modal/ReportExportImagesModal"; import ReportResponse, { ReportResponseProps } from "./ReportResponse"; type ReportResponsesProps = { + defaultLanguage: string; questions: ReportsQuestion[]; responses: AnswerResponse[]; }; -const ReportResponses = ({ questions, responses }: ReportResponsesProps) => { +const ReportResponses = ({ defaultLanguage, questions, responses }: ReportResponsesProps) => { const [showImagesModal, setShowImagesModal] = useState(false); + const { locale } = useAppSelector(state => state.app); + const intl = useIntl(); const data = useMemo(() => { - return questions - .map(q => { - const response = responses.find(r => r.name === q.name); - if (!response) return undefined; - const formattedQuestion = q.name - .split("-") - .map(s => s[0].toUpperCase() + s.slice(1)) - .join(",") - .replace(",", " "); + return questions?.reduce( + (combinedResponses, currentQuestionDetails, currentQuestionIndex) => { + const copyCombinedResponses = [...combinedResponses]; - return { - // @ts-expect-error - question: `${formattedQuestion}: ${q.label.en}`, - response: response.value ?? null, - childQuestions: responses.filter(response => - q.childQuestions?.find(question => question.name === response.name) - ), - type: q.type + const response = responses.find(r => r.name === currentQuestionDetails.name); + if (!response) return copyCombinedResponses; + + const generateCombineResponse = ({ + label, + type, + value, + childQuestion = false + }: { + label: string; + type: string; + value?: string; + childQuestion?: boolean; + }) => { + const formattedQuestion = intl.formatMessage( + { id: childQuestion ? "reports.preview.childQuestion.id" : "reports.preview.question.id" }, + { index: currentQuestionIndex + 1 } + ); + + return { + question: `${formattedQuestion} ${label}`, + response: value ?? null, + type, + childQuestions: [] as AnswerResponse[] + }; }; - }) - .filter(x => x) as ReportResponseProps[]; - }, [questions, responses]); + + const combineResponse = generateCombineResponse({ + // @ts-ignore + label: currentQuestionDetails.label[locale] ?? currentQuestionDetails.label[defaultLanguage], + type: currentQuestionDetails.type, + value: response.value + }); + + // When the question type is "audio" + // Each child question contains the audio file information + // Add this to the combineResponse object for later + // @see src/pages/reports/report/components/ReportResponse.tsx + if (currentQuestionDetails.type === "audio") { + combineResponse.childQuestions = responses.filter(response => + currentQuestionDetails.childQuestions?.find(question => question.name === response.name) + ); + } + + copyCombinedResponses.push(combineResponse); + + // When the question type isn't "audio" + // Each child question is considered a separate response + // Generate a Combined Response for each child + if (currentQuestionDetails.type !== "audio" && currentQuestionDetails.childQuestions?.length) { + for (let i = 0; i < currentQuestionDetails.childQuestions.length; i++) { + const childQuestionDetails = currentQuestionDetails.childQuestions[i]; + const childQuestionResponse = responses.find(r => r.name === childQuestionDetails.name); + + copyCombinedResponses.push( + generateCombineResponse({ + // @ts-ignore + label: childQuestionDetails.label[locale] ?? childQuestionDetails.label[defaultLanguage], + type: childQuestionDetails.type, + value: childQuestionResponse?.value, + childQuestion: true + }) + ); + } + } + + return copyCombinedResponses; + }, + [] + ); + }, [questions, responses, locale, defaultLanguage, intl]); const hasImages = useMemo(() => { const found = data.find(item => item.type === "blob");