Proyectos de Subversion LeadersLinked - Backend

Rev

Rev 15128 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
10540 stevensc 1
/* eslint-disable no-mixed-spaces-and-tabs */
15126 stevensc 2
import React, { useState, useEffect } from 'react'
10513 stevensc 3
import axios from 'axios'
15126 stevensc 4
import parse from 'html-react-parser'
10513 stevensc 5
import { useForm } from 'react-hook-form'
6
import { useDispatch } from 'react-redux'
7
import { addNotification } from '../../../redux/notification/notification.actions'
10436 stevensc 8
 
15126 stevensc 9
const FormView = ({
10
	actionLink,
11
	type_link,
12
	vacancy_link,
13
	vacancies,
14
	add_link,
15
	setActionLink,
16
	action,
17
	setAction
18
}) => {
10439 stevensc 19
 
10558 stevensc 20
	// States
15375 stevensc 21
	const [loading, setLoading] = useState(false)
10845 stevensc 22
	const [vacancyOptions, setVacancyOptions] = useState(vacancies)
23
	const [vacancyUrl, setVacancyUrl] = useState(vacancy_link.replace('UUID_PLACEHOLDER', vacancies[0].uuid))
10840 stevensc 24
	const [typeOptions, setTypeOptions] = useState({
25
		url: type_link,
26
		value: ''
27
	})
10558 stevensc 28
	const [generalOptions, setGeneralOptions] = useState({
29
		uuid: '',
30
		name: '',
31
		description: '',
32
		functions: '',
33
		objectives: ''
34
	})
10852 stevensc 35
	const [candidatesOptions, setCandidatesOptions] = useState([])
10853 stevensc 36
	const [competencies, setCompetencies] = useState([{
37
		competency_uuid: '',
38
		competency_name: '',
39
		competency_type_uuid: '',
40
		competency_type_name: '',
41
		behaviors: []
42
	}])
11069 stevensc 43
	const [pointsOptions] = useState([
15090 efrain 44
		{ label: 'N/A', value: 0 },
45
		{ label: '25%', value: 1 },
46
		{ label: '50%', value: 2 },
47
		{ label: '75%', value: 3 },
48
		{ label: '100%', value: 4 }
49
	])
50
	const [pointsGlobalOptions] = useState([
10558 stevensc 51
		{ label: 'Sugerir otro cargo', value: 0 },
52
		{ label: '25%', value: 1 },
53
		{ label: '50%', value: 2 },
54
		{ label: '75%', value: 3 },
55
		{ label: '100%', value: 4 }
56
	])
11069 stevensc 57
	const [statusOptions] = useState([
10558 stevensc 58
		{ label: 'Aceptado', value: 'a' },
59
		{ label: 'Rechazado', value: 'r' }
60
	])
10516 stevensc 61
 
10558 stevensc 62
	// Hooks
10852 stevensc 63
	const { setValue, register, watch, handleSubmit } = useForm()
10558 stevensc 64
	const dispatch = useDispatch()
10439 stevensc 65
 
11071 stevensc 66
	const onSubmit = () => {
15375 stevensc 67
		setLoading(true)
10856 stevensc 68
		const content = []
69
		competencies.forEach(competency => competency.behaviors.forEach(behavior => {
70
			content.push({
10852 stevensc 71
				competencyUuid: behavior.competency_uuid,
72
				behaviorUuid: behavior.uuid,
11075 stevensc 73
				comment: watch(`${behavior.competency_uuid}-${behavior.uuid}-comment`),
11073 stevensc 74
				evaluation: watch(`select-${behavior.competency_uuid}-${behavior.uuid}`)
10856 stevensc 75
			})
10853 stevensc 76
		}))
10852 stevensc 77
 
78
		const submitData = new FormData()
10865 stevensc 79
		submitData.append('content', JSON.stringify(content))
10852 stevensc 80
		submitData.append('candidate_uuid', watch('candidate'))
81
		submitData.append('points', watch('points'))
82
		submitData.append('comment', watch('comment'))
83
		submitData.append('status', watch('status'))
84
 
10859 stevensc 85
		axios.post(actionLink, submitData)
86
			.then(({ data }) => {
87
				if (!data.success) {
11071 stevensc 88
					typeof data.data === 'string'
89
						?
90
						dispatch(addNotification({
91
							style: 'danger',
92
							msg: data.data
93
						}))
14738 stevensc 94
						: Object.entries(data.data).map(([key, value]) =>
95
							value.map(err =>
96
								dispatch(addNotification({
97
									style: 'danger',
98
									msg: `${key}: ${err}`
99
								}))
100
							)
101
						)
11072 stevensc 102
					return
10859 stevensc 103
				}
15126 stevensc 104
				setAction('')
10859 stevensc 105
				dispatch(addNotification({
106
					style: 'success',
107
					msg: `Registro ${action === 'edit' ? 'actualizado' : 'añadido'}`
108
				}))
109
			})
15375 stevensc 110
			.finally(() => setLoading(true))
10852 stevensc 111
	}
112
 
10558 stevensc 113
	useEffect(() => {
10840 stevensc 114
		if (action === 'edit') {
115
			axios.get(actionLink)
116
				.then(({ data }) => {
117
					const resData = data.data
118
 
119
					if (!data.success) {
11071 stevensc 120
						return dispatch(addNotification({
11051 stevensc 121
							style: 'danger',
10840 stevensc 122
							msg: 'Ha ocurrido un error'
123
						}))
124
					}
125
 
126
					setCompetencies(resData.job_description.competencies)
10844 stevensc 127
					setCandidatesOptions([resData.candidate])
128
					setVacancyOptions([{ name: resData.vacancy.name, uuid: resData.vacancy.uuid }])
10843 stevensc 129
					setTypeOptions({ ...typeOptions, value: resData.interview.type === 'r' ? 'Entrevista por Recursos Humanos' : 'Entrevista por Potencial superior' })
10840 stevensc 130
					setGeneralOptions({
131
						...generalOptions,
132
						name: resData.vacancy.name,
133
						uuid: resData.vacancy.uuid,
134
						description: resData.vacancy.description,
135
						functions: resData.job_description.functions,
136
						objectives: resData.job_description.objectives
137
					})
11237 stevensc 138
					setValue('comment', resData.interview.comment)
139
					setValue('points', resData.interview.points)
140
					setValue('status', resData.interview.status)
11073 stevensc 141
					resData.interview.content.forEach((obj) => {
142
						setValue(`select-${obj.competencyUuid}-${obj.behaviorUuid}`, obj.evaluation)
11074 stevensc 143
						setValue(`${obj.competencyUuid}-${obj.behaviorUuid}-comment`, obj.comment)
11073 stevensc 144
					})
10840 stevensc 145
				})
146
		}
147
	}, [action])
148
 
149
	useEffect(() => {
150
		axios.get(typeOptions.url)
10753 stevensc 151
			.then(({ data }) => {
10513 stevensc 152
 
10753 stevensc 153
				if (!data.success) {
11071 stevensc 154
					return dispatch(addNotification({
11051 stevensc 155
						style: 'danger',
10753 stevensc 156
						msg: 'Ha ocurrido un error'
157
					}))
158
				}
10513 stevensc 159
 
10843 stevensc 160
				setTypeOptions({ ...typeOptions, value: data.data })
10753 stevensc 161
			})
162
 
10840 stevensc 163
	}, [typeOptions.url])
10516 stevensc 164
 
10843 stevensc 165
	useEffect(() => {
10935 stevensc 166
		if (action == 'add') {
167
			axios.get(vacancyUrl)
168
				.then(({ data }) => {
169
					const resData = data.data
10843 stevensc 170
 
10935 stevensc 171
					if (!data.success) {
11071 stevensc 172
						return dispatch(addNotification({
11051 stevensc 173
							style: 'danger',
10935 stevensc 174
							msg: 'Ha ocurrido un error'
175
						}))
176
					}
10843 stevensc 177
 
10935 stevensc 178
					setCandidatesOptions(resData.candidates)
179
					setCompetencies(resData.job_description.competencies)
180
					setTypeOptions({ ...typeOptions, value: resData.interview.type === 'r' ? 'Entrevista por Recursos Humanos' : 'Entrevista por Potencial superior' })
181
					setGeneralOptions({
182
						...generalOptions,
183
						name: resData.vacancy.name,
184
						uuid: resData.vacancy.uuid,
185
						description: resData.vacancy.description,
186
						functions: resData.job_description.functions,
187
						objectives: resData.job_description.objectives
188
					})
10843 stevensc 189
				})
10935 stevensc 190
		}
10843 stevensc 191
	}, [vacancyUrl])
192
 
10558 stevensc 193
	return (
194
		<section className="content">
195
			<div className="container-fluid">
196
				<div className="row">
197
					<div className="col-12">
10852 stevensc 198
						<form onSubmit={handleSubmit(onSubmit)}>
199
							<div className='card'>
200
								<div className="card-header">
201
									<ul className="nav nav-tabs" id="myTab" role="tablist">
202
										<li className="nav-item" role="presentation">
203
											<button className="nav-link active" id="home-tab" data-toggle="tab" data-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">General</button>
204
										</li>
205
										<li className="nav-item" role="presentation">
206
											<button className="nav-link" id="profile-tab" data-toggle="tab" data-target="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Competencias</button>
207
										</li>
208
										<li className="nav-item" role="presentation">
209
											<button className="nav-link" id="contact-tab" data-toggle="tab" data-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="false">Conclusiones</button>
210
										</li>
211
									</ul>
212
								</div>
213
								<div className="card-body">
214
									<div className="tab-content" id="myTabContent">
215
										<div className="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
216
											<div className="row p-3 justify-content-between">
217
												<div className="col-6">
218
													<div className="form-group">
219
														<label>Vacantes</label>
10856 stevensc 220
														<select
221
															className='form-control'
222
															name='vacancy' ref={register}
223
															disabled={action === 'edit'}
224
															onChange={(e) => {
225
																setVacancyUrl(vacancy_link.replace('UUID_PLACEHOLDER', e.target.value))
226
																setActionLink(add_link.replace('UUID_PLACEHOLDER', e.target.value))
227
															}}>
10852 stevensc 228
															{
229
																vacancyOptions.map(({ name, uuid }) => (
230
																	<option selected={generalOptions.name === name} key={uuid} value={uuid}>{name}</option>
231
																))
232
															}
233
														</select>
234
													</div>
10569 stevensc 235
												</div>
10852 stevensc 236
												<div className="col-6">
237
													<div className="form-group">
238
														<label>Candidatos</label>
239
														<select className='form-control' name='candidate' ref={register} disabled={action === 'edit'} onChange={(e) => setTypeOptions(prev => ({ ...prev, url: type_link.replace('UUID_PLACEHOLDER', e.target.value) }))}>
240
															{
241
																candidatesOptions.map(({ first_name, last_name, uuid }) => (
242
																	<option selected={watch('candidate') === uuid} key={uuid} value={uuid}>{`${first_name} ${last_name}`}</option>
243
																))
244
															}
245
														</select>
246
													</div>
247
												</div>
10558 stevensc 248
											</div>
15127 stevensc 249
											<h5 className='mb-3'>{typeOptions.value}</h5>
10852 stevensc 250
											<div className="card">
251
												<div className="card-body">
15128 stevensc 252
													<h5>{generalOptions.name}</h5>
253
													<p className='mb-2'>{parse(generalOptions.description)}</p>
254
													<h6>Funciones</h6>
255
													<p className='mb-2'>{parse(generalOptions.functions)}</p>
256
													<h6>Objetivos</h6>
257
													<p className='mb-2'>{parse(generalOptions.objectives)}</p>
10569 stevensc 258
												</div>
10558 stevensc 259
											</div>
260
										</div>
10852 stevensc 261
										<div className="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab">
15126 stevensc 262
											{competencies.map((competency) => (
263
												<div className="card" key={competency.competency_uuid}>
264
													<div className="card-header">
265
														<h5>{competency.competency_name} - {competency.competency_type_name}</h5>
266
													</div>
267
													<div className="card-body">
268
														<div className="table-responsive">
269
															{
270
																competency.behaviors
271
																&&
272
																competency.behaviors.map((behavior) => (
273
																	<table key={behavior.uuid} className="table table-hover">
274
																		<thead>
275
																			<tr>
276
																				<th style={{ width: '20%' }}>Conducta Observable</th>
277
																				<th style={{ width: '60%' }}>Comentario</th>
278
																				<th style={{ width: '20%' }}>Evaluación</th>
279
																			</tr>
280
																		</thead>
281
																		<tbody>
282
																			<tr>
283
																				<td style={{ width: '20%' }}>{behavior.description}</td>
284
																				<td style={{ width: '60%' }}>
285
																					<input
286
																						type="text"
287
																						name={`${behavior.competency_uuid}-${behavior.uuid}-comment`}
288
																						maxLength="80"
289
																						ref={register}
290
																						className='form-control w100'
291
																					/>
292
																				</td>
293
																				<td style={{ width: '20%' }}>
294
																					<select className='form-control' name={`select-${behavior.competency_uuid}-${behavior.uuid}`} ref={register}>
295
																						{
296
																							pointsOptions.map(({ label, value }) => {
297
																								return <option selected={watch(`select-${behavior.competency_uuid}-${behavior.uuid}`) === value} key={value} value={value}>{label}</option>
298
																							})
299
																						}
300
																					</select>
301
																				</td>
302
																			</tr>
303
																		</tbody>
304
																	</table>
305
																))
306
															}
10852 stevensc 307
														</div>
308
													</div>
15126 stevensc 309
												</div>
310
											))
10852 stevensc 311
											}
312
										</div>
313
										<div className="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">
314
											<div className="form-group">
315
												<label>Comentario</label>
15090 efrain 316
												<textarea type="text" name="comment" className="form-control" rows="5" cols="50" ref={register} />
10558 stevensc 317
											</div>
10852 stevensc 318
											<div className="form-group">
319
												<label>Evaluación</label>
11237 stevensc 320
												<select className='form-control' name='points' ref={register}>
10852 stevensc 321
													{
15090 efrain 322
														pointsGlobalOptions.map(({ label, value }) => (
10852 stevensc 323
															<option selected={watch('points') === value} key={value} value={value}>{label}</option>
324
														))
325
													}
326
												</select>
327
											</div>
328
											<div className="form-group">
329
												<label>Estatus</label>
11237 stevensc 330
												<select className='form-control' name='status' ref={register}>
10852 stevensc 331
													{
332
														statusOptions.map(({ label, value }) => (
333
															<option selected={watch('status') === value} key={value} value={value}>{label}</option>
334
														))
335
													}
336
												</select>
337
											</div>
10558 stevensc 338
										</div>
339
									</div>
10852 stevensc 340
									<div className="form-group">
15375 stevensc 341
										<button
342
											className="btn btn-primary btn-form-save-close mr-2"
343
											disabled={loading}
344
											type="submit"
345
										>
10852 stevensc 346
											Guardar
347
										</button>
348
										<button
349
											type="button"
350
											className="btn btn-secondary btn-edit-cancel"
15126 stevensc 351
											onClick={() => setAction('')}
10852 stevensc 352
										>
353
											Cancelar
354
										</button>
10558 stevensc 355
									</div>
356
								</div>
357
							</div>
10852 stevensc 358
						</form>
10558 stevensc 359
					</div>
360
				</div>
361
			</div>
362
		</section >
363
	)
10436 stevensc 364
}
365
export default FormView