Operation.jsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. import * as React from 'react';
  2. import {
  3. Button, Dialog, DialogActions, DialogContent,
  4. FormControlLabel, Checkbox, Box, Stack,
  5. TextField,CircularProgress
  6. } from '@mui/material'
  7. import { AddCircle } from '@mui/icons-material/';
  8. import { MailTable } from './Steps/MailTable';
  9. import { Col, Row } from 'react-bootstrap'
  10. import toast, { Toaster } from 'react-hot-toast';
  11. import * as Yup from 'yup';
  12. import { useQueryClient } from 'react-query'
  13. import { Service } from '../../Utils/HTTP.js'
  14. import { useSelector } from 'react-redux'
  15. import { useFormik, Form, FormikProvider } from 'formik';
  16. import { AdapterDateFns as DateFnsUtils } from '@mui/x-date-pickers/AdapterDateFns';
  17. import { DesktopDatePicker } from '@mui/x-date-pickers/DesktopDatePicker';
  18. import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
  19. function Candidatos(props){
  20. const CandidatoSchema = Yup.object().shape({
  21. nombres:
  22. Yup.string()
  23. .min(2, 'Demasiado corto!')
  24. .max(50, 'Demasiado largo!'),
  25. apellidos:
  26. Yup.string()
  27. .min(2, 'Demasiado corto!').max(50, 'Demasiado Largo!'),
  28. mail:
  29. Yup.string()
  30. .email("Correo no valido")
  31. });
  32. let [password, setPassword] = React.useState([]);
  33. let { candidatos } = props
  34. console.log('operation props candidatos', candidatos)
  35. const formik = useFormik({
  36. initialValues: {
  37. nombres: "",
  38. apellidos: "",
  39. mail: "",
  40. },
  41. onSubmit: () => {
  42. if(password.length <= 0){
  43. toast.error("Seleciona almenos un destino")
  44. return;
  45. }
  46. console.log('submited')
  47. },
  48. validationSchema: CandidatoSchema,
  49. });
  50. const { errors, touched, handleSubmit, getFieldProps, values, resetForm,isValid } = formik;
  51. const addToList = () => {
  52. if(!values.nombres || !values.apellidos || !values.mail){
  53. return toast.error("Completa la informacion del candidato")
  54. }
  55. if(!isValid) {
  56. return toast.error("Completa la informacion del candidato")
  57. }
  58. let user = {
  59. 'nombres': values.nombres,
  60. 'apellidos': values.apellidos,
  61. 'mail': values.mail,
  62. }
  63. let new_users = [...password.candidatos, user ]
  64. setPassword({...candidatos, candidatos: new_users })
  65. resetForm();
  66. }
  67. const removeFromList = (umail) => {
  68. let without = password.candidatos.filter( user => user.mail !== umail )
  69. setPassword({...password, candidatos: without })
  70. }
  71. return (
  72. <FormikProvider style={{ padding: 25 }} value={formik}>
  73. <Form autoComplete="off" noValidate onSubmit={handleSubmit}>
  74. <Stack spacing={3}>
  75. <Stack style={{paddingTop: 15}} direction={{ xs: 'column', sm: 'row' }} spacing={2}>
  76. <TextField
  77. label="Nombre"
  78. fullWidth
  79. {...getFieldProps('nombres')}
  80. error={Boolean(touched.nombres && errors.nombres)}
  81. helperText={touched.nombres && errors.nombres}
  82. />
  83. <TextField
  84. label="Apellidos"
  85. fullWidth
  86. {...getFieldProps('apellidos')}
  87. error={Boolean(touched.apellidos && errors.apellidos)}
  88. helperText={touched.apellidos && errors.apellidos}
  89. />
  90. </Stack>
  91. <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>
  92. <TextField
  93. fullWidth
  94. type="email"
  95. label="Correo Electronico"
  96. {...getFieldProps('mail')}
  97. error={Boolean(touched.mail && errors.mail)}
  98. helperText={touched.mail && errors.mail}
  99. />
  100. <Button onClick={addToList}>
  101. <AddCircle style={{color:'var(--main)'}}/>
  102. </Button>
  103. </Stack>
  104. <MailTable
  105. remove={removeFromList}
  106. users={candidatos}
  107. />
  108. <Box sx={{ mb: 2 }}>
  109. <div style={{ paddingTop: 15 }}>
  110. <Button
  111. type="submit"
  112. className="registerBtn"
  113. variant="contained"
  114. sx={{ mt: 1, mr: 1 }}
  115. >
  116. {'Siguiente'}
  117. </Button>
  118. <Button
  119. disabled={false}
  120. onClick={() => console.log('regresar')}
  121. sx={{ mt: 1, mr: 1 }}
  122. >
  123. Regresar
  124. </Button>
  125. </div>
  126. </Box>
  127. </Stack>
  128. <Toaster position="top-right" />
  129. </Form>
  130. </FormikProvider>
  131. );
  132. }
  133. export function ModalEdit(props) {
  134. const auth = useSelector((state) => state.token)
  135. let [data, setData] = React.useState(null)
  136. let { password, open, handleOpen } = props
  137. let { pwd, plz } = password
  138. React.useEffect(() => {
  139. const getPassword = async () => {
  140. let rest = new Service(`/contrasenia/${btoa(pwd)}/${plz}`)
  141. return await rest.getQuery(auth.token)
  142. }
  143. getPassword()
  144. .then(resp => setData(resp.data))
  145. .catch(error => console.log(error))
  146. }, [auth.token, pwd, plz])
  147. return (
  148. <Dialog
  149. fullWidth="md"
  150. maxWidth="md"
  151. open={open}
  152. onClose={() => handleOpen(false)}
  153. aria-labelledby="alert-dialog-title"
  154. aria-describedby="alert-dialog-description"
  155. >
  156. <DialogContent>
  157. {
  158. data ?
  159. <ModalForm
  160. password={data}
  161. handleOpen={handleOpen}
  162. token={auth.token}
  163. /> : <Loading />
  164. }
  165. </DialogContent>
  166. </Dialog>
  167. )
  168. }
  169. function Loading() {
  170. return (
  171. <CircularProgress style={{ color: 'var(--main)' }} />
  172. )
  173. }
  174. function ModalForm(props) {
  175. const pwdSchema = Yup.object().shape({
  176. id: Yup.number(),
  177. pwd: Yup.string().required("Escoge un nombre valido"),
  178. deadpwd: Yup.date().required("Escoge una fecha valida"),
  179. state: Yup.number(),
  180. dateToActived: Yup.date('Escoge una fecha valida').required("Escoge una fecha valida"),
  181. })
  182. const queryClient = useQueryClient();
  183. let { password } = props
  184. console.log("227 PWD: ", password)
  185. let candidatos = password.candidatospwds.map( pwd => {
  186. let { apellidos, nombre,mail} = pwd.candi
  187. return { nombres: nombre, apellidos, mail }
  188. })
  189. const formik = useFormik({
  190. initialValues: {
  191. state: 1,
  192. pwd: atob(password.pwd),
  193. deadpwd: password.deadpwd,
  194. dateToActived: password.dateToActived,
  195. },
  196. onSubmit: (fields) => {
  197. let rest = new Service('/contrasenia/create');
  198. let { deadpwd, dateToActived, pwd } = fields
  199. fields['pwd'] = btoa(pwd);
  200. fields['deadpwd'] = new Date(deadpwd).toISOString();
  201. fields['dateToActived'] = new Date(dateToActived).toISOString();
  202. fields['candidato_id'] = props.initialValues.candidato_id
  203. fields['plaza_id'] = props.initialValues.plaza_id
  204. rest.put(fields, props.token)
  205. .then(result => {
  206. queryClient.invalidateQueries('passwords')
  207. console.log(result)
  208. setTimeout(() => {
  209. props.handleOpen(false)
  210. }, 1000)
  211. toast.success("Contraseña Actualizada")
  212. })
  213. .catch(bad => {
  214. console.log('ERROR', bad)
  215. toast.error("Ocurrio un error")
  216. })
  217. },
  218. validationSchema: pwdSchema,
  219. })
  220. const { errors, touched, handleSubmit, getFieldProps, values, setValues } = formik;
  221. return (
  222. <Row>
  223. <Col>
  224. <FormikProvider value={formik}>
  225. <Form style={{ padding: 20, maxWidth: 950 }} autoComplete="off" noValidate onSubmit={handleSubmit}>
  226. <Stack spacing={4}>
  227. <TextField
  228. value={btoa(values.pwd)}
  229. variant="filled"
  230. disabled
  231. fullWidth
  232. type="text"
  233. label="Contraseña Cifrada"
  234. />
  235. <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>
  236. <TextField
  237. type="text"
  238. label="Contraseña"
  239. {...getFieldProps('pwd')}
  240. error={Boolean(touched.pwd && errors.pwd)}
  241. helperText={touched.pwd && errors.pwd}
  242. />
  243. <FormControlLabel
  244. control={
  245. <Checkbox
  246. checked={values.state === 1}
  247. onChange={(event) => {
  248. let check = event.target.checked;
  249. setValues({
  250. ...values,
  251. state: check ? 1 : 0
  252. })
  253. }}
  254. />
  255. }
  256. label="Activa"
  257. />
  258. </Stack>
  259. <LocalizationProvider
  260. dateAdapter={DateFnsUtils}>
  261. <DesktopDatePicker
  262. label="Fecha de Activación"
  263. fullWidth
  264. inputFormat="dd/MM/yyyy"
  265. value={values.dateToActived}
  266. onChange={(val) => setValues({ ...values, dateToActived: val })}
  267. renderInput={(params) =>
  268. <TextField
  269. {...getFieldProps('dateToActived')}
  270. error={Boolean(touched.dateToActived && errors.dateToActived)}
  271. helperText={touched.dateToActived && errors.dateToActived}
  272. disabled={true}
  273. label="Fecha de Activación"
  274. fullWidth
  275. {...params}
  276. />}
  277. />
  278. </LocalizationProvider>
  279. <LocalizationProvider
  280. dateAdapter={DateFnsUtils}>
  281. <DesktopDatePicker
  282. label="Fecha de Vencimiento"
  283. fullWidth
  284. inputFormat="dd/MM/yyyy"
  285. {...getFieldProps('deadpwd')}
  286. value={values.deadpwd}
  287. onChange={(val) => setValues({ ...values, deadpwd: new Date(val) })
  288. }
  289. renderInput={(params) =>
  290. <TextField
  291. error={Boolean(touched.deadpwd && errors.deadpwd)}
  292. helperText={touched.deadpwd && errors.deadpwd}
  293. disabled={true}
  294. label="Fecha de Vencimiento"
  295. fullWidth
  296. {...params}
  297. />}
  298. />
  299. </LocalizationProvider>
  300. <DialogActions>
  301. <Button onClick={() => props.handleOpen(false)}>
  302. Cerrar
  303. </Button>
  304. <Button
  305. type="submit"
  306. className="registerBtn"
  307. style={{ color: 'white' }}
  308. >
  309. Guardar
  310. </Button>
  311. </DialogActions>
  312. </Stack>
  313. </Form>
  314. <Toaster position="bottom-right" />
  315. </FormikProvider >
  316. </Col>
  317. <Col>
  318. <Candidatos candidatos={candidatos} />
  319. </Col>
  320. </Row>
  321. )
  322. }