Proyectos de Subversion LeadersLinked - Backend

Rev

Rev 13008 | Rev 13068 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
12709 stevensc 1
/* eslint-disable no-mixed-spaces-and-tabs */
2
import React, { useState, useEffect } from 'react'
3
import axios from 'axios'
12733 stevensc 4
import parse from 'html-react-parser'
12709 stevensc 5
import { useForm } from 'react-hook-form'
6
import { useDispatch } from 'react-redux'
12710 stevensc 7
import { useHistory, useParams } from 'react-router-dom'
12709 stevensc 8
import { addNotification } from '../../../redux/notification/notification.actions'
9
import DescriptionInput from '../../../shared/DescriptionInput'
10
import SectionModal from '../components/SectionModal'
12993 stevensc 11
import DeleteModal from '../../../shared/DeleteModal'
12996 stevensc 12
import QuestionModal from '../components/QuestionModal'
12709 stevensc 13
 
14
const sectionTypeOptions = {
15
	open: 'Abierto',
13007 stevensc 16
	simple: 'Simple',
17
	multiple: 'Multiple'
12709 stevensc 18
}
19
 
13067 stevensc 20
const INITIAL_OPTION = {
21
	slug_section: '',
22
	slug_question: '',
23
	slug_option: '',
24
	text: '',
25
	checked: false,
26
	position: 0
27
}
28
 
12709 stevensc 29
const INITIAL_SECTION = {
30
	slug_section: '',
31
	name: '',
32
	text: '',
33
	position: 0,
34
	questions: [],
35
	status: 0
36
}
37
 
38
const INITIAL_QUESTION = {
39
	slug_section: '',
40
	slug_question: '',
41
	text: '',
42
	type: '',
43
	position: 0,
44
	maxlength: '0',
45
	multiline: '0',
46
	range: '0',
47
	options: [],
48
	answer: ''
49
}
50
 
51
 
52
const FormView = ({ actionLink }) => {
53
 
54
	// Hooks
55
	const history = useHistory()
12710 stevensc 56
	const { action } = useParams()
12709 stevensc 57
	const dispatch = useDispatch()
58
	const { register, setValue, watch, reset } = useForm()
59
 
60
	// Section modal states
61
	const [isShowSection, setIsShowSectionModal] = useState(false)
62
	const [sectionSelected, setSectionSelected] = useState(INITIAL_SECTION)
63
	const [sectionType, setSectionType] = useState('add')
64
 
13067 stevensc 65
	// Question modal states
12709 stevensc 66
	const [isShowQuestion, setIsShowQuestionModal] = useState(false)
67
	const [questionSelected, setQuestionSelected] = useState(INITIAL_QUESTION)
68
	const [questionType, setQuestionType] = useState('add')
69
 
13067 stevensc 70
	// Option modal states
71
	const [isShowOption, setIsShowOptionModal] = useState(false)
72
	const [optionSelected, setOptionSelected] = useState(INITIAL_OPTION)
73
	const [optionType, setOptionType] = useState('add')
74
 
12709 stevensc 75
	const [content, setContent] = useState([])
76
	const [status, setStatus] = useState('A')
12993 stevensc 77
	const [showDeleteModal, setShowDeleteModal] = useState(false)
78
	const [deleteType, setDeleteType] = useState('section')
13007 stevensc 79
	const deleteSlugsOptions = {
80
		section: sectionSelected.slug_section,
81
		question: questionSelected.slug_question
82
	}
12709 stevensc 83
 
13067 stevensc 84
	// Section methods
12709 stevensc 85
	const showSectionModal = (section = INITIAL_SECTION, type = 'add') => {
86
		setSectionSelected(section)
87
		setSectionType(type)
13007 stevensc 88
		setIsShowSectionModal(true)
12709 stevensc 89
	}
90
 
91
	const closeSectionModal = () => {
92
		setIsShowSectionModal(false)
93
		setSectionSelected(INITIAL_SECTION)
94
	}
95
 
12991 stevensc 96
	const addSection = (name, text) => {
12836 stevensc 97
		const uuid = new Date().getTime()
12991 stevensc 98
		let position = content.length
99
		console.log(name)
100
		console.log(text)
12836 stevensc 101
 
12990 stevensc 102
		setContent(prev => [...prev, {
12836 stevensc 103
			slug_section: `section${uuid}`,
104
			name: name,
105
			text: text,
106
			position: position,
107
			questions: [],
108
			status: 0
12990 stevensc 109
		}])
12709 stevensc 110
	}
111
 
12991 stevensc 112
	const editSection = (name, text, slug) => {
12992 stevensc 113
		setContent(current =>
114
			current.map(currentSection => {
115
				if (currentSection.slug_section === slug) {
116
					return { ...currentSection, name: name, text: text }
117
				}
12991 stevensc 118
 
12992 stevensc 119
				return currentSection
120
			})
121
		)
12709 stevensc 122
	}
123
 
13067 stevensc 124
	const deleteSection = (slug) => {
125
		setContent(current =>
126
			current.filter(currentSection => {
127
				return currentSection.slug_section !== slug
128
			}),
129
		)
130
	}
131
 
132
	// Question methods
12709 stevensc 133
	const showQuestionModal = (question = INITIAL_QUESTION, type = 'add') => {
134
		setIsShowQuestionModal(true)
135
		setQuestionType(type)
136
		setQuestionSelected(question)
137
	}
138
 
139
	const closeQuestionModal = () => {
140
		setIsShowQuestionModal(false)
141
		setQuestionSelected(INITIAL_QUESTION)
142
	}
143
 
144
	const addQuestion = (question) => {
12996 stevensc 145
		const uuid = new Date().getTime()
146
 
13004 stevensc 147
		setContent(current =>
148
			current.map(currentSection => {
149
				if (currentSection.slug_section === sectionSelected.slug_section) {
150
					return {
151
						...currentSection,
152
						questions: [
153
							...currentSection.questions,
154
							{
155
								...question,
156
								slug_question: `question${uuid}`,
157
								slug_section: sectionSelected.slug_section,
158
							}
159
						]
160
					}
161
				}
13002 stevensc 162
 
13004 stevensc 163
				return currentSection
164
			})
165
		)
12709 stevensc 166
	}
167
 
168
	const editQuestion = (question) => {
13006 stevensc 169
		setContent(current =>
170
			current.map(currentSection => {
171
				if (currentSection.slug_section === sectionSelected.slug_section) {
13001 stevensc 172
 
13006 stevensc 173
					const newQuestions = currentSection.questions.map((currentQuestion) => {
174
						if (currentQuestion.slug_question === question.slug_question) {
175
							return question
176
						}
12709 stevensc 177
 
13006 stevensc 178
						return currentQuestion
179
					})
180
 
181
					return { ...currentSection, questions: newQuestions }
182
				}
13007 stevensc 183
 
13006 stevensc 184
				return currentSection
185
			})
186
		)
12709 stevensc 187
	}
188
 
13067 stevensc 189
	const deleteQuestion = (slug) => {
190
		setContent(current =>
191
			current.map(currentSection => {
192
				if (currentSection.slug_section === sectionSelected.slug_section) {
193
					return {
194
						...currentSection,
195
						questions: currentSection.questions.filter((currentQuestion) => currentQuestion.slug_question !== slug)
196
					}
197
				}
198
				return currentSection
199
			}),
200
		)
201
	}
202
 
203
	// Option methods
204
	const showOptionModal = (option = INITIAL_OPTION, type = 'add') => {
205
		setIsShowOptionModal(true)
206
		setOptionType(type)
207
		setOptionSelected(option)
208
	}
209
 
210
	const addOption = (option) => {
211
		const uuid = new Date().getTime()
212
 
213
		setContent(current =>
214
			current.map(currentSection => {
215
				if (currentSection.slug_section === sectionSelected.slug_section) {
216
 
217
					currentSection.questions.map(currentQuestion => {
218
						if (currentQuestion.slug_question === questionSelected.slug_question) {
219
							return {
220
								...currentQuestion,
221
								options: [
222
									...currentQuestion.options,
223
									{
224
										...option,
225
										slug_question: questionSelected.slug_question,
226
										slug_section: sectionSelected.slug_section,
227
										slug_option: `option${uuid}`
228
									}
229
								]
230
							}
231
						}
232
 
233
						return currentQuestion
234
					})
235
				}
236
 
237
				return currentSection
238
			})
239
		)
240
	}
241
 
242
	const deleteOption = (slug) => {
243
		setContent(current =>
244
			current.map(currentSection => {
245
				if (currentSection.slug_section === sectionSelected.slug_section) {
246
 
247
					currentSection.questions.map(question => {
248
 
249
						if (question.slug_question === questionSelected.slug_question) {
250
							return {
251
								...question,
252
								options: question.options.filter(option => option.slug_option !== slug)
253
							}
254
						}
255
 
256
						return question
257
					})
258
				}
259
 
260
				return currentSection
261
			}),
262
		)
263
	}
264
 
265
	// General methods
266
	const deleteHandler = (type, slug) => {
267
		if (type === 'section') {
268
			return deleteSection(slug)
269
		}
270
		if (type === 'question') {
271
			return deleteQuestion(slug)
272
		}
273
		if (type === 'option') {
274
			return deleteOption(slug)
275
		}
276
	}
277
 
12709 stevensc 278
	const onSubmit = () => {
279
		const submitData = new FormData()
280
		submitData.append('name', watch('name'))
281
		submitData.append('description', watch('description'))
282
		submitData.append('text', watch('text'))
283
		submitData.append('status', status)
12791 stevensc 284
		submitData.append('content', JSON.stringify(content))
12709 stevensc 285
 
286
		axios.post(actionLink, submitData)
287
			.then(({ data }) => {
288
				if (!data.success) {
289
					return dispatch(addNotification({
290
						style: 'danger',
291
						msg: typeof data.data === 'string'
292
							? data.data
293
							: 'Ha ocurrido un error'
294
					}))
295
				}
296
 
297
				dispatch(addNotification({
298
					style: 'success',
299
					msg: data.data
300
				}))
301
			})
302
	}
303
 
304
	const submitAndClose = () => {
305
		onSubmit()
306
		reset()
307
		history.goBack()
308
	}
309
 
310
	useEffect(() => {
13008 stevensc 311
		register('text')
312
		register('description')
313
	}, [])
314
 
315
	useEffect(() => {
12726 stevensc 316
		if (action === 'edit') {
317
			axios.get(actionLink)
318
				.then(({ data }) => {
319
					if (!data.success) {
320
						return dispatch(addNotification({
321
							style: 'danger',
322
							msg: 'Ha ocurrido un error'
323
						}))
324
					}
12709 stevensc 325
 
13008 stevensc 326
					register('text')
327
					register('description')
328
 
329
					setContent(data.data.content)
330
					setStatus(data.data.status)
331
 
12726 stevensc 332
					setValue('name', data.data.name)
333
					setValue('description', data.data.description)
334
					setValue('text', data.data.description)
335
				})
336
		}
12709 stevensc 337
	}, [actionLink])
338
 
13008 stevensc 339
 
12709 stevensc 340
	return (
341
		<>
342
			<section className="content">
343
				<div className="row" style={{ padding: 16 }}>
344
					<div className="col-xs-12 col-md-12">
345
						<div className="form-group">
346
							<label>Nombre</label>
347
							<input type="text" name="name" className='form-control' ref={register({ required: true, maxLength: 50 })} />
348
						</div>
349
						<div className="form-group">
350
							<label htmlFor="form-description">Descripción</label>
12856 stevensc 351
							<DescriptionInput
12733 stevensc 352
								defaultValue={watch('description') ? parse(watch('description')) : ''}
12709 stevensc 353
								name='description'
354
								onChange={setValue}
12856 stevensc 355
							/>
12709 stevensc 356
						</div>
357
						<div className="form-group">
358
							<label htmlFor="form-description">Texto</label>
12856 stevensc 359
							<DescriptionInput
12733 stevensc 360
								defaultValue={watch('text') ? parse(watch('text')) : ''}
12709 stevensc 361
								name='text'
362
								onChange={setValue}
12856 stevensc 363
							/>
12709 stevensc 364
						</div>
365
						<div className="form-group">
366
							<label htmlFor="form-status">Estatus</label>
367
							<select name="form-status" className="form-control" onChange={(e) => setStatus(e.target.value)} value={status}>
12728 stevensc 368
								<option value="A">Activo</option>
369
								<option value="I">Inactivo</option>
12709 stevensc 370
							</select>
371
						</div>
372
						<br />
373
						<div className="row">
374
							<div className="col-xs-12 col-md-12">
375
								<div className="panel-group" id="rows" >
376
									<div className="form-group">
377
										<div className="row">
378
											<div className="col-xs-12 col-md-12">
379
												<hr />
12994 stevensc 380
												<div className="d-flex justify-content-end">
381
													<button className='btn btn-primary' onClick={() => showSectionModal()}>
382
														<i className="fa fa-plus" />
383
														Agregar sección
384
													</button>
385
												</div>
12709 stevensc 386
												<br />
387
												<div className="panel-group" id="rows-job-competencies" >
388
													{
389
														content.length > 0
12836 stevensc 390
														&&
391
														content.map((section) => {
12709 stevensc 392
 
12836 stevensc 393
															return (
394
																<div className="panel panel-default" key={section.slug_section}>
395
																	<div className="panel-heading">
396
																		<h4 className="panel-title">
397
																			<a className="accordion-toggle" data-toggle="collapse" aria-expanded="true" data-parent={`panel-${section.slug_section}`} href={`#collapse-${section.slug_section}`}>
398
																				<span className={`section-name${section.slug_section}`}>
399
																					{section.name}
400
																				</span>
401
																			</a>
402
																		</h4>
403
																	</div>
404
																	<div id="collapse-section1661528423935" className="panel-collapse in collapse show">
405
																		<div className="panel-body">
406
																			<div className="table-responsive">
407
																				<table className="table table-bordered">
408
																					<thead>
409
																						<tr>
410
																							<th style={{ width: '10%' }}>Elemento</th>
411
																							<th style={{ width: '50%' }}>Texto</th>
412
																							<th style={{ width: '10%' }}>Tipo</th>
413
																							<th style={{ width: '20%' }}>Acciones</th>
414
																						</tr>
415
																					</thead>
416
																					<tbody>
417
																						<tr className="tr-section">
418
																							<td className="text-left">Sección</td>
419
																							<td className="text-left">{section.name}</td>
420
																							<td />
421
																							<td>
422
																								<button className="btn btn-default" onClick={() => showSectionModal(section, 'edit')}>
423
																									<i className="fa fa-edit" />
424
																									Editar Sección
425
																								</button>
12994 stevensc 426
																								<button className="btn btn-default" onClick={() => {
13007 stevensc 427
																									setSectionSelected(section)
428
																									setDeleteType('section')
12993 stevensc 429
																									setShowDeleteModal(true)
430
																								}}>
12836 stevensc 431
																									<i className="fa fa-ban" />
432
																									Borrar Sección
433
																								</button>
13003 stevensc 434
																								<button className="btn btn-default" onClick={() => {
13007 stevensc 435
																									setSectionSelected(section)
13003 stevensc 436
																									showQuestionModal()
437
																								}}>
12836 stevensc 438
																									<i className="fa fa-plus" />
439
																									Agregar  Pregunta
440
																								</button>
441
																							</td>
442
																						</tr>
443
																						{
444
																							section.questions.map((question) => (
13067 stevensc 445
																								<>
446
																									<tr key={question.slug_question} className="tr-question">
447
																										<td className="text-left">Pregunta</td>
448
																										<td className="text-left">
449
																											{parse(question.text)}
450
																										</td>
451
																										<td className="text-capitalize">
452
																											{sectionTypeOptions[question.type]}
453
																										</td>
454
																										<td>
455
																											<button className="btn btn-default" onClick={() => {
456
																												setSectionSelected(section)
457
																												showQuestionModal(question, 'edit')
458
																											}}>
459
																												<i className="fa fa-edit" /> Editar Pregunta
12996 stevensc 460
																											</button>
13067 stevensc 461
																											<button className="btn btn-default" onClick={() => {
462
																												setQuestionSelected(question)
463
																												setDeleteType('question')
464
																												setShowDeleteModal(true)
465
																											}}>
466
																												<i className="fa fa-ban" /> Borrar Pregunta
467
																											</button>
468
																											{
469
																												question.type !== 'open'
470
																												&&
471
																												<button className="btn btn-default">
472
																													<i className="fa fa-plus" /> Agregar opción
473
																												</button>
474
																											}
475
																										</td>
476
																									</tr>
477
																									{
478
																										question.options.map(option => (
479
																											<tr key={option.slug_question} className="tr-option">
480
																												<td className="text-left">Pregunta</td>
481
																												<td className="text-left">
482
																													{parse(option.text)}
483
																												</td>
484
																												<td />
485
																												<td>
486
																													<button className="btn btn-default" onClick={() => {
487
																														setSectionSelected(section)
488
																														setQuestionSelected(question)
489
																														showOptionModal(option, 'edit')
490
																													}}>
491
																														<i className="fa fa-edit" /> Editar opción
492
																													</button>
493
																													<button className="btn btn-default" onClick={() => {
494
																														setOptionSelected(option)
495
																														setQuestionSelected(question)
496
																														setDeleteType('option')
497
																														setShowDeleteModal(true)
498
																													}}>
499
																														<i className="fa fa-ban" /> Borrar opción
500
																													</button>
501
																												</td>
502
																											</tr>
503
																										))
504
																									}
505
																								</>
12836 stevensc 506
																							))
507
																						}
13067 stevensc 508
 
12836 stevensc 509
																					</tbody>
510
																				</table>
511
																			</div>
512
																		</div>
513
																	</div>
514
																</div>
515
															)
516
														})
12709 stevensc 517
													}
518
												</div>
519
											</div>
520
										</div>
521
									</div>
522
								</div>
523
							</div>
524
						</div>
525
						<div className="d-flex" style={{ gap: '5px' }}>
526
							<button type="button" className="btn btn-info" onClick={onSubmit}>Guardar & Continuar</button>
527
							<button type="button" className="btn btn-primary" onClick={submitAndClose}>Guardar & Cerrar</button>
528
							<button type="button" className="btn btn-secondary" onClick={() => history.goBack()}>Cancelar</button>
529
						</div>
530
					</div>
531
				</div >
532
			</section >
533
			<SectionModal
534
				show={isShowSection}
12836 stevensc 535
				sectionType={sectionType}
12709 stevensc 536
				section={sectionSelected}
537
				closeModal={closeSectionModal}
538
				onSubmit={sectionType === 'add' ? addSection : editSection}
539
			/>
12996 stevensc 540
			<QuestionModal
541
				show={isShowQuestion}
542
				questionType={questionType}
543
				question={questionSelected}
544
				closeModal={closeQuestionModal}
545
				onSubmit={questionType === 'add' ? addQuestion : editQuestion}
546
			/>
13067 stevensc 547
			<OptionModal
548
				show={isShowOption}
549
				questionType={optionType}
550
				question={optionSelected}
551
				closeModal={closeOptionModal}
552
				onSubmit={optionType === 'add' ? addOption : editQuestion}
553
			/>
12993 stevensc 554
			<DeleteModal
555
				isOpen={showDeleteModal}
556
				closeModal={() => setShowDeleteModal(false)}
13007 stevensc 557
				onComplete={() => deleteHandler(deleteType, deleteSlugsOptions[deleteType])}
12993 stevensc 558
				message="Registro eliminado"
559
			/>
12709 stevensc 560
		</>
561
	)
562
}
563
 
564
export default FormView