1
1
import React from 'react'
2
- import { useState } from 'react'
2
+ import { useState , useEffect } from 'react'
3
3
import questionService from "../../services/questions"
4
+ import categoryService from "../../services/categories"
4
5
5
6
function EditQn ( { question, handleClose, editQuestion } ) {
6
- const [ category , setCategory ] = useState ( question . category ) ;
7
+ const [ categories , setCategories ] = useState ( question . category ) ;
8
+ const [ categoryInput , setCategoryInput ] = useState ( '' ) ;
9
+ const [ categoriesFromDB , setCategoriesFromDB ] = useState ( [ ] ) ;
7
10
const [ complexity , setComplexity ] = useState ( question . complexity ) ;
8
11
const [ description , setDescription ] = useState ( question . description ) ;
9
12
const [ title , setTitle ] = useState ( question . title ) ;
10
13
const [ error , setError ] = useState ( null ) ;
11
14
15
+ useEffect ( ( ) => {
16
+ categoryService . getAllCategories ( )
17
+ . then ( result => {
18
+ // console.log("API call successful. Result:", result);
19
+ setCategoriesFromDB ( Array . isArray ( result ) ? result : [ ] ) ;
20
+ // console.log("categoriesFromDB after set:", categoriesFromDB);
21
+ } )
22
+ . catch ( err => console . log ( "Error fetching categories:" , err ) ) ;
23
+ } , [ ] ) ;
24
+
25
+ const handleCategoryInputChange = ( e ) => {
26
+ setCategoryInput ( e . target . value ) ;
27
+ } ;
28
+
29
+ const handleAddCategory = ( ) => {
30
+ if ( categoryInput && ! categories . includes ( categoryInput ) ) {
31
+ setCategories ( [ ...categories , categoryInput ] ) ;
32
+ }
33
+ console . log ( `categories are: ${ categories } ` ) ;
34
+ setCategoryInput ( '' ) ;
35
+ } ;
36
+
37
+ const handleCategorySelect = ( suggestion ) => {
38
+ if ( ! categories . includes ( suggestion . name ) ) {
39
+ setCategories ( [ ...categories , suggestion . name ] ) ;
40
+ }
41
+ setCategoryInput ( '' ) ;
42
+ } ;
43
+
44
+ const handleRemoveCategory = ( categoryToRemove ) => {
45
+ setCategories ( categories . filter ( ( category ) => category !== categoryToRemove ) ) ;
46
+ } ;
47
+
12
48
const Update = ( e ) => {
13
49
e . preventDefault ( ) ;
50
+ console . log ( "updated categories:" , categories )
51
+ const updatedQuestion = {
52
+ category : categories ,
53
+ complexity,
54
+ description,
55
+ title,
56
+ } ;
57
+ console . log ( "updated qn" , updatedQuestion )
14
58
15
- // To remove empty strings and extra spaces
16
- const delimeter = ", "
17
- const categoryString = category . join ( delimeter ) ;
18
- const cleanedCategoryArray = categoryString . split ( delimeter ) . filter ( item => item . trim ( ) !== "" ) ;
59
+ const dbTopicNames = categoriesFromDB . map ( cat => cat . name ) ;
60
+ const newCategories = categories . filter ( item => ! dbTopicNames . includes ( item ) ) ;
61
+ console . log ( `newCategories are ${ newCategories } ` ) ;
19
62
20
- const updatedQuestion = {
21
- category : cleanedCategoryArray ,
22
- complexity,
23
- description,
24
- title,
63
+ categoryService . createCategories ( newCategories )
64
+ . then ( result => console . log ( result . data ) )
65
+ . catch ( e => {
66
+ if ( e . response && e . response . status === 400 ) {
67
+ setError ( e . response . data . error ) ;
68
+ }
69
+ console . error ( 'Error updating category:' , e ) ;
70
+ } ) ;
71
+
72
+ questionService . updateQuestion ( question . _id , updatedQuestion )
73
+ . then ( result => {
74
+
75
+ editQuestion ( question . _id , updatedQuestion ) ;
76
+ console . log ( 'Question edited successfully:' , result )
77
+ handleClose ( ) ;
78
+ } )
79
+ . catch ( e => {
80
+ if ( e . response && e . response . status === 400 ) {
81
+ setError ( e . response . data . error )
82
+ // console.log("error is:", error)
83
+ }
84
+ console . error ( 'Error updating question:' , e ) ;
85
+ } ) ;
25
86
} ;
26
- console . log ( "category array: " , cleanedCategoryArray )
27
- console . log ( "db_id:" , question . _id )
28
- console . log ( category , complexity , description , title ) ;
29
-
30
- questionService . updateQuestion ( question . _id , updatedQuestion )
31
- . then ( result => {
32
-
33
- editQuestion ( question . _id , updatedQuestion ) ;
34
- console . log ( 'Question edited successfully:' , result )
35
- handleClose ( ) ;
36
- } )
37
- . catch ( e => {
38
- if ( e . response && e . response . status === 400 ) {
39
- setError ( e . response . data . error )
40
- // console.log("error is:", error)
41
- }
42
- console . error ( 'Error updating question:' , e ) ;
43
- } ) ;
44
- } ;
87
+
88
+ const filteredSuggestions = Array . isArray ( categoriesFromDB )
89
+ ? categoriesFromDB . filter ( suggestion =>
90
+ suggestion . name . toLowerCase ( ) . includes ( categoryInput . toLowerCase ( ) )
91
+ )
92
+ : [ ] ;
45
93
46
94
return (
47
95
< div className = 'd-flex bg-primary justify-content-center align-items-center' >
@@ -55,8 +103,98 @@ function EditQn({ question, handleClose, editQuestion }) {
55
103
</ div >
56
104
< div className = "mb-2" >
57
105
< label htmlFor = "" > Category</ label >
58
- < input type = "text" placeholder = 'Data Structures' className = 'form-control'
59
- value = { category . join ( "," ) } onChange = { ( e ) => setCategory ( e . target . value . split ( "," ) ) } />
106
+ < input
107
+ type = "text"
108
+ placeholder = 'Find or create a category'
109
+ className = 'form-control'
110
+ value = { categoryInput }
111
+ onChange = { handleCategoryInputChange }
112
+ onKeyDown = { ( e ) => e . key === 'Enter' && ( e . preventDefault ( ) , handleAddCategory ( ) ) }
113
+ />
114
+
115
+ { /* Outer container with rounded corners and border */ }
116
+ { categoryInput && (
117
+ < div style = { {
118
+ border : "1px solid #ccc" ,
119
+ borderRadius : "6px" ,
120
+ paddingTop : "2px" ,
121
+ marginTop : "5px" ,
122
+ maxWidth : "100%" ,
123
+ } } >
124
+ { /* Scrollable inner container for suggestion items */ }
125
+ < div style = { {
126
+ maxHeight : "150px" , // Approx height for 3 items
127
+ overflowY : "auto" , // Scrollbar only if > 3 items
128
+ overflowX : "hidden" ,
129
+ } } >
130
+ { filteredSuggestions . map ( ( suggestion , index ) => (
131
+ < li
132
+ key = { index }
133
+ onClick = { ( ) => handleCategorySelect ( suggestion ) }
134
+ style = { {
135
+ cursor : 'pointer' ,
136
+ padding : "10px 10px" ,
137
+ margin : "0px 10px" ,
138
+ backgroundColor : "#fff" ,
139
+ display : "flex" ,
140
+ alignItems : "center" ,
141
+ transition : "background-color 0.2s" ,
142
+ borderBottom : index === filteredSuggestions . length - 1 ? "none" : "1px solid #e0e0e0"
143
+ } }
144
+ onMouseOver = { ( e ) => e . currentTarget . style . backgroundColor = "#f1f3f5" }
145
+ onMouseOut = { ( e ) => e . currentTarget . style . backgroundColor = "#fff" }
146
+ >
147
+ < span style = { { color : "#28a745" , marginRight : "8px" } } > +</ span >
148
+ { suggestion . name }
149
+ </ li >
150
+ ) ) }
151
+ </ div >
152
+
153
+ { /* "New category" item */ }
154
+ { ! filteredSuggestions . some ( suggestion => suggestion . name . toLowerCase ( ) === categoryInput . toLowerCase ( ) ) && (
155
+ < li
156
+ onClick = { handleAddCategory }
157
+ style = { {
158
+ cursor : 'pointer' ,
159
+ padding : "10px 15px" ,
160
+ fontStyle : 'italic' ,
161
+ color : 'gray' ,
162
+ backgroundColor : "#fff" ,
163
+ display : "flex" ,
164
+ alignItems : "center" ,
165
+ transition : "background-color 0.2s" ,
166
+ borderTop : "1px solid #e0e0e0" , // Border above if there are suggestions
167
+ borderBottomRightRadius : "6px" ,
168
+ borderBottomLeftRadius : "6px" ,
169
+ } }
170
+ onMouseOver = { ( e ) => e . currentTarget . style . backgroundColor = "#f1f3f5" }
171
+ onMouseOut = { ( e ) => e . currentTarget . style . backgroundColor = "#fff" }
172
+ >
173
+ New category: "{ categoryInput } ". Press Enter to add.
174
+ </ li >
175
+ ) }
176
+ </ div >
177
+ ) }
178
+
179
+ { /* Display selected categories as tags */ }
180
+ < div style = { { marginTop : '10px' } } >
181
+ { categories . map ( ( category , index ) => (
182
+ < span
183
+ key = { index }
184
+ style = { {
185
+ display : 'inline-block' ,
186
+ padding : '5px' ,
187
+ margin : '5px' ,
188
+ backgroundColor : '#e0e0e0' ,
189
+ borderRadius : '5px' ,
190
+ cursor : 'pointer'
191
+ } }
192
+ onClick = { ( ) => handleRemoveCategory ( category ) }
193
+ >
194
+ { category } ×
195
+ </ span >
196
+ ) ) }
197
+ </ div >
60
198
</ div >
61
199
< div className = "container my-3" >
62
200
< h5 > Complexity</ h5 >
0 commit comments