@@ -11,7 +11,7 @@ import { DialogModule } from 'primeng/dialog';
11
11
import { MultiSelectModule } from 'primeng/multiselect' ;
12
12
import { FormControl , FormGroup , ReactiveFormsModule } from '@angular/forms' ;
13
13
import { DropdownModule } from 'primeng/dropdown' ;
14
- import { Question } from './question.model' ;
14
+ import { Question , SingleQuestionResponse , QuestionBody } from './question.model' ;
15
15
import { Column } from './column.model' ;
16
16
import { Topic } from './topic.model' ;
17
17
import { Difficulty } from './difficulty.model' ;
@@ -70,76 +70,16 @@ export class QuestionsComponent implements OnInit {
70
70
71
71
ngOnInit ( ) {
72
72
// two way binding for forms is not working for some reason unless question is initialised with empty values
73
- this . question = {
74
- _id : '' ,
75
- id : - 1 ,
76
- title : '' ,
77
- topics : [ ] ,
78
- description : '' ,
79
- difficulty : '' ,
80
- } ;
81
-
82
- forkJoin ( {
83
- questions : this . questionService . getQuestions ( ) ,
84
- topics : this . questionService . getTopics ( ) ,
85
- } ) . subscribe ( {
86
- next : results => {
87
- this . questions = results . questions . data || [ ] ;
88
- this . topics =
89
- results . topics . data ?. map ( topic => ( {
90
- label : topic ,
91
- value : topic ,
92
- } ) ) || [ ] ;
93
- } ,
94
- error : ( error : Error ) => {
95
- console . error ( error ) ;
96
- this . questions = [ ] ;
97
- this . topics = [ ] ;
98
- this . messageService . add ( {
99
- severity : 'error' ,
100
- summary : 'Error' ,
101
- detail : 'Failed to load data. Please try again later.' ,
102
- life : 3000 ,
103
- } ) ;
104
- } ,
105
- complete : ( ) => {
106
- // TODO: add loading state for this
107
- console . log ( 'complete' ) ;
108
- } ,
109
- } ) ;
73
+ this . initQuestion ( ) ;
110
74
111
- this . difficulties = [
112
- { label : DifficultyLevels . EASY , value : DifficultyLevels . EASY } ,
113
- { label : DifficultyLevels . MEDIUM , value : DifficultyLevels . MEDIUM } ,
114
- { label : DifficultyLevels . HARD , value : DifficultyLevels . HARD } ,
115
- ] ;
75
+ // fetch data from API call
76
+ this . handleInitData ( ) ;
116
77
117
- this . questionFormGroup = new FormGroup ( {
118
- selectedTopics : new FormControl < string [ ] | null > ( [ ] ) ,
119
- selectedDifficulty : new FormControl < Difficulty [ ] | null > ( [ ] ) ,
120
- textTitle : new FormControl < string | null > ( '' ) ,
121
- textDescription : new FormControl < string | null > ( '' ) ,
122
- } ) ;
123
-
124
- // Dropdown difficulty listener
125
- this . questionFormGroup . get ( 'selectedDifficulty' ) ?. valueChanges . subscribe ( v => {
126
- this . question . difficulty = v ;
127
- } ) ;
128
-
129
- // Multiselect topics listener
130
- this . questionFormGroup . get ( 'selectedTopics' ) ?. valueChanges . subscribe ( v => {
131
- this . question . topics = v ;
132
- } ) ;
78
+ this . initDifficulties ( ) ;
133
79
134
- // text title listener
135
- this . questionFormGroup . get ( 'textTitle' ) ?. valueChanges . subscribe ( v => {
136
- this . question . title = v ;
137
- } ) ;
80
+ this . initFormGroup ( ) ;
138
81
139
- // text description listener
140
- this . questionFormGroup . get ( 'textDescription' ) ?. valueChanges . subscribe ( v => {
141
- this . question . description = v ;
142
- } ) ;
82
+ this . initListeners ( ) ;
143
83
}
144
84
145
85
openNewQuestion ( ) {
@@ -155,14 +95,7 @@ export class QuestionsComponent implements OnInit {
155
95
header : 'Delete Confirmation' ,
156
96
icon : 'pi pi-exclamation-triangle' ,
157
97
accept : ( ) => {
158
- this . questions = this . questions ?. filter ( val => ! this . selectedQuestions ?. includes ( val ) ) ;
159
- this . selectedQuestions = null ;
160
- this . messageService . add ( {
161
- severity : 'success' ,
162
- summary : 'Successful' ,
163
- detail : 'Question(s) Deleted' ,
164
- life : 3000 ,
165
- } ) ;
98
+ this . handleDeleteQuestionResponse ( ) ;
166
99
} ,
167
100
} ) ;
168
101
}
@@ -181,36 +114,26 @@ export class QuestionsComponent implements OnInit {
181
114
182
115
if ( this . question . id ) {
183
116
// update
184
- if ( this . questions ) {
185
- this . questions [ this . questions . findIndex ( x => x . id == this . question . id ) ] = this . question ;
186
- }
187
-
188
- this . messageService . add ( {
189
- severity : 'success' ,
190
- summary : 'Successful' ,
191
- detail : 'Question has been updated successfully' ,
192
- life : 3000 ,
193
- } ) ;
117
+ const { id, ...questionBody } = this . question ;
118
+ this . handleEditQuestionResponse ( id , questionBody ) ;
194
119
} else {
195
120
// add
196
- this . question . id = this . createId ( ) ;
197
-
198
- if ( this . questions ) {
199
- this . questions = [ ...this . questions , this . question ] ;
200
- }
201
-
202
- this . messageService . add ( {
203
- severity : 'success' ,
204
- summary : 'Successful' ,
205
- detail : 'New Question Added' ,
206
- life : 3000 ,
207
- } ) ;
121
+ this . handleAddQuestionResponse ( ) ;
208
122
}
209
123
210
124
this . isDialogVisible = false ;
211
125
this . question = { } as Question ;
212
126
}
213
127
128
+ resetFormGroup ( ) {
129
+ this . questionFormGroup . reset ( {
130
+ selectedTopics : [ ] ,
131
+ selectedDifficulty : '' ,
132
+ textTitle : '' ,
133
+ textDescription : '' ,
134
+ } ) ;
135
+ }
136
+
214
137
editQuestion ( question : Question ) {
215
138
this . question . id = question . id ;
216
139
this . questionFormGroup . patchValue ( {
@@ -222,17 +145,165 @@ export class QuestionsComponent implements OnInit {
222
145
this . isDialogVisible = true ;
223
146
}
224
147
225
- // assuming newest question is always appended at the back
226
- createId ( ) {
227
- return this . questions ? Number ( this . questions . at ( - 1 ) ?. id ) + 1 : - 1 ;
148
+ initListeners ( ) {
149
+ // Dropdown difficulty listener
150
+ this . questionFormGroup . get ( 'selectedDifficulty' ) ?. valueChanges . subscribe ( v => {
151
+ this . question . difficulty = v ;
152
+ } ) ;
153
+
154
+ // Multiselect topics listener
155
+ this . questionFormGroup . get ( 'selectedTopics' ) ?. valueChanges . subscribe ( v => {
156
+ this . question . topics = v ;
157
+ } ) ;
158
+
159
+ // text title listener
160
+ this . questionFormGroup . get ( 'textTitle' ) ?. valueChanges . subscribe ( v => {
161
+ this . question . title = v ;
162
+ } ) ;
163
+
164
+ // text description listener
165
+ this . questionFormGroup . get ( 'textDescription' ) ?. valueChanges . subscribe ( v => {
166
+ this . question . description = v ;
167
+ } ) ;
228
168
}
229
169
230
- resetFormGroup ( ) {
231
- this . questionFormGroup . reset ( {
232
- selectedTopics : [ ] ,
233
- selectedDifficulty : '' ,
234
- textTitle : '' ,
235
- textDescription : '' ,
170
+ initFormGroup ( ) {
171
+ this . questionFormGroup = new FormGroup ( {
172
+ selectedTopics : new FormControl < string [ ] | null > ( [ ] ) ,
173
+ selectedDifficulty : new FormControl < Difficulty [ ] | null > ( [ ] ) ,
174
+ textTitle : new FormControl < string | null > ( '' ) ,
175
+ textDescription : new FormControl < string | null > ( '' ) ,
176
+ } ) ;
177
+ }
178
+
179
+ initDifficulties ( ) {
180
+ this . difficulties = [
181
+ { label : DifficultyLevels . EASY , value : DifficultyLevels . EASY } ,
182
+ { label : DifficultyLevels . MEDIUM , value : DifficultyLevels . MEDIUM } ,
183
+ { label : DifficultyLevels . HARD , value : DifficultyLevels . HARD } ,
184
+ ] ;
185
+ }
186
+
187
+ initQuestion ( ) {
188
+ this . question = {
189
+ id : - 1 ,
190
+ title : '' ,
191
+ topics : [ ] ,
192
+ description : '' ,
193
+ difficulty : '' ,
194
+ } ;
195
+ }
196
+
197
+ handleAddQuestionResponse ( ) {
198
+ this . questionService . addQuestion ( this . question ) . subscribe ( {
199
+ next : ( response : SingleQuestionResponse ) => {
200
+ if ( this . questions ) {
201
+ this . questions = [ ...this . questions , response . data ] ;
202
+ }
203
+ } ,
204
+ error : ( error : Error ) => {
205
+ console . log ( error ) ;
206
+ this . messageService . add ( {
207
+ severity : 'error' ,
208
+ summary : 'Error' ,
209
+ detail : 'Failed to add new question. Please try again later.' ,
210
+ life : 3000 ,
211
+ } ) ;
212
+ } ,
213
+ complete : ( ) => {
214
+ this . messageService . add ( {
215
+ severity : 'success' ,
216
+ summary : 'Successful' ,
217
+ detail : 'New Question Added' ,
218
+ life : 3000 ,
219
+ } ) ;
220
+ } ,
221
+ } ) ;
222
+ }
223
+
224
+ handleDeleteQuestionResponse ( ) {
225
+ const deleteRequests = this . selectedQuestions ?. map ( q => this . questionService . deleteQuestion ( q . id ) ) ;
226
+
227
+ forkJoin ( deleteRequests ! ) . subscribe ( {
228
+ next : ( ) => {
229
+ // delete locally
230
+ this . questions = this . questions ?. filter ( val => ! this . selectedQuestions ?. includes ( val ) ) ;
231
+ this . selectedQuestions = null ;
232
+ } ,
233
+ error : ( ) => {
234
+ // Handle any errors from the forkJoin if necessary
235
+ this . messageService . add ( {
236
+ severity : 'error' ,
237
+ summary : 'Error' ,
238
+ detail : 'Some questions could not be deleted. Please try again later.' ,
239
+ life : 3000 ,
240
+ } ) ;
241
+ } ,
242
+ complete : ( ) => {
243
+ this . messageService . add ( {
244
+ severity : 'success' ,
245
+ summary : 'Successful' ,
246
+ detail : 'Question(s) Deleted' ,
247
+ life : 3000 ,
248
+ } ) ;
249
+ } ,
250
+ } ) ;
251
+ }
252
+
253
+ handleEditQuestionResponse ( id : number , question : QuestionBody ) {
254
+ this . questionService . updateQuestion ( id , question ) . subscribe ( {
255
+ next : ( response : SingleQuestionResponse ) => {
256
+ this . questions [ this . questions . findIndex ( x => x . id == id ) ] = response . data ;
257
+ } ,
258
+ error : ( error : Error ) => {
259
+ console . log ( error ) ;
260
+ console . log ( question ) ;
261
+ this . messageService . add ( {
262
+ severity : 'error' ,
263
+ summary : 'Error' ,
264
+ detail : 'Failed to edit question. Please try again later.' ,
265
+ life : 3000 ,
266
+ } ) ;
267
+ } ,
268
+ complete : ( ) => {
269
+ this . messageService . add ( {
270
+ severity : 'success' ,
271
+ summary : 'Successful' ,
272
+ detail : 'Question has been updated successfully' ,
273
+ life : 3000 ,
274
+ } ) ;
275
+ } ,
276
+ } ) ;
277
+ }
278
+
279
+ handleInitData ( ) {
280
+ forkJoin ( {
281
+ questions : this . questionService . getQuestions ( ) ,
282
+ topics : this . questionService . getTopics ( ) ,
283
+ } ) . subscribe ( {
284
+ next : results => {
285
+ this . questions = results . questions . data || [ ] ;
286
+ this . topics =
287
+ results . topics . data ?. map ( topic => ( {
288
+ label : topic ,
289
+ value : topic ,
290
+ } ) ) || [ ] ;
291
+ } ,
292
+ error : ( error : Error ) => {
293
+ console . error ( error ) ;
294
+ this . questions = [ ] ;
295
+ this . topics = [ ] ;
296
+ this . messageService . add ( {
297
+ severity : 'error' ,
298
+ summary : 'Error' ,
299
+ detail : 'Failed to load data. Please try again later.' ,
300
+ life : 3000 ,
301
+ } ) ;
302
+ } ,
303
+ complete : ( ) => {
304
+ // TODO: add loading state for this
305
+ console . log ( 'complete' ) ;
306
+ } ,
236
307
} ) ;
237
308
}
238
309
}
0 commit comments