Skip to content

Commit a360ece

Browse files
Refactor question type cleaning to remove irrelevant properties
1 parent 86b3dca commit a360ece

File tree

1 file changed

+37
-25
lines changed

1 file changed

+37
-25
lines changed

src/components/interactive-builder/modals/question/question.modal.tsx

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,36 @@ interface QuestionModalProps {
3030
}
3131

3232
/**
33-
* Mapping of allowed top‑level property keys for each question type.
34-
* Adjust these keys as needed for your implementation.
33+
* Common properties that are required for all question types.
3534
*/
36-
const allowedPropertiesMapping: Record<string, string[]> = {
37-
control: ['id', 'label', 'type', 'questionOptions'],
38-
encounterDatetime: ['id', 'label', 'type', 'questionOptions', 'datePickerFormat'],
39-
encounterLocation: ['id', 'label', 'type', 'questionOptions'],
40-
encounterProvider: ['id', 'label', 'type', 'questionOptions'],
41-
encounterRole: ['id', 'label', 'type', 'questionOptions'],
42-
obs: ['id', 'label', 'type', 'questionOptions'],
43-
obsGroup: ['id', 'label', 'type', 'questionOptions', 'questions'],
44-
patientIdentifier: ['id', 'label', 'type', 'questionOptions'],
45-
testOrder: ['id', 'label', 'type', 'questionOptions'],
46-
programState: ['id', 'label', 'type', 'questionOptions'],
35+
const requiredProperties: Array<keyof FormField> = ['id', 'label', 'type', 'questionOptions'];
36+
37+
/**
38+
* Type-specific properties.
39+
*/
40+
const typeSpecificProperties: Record<string, Array<keyof FormField>> = {
41+
control: [],
42+
encounterDatetime: ['datePickerFormat'],
43+
encounterLocation: [],
44+
encounterProvider: [],
45+
encounterRole: [],
46+
obs: ['required'],
47+
obsGroup: ['questions'],
48+
patientIdentifier: [],
49+
testOrder: [],
50+
programState: [],
4751
};
4852

53+
/**
54+
* Merge required properties with type-specific ones.
55+
*/
56+
const allowedPropertiesMapping: Record<string, string[]> = Object.fromEntries(
57+
Object.entries(typeSpecificProperties).map(([type, props]) => {
58+
const mergedProps = new Set<string>([...requiredProperties, ...props]);
59+
return [type, Array.from(mergedProps)];
60+
}),
61+
);
62+
4963
/**
5064
* Mapping of allowed keys for the nested questionOptions object per question type.
5165
*/
@@ -55,7 +69,7 @@ const allowedQuestionOptionsMapping: Record<string, string[]> = {
5569
encounterLocation: ['rendering'],
5670
encounterProvider: ['rendering'],
5771
encounterRole: ['rendering', 'isSearchable'],
58-
obs: ['rendering', 'concept'],
72+
obs: ['rendering', 'concept', 'answers'],
5973
obsGroup: ['rendering', 'concept'],
6074
patientIdentifier: ['rendering', 'identifierType', 'minLength', 'maxLength'],
6175
testOrder: ['rendering'],
@@ -81,12 +95,11 @@ function cleanQuestionOptionsForType(options: any, newType: string): any {
8195
*/
8296
function cleanFormFieldForType(field: FormField, newType: string): FormField {
8397
const allowedKeys = allowedPropertiesMapping[newType] || [];
84-
const cleaned: Partial<FormField> = {} as Partial<FormField>;
98+
const cleaned: Partial<FormField> = {};
8599

86-
// Copy only allowed top‑level properties.
87-
(allowedKeys as (keyof FormField)[]).forEach((key) => {
100+
allowedKeys.forEach((key) => {
88101
if (key in field) {
89-
(cleaned as any)[key] = field[key];
102+
(cleaned as any)[key] = field[key as keyof FormField];
90103
}
91104
});
92105

@@ -95,7 +108,9 @@ function cleanFormFieldForType(field: FormField, newType: string): FormField {
95108
cleaned.questionOptions = cleanQuestionOptionsForType(cleaned.questionOptions, newType);
96109
}
97110

98-
return { ...cleaned, type: newType } as FormField;
111+
cleaned.type = newType;
112+
113+
return cleaned as FormField;
99114
}
100115

101116
const QuestionModalContent: React.FC<QuestionModalProps> = ({
@@ -139,8 +154,6 @@ const QuestionModalContent: React.FC<QuestionModalProps> = ({
139154
allIds.push(formField.id);
140155
}
141156
const occurrences = allIds.filter((id) => id === idToTest).length;
142-
143-
// Return true if ID occurs more than once
144157
return occurrences > 1;
145158
},
146159
[schema, getAllQuestionIds, formField, formFieldProp],
@@ -158,12 +171,11 @@ const QuestionModalContent: React.FC<QuestionModalProps> = ({
158171
}));
159172
}, [setFormField]);
160173

161-
// Updated deletion: filter out the question by its id.
162174
const deleteObsGroupQuestion = useCallback(
163-
(id: string) => {
175+
(index: number) => {
164176
setFormField((prevFormField) => ({
165177
...prevFormField,
166-
questions: prevFormField.questions?.filter((q) => q.id !== id) || [],
178+
questions: prevFormField.questions?.filter((_, i) => i !== index) || [],
167179
}));
168180
},
169181
[setFormField],
@@ -241,7 +253,7 @@ const QuestionModalContent: React.FC<QuestionModalProps> = ({
241253
<Question checkIfQuestionIdExists={checkIfQuestionIdExists} />
242254
<Button
243255
kind="danger"
244-
onClick={() => deleteObsGroupQuestion(question.id)}
256+
onClick={() => deleteObsGroupQuestion(index)}
245257
className={styles.deleteObsGroupQuestionButton}
246258
>
247259
{t('deleteQuestion', 'Delete question')}

0 commit comments

Comments
 (0)