@@ -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 */
8296function 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
101116const 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