/* eslint-disable @typescript-eslint/no-explicit-any */ import { get } from '@/rtk/helpers/apiService' import { Box, Button, Checkbox, CloseButton, Container, Group, MultiSelect, Pagination, RadioGroup, Select, Skeleton, Table, Text, TextInput, Tooltip, rem, } from '@mantine/core' import { DateInput, DateTimePicker } from '@mantine/dates' import { IconArrowBadgeLeftFilled, IconArrowBadgeRightFilled, IconArrowsSort, IconFilterExclamation, IconFilterSearch, IconSortAscendingLetters, IconSortDescendingLetters, IconX, } from '@tabler/icons-react' import { ReactNode, useEffect, useState } from 'react' import { useLocation, useNavigate } from 'react-router-dom' import classes from './DataTable.module.css' import { history } from '@/rtk/helpers/history' export enum TypeFilter { text = 'text', boolean = 'boolean', datetime = 'datetime', date = 'date', select = 'select', MultiSelect = 'MultiSelect', } type Column = { name: string size: string header: string render?: (row: any, data?: any[]) => ReactNode } const sortByProperty = (property: string, type: string) => { switch (type) { case 'asc': return (a: any, b: any) => { if (a[property] < b[property]) { return -1 } else if (a[property] > b[property]) { return 1 } else { return 0 } } case 'desc': return (a: any, b: any) => { if (a[property] > b[property]) { return -1 } else if (a[property] < b[property]) { return 1 } else { return 0 } } } } export const DataTableAll = ({ data, columns, pagination, searchInput, checkBox, size, infoTotal, componentRight, }: { data: any[] columns: Column[] pagination?: boolean searchInput?: boolean checkBox?: boolean size: string infoTotal?: React.ReactNode // Set the type to ReactNode to allow JSX elements componentRight?: React.ReactNode }) => { const [Tdata, setTData] = useState(data) // const [tempData, setTempData] = useState([]) const [search, setSearch] = useState('') const [statusSort, setStatusSort] = useState({ name: '', status: 'clear', }) const [perPage, setPerPage] = useState(10) const [page, setPage] = useState(1) const [selectedRows, setSelectedRows] = useState([]) const headers = columns.map((col) => ( {col.header}{' '} Desc } color="gray" > { setStatusSort({ name: col.name, status: 'desc' }) // localStorage.setItem('package__table_sort', JSON.stringify({ name: col.name, status: 'desc' })) // setTData(data.slice().sort(sortByProperty(col.name, 'desc'))) }} className={classes.iconSort} /> Asc } color="gray" > { setStatusSort({ name: col.name, status: 'asc' }) // localStorage.setItem('package__table_sort', JSON.stringify({ name: col.name, status: 'asc' })) // setTData(data.slice().sort(sortByProperty(col.name, 'asc'))) }} className={classes.iconSort} /> Clear } color="gray" > { setStatusSort({ name: col.name, status: 'clear' }) }} className={classes.iconSort} /> )) const rows = Tdata.map((element, index) => { const row = columns.map((col) => { if (col.render) { return ( {col.render(element, Tdata)} ) } else { if (element[col.name]) { return ( {element[col.name].toString()} ) } else { return ( null ) } } }) return ( Object.keys(obj).every((key) => obj[key] === element[key]), ) ? 'var(--mantine-color-blue-light)' : undefined } > Object.keys(obj).every((key) => obj[key] === element[key]), )} onChange={(event) => setSelectedRows( event.currentTarget.checked ? [...selectedRows, element] : selectedRows.filter((position) => position !== element), ) } /> {row} ) }) const [debounceTimer, setDebounceTimer] = useState() const handleInput = (e: any) => { clearTimeout(debounceTimer) setDebounceTimer( setTimeout(() => { searchInArray(e) }, 500), ) } const searchInArray = (query: string) => { if (query !== '') { setTData( data.filter((obj) => Object.values(obj).some( (value: any) => value !== null && value.toString().toLowerCase().includes(query.toLowerCase()), ), ), ) } else { if (pagination) { const temp = data.slice(perPage * (page - 1), perPage * page) setTData(temp) } else { setTData(data) } } } const areObjectsEqual = (obj1: any, obj2: any) => { return Object.keys(obj1).every((key) => obj1[key] === obj2[key]) } const checkSubArray = (arr1: any[], arr2: any[]) => { return arr1.some((obj1: any) => arr2.some((obj2: any) => areObjectsEqual(obj1, obj2)), ) } useEffect(() => { if (pagination) { setTData(data.slice(perPage * (page - 1), perPage * page)) } else { if (statusSort.status !== 'clear') { setTData( data.slice().sort(sortByProperty(statusSort.name, statusSort.status)), ) } else { setTData(data) } } }, [data, statusSort]) useEffect(() => { if (pagination) { const temp = data.slice(perPage * (page - 1), perPage * page) setTData(temp) } }, [page, perPage]) return ( { setSearch('') handleInput('') }} style={{ display: search ? undefined : 'none' }} /> } placeholder="🔍 Search" onChange={(e) => { handleInput(e.target.value) setSearch(e.target.value) }} /> {search !== '' ? ( Found {Tdata.length} matches out of {data.length} entries ) : ( Show {perPage * (page - 1) + 1} to {data.length} of {data.length}{' '} entries )} {infoTotal} setPage(e)} /> { setDataFilter({ ...dataFilter, [item.key]: e }) }} data={item.data} /> ) case TypeFilter.MultiSelect: return ( { urlParams.set(item.key, values.join(',')) history.push({ pathName: location.pathname, search: urlParams.toString(), }) setDataFilter({ ...dataFilter, [item.key]: values, }) }} searchable /> ) } })} 0 ? 'flex' : 'none', }} onClick={() => setOpenedFilter(!openedFilter)} > {Object.values(dataFilter).filter( (value) => value === '' || value === null, ).length === Object.keys(dataFilter).length ? ( ) : ( )} value === '' || value === null, ).length !== Object.values(dataFilter).length ? 'red' : '' } > Filter { setSearch('') }} style={{ display: search ? undefined : 'none' }} /> } placeholder="🔍 Search" onChange={(e) => { setSearch(e.target.value) }} onKeyUp={() => { handleData(1500, setPage) }} /> Show {baseData.from} to {baseData.to} of {baseData.total} entries {baseData.links.map((element: any, index: number) => { switch (element.label) { case '« Previous': return ( ) case 'Next »': return ( ) case '...': return ( {' '} ... {' '} ) default: return ( ) } })}