Selector.jsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import React from 'react'
  2. import PropTypes from "prop-types";
  3. import { Select as AntdSelect, Tag } from 'antd'
  4. import { useModels } from '../hooks';
  5. import { agregarFaltantes } from '../utilities';
  6. const Selector = ({
  7. modelsParams,
  8. labelProp,
  9. valueProp,
  10. render,
  11. append,
  12. deleteSelected,
  13. extraParams,
  14. onChange,
  15. labelInValue = false,
  16. filtered = [],
  17. tagOptions,
  18. ...props
  19. }) => {
  20. const [request, setRequest] = React.useState({});
  21. const [buscarValue, setBuscarValue] = React.useState('');
  22. const [timer, setTimer] = React.useState(null);
  23. const [selected, setSelected] = React.useState([...filtered]);
  24. const extraParamsMemo = React.useMemo(() => ({ buscar: buscarValue, ...extraParams }),
  25. [buscarValue, extraParams]
  26. );
  27. const requestMemo = React.useMemo(() => ({
  28. name: modelsParams?.name || "",
  29. ordenar: modelsParams?.ordenar || "id-desc",
  30. limite: modelsParams?.limite || 20,
  31. expand: modelsParams?.expand || "",
  32. extraParams: extraParamsMemo,
  33. }), [extraParamsMemo, modelsParams]);
  34. const {
  35. models: modelsData,
  36. modelsLoading: modelsDataLoading,
  37. modelsError
  38. } = useModels(request);
  39. const onSearch = (value) => {
  40. clearTimeout(timer);
  41. const newTimer = setTimeout(() => {
  42. setBuscarValue(value);
  43. }, 300);
  44. setTimer(newTimer);
  45. };
  46. if(!render) {
  47. render = (value) => value;
  48. }
  49. if (!append) {
  50. append = [];
  51. }
  52. const _onChange = (_, option) => {
  53. setSelected(ultimoEstado => agregarFaltantes(ultimoEstado, option, "id"));
  54. }
  55. const options = React.useMemo(() => {
  56. let aux = agregarFaltantes([...modelsData], [...append], valueProp);
  57. aux = aux.filter(item => !selected.find(i => item.id === i.id));
  58. return aux;
  59. }, [append, modelsData, selected, valueProp]);
  60. let _options = []
  61. if (tagOptions) {
  62. for (let i = 10; i < 36; i++) {
  63. _options.push({
  64. value: i.toString(36) + i,
  65. label: i.toString(36) + i,
  66. });
  67. }
  68. }
  69. React.useEffect(() => {
  70. setRequest(requestMemo);
  71. return () => {
  72. setRequest({});
  73. };
  74. }, [requestMemo]);
  75. React.useEffect(() => {
  76. if(onChange) {
  77. onChange && onChange(selected);
  78. }
  79. }, [selected, onChange]);
  80. if(modelsError) {
  81. return <Tag color='red'>error al obtener información de selector.</Tag>
  82. }
  83. return (
  84. <AntdSelect
  85. {...props}
  86. labelInValue={labelInValue}
  87. mode="multiple"
  88. showSearch
  89. onSearch={onSearch}
  90. defaultActiveFirstOption={false}
  91. filterOption={false}
  92. notFoundContent={null}
  93. allowClear={true}
  94. style={{ width: '100%' }}
  95. loading={modelsDataLoading}
  96. onChange={_onChange}
  97. onClear={() => setSelected([])}
  98. options={ options.map(i => ({
  99. ...i,
  100. label: render(i[labelProp], i),
  101. value: i[valueProp],
  102. }))}
  103. onDeselect={(v) => {
  104. setSelected(ls => ls.filter(i => i.id !== v.value))
  105. }}
  106. />
  107. )
  108. }
  109. Selector.propTypes = {
  110. modelsParams: PropTypes.object.isRequired,
  111. labelProp: PropTypes.string.isRequired,
  112. valueProp: PropTypes.string.isRequired,
  113. render: PropTypes.func,
  114. notIn: PropTypes.string,
  115. onDeselected: PropTypes.func,
  116. deleteSelected: PropTypes.string,
  117. filtered: PropTypes.array,
  118. };
  119. export default Selector