/*
* 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 { useMemo } from 'react';
import type {
PropsWithParentIsReadOnlyAttribute,
PropsWithParentIsRepeatGroupAttribute,
PropsWithParentStylesAttribute
} from '../../../interfaces/renderProps.interface';
import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
import { QGroupContainerBox } from '../../Box.styles';
import Card from '@mui/material/Card';
import Collapse from '@mui/material/Collapse';
import Divider from '@mui/material/Divider';
import { TransitionGroup } from 'react-transition-group';
import { createEmptyQrItem } from '../../../utils/qrItem';
import RepeatGroupItem from './RepeatGroupItem';
import AddItemButton from './AddItemButton';
import type { RepeatGroupSingleModel } from '../../../interfaces/repeatGroup.interface';
import useReadOnly from '../../../hooks/useReadOnly';
import { getGroupCollapsible } from '../../../utils/qItem';
import AccordionSummary from '@mui/material/AccordionSummary';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import AccordionDetails from '@mui/material/AccordionDetails';
import GroupHeading from '../GroupItem/GroupHeading';
import { itemHasLabelHeadingContent } from '../../../utils/itemTextToDisplay';
import { isGroupAddItemButtonHidden } from '../../../utils/extensions';
import GroupAccordion from '../GroupItem/GroupAccordion';
import { getQrRepeatGroupInstanceIndexes } from '../../../utils/repeatGroup';
interface RepeatGroupViewProps
extends PropsWithParentIsReadOnlyAttribute,
PropsWithParentIsRepeatGroupAttribute,
PropsWithParentStylesAttribute {
qItem: QuestionnaireItem;
repeatGroups: RepeatGroupSingleModel[];
groupCardElevation: number;
onAnswerChange: (newQrItem: QuestionnaireResponseItem, index: number) => void;
onAddItem: () => void;
onRemoveItem: (index: number) => void;
}
/**
* Main component to render a repeating, group Questionnaire item.
* Store and manages the state of multiple instances of GroupItem in a repeating group.
*
* @author Sean Fong
*/
function RepeatGroupView(props: RepeatGroupViewProps) {
const {
qItem,
repeatGroups,
groupCardElevation,
parentIsReadOnly,
parentStyles,
onAnswerChange,
onAddItem,
onRemoveItem
} = props;
const readOnly = useReadOnly(qItem, parentIsReadOnly);
const showGroupHeading = itemHasLabelHeadingContent(qItem);
// Each instance's index within the QuestionnaireResponse, computed once for the whole list rather
// than re-derived per instance, so rendering n instances stays linear.
const qrInstanceIndexes = useMemo(
() => getQrRepeatGroupInstanceIndexes(repeatGroups),
[repeatGroups]
);
const groupCollapsibleValue = getGroupCollapsible(qItem);
if (groupCollapsibleValue) {
const isDefaultOpen = groupCollapsibleValue === 'default-open';
return (
} sx={{ minHeight: '28px' }}>
{showGroupHeading ? (
) : null}
{showGroupHeading ? : null}
{repeatGroups.map(({ id, qrItem: nullableQrItem }, index) => {
const answeredQrItem = createEmptyQrItem(qItem, undefined);
if (nullableQrItem) {
answeredQrItem.item = nullableQrItem.item;
}
return (
onRemoveItem(index)}
onQrItemChange={(newQrItem) => onAnswerChange(newQrItem, index)}
/>
);
})}
{!isGroupAddItemButtonHidden(qItem) && (
)}
);
}
return (
{showGroupHeading ? (
<>
>
) : null}
{repeatGroups.map(({ id, qrItem: nullableQrItem }, index) => {
const answeredQrItem = createEmptyQrItem(qItem, undefined);
if (nullableQrItem) {
answeredQrItem.item = nullableQrItem.item;
}
return (
onRemoveItem(index)}
onQrItemChange={(newQrItem) => onAnswerChange(newQrItem, index)}
/>
{index < repeatGroups.length - 1 ? (
) : null}
);
})}
{!isGroupAddItemButtonHidden(qItem) && (
)}
);
}
export default RepeatGroupView;