import type { QuestionnaireResponse } from 'fhir/r4'; import { changedAnswers } from '../../utils/changedAnswers'; interface QuestionnaireAnswersProps { response: QuestionnaireResponse | undefined; /** The deck's own words for SENT answers. Overridable so a staff surface can say whose answers these are. */ heading?: string; /** The previous sent version, when these answers were amended. */ previous?: QuestionnaireResponse; /** When the amendment was made, for the "changed " half of the line. */ changedOn?: string; /** When the previous version was sent, for a reader who needs both dates. */ previousOn?: string; } /** * - WHAT YOU SENT, drawn as a record rather than as a form you cannot use. * * WHY NOT AN INERT FORM, which is what this replaced. Wrapping the live questionnaire in `Disabled` put * the right content in the wrong clothes, and it was wrong twice: * * a disabled form reads as a form you FAILED TO ACTIVATE, not as something finished; * disabled controls are skipped or unlabelled by screen readers and their greyed text fails * contrast - so the one thing a patient has a legal right to read becomes the least readable * thing on the screen. * * The second is the one that decides it. A patient's own answers are theirs to re-read, and a rendering * that a screen reader walks past is not a reading. * * WHY NOT `renderField`, which is this codebase's other label-and-value idiom. That row is horizontal - * label left, value right - and is built for short values inside a bordered group. A questionnaire * question is a sentence ("Anything else we should know before your visit?") and its answer can be a * paragraph; side by side, both wrap into two narrow columns. The label sits ABOVE the value here for * that reason and no other. * * NO BORDER, NO ROUNDING, NO SURFACE - and this is the trap rather than a preference. The form question * in this same modal is a bordered rounded box. If a read row is given a box it becomes, to the eye, * exactly the control it must not be mistaken for, whatever the markup says. A hairline under each row * is the whole separation. */ export const QuestionnaireAnswers = ({ response, heading = 'What you sent', previous, changedOn, previousOn, }: QuestionnaireAnswersProps) => { const answers = changedAnswers(response, previous); // A draft that was never sent, such as one left on a voided task, is not "what you sent". const sent = response?.status === 'completed' || response?.status === 'amended'; // Nothing was answered. Silence is right: the surfaces that mount this already say what the task is // and what state it is in, and an empty "What you sent" heading would assert that the patient sent // nothing when the likelier truth is that this response is not the one being read. if (!answers.length) return null; return (

{sent ? heading : 'Saved, not sent'}

{answers.map(({ linkId, question, answer, was, changed }) => (
{question} {answer ?? 'No answer'} {/* Shown only on changed answers, including added and removed ones. */} {changed && ( Was: {was ?? 'no answer'} {previousOn ? ` (sent ${previousOn})` : ''} {changedOn ? ` ยท changed ${changedOn}` : ''} )}
))}
); }; export default QuestionnaireAnswers;