DependenciaDetalle.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. import React, { useState, useEffect, useMemo } from "react";
  2. import { Form, Button, Row, Col, Input, Modal, Table, Typography, Select } from "antd";
  3. import { SaveOutlined, PlusOutlined, CloseCircleOutlined } from "@ant-design/icons";
  4. import { useQuery, useModels, useModel } from "../../../hooks";
  5. import { useHistory } from "react-router-dom";
  6. // import { firestore } from "../../../services/firebase";
  7. import { ViewLoading } from "../../../components";
  8. import { DefaultLayout } from "../../../components/layouts";
  9. // import { addDoc, collection, doc, getDoc, updateDoc } from "firebase/firestore";
  10. import HttpService from "../../../services/httpService";
  11. import { emptyRequest } from "../../../constants/requests";
  12. import { respuestas } from "../../../utilities";
  13. const { Title } = Typography;
  14. const DependenciaDetalle = () => {
  15. // const firebaseCollection = "dependencias";
  16. const query = useQuery();
  17. const history = useHistory();
  18. const { TextArea } = Input;
  19. const id = query.get("id");
  20. const editando = Boolean(id);
  21. const titulo = editando ? "Editar dependencia" : "Agregar dependencia";
  22. const url = "/administracion/dependencias";
  23. const [form] = Form.useForm();
  24. // const [dependencia, setDependencia] = useState([]);
  25. // const [cargandoDependencia, setCargandoDependencia] = useState(true);
  26. const [guadandoCargando, setGuardandoCargando] = useState(false);
  27. const [buscarValue, setBuscarValue] = useState('');
  28. const [requestUsuarios, setRequestUsuarios] = useState({});
  29. const [timer, setTimer] = useState(null);
  30. const [miembros, setMiembros] = useState([]);
  31. const [miembrosLoading, setMiembrosLoading] = useState(false);
  32. const [usuario, setUsuario] = useState(null);
  33. const [miembro, setMiembro] = useState(null);
  34. const [lideres, setLideres] = useState([]);
  35. const [request, setRequest] = useState(emptyRequest);
  36. const requestParams = useMemo(() => ({
  37. name: 'v1/dependencia',
  38. id: id,
  39. expand: 'lideres,usuarios'
  40. }), [id]);
  41. const usuarioExtraParams = React.useMemo(() => ({ q: buscarValue }), [buscarValue])
  42. const usuariosParams = React.useMemo(() => ({
  43. name: 'v1/usuario',
  44. limite: 20,
  45. ordenar: 'nombre-asc',
  46. expand: 'grupos',
  47. extraParams: usuarioExtraParams
  48. }), [usuarioExtraParams])
  49. const {
  50. model,
  51. modelLoading
  52. } = useModel(request);
  53. const [
  54. models,
  55. modelsLoading, , ,
  56. ] = useModels(requestUsuarios);
  57. const columnasMiembros = [
  58. { title: 'Nombre', dataIndex: 'nombre', key: 'nombre', },
  59. { title: 'Correo', dataIndex: 'email', key: 'email', },
  60. {
  61. title: '', dataIndex: 'id', key: 'id', render: (text) =>
  62. <Button
  63. danger
  64. icon={<CloseCircleOutlined />}
  65. onClick={() => setMiembros(miembros.filter(l => l.id !== text))}
  66. />
  67. },
  68. ]
  69. const columnasLideres = [
  70. { title: 'Nombre', dataIndex: 'nombre', key: 'nombre', },
  71. {
  72. title: '', dataIndex: 'id', key: 'id', render: (text) =>
  73. <Button
  74. danger
  75. icon={<CloseCircleOutlined />}
  76. onClick={() => setLideres(lideres.filter(l => l.id !== text))}
  77. />
  78. },
  79. ]
  80. const onSearchUsuarios = (value) => {
  81. clearTimeout(timer);
  82. const newTimer = setTimeout(() => {
  83. setBuscarValue(value);
  84. }, 300);
  85. setTimer(newTimer);
  86. };
  87. const onFinish = async (values) => {
  88. try {
  89. setGuardandoCargando(true);
  90. let body = {
  91. ...values,
  92. // timestamp: editando ? dependencia?.timestamp : new Date(),
  93. // estatus: editando ? dependencia?.estatus : true,
  94. sincronizado: null,
  95. lideres: lideres.map(l => ({
  96. id: l.id,
  97. nombre: l.nombre,
  98. })),
  99. usuarios: miembros.map(l => ({
  100. id: l.id,
  101. nombre: l.nombre,
  102. }))
  103. };
  104. if (editando) {
  105. body.id = model?.id;
  106. }
  107. const res = await HttpService.post('v1/dependencia', body);
  108. respuestas(res);
  109. if (res?.status === 200) {
  110. Modal.success({
  111. title: "Éxito",
  112. content: "Dependencia guardada correctamente",
  113. });
  114. history.push(url);
  115. }
  116. // comentario prueba
  117. // Agregamos o editamos el documento grupo
  118. /* if (editando) {
  119. await updateDoc(doc(firestore, firebaseCollection, id), body);
  120. } else {
  121. await addDoc(collection(firestore, firebaseCollection), body);
  122. } */
  123. } catch (error) {
  124. Modal.warning({
  125. title: "Atención",
  126. content: "Hubo un problema al guardar, intentalo de nuevo.",
  127. });
  128. console.log("Error al guardar: ", error);
  129. } finally {
  130. setGuardandoCargando(false);
  131. }
  132. };
  133. const onFinishFailed = () => {
  134. Modal.warning({
  135. title: "Atención",
  136. content: "Por favor revise los datos.",
  137. style: { marginTop: "20vh" },
  138. });
  139. };
  140. useEffect(() => {
  141. setRequest(requestParams);
  142. return () => setRequest({});
  143. }, [requestParams]);
  144. useEffect(() => {
  145. setRequestUsuarios(usuariosParams);
  146. return () => setRequestUsuarios({});
  147. }, [usuariosParams]);
  148. /* useEffect(() => {
  149. if (editando && id) {
  150. const getMiembros = async () => {
  151. setMiembrosLoading(true);
  152. const response = await HttpService.get(`v1/usuario?ordenar=nombre-asc&idDependencia=${id}&limite=-1`);
  153. if (!response.isError) {
  154. setMiembros(response.resultado);
  155. setMiembrosLoading(false);
  156. }
  157. }
  158. getMiembros();
  159. }
  160. }, [editando, id]); */
  161. /* useEffect(() => {
  162. let mounted = true;
  163. if (mounted && editando) {
  164. try {
  165. setTimeout(async () => {
  166. const docRef = doc(firestore, "dependencias", id);
  167. const docSnap = await getDoc(docRef);
  168. setDependencia(docSnap.data());
  169. const { usuarios } = docSnap.data();
  170. if (usuarios?.length > 0) {
  171. setLideres(usuarios);
  172. }
  173. }, 0);
  174. } catch (error) {
  175. console.log("Error al obtener dependencia: ", error);
  176. } finally {
  177. setCargandoDependencia(false);
  178. }
  179. }
  180. return () => (mounted = false);
  181. }, [editando, id]); */
  182. useEffect(() => {
  183. if (model && editando) {
  184. form.setFieldsValue({
  185. ...model,
  186. });
  187. if (model?.lideres) {
  188. setLideres(model?.lideres);
  189. }
  190. if (model?.usuarios) {
  191. setMiembros(model?.usuarios);
  192. }
  193. }
  194. }, [editando, form, model]);
  195. if (modelLoading && editando) return <ViewLoading />;
  196. return (
  197. <DefaultLayout title={titulo} multipleButtonData={[]}>
  198. <Form
  199. name="form"
  200. form={form}
  201. autoComplete="off"
  202. layout="vertical"
  203. onFinish={onFinish}
  204. onFinishFailed={onFinishFailed}
  205. >
  206. {/* Nombre de la dependecia */}
  207. <Row gutter={10}>
  208. <Col
  209. className="gutter-row"
  210. xs={{ span: 24 }}
  211. sm={{ span: 24 }}
  212. md={{ span: 12 }}
  213. lg={{ span: 12 }}
  214. >
  215. <Form.Item
  216. label="Nombre de la dependencia"
  217. name="nombre"
  218. rules={[{ required: true, message: "Requerido" }]}
  219. >
  220. <Input placeholder="Ingresa un nombre..." />
  221. </Form.Item>
  222. </Col>
  223. </Row>
  224. {/* Descripción */}
  225. <Row gutter={10}>
  226. <Col className="gutter-row" span={24}>
  227. <Form.Item
  228. label="Descripción"
  229. name="descripcion"
  230. rules={[{ required: true, message: "Requerido" }]}
  231. >
  232. <TextArea rows={4} placeholder="Ingrese una Descripción" />
  233. </Form.Item>
  234. </Col>
  235. </Row>
  236. <Row gutter={10}>
  237. <Col className="gutter-row" span={12}>
  238. <Title level={4}>Miembros</Title>
  239. <Row>
  240. <Col span={22}>
  241. <Form.Item
  242. label="Usuarios"
  243. rules={[{
  244. required: true,
  245. message: 'Selecciona un usuario!',
  246. }]}
  247. hasFeedback
  248. >
  249. <Select
  250. showSearch
  251. onSearch={onSearchUsuarios}
  252. allowClear
  253. placeholder="Elige a un usuario"
  254. optionFilterProp="children"
  255. filterOption={(input, option) => (option?.label ?? '').toLowerCase().includes(input.toLowerCase())}
  256. loading={modelsLoading}
  257. onChange={(_, item) => {
  258. setMiembro(item);
  259. console.log("item", item);
  260. }}
  261. options={models?.length > 0 && models?.map(i => ({
  262. ...i,
  263. value: i.id,
  264. label: i.nombre
  265. }))}
  266. value={miembro}
  267. />
  268. </Form.Item>
  269. </Col>
  270. <Col span={2}>
  271. <Form.Item label="&nbsp;">
  272. <Button
  273. type="default"
  274. icon={<PlusOutlined />}
  275. shape="circle"
  276. size="middle"
  277. style={{
  278. // marginTop: 70,
  279. marginLeft: 10
  280. }}
  281. onClick={() => {
  282. if (miembro) {
  283. //agregar sólo si no existe en el array, con esto evitamos duplicados
  284. if (!miembros.find(i => i.id === miembro.id)) {
  285. setMiembros([...miembros, miembro]);
  286. setMiembro(null);
  287. }
  288. }
  289. }}
  290. />
  291. </Form.Item>
  292. </Col>
  293. </Row>
  294. <Table
  295. columns={columnasMiembros}
  296. dataSource={miembros}
  297. loading={miembrosLoading}
  298. size="small"
  299. rowKey="id"
  300. scroll={{ y: 400 }}
  301. pagination={
  302. miembros.length > 10
  303. ? {
  304. pageSize: 10,
  305. position: ["bottomCenter"],
  306. showTotal: (total, range) => `${range[0]}-${range[1]} de ${total} registros`,
  307. } : false
  308. }
  309. />
  310. <br />
  311. </Col>
  312. <Col className="gutter-row" span={12}>
  313. <Row>
  314. <Col span={22}>
  315. <Title level={4}>Líderes</Title>
  316. <Form.Item
  317. label="Usuarios"
  318. rules={[{
  319. required: true,
  320. message: 'Selecciona un usuario!',
  321. }]}
  322. hasFeedback
  323. >
  324. <Select
  325. showSearch
  326. onSearch={onSearchUsuarios}
  327. allowClear
  328. placeholder="Elige a un usuario"
  329. optionFilterProp="children"
  330. filterOption={(input, option) => (option?.label ?? '').toLowerCase().includes(input.toLowerCase())}
  331. loading={modelsLoading}
  332. onChange={(_, item) => {
  333. setUsuario(item);
  334. console.log("item", item);
  335. }}
  336. options={models?.length > 0 && models?.map(i => ({
  337. ...i,
  338. value: i.id,
  339. label: i.nombre
  340. }))}
  341. value={usuario}
  342. />
  343. </Form.Item>
  344. </Col>
  345. <Col span={2}>
  346. <Button
  347. type="default"
  348. icon={<PlusOutlined />}
  349. shape="circle"
  350. size="middle"
  351. style={{
  352. marginTop: 70,
  353. marginLeft: 10
  354. }}
  355. onClick={() => {
  356. if (usuario) {
  357. //agregar sólo si no existe en el array, con esto evitamos duplicados
  358. if (!lideres.find(i => i.id === usuario.id)) {
  359. setLideres([...lideres, usuario]);
  360. setUsuario(null);
  361. }
  362. }
  363. }}
  364. />
  365. </Col>
  366. </Row>
  367. <Table
  368. columns={columnasLideres}
  369. dataSource={lideres}
  370. size="small"
  371. rowKey="id"
  372. pagination={
  373. lideres.length > 10
  374. ? {
  375. pageSize: 10,
  376. position: ["bottomCenter"],
  377. showTotal: (total, range) => `${range[0]}-${range[1]} de ${total} registros`,
  378. } : false
  379. }
  380. />
  381. </Col>
  382. </Row>
  383. <Row gutter={10}>
  384. <Col
  385. xs={{ span: 24 }}
  386. sm={{ span: 24 }}
  387. md={{ span: 12 }}
  388. lg={{ span: 8 }}
  389. >
  390. <Button
  391. type="primary"
  392. htmlType="submit"
  393. icon={<SaveOutlined />}
  394. block
  395. size="large"
  396. loading={guadandoCargando}
  397. >
  398. Guardar
  399. </Button>
  400. </Col>
  401. </Row>
  402. </Form>
  403. </DefaultLayout>
  404. )
  405. }
  406. export default DependenciaDetalle