umami/src/components/common/DataTable.tsx

96 lines
2.5 KiB
TypeScript
Raw Normal View History

2023-09-29 12:29:22 +00:00
import { ReactNode, Dispatch, SetStateAction } from 'react';
import classNames from 'classnames';
import { Banner, Loading, SearchField } from 'react-basics';
2023-08-25 18:54:44 +00:00
import { useMessages } from 'components/hooks';
import Empty from 'components/common/Empty';
import Pager from 'components/common/Pager';
import styles from './DataTable.module.css';
const DEFAULT_SEARCH_DELAY = 600;
2023-08-25 18:54:44 +00:00
2023-09-29 12:29:22 +00:00
export interface DataTableProps {
result: {
page: number;
pageSize: number;
count: number;
data: any[];
};
params: {
query: string;
page: number;
};
setParams: Dispatch<SetStateAction<{ query: string; page: number }>>;
isLoading: boolean;
error: unknown;
searchDelay?: number;
showSearch?: boolean;
showPaging?: boolean;
children: ReactNode | ((data: any) => ReactNode);
}
2023-08-25 18:54:44 +00:00
export function DataTable({
2023-09-29 12:29:22 +00:00
result,
params,
setParams,
isLoading,
error,
2023-08-25 18:54:44 +00:00
searchDelay,
showSearch = true,
showPaging = true,
children,
2023-09-29 12:29:22 +00:00
}: DataTableProps) {
2023-08-25 18:54:44 +00:00
const { formatMessage, labels, messages } = useMessages();
2023-09-29 12:29:22 +00:00
const { pageSize, count } = result || {};
const { query, page } = params || {};
const hasData = Boolean(!isLoading && result?.data?.length);
const noResults = Boolean(!isLoading && query && !hasData);
2023-08-25 18:54:44 +00:00
const handleSearch = query => {
setParams({ ...params, query });
2023-08-25 18:54:44 +00:00
};
const handlePageChange = page => {
setParams({ ...params, page });
2023-08-25 18:54:44 +00:00
};
if (error) {
return <Banner variant="error">{formatMessage(messages.error)}</Banner>;
}
2023-08-25 18:54:44 +00:00
return (
<>
{(hasData || query || isLoading) && showSearch && (
2023-08-25 18:54:44 +00:00
<SearchField
className={styles.search}
value={query}
onChange={handleSearch}
delay={searchDelay || DEFAULT_SEARCH_DELAY}
autoFocus={true}
placeholder={formatMessage(labels.search)}
/>
)}
<div
className={classNames(styles.body, { [styles.status]: isLoading || noResults || !hasData })}
>
2023-09-29 12:29:22 +00:00
{hasData ? (typeof children === 'function' ? children(result) : children) : null}
{isLoading && <Loading icon="dots" />}
{!isLoading && !hasData && !query && (
<Empty message={formatMessage(messages.noDataAvailable)} />
)}
{noResults && <Empty message={formatMessage(messages.noResultsFound)} />}
</div>
2023-08-25 18:54:44 +00:00
{showPaging && (
<Pager
className={styles.pager}
page={page}
pageSize={pageSize}
count={count}
onPageChange={handlePageChange}
/>
)}
</>
2023-08-25 18:54:44 +00:00
);
}
export default DataTable;