UNPKG

es-grid-template

Version:

es-grid-template

454 lines (447 loc) 17.8 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import React, { Fragment, useState } from "react"; import styled from "styled-components"; import { Badge, Button, Tooltip } from "antd"; import { Filter } from "becoxy-icons"; import { DatePicker, TimePicker, TreeSelect, Popover, Input } from "rc-master-ui"; import { checkDecimalSeparator, checkThousandSeparator, convertDateToDayjs, convertDayjsToDate, isArraysEqual, isEmpty, isObjEmpty } from "./hooks"; import CheckboxControl from "./checkbox-control"; import { AsyncSelect } from "./async-select"; import { NumericFormat } from 'react-numeric-component'; import classnames from "classnames"; import { getDefaultOperator } from "rc-master-ui/es/table/util"; const { RangePicker } = DatePicker; const MainFilter = styled.div.withConfig({ displayName: "MainFilter", componentId: "es-grid-template__sc-zdl2xa-0" })([".filter-left{display:flex;flex-direction:column;gap:1rem;width:", ";border-right:1px solid #c4c4c4;}@media (max-width:576px){flex-direction:column-reverse;gap:1rem;.filter-left{width:100%;border-right:0;}}"], props => `${props.leftFilterWidth}px`); const GridFilter = styled.div.withConfig({ displayName: "GridFilter", componentId: "es-grid-template__sc-zdl2xa-1" })(["display:grid;gap:10px;padding-right:1rem;padding-left:1rem;max-height:500px;overflow:auto;overflow-x:hidden;flex-wrap:wrap;grid-template-columns:repeat(2,minmax(250px,1fr));.grid-item-filter{}.adv-form-input{height:32px;}@media (max-width:720px){grid-template-columns:repeat(1,minmax(250px,1fr));}"]); const BoxAction = styled.div.withConfig({ displayName: "BoxAction", componentId: "es-grid-template__sc-zdl2xa-2" })(["border-top:1px solid #c4c4c4;padding-top:0.75rem;display:flex;justify-content:end;gap:10px;.btn-action{background:none !important;border:none !important;&.btn-action-submit{color:#df4318;&:disabled{background-color:#f0f0f0 !important;}&:hover{color:#df4318 !important;}}&:hover{background-color:#f0f0f0 !important;}}"]); // const FilterContainer = styled.div<{ contentWidth?: number }>` // .customizer { // right: ${props => (props.contentWidth ? `-${props.contentWidth}px` : '-400px')}; // width: ${props => (props.contentWidth ? `${props.contentWidth}px` : '400px')}; // } // .customizer.open { // right: 0; // } // .adv-form-input { // height: 32px; // } // .checkbox-dropdown { // .ant-select-tree-treenode { // .ant-select-tree-switcher.ant-select-tree-switcher-noop { // width: 0 !important; // } // } // } // ` const AdvanceFilter = props => { const { columns: defaultColumns, dataSourceFilter, onFilter, // mode = 'dropdown', defaultFilter, leftFilterWidth = 280, format, t } = props; // const columnsChooseRef: any = useRef(null) const menuRef = React.useRef(null); // const [selectedKeys, setSelectedKeys] = useState<string[]>([]); // const [isManualUpdate, setIsManualUpdate] = useState(false); const [prevFilter, setPrevFilter] = useState([]); const [filterColumns, setFilterColumns] = useState([]); const [clicked, setClicked] = useState(false); const [columns, setColumns] = useState([]); const count = 4; // const count = useMemo(() => { // // const uniqueItems = prevFilter.filter((item, index, arr) => { // return arr.findIndex(el => el.field === item.field) === index // }) // // return uniqueItems?.filter((quer: any) => quer.filterOption && quer.filterOption?.value).length ?? 0 // // }, [prevFilter]) React.useEffect(() => { if (defaultColumns) { const filter = defaultColumns.filter(it => it.visible !== false && it.allowFiltering !== false && it.field !== '#' && it.field !== 'command'); const tmpFilter = filter.map(it => ({ ...it, filterOption: { key: it.field, field: it.field, value: undefined, predicate: undefined, operator: it?.filterOption?.operator ? it.filterOption.operator : getDefaultOperator(it) } })); setColumns(filter); setPrevFilter(tmpFilter); setFilterColumns(tmpFilter); } }, [defaultColumns, defaultFilter]); const hide = () => { setClicked(false); }; const handleClickChange = open => { setClicked(open); if (defaultFilter) { setFilterColumns(defaultFilter ?? []); } }; const handleAccept = () => { const query = filterColumns.filter(quer => quer.filterOption && (quer.filterOption?.value || quer.filterOption?.value === 0)).map(quer => quer.filterOption); if (onFilter && !isArraysEqual(filterColumns, defaultFilter ?? [])) { onFilter(query, filterColumns); } hide(); setPrevFilter(filterColumns); }; const handleReset = () => { setFilterColumns(columns); }; const handleCancel = () => { hide(); setFilterColumns(prevFilter); }; const renderFilter = (tmpColumn, index) => { const find = filterColumns.find(it => it.field === tmpColumn.field); const column = find ? find : tmpColumn; let valueFilter; if (column?.typeFilter === 'Checkbox' || column?.typeFilter === 'CheckboxDropdown' || tmpColumn?.filterOption?.multiple) { const currentValueFilter = filterColumns.filter(it => it.field === column?.field && (it.filterOption?.value || it.filterOption?.value === 0)); valueFilter = currentValueFilter.map(it => it.filterOption?.value); } else if (column?.typeFilter === 'DateRange') { const currentValueFilter = filterColumns.filter(it => it.field === column?.field); const findStartDate = currentValueFilter.find(it => it.filterOption?.operator === 'greaterthanorequal'); const findEndDate = currentValueFilter.find(it => it.filterOption?.operator === 'lessthanorequal'); const startDate = findStartDate ? convertDateToDayjs(findStartDate.filterOption?.value, column?.format?.dateFormat ?? 'DD/MM/YYYY') : ''; const endDate = findEndDate ? convertDateToDayjs(findEndDate.filterOption?.value, column?.format?.dateFormat ?? 'DD/MM/YYYY') : ''; valueFilter = [startDate, endDate]; } else { // single Value valueFilter = column?.filterOption?.value; } const options = dataSourceFilter?.find(it => it.key === column?.field)?.data; const loadOptions = dataSourceFilter?.find(it => it.key === column?.field)?.loadOptions; switch (column?.typeFilter) { case "Checkbox": return /*#__PURE__*/React.createElement(CheckboxControl, { value: valueFilter, options: options ?? [], onChange: val => { console.log(val); // onChangeValueFilter(column, val, true) } }); case 'Dropdown': return ( /*#__PURE__*/ // <Select // showSearch // allowClear // style={{ width: '100%' }} // placeholder='Search to Select' // optionFilterProp='label' // value={valueFilter} // mode={tmpColumn.filterOption?.multiple ? 'multiple' : undefined} // options={options ?? []} // onChange={val => { // onChangeValueFilter(column, val) // }} // dropdownStyle={{ zIndex: 9999 }} // popupClassName={'adv-popup-container'} // getPopupContainer={() => menuRef.current} // className='filter-item-control' // /> React.createElement(AsyncSelect, { showSearch: true, allowClear: true, style: { width: '100%' }, placeholder: "Search to Select", optionFilterProp: "label", value: valueFilter, mode: tmpColumn.filterOption?.multiple ? 'multiple' : undefined, options: options ?? [], defaultOptions: options ?? [], onChange: val => { console.log(val); // onChangeValueFilter(column, val) }, loadOptions: loadOptions, dropdownStyle: { zIndex: 9999 }, popupClassName: 'adv-popup-container' // getPopupContainer={() => menuRef.current} , className: "filter-item-control" }) ); case 'CheckboxDropdown': return /*#__PURE__*/React.createElement(TreeSelect, { showSearch: true, style: { width: '100%' }, value: valueFilter, multiple: true, treeCheckable: true, dropdownStyle: { maxHeight: 400, overflow: 'auto', zIndex: 9999 }, placeholder: "Please select", allowClear: true, maxTagCount: 'responsive', onChange: val => { console.log(val); // onChangeValueFilter(column, val, true) }, treeData: options, popupClassName: 'adv-popup-container checkbox-dropdown' // getPopupContainer={() => menuRef.current} }); case 'DateRange': return /*#__PURE__*/React.createElement(RangePicker, { format: { format: column.format?.dateFormat ?? 'DD/MM/YYYY', type: 'mask' }, defaultValue: valueFilter, value: valueFilter, placeholder: ['Ngày bắt đầu', 'Ngày kết thúc'], popupStyle: { zIndex: 9999 }, onChange: (value, dateString) => { const newDateRangeValue = [dateString[0] ? convertDayjsToDate(dateString[0], column.format?.dateFormat ?? 'DD/MM/YYYY') : '', dateString[1] ? convertDayjsToDate(dateString[1], column.format?.dateFormat ?? 'DD/MM/YYYY') : '']; console.log(newDateRangeValue); // onChangeValueFilter(column, newDateRangeValue) }, style: { width: '100%' }, popupClassName: 'adv-popup-container' // getPopupContainer={() => menuRef.current} }); case 'Date': const dateValue = valueFilter ? convertDateToDayjs(valueFilter, column.format?.dateFormat ?? 'DD/MM/YYYY') : null; return /*#__PURE__*/React.createElement(DatePicker, { format: { format: column.format?.dateFormat ?? 'DD/MM/YYYY', type: 'mask' }, style: { width: '100%' }, defaultValue: dateValue, value: dateValue, placeholder: 'Chọn ngày', onChange: (val, dateString) => { const newDateTimeValue = dateString ? convertDayjsToDate(dateString, column.format?.dateFormat ?? 'DD/MM/YYYY') : null; // onChangeValueFilter(column, newDateTimeValue) console.log(newDateTimeValue); }, popupStyle: { zIndex: 9999 }, popupClassName: 'adv-popup-container' // getPopupContainer={() => menuRef.current} }); case 'Datetime': const dateTimeValue = valueFilter ? convertDateToDayjs(valueFilter, column.format?.dateFormat ?? 'DD/MM/YYYY HH:mm') : null; return /*#__PURE__*/React.createElement(DatePicker, { format: { format: column.format?.datetimeFormat ?? 'DD/MM/YYYY HH:mm', type: 'mask' }, style: { width: '100%' }, showTime: column.typeFilter === 'Datetime', defaultValue: dateTimeValue, value: dateTimeValue, placeholder: 'Chọn ngày', onChange: (val, dateString) => { const newDateTimeValue = dateString ? convertDayjsToDate(dateString, column.format?.datetimeFormat ?? 'DD/MM/YYYY HH:mm') : null; console.log('newDateTimeValue', newDateTimeValue); // onChangeValueFilter(column, newDateTimeValue) }, popupStyle: { zIndex: 9999 }, popupClassName: 'adv-popup-container' }); case 'DropTree': return /*#__PURE__*/React.createElement(TreeSelect, { showSearch: true, style: { width: '100%' }, value: valueFilter, multiple: tmpColumn.filterOption?.multiple, treeCheckable: tmpColumn.filterOption?.treeCheckable, dropdownStyle: { maxHeight: 400, overflow: 'auto', zIndex: 9999 }, placeholder: "Please select", allowClear: true, onChange: () => { // onChangeValueFilter(column, val, tmpColumn.filterOption?.multiple) }, treeData: options, maxTagCount: 'responsive', popupClassName: 'adv-popup-container' }); case 'Time': return /*#__PURE__*/React.createElement(TimePicker, { format: { format: column.format?.timeFormat ?? 'HH:mm', type: 'mask' }, defaultValue: valueFilter ?? null, onChange: (values, timeString) => { const newTimeValue = timeString ? timeString : null; console.log(newTimeValue); // onChangeValueFilter(column, newTimeValue) }, style: { width: '100%' }, popupStyle: { zIndex: 9999 }, popupClassName: 'adv-popup-container' }); case 'Number': const thousandSeparator = column.format?.thousandSeparator ? column.format?.thousandSeparator : format?.thousandSeparator; const decimalSeparator = column.format?.decimalSeparator ? column.format?.decimalSeparator : format?.decimalSeparator; const numericFormatProps = { thousandSeparator: checkThousandSeparator(thousandSeparator, decimalSeparator), decimalSeparator: checkDecimalSeparator(thousandSeparator, decimalSeparator), decimalScale: !isObjEmpty(column.format?.decimalScale) ? column.format?.decimalScale : undefined, fixedDecimalScale: !isEmpty(column.format?.fixedDecimalScale) ? column.format?.fixedDecimalScale : false, allowNegative: column.format?.allowNegative ?? false, prefix: column.format?.prefix ?? undefined, suffix: column.format?.suffix ?? undefined }; const valueNumeric = valueFilter || valueFilter === 0 ? valueFilter.toString() : ''; return /*#__PURE__*/React.createElement(NumericFormat, _extends({}, numericFormatProps, { value: valueNumeric, customInput: Input // valueIsNumericString={true} , autoComplete: 'off', className: classnames('adv-form-input form-control', {}), onValueChange: values => { console.log('values', values); // onChangeValueFilter(column as any, values.floatValue) } })); default: return /*#__PURE__*/React.createElement(Input, { placeholder: 'Nhập giá trị', value: valueFilter ? valueFilter : '', style: { padding: '0.3rem 0.5rem', lineHeight: '1.25' }, autoFocus: index === 0, onChange: val => { console.log(val); // onChangeValueFilter(column as any, val.target.value) }, className: "adv-form-input" }); } }; const content = /*#__PURE__*/React.createElement("div", { ref: menuRef, className: 'd-flex flex-column' }, /*#__PURE__*/React.createElement(MainFilter, { leftFilterWidth: leftFilterWidth, className: 'd-flex pb-1' }, /*#__PURE__*/React.createElement("div", { style: { flex: 1 } }, /*#__PURE__*/React.createElement(GridFilter, { className: 'grid-filter' }, columns.map((it, index) => { return /*#__PURE__*/React.createElement("div", { className: 'grid-item-filter', key: index }, /*#__PURE__*/React.createElement("p", { className: 'm-0', style: { minHeight: 21 } }, t ? t(it.headerText ?? '') : it.headerText), renderFilter(it, index)); })))), /*#__PURE__*/React.createElement(BoxAction, { className: '' }, /*#__PURE__*/React.createElement(Button, { className: 'btn-action btn-action-cancel', variant: "outlined", onClick: handleReset }, t ? t('Reset') : 'Reset'), /*#__PURE__*/React.createElement(Button, { className: 'btn-action btn-action-cancel', variant: "outlined", onClick: handleCancel }, t ? t('Cancel') : 'Cancel'), /*#__PURE__*/React.createElement(Button, { className: classnames('btn-action btn-action-submit', { disable: !columns.find(item => item.visible !== false || item.visible) }), variant: "outlined", onClick: handleAccept, disabled: !columns.find(item => item.visible !== false || item.visible) }, t ? t('Accept') : 'Accept'))); return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(Popover, { placement: 'bottomLeft' // content={ // <div style={{minWidth: 250}}> // // </div> // } , content: content, trigger: "click", open: clicked, onOpenChange: handleClickChange, arrow: false }, /*#__PURE__*/React.createElement(Tooltip, { arrow: false, title: 'Cài đặt' }, count > 0 ? /*#__PURE__*/React.createElement(Badge, { size: "small", count: count, color: "danger" }, /*#__PURE__*/React.createElement(Filter, { fontSize: 16, style: { cursor: 'pointer' } })) : /*#__PURE__*/React.createElement(Filter, { fontSize: 16, style: { cursor: 'pointer' } })))); }; export default AdvanceFilter;