1
- import React , { useEffect , useState } from "react" ;
1
+ import React , { useEffect , useState , useCallback } from "react" ;
2
2
import Accordion from "@material-ui/core/Accordion" ;
3
3
import AccordionDetails from "@material-ui/core/AccordionDetails" ;
4
4
import AccordionSummary from "@material-ui/core/AccordionSummary" ;
@@ -19,25 +19,23 @@ export function ManageFaq() {
19
19
const [ open , setOpenToast ] = useState ( false ) ;
20
20
const [ toastMessage , setToastMessage ] = useState ( "" ) ;
21
21
const [ severity , setSeverity ] = useState ( "success" ) ;
22
- const [ reload , setReload ] = useState ( true ) ;
23
- const [ editedFaq , setEditedFaq ] = useState ( null ) ;
22
+ const [ reload , setReload ] = useState ( false ) ;
23
+ const [ faqObject , setFaqObject ] = useState ( { } ) ;
24
24
const [ openEditDialog , setOpenEditDialog ] = useState ( false ) ;
25
- const [ editedQuestion , setEditedQuestion ] = useState ( "" ) ;
26
- const [ editedAnswer , setEditedAnswer ] = useState ( "" ) ;
27
- const [ editedIsActive , setEditedIsActive ] = useState ( true ) ;
28
- const [ editedTags , setEditedTags ] = useState ( [ ] ) ;
25
+ const [ formErrors , setFormErrors ] = useState ( { } ) ;
29
26
30
- const handleCloseToast = ( ) => {
27
+ const handleCloseToast = useCallback ( ( ) => {
31
28
setTimeout ( ( ) => {
32
29
setOpenToast ( false ) ;
33
30
} , 500 ) ;
34
- } ;
31
+ } , [ ] ) ;
35
32
36
33
const handleChange = ( panel ) => ( event , isExpanded ) => {
37
34
setExpanded ( isExpanded ? panel : false ) ;
38
35
} ;
39
36
40
- async function fetchAllFaq ( ) {
37
+ const fetchAllFaq = useCallback ( async ( ) => {
38
+ setIsFetching ( true ) ;
41
39
try {
42
40
const response = await fetch ( `${ END_POINT } /faq/getFaq` ) ;
43
41
const data = await response . json ( ) ;
@@ -47,7 +45,7 @@ export function ManageFaq() {
47
45
console . log ( err . message ) ;
48
46
setIsFetching ( false ) ;
49
47
}
50
- }
48
+ } , [ ] ) ;
51
49
52
50
const deleteFaq = async ( faqId ) => {
53
51
setIsFetching ( true ) ;
@@ -88,7 +86,7 @@ export function ManageFaq() {
88
86
"Content-Type" : "application/json" ,
89
87
authorization : `Bearer ${ localStorage . getItem ( "token" ) } ` ,
90
88
} ,
91
- body : JSON . stringify ( { faqId : faqId , ...updatedFaqDetails } ) ,
89
+ body : JSON . stringify ( { faqId, ...updatedFaqDetails } ) ,
92
90
} ) ;
93
91
94
92
if ( ! response . ok ) {
@@ -99,7 +97,7 @@ export function ManageFaq() {
99
97
setToastMessage ( data . message ) ;
100
98
setOpenToast ( true ) ;
101
99
setSeverity ( "success" ) ;
102
- setReload ( ! reload ) ;
100
+ setReload ( ( prev ) => ! prev ) ;
103
101
} catch ( error ) {
104
102
console . error ( "Failed to update FAQ:" , error . message ) ;
105
103
setToastMessage ( "Failed to update FAQ" ) ;
@@ -108,35 +106,42 @@ export function ManageFaq() {
108
106
}
109
107
} ;
110
108
111
- useEffect ( ( ) => {
112
- fetchAllFaq ( ) ;
113
- } , [ reload ] ) ;
114
-
115
109
const handleEdit = ( faqId ) => {
116
110
const editedFaq = faqs . find ( ( faq ) => faq . _id === faqId ) ;
117
- setEditedFaq ( editedFaq ) ;
118
- setEditedQuestion ( editedFaq . question ) ;
119
- setEditedAnswer ( editedFaq . answer ) ;
120
- setEditedIsActive ( editedFaq . isActive ) ;
121
- setEditedTags ( editedFaq . tags ) ;
111
+ setFaqObject ( editedFaq ) ;
122
112
setOpenEditDialog ( true ) ;
123
113
} ;
124
114
125
115
const handleSaveEdit = ( ) => {
126
- const updatedFaq = {
127
- question : editedQuestion ,
128
- answer : editedAnswer ,
129
- isActive : editedIsActive ,
130
- tags : editedTags ,
131
- } ;
132
- updateFaq ( editedFaq . _id , updatedFaq ) ;
133
- setOpenEditDialog ( false ) ;
116
+ if ( validateForm ( ) ) {
117
+ updateFaq ( faqObject . _id , faqObject ) ;
118
+ setOpenEditDialog ( false ) ;
119
+ }
134
120
} ;
135
121
136
122
const handleCancelEdit = ( ) => {
137
- setOpenEditDialog ( false ) ;
123
+ setOpenEditDialog ( false ) ;
124
+ } ;
125
+
126
+ const validateForm = ( ) => {
127
+ const errors = { } ;
128
+ if ( ! faqObject . question ) {
129
+ errors . question = "* Question is required" ;
130
+ }
131
+ if ( ! faqObject . answer ) {
132
+ errors . answer = "* Answer is required" ;
133
+ }
134
+ if ( ! faqObject . tags . length || faqObject . tags [ 0 ] === "" ) {
135
+ errors . tags = "* At least one tag is required" ;
136
+ }
137
+ setFormErrors ( errors ) ;
138
+ return Object . keys ( errors ) . length === 0 ;
138
139
} ;
139
140
141
+ useEffect ( ( ) => {
142
+ fetchAllFaq ( ) ;
143
+ } , [ fetchAllFaq , reload ] ) ;
144
+
140
145
return (
141
146
< div >
142
147
< h1 style = { { textAlign : "center" } } > Manage FAQ</ h1 >
@@ -209,60 +214,80 @@ export function ManageFaq() {
209
214
) }
210
215
</ div >
211
216
</ div >
212
- { editedFaq && openEditDialog && (
217
+ { faqObject && openEditDialog && (
213
218
< div className = { style [ "blur-background" ] } >
214
- < div className = { style [ "edit-dialog" ] } >
215
- < h2 className = { style [ "edit-dialog-heading" ] } > Edit FAQ</ h2 >
216
- < div className = { style [ "edit-form" ] } >
217
- < label htmlFor = "editedQuestion" > Question:</ label >
218
- < input
219
- id = "editedQuestion"
220
- type = "text"
221
- value = { editedQuestion }
222
- onChange = { ( e ) => setEditedQuestion ( e . target . value ) }
223
- className = { style [ "faq-input" ] }
224
- />
225
- < label htmlFor = "editedAnswer" > Answer:</ label >
226
- < input
227
- id = "editedAnswer"
228
- type = "text"
229
- value = { editedAnswer }
230
- onChange = { ( e ) => setEditedAnswer ( e . target . value ) }
231
- className = { style [ "faq-input" ] }
232
- />
233
- < label htmlFor = "editedIsActive" > Is Active:</ label >
234
- < input
235
- id = "editedIsActive"
236
- type = "checkbox"
237
- checked = { editedIsActive }
238
- onChange = { ( e ) => setEditedIsActive ( e . target . checked ) }
239
- className = { style [ "faq-input" ] }
240
- />
241
- < label htmlFor = "editedTags" > Tags:</ label >
242
- < input
243
- id = "editedTags"
244
- type = "text"
245
- value = { editedTags }
246
- onChange = { ( e ) => setEditedTags ( e . target . value . split ( "," ) ) }
247
- className = { style [ "faq-input" ] }
248
- />
249
- < div className = { style [ "submit-btn" ] } >
250
- < Button2
251
- className = { style [ "submit-btn-text" ] }
252
- label = "Save"
253
- type = "submit"
254
- onClick = { handleSaveEdit }
219
+ < div className = { style [ "edit-dialog" ] } >
220
+ < h2 className = { style [ "edit-dialog-heading" ] } > Edit FAQ</ h2 >
221
+ < div className = { style [ "edit-form" ] } >
222
+ < label htmlFor = "editedQuestion" > Question:</ label >
223
+ < input
224
+ id = "editedQuestion"
225
+ type = "text"
226
+ value = { faqObject . question }
227
+ onChange = { ( e ) =>
228
+ setFaqObject ( { ...faqObject , question : e . target . value } )
229
+ }
230
+ className = { style [ "faq-input" ] }
231
+ />
232
+ { formErrors . question && (
233
+ < span className = { style [ "error" ] } > { formErrors . question } </ span >
234
+ ) }
235
+ < label htmlFor = "editedAnswer" > Answer:</ label >
236
+ < input
237
+ id = "editedAnswer"
238
+ type = "text"
239
+ value = { faqObject . answer }
240
+ onChange = { ( e ) =>
241
+ setFaqObject ( { ...faqObject , answer : e . target . value } )
242
+ }
243
+ className = { style [ "faq-input" ] }
244
+ />
245
+ { formErrors . answer && (
246
+ < span className = { style [ "error" ] } > { formErrors . answer } </ span >
247
+ ) }
248
+ < label htmlFor = "editedIsActive" > Is Active:</ label >
249
+ < input
250
+ id = "editedIsActive"
251
+ type = "checkbox"
252
+ checked = { faqObject . isActive }
253
+ onChange = { ( e ) =>
254
+ setFaqObject ( { ...faqObject , isActive : e . target . checked } )
255
+ }
256
+ className = { style [ "checkbox" ] }
255
257
/>
256
- < Button2
257
- className = { style [ "submit-btn-text" ] }
258
- label = "Cancel"
259
- type = "submit"
260
- onClick = { handleCancelEdit }
258
+ < label htmlFor = "editedTags" > Tags:</ label >
259
+ < input
260
+ id = "editedTags"
261
+ type = "text"
262
+ value = { faqObject . tags . join ( "," ) }
263
+ onChange = { ( e ) =>
264
+ setFaqObject ( {
265
+ ...faqObject ,
266
+ tags : e . target . value . split ( "," ) . map ( tag => tag . trim ( ) ) ,
267
+ } )
268
+ }
269
+ className = { style [ "faq-input" ] }
261
270
/>
271
+ { formErrors . tags && (
272
+ < span className = { style [ "error" ] } > { formErrors . tags } </ span >
273
+ ) }
274
+ < div className = { style [ "submit-btn" ] } >
275
+ < Button2
276
+ className = { style [ "submit-btn-text" ] }
277
+ label = "Save"
278
+ type = "submit"
279
+ onClick = { handleSaveEdit }
280
+ />
281
+ < Button2
282
+ className = { style [ "submit-btn-text" ] }
283
+ label = "Cancel"
284
+ type = "button"
285
+ onClick = { handleCancelEdit }
286
+ />
287
+ </ div >
262
288
</ div >
263
289
</ div >
264
290
</ div >
265
- </ div >
266
291
) }
267
292
< SimpleToast
268
293
open = { open }
@@ -273,4 +298,3 @@ export function ManageFaq() {
273
298
</ div >
274
299
) ;
275
300
}
276
-
0 commit comments