/* * Copyright 2025 Commonwealth Scientific and Industrial Research * Organisation (CSIRO) ABN 41 687 119 230. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import React from 'react'; import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4'; import FormBodyTabbed from './FormBodyTabbed'; import { containsTabs, isTabContainer } from '../../utils/tabs'; import GroupItem from '../FormComponents/GroupItem/GroupItem'; import SingleItem from '../FormComponents/SingleItem/SingleItem'; import type { PropsWithParentIsReadOnlyAttribute, PropsWithQrItemChangeHandler, PropsWithQrRepeatGroupChangeHandler } from '../../interfaces/renderProps.interface'; import FormBodyCollapsible from './FormBodyCollapsible'; import useResponsive from '../../hooks/useResponsive'; import useHidden from '../../hooks/useHidden'; import GroupItemSwitcher from '../FormComponents/GroupItem/GroupItemSwitcher'; import useReadOnly from '../../hooks/useReadOnly'; import Box from '@mui/material/Box'; import { isRepeatItemAndNotCheckbox, isSpecificItemControl } from '../../utils'; import GroupTable from '../FormComponents/Tables/GroupTable'; import RepeatItem from '../FormComponents/RepeatItem/RepeatItem'; import GridGroup from '../FormComponents/GridGroup/GridGroup'; import { useRendererConfigStore } from '../../stores'; import { isPage } from '../../utils/page'; import FormBodyPageContainer from './FormBodyPageContainer'; interface FormTopLevelItemProps extends PropsWithQrItemChangeHandler, PropsWithQrRepeatGroupChangeHandler, PropsWithParentIsReadOnlyAttribute { topLevelQItem: QuestionnaireItem; topLevelQRItemOrItems: QuestionnaireResponseItem | QuestionnaireResponseItem[] | null; wholeFormIsPaginated: boolean; } function FormTopLevelItem(props: FormTopLevelItemProps) { const { topLevelQItem, topLevelQRItemOrItems, parentIsReadOnly, wholeFormIsPaginated, onQrItemChange, onQrRepeatGroupChange } = props; const itemIsTabContainer = isTabContainer(topLevelQItem); const itemContainsTabs = containsTabs(topLevelQItem); // itemIsPageContainer is there for backwards compatibility only - see https://github.com/aehrc/smart-forms/issues/1041 // The proper way to do it ATM is to make every single top-level item a page // Unfortunately, "header" and "footer" itemControl is not supported. const itemIsPageContainer = isPage(topLevelQItem); const showTabbedFormAt = useRendererConfigStore.use.showTabbedFormAt(); const isTabbedForm = useResponsive(showTabbedFormAt); const itemIsGroup = topLevelQItem.type === 'group'; const readOnly = useReadOnly(topLevelQItem, parentIsReadOnly); const itemIsHidden = useHidden(topLevelQItem); if (itemIsHidden) { return null; } // If item has multiple answers, use a group item switcher to determine how to render it. const hasMultipleAnswers = Array.isArray(topLevelQRItemOrItems); if (hasMultipleAnswers) { return ( ); } // At this point, item only has one answer const topLevelQRItem = topLevelQRItemOrItems; // If form is tabbed, it is rendered as a tabbed form if (itemContainsTabs || itemIsTabContainer) { if (isTabbedForm) { return ( ); } return ( ); } /* Using "page" item as a page-container - only preserved for backwards compatibility (not complaint with https://hl7.org/fhir/extensions/CodeSystem-questionnaire-item-control.html#questionnaire-item-control-page) * - The first "page" item in the questionnaire will be considered as a page-container, and all its children will be considered as pages * - All other pages will be ignored by the renderer * - You can have non-page items in the same level as the page-container to be used as faux headers or footers * - Ensure that only group items are in the page-container * Note: This will only be used if wholeFormIsPaginated=false */ if (!wholeFormIsPaginated && itemIsPageContainer) { return ( ); } // If form is untabbed, it is rendered as a regular group if (itemIsGroup) { // Item is 'grid' const itemIsGrid = isSpecificItemControl(topLevelQItem, 'grid'); if (itemIsGrid) { return ( ); } // GroupTable "gtable" can be rendered with either repeats:true or false if (isSpecificItemControl(topLevelQItem, 'gtable')) { return ( ); } return ( ); } // Otherwise, it is rendered as a non-group item const itemRepeatsAndIsNotCheckbox = isRepeatItemAndNotCheckbox(topLevelQItem); if (itemRepeatsAndIsNotCheckbox) { return ( ); } return ( ); } export default FormTopLevelItem;